summary refs log tree commit diff
diff options
context:
space:
mode:
authorWlodekM <[email protected]>2025-04-03 11:20:33 +0300
committerWlodekM <[email protected]>2025-04-03 11:20:33 +0300
commit8702826717b3e916ef774004c4de99b96d04ddff (patch)
treed0df9a4901d79f6a3d9fd03e00afd6039d6cdd2d
parentc50e619bef9ecd2266ee904b87c6401cb0572660 (diff)
debugging stuff
-rw-r--r--65c02.ts1
-rw-r--r--runtime.ts101
2 files changed, 85 insertions, 17 deletions
diff --git a/65c02.ts b/65c02.ts
index 5720a75..9d286d9 100644
--- a/65c02.ts
+++ b/65c02.ts
@@ -169,7 +169,6 @@ export default class The65c02 {
             throw `not found ${instruction}`
         if (!this.instructions[opm[instruction].mnemonic])
             throw `not implement, sowwy (${opm[instruction].mnemonic}.ts not found)`;
-        console.debug(this.programCounter.num().toString(16).padStart(4, '0'),opm[instruction].mnemonic, opm[instruction].mode)
         this.instructions[opm[instruction].mnemonic].call(this, opm[instruction].mode);
     }
     //SECTION - utils
diff --git a/runtime.ts b/runtime.ts
index eedcd70..2a16536 100644
--- a/runtime.ts
+++ b/runtime.ts
@@ -1,4 +1,5 @@
 import The65c02, { BitField, Pin } from "./65c02.ts";
+import matrix from "./opcode_matrix.json" with { type: "json" };
 
 // the thing used for ram
 const ram = new Uint8Array(2**16);
@@ -35,39 +36,107 @@ cpu.cycle()
 //the cpu reset, pull RESB high and start execution!
 cpu.io.reset.HI()
 
+function inspect() {
+    console.log('IO status:')
+    console.log(Object.entries(cpu.io)
+        .map(([name, io]) => {
+            if (io instanceof Pin) {
+                return ` ${name}: ${' '.repeat(20 - name.length)}${io.high ? "HI" : "LO"}`
+            } else if (io instanceof BitField) {
+                return ` ${name}: ${' '.repeat(20 - name.length)}${io.bits.map(k=>+k).join('')} (0x${io.num().toString(16)})`
+            }
+        }).join('\n'));
+    
+    console.log('\nregisters:')
+    console.log(` A:      ${cpu.regA.bits.map(k=>+k).join('')} (0x${cpu.regA.num().toString(16)})`)
+    console.log(` X:      ${cpu.regX.bits.map(k=>+k).join('')} (0x${cpu.regX.num().toString(16)})`)
+    console.log(` Y:      ${cpu.regY.bits.map(k=>+k).join('')} (0x${cpu.regY.num().toString(16)})`)
+    console.log(` SP:     ${cpu.stackPointer.bits.map(k=>+k).join('')} (0x${cpu.stackPointer.num().toString(16)})`)
+    console.log(` PC:     ${cpu.programCounter.bits.map(k=>+k).join('')} (0x${cpu.programCounter.num().toString(16)})`)
+}
+
 const debug = Deno.args.includes('-d')
 
+let skip = 0;
+let breakpoints: number[] = []
+let instBreakpoints: string[] = []
+
 // repeat until the cpu requests an interrupt
 while (!cpu.io.interruptRequest.high) {
     cpu.cycle();
 
     // debug step-by-step mode
-    if (debug) {
+    dbg: if (debug) {
+        const goog = Object.entries(matrix).find(([k]) => k == ram[cpu.programCounter.num()].toString(16));
+        if (!goog) {
+            console.log('uh')
+            break dbg;
+        }
+        const instr = goog[1];
+        console.debug(cpu.programCounter.num().toString(16).padStart(4, '0'),instr.mnemonic, instr.mode)
+        if (instBreakpoints.includes(instr.mnemonic)) {
+            instBreakpoints = instBreakpoints.filter(k => k != instr.mnemonic)
+            skip = 0;
+            console.log('hit instruction breakpoint on', cpu.programCounter.num().toString(16))
+        }
+        if (breakpoints.includes(cpu.programCounter.num())) {
+            breakpoints = breakpoints.filter(k => k != cpu.programCounter.num())
+            skip = 0;
+            console.log('hit breakpoint on', cpu.programCounter.num().toString(16))
+        }
+        if (skip > 0) {
+            skip--
+            break dbg;
+        }
         const i = new Uint8Array(8);
+        Deno.stdout.write(Uint8Array.from(['.'.charCodeAt(0)]))
         await Deno.stdin.read(i);
         if (i[0] == 'b'.charCodeAt(0)) {
             console.log('BREAK!!')
             break;
+        } else if (i[0] == 'i'.charCodeAt(0)) {
+            inspect()
+        } else if (i[0] == 's'.charCodeAt(0)) {
+            console.log('stack:')
+            for (let i = 0; i < cpu.stackPointer.num(); i++) {
+                console.log(` ${i.toString(16).padStart(2, '0')} ${ram[0x01FF - i].toString(2).padStart(8, '0')} (0x${ram[0x01FF - i].toString(16).padStart(4, '0')} ${ram[0x01FF - i]})`)
+            }
+        } else if (i[0] == 'k'.charCodeAt(0)) {
+            const num = +(new TextDecoder().decode(i.slice(1, 7)).replaceAll('\0', ''));
+            if (Number.isNaN(num)) {
+                console.log('NaN')
+                break dbg;
+            }
+            skip = num;
+            console.log(`skipping ${num} cycles`)
+        } else if (i[0] == 'r'.charCodeAt(0)) {
+            const num = i[2] ? parseInt(new TextDecoder().decode(i.slice(1, 7)).replace('\n', '').replaceAll('\0', ''), 16) : cpu.programCounter.num();
+            console.log(`set breakpoint on`, num.toString(16))
+            breakpoints.push(num)
+        } else if (i[0] == '?'.charCodeAt(0)) {
+            console.log(`b - break, exit
+i - inspect
+s - inspect stack
+k[NUM] - skip
+r[ADR] - breakpoint
+g[ADR] - goto, change PC
+I[INS] - breakpoint instruction`);
+        } else if (i[0] == 'g'.charCodeAt(0)) {
+            const num = i[2] ? parseInt(new TextDecoder().decode(i.slice(1, 7)).replace('\n', '').replaceAll('\0', ''), 16) : cpu.programCounter.num();
+            console.log(`PC set to`, num.toString(16))
+            cpu.programCounter.set(num)
+        } else if (i[0] == 'I'.charCodeAt(0)) {
+            const instr = new TextDecoder().decode(i.slice(1, 7)).replace('\n', '').replaceAll('\0', '')
+            console.log(`instruction breakpoint set on`, instr)
+            instBreakpoints.push(instr)
         }
     }
 }
 
-console.log('end of execution\n\nIO status:')
-console.log(Object.entries(cpu.io)
-    .map(([name, io]) => {
-        if (io instanceof Pin) {
-            return ` ${name}: ${' '.repeat(20 - name.length)}${io.high ? "HI" : "LO"}`
-        } else if (io instanceof BitField) {
-            return ` ${name}: ${' '.repeat(20 - name.length)}${io.bits.map(k=>+k).join('')} (0x${io.num().toString(16)})`
-        }
-    }).join('\n'));
-
-console.log('\nregisters:')
-console.log(` A: ${cpu.regA.bits.map(k=>+k).join('')} (0x${cpu.regA.num().toString(16)})`)
-console.log(` X: ${cpu.regX.bits.map(k=>+k).join('')} (0x${cpu.regX.num().toString(16)})`)
-console.log(` Y: ${cpu.regY.bits.map(k=>+k).join('')} (0x${cpu.regY.num().toString(16)})`)
+console.log('end of execution\n\n')
+inspect()
 
-console.debug('\nRAM:')
+// console.debug('\nRAM:')
 Deno.writeFileSync('ram.bin', ram)
 // new Deno.Command('hexdump', {
 //     args: ['-C', 'ram.bin']