diff options
Diffstat (limited to 'pc-thing/runtime_new.ts')
-rw-r--r-- | pc-thing/runtime_new.ts | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/pc-thing/runtime_new.ts b/pc-thing/runtime_new.ts new file mode 100644 index 0000000..f0045d6 --- /dev/null +++ b/pc-thing/runtime_new.ts @@ -0,0 +1,134 @@ +import { PC } from "./pc.ts"; + +type instruction = { function: (this: PC, argv: number[]) => void, args: number } + +class Runtime { + pc: PC = new PC(true) + instructions: Record<string, instruction> = {} + instructionNames: string[] = [] + + addInstruction(name: string, instruction: instruction) { + this.instructionNames.push(name) + this.instructions[name] = instruction + } + + run(line: number[]) { + const instructionId = this.pc.instructions[line.shift() ?? -1] + if (instructionId == undefined || !this.instructions[instructionId]) + throw 'unknown instruction (1)'; + const instruction = this.instructions[instructionId]; + if (!instruction) + throw 'unknown instruction (2)'; + try { + instruction.function.call(this.pc, line) + } catch (error) { + console.error(error, 'at', this.pc.programPointer, instructionId) + } + } +} + +const disk = [...Deno.readFileSync('disk.img')].reduce<number[]>((result, value, index, array) => { + if (index % 2 === 0) { + result.push(value | (array[index + 1] << 8)) + } + return result; +}, []) + +const runtime = new Runtime() + +runtime.pc.getSegment = function getSegment(segment: number): Uint16Array { + const seg = disk.slice(segment * 512, (segment + 1) * 512); + console.log(`getSegment( ${segment} ):`, seg) + return Uint16Array.from(seg.fill(seg.length, 512)) +} + +const dir = Deno.readDirSync('instructions_new'); + +for (const filename of dir) { + runtime.addInstruction(filename.name.replace(/\..*?$/g, ''), + (await import('./instructions_new/' + filename.name)).default) +} + +runtime.addInstruction('end', { function: () => { }, args: 0 }) + +const iram = Deno.readFileSync("iram.bin") + +runtime.pc.mem = runtime.pc.mem.toSpliced(65534 / 2 + 1, 0, ...[...iram].reduce<number[]>((result, value, index, array) => { + if (index % 2 === 0) { + result.push(value | (array[index + 1] << 8)) + } + return result; +}, [])) + +runtime.pc.programPointer = 65536 / 2 + +const haltEvents = new EventTarget() + +function waitUntilNotInterrupted(): Promise<void> { + return new Promise((resolve) => { + const callback = () => { + resolve() + haltEvents.removeEventListener('unHalted', callback) + } + haltEvents.addEventListener('unHalted', callback) + }) +} + +function gotoInterrupt() { + // console.log("INTERRUPT!", runtime.pc.mem[0x7000]) + if (!runtime.pc.mem[0x7000]) + return; + runtime.pc.halted = false + haltEvents.dispatchEvent(new Event('unHalted')); + runtime.pc.returnStack.push(runtime.pc.programPointer - 1); + runtime.pc.programPointer = runtime.pc.mem[0x7000] +} + +const interruptInterval = setInterval(gotoInterrupt, 10) + +const endInst = (Object.entries(runtime.pc.instructions) as [unknown, string][] as [number, string][]) + .find(([_, b]: [number, string]) => b == 'end') +if (!endInst) throw 'where the fuck is the end instruction' +const endInstId = endInst[0]; + + +let c = 0 +while ( + runtime.pc.mem[runtime.pc.programPointer] != endInstId && + runtime.pc.programPointer != 0xFFFF - 1) { + try { + const definition = Object.entries(runtime.pc.instructions).find(([a]) => +a == runtime.pc.mem[runtime.pc.programPointer]) + if (!definition || !definition[1]) throw `what the fuck is that (unknown instruction) +at ${runtime.pc.programPointer} (${runtime.pc.programPointer.toString(16)}/${(runtime.pc.programPointer * 2).toString(16)}/${(runtime.pc.programPointer * 2 - (2 ** 16)).toString(16)}) +instruction: ${runtime.pc.mem[runtime.pc.programPointer]}` + const instruction = definition[1] + runtime.pc.programPointer++ + // console.debug(instruction, runtime.instructions, definition) + const args = []; + if (Deno.args.includes('-d')) + console.debug(runtime.pc.programPointer, definition, instruction, runtime.pc.mem[runtime.pc.programPointer + 1]) + while (args.length < runtime.instructions[instruction].args) { + args.push(runtime.pc.mem[runtime.pc.programPointer]) + runtime.pc.programPointer++ + } + runtime.run([+definition[0], ...args]) + // runtime.pc.programPointer++ + c++ + } catch (error) { + console.error(error); + break; + } + if (runtime.pc.halted) { + await waitUntilNotInterrupted() + } +} + +clearInterval(interruptInterval) + +if (Deno.args.includes('-d')) + console.debug(Object.values(runtime.pc.instructions)) +console.debug('end of execution, dumping ram', runtime.pc.mem) +Deno.writeFileSync('ram.bin', Uint8Array.from(runtime.pc.mem.map(a => [a & 0x00FF, (a & 0xFF00) >> 8]).flatMap(([a, b]) => [a, b]))) +new Deno.Command('hexdump', { + args: ['-C', 'ram.bin'] +}).spawn() |