6502 emulator for Commodore 64 ROMs, serial terminal edition for MBED. Recommend terminal echo on, line edit on, caps lock, 115200bps, implicit carriage return on newline, currently non-buffered so don't paste lots of stuff
More details at:
[https://github.com/davervw] [https://techwithdave.davevw.com/2020/03/simple-emu-c64.html]
Diff: emu6502.cpp
- Revision:
- 4:0461c100cbbb
- Parent:
- 0:90de1cbc8a5f
- Child:
- 7:f49fa56672d8
--- a/emu6502.cpp Fri Apr 10 04:32:54 2020 +0000 +++ b/emu6502.cpp Sun Apr 12 19:26:44 2020 +0000 @@ -11,7 +11,6 @@ // davevw.com // // Permission is hereby granted, free of charge, to any person obtaining a copy -// // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell @@ -55,6 +54,8 @@ bool trace = false; bool step = false; +#define USE_IRQ 0 + extern void ResetRun(bool (*ExecutePatch)(void)) { ushort addr = (ushort)((GetMemory(0xFFFC) | (GetMemory(0xFFFD) << 8))); // RESET vector @@ -98,9 +99,9 @@ static void BRK(byte *p_bytes) { ++PC; - PHP(); Push(HI(PC)); Push(LO(PC)); + PHP(); B = true; PC = (ushort)(GetMemory(0xFFFE) + (GetMemory(0xFFFF) << 8)); *p_bytes = 0; @@ -186,7 +187,7 @@ } } -static void ADC(byte value) +static void ADC_OP(byte value) { int result; if (D) @@ -228,7 +229,7 @@ SetA(A & value); } -static void BIT(byte value) +static void BIT_OP(byte value) { Z = (A & value) == 0; N = (value & 0x80) != 0; @@ -491,8 +492,8 @@ static void RTI(ushort *p_addr, byte *p_bytes) { PLP(); + byte lo = Pop(); byte hi = Pop(); - byte lo = Pop(); *p_bytes = 0; // make sure caller does not increase addr by one *p_addr = (ushort)((hi << 8) | lo); } @@ -660,39 +661,60 @@ bool conditional; byte bytes; +#if (USE_IRQ == 1) + // IRQ support + Timer timer; + const double interrupt_time = 1.0 / 60.0 ; // 60 times per second + timer.start(); + double timer_then = timer.read(); +#endif + PC = addr; while (true) { while (true) { - bytes = 1; - //bool breakpoint = false; - //if (Breakpoints.Contains(PC)) - // breakpoint = true; - bool breakpoint = (addr == 0xFD88); - if (trace || breakpoint || step) +#if (USE_IRQ == 1) + if (!I && (timer.read()-timer_then) >= interrupt_time) // IRQ + { + timer_then = timer.read(); // reset timer + Push(HI(PC)); + Push(LO(PC)); + PHP(); + I = true; + PC = (GetMemory(0xfffe) | (GetMemory(0xffff) << 8)); + } + else +#endif { - ushort addr2; - char line[27]; - char dis[13]; - DisassembleLong(PC, &conditional, &bytes, &addr2, dis, sizeof(dis), line, sizeof(line)); - char state[33]; - GetDisplayState(state, sizeof(state)); - char full_line[80]; - snprintf(full_line, sizeof(full_line), "%-30s%s\n", line, state); -#ifdef WIN32 - OutputDebugStringA(full_line); -#else - pc.printf("%s", full_line); -#endif - if (step) - step = step; // user can put debug breakpoint here to allow stepping - if (breakpoint) - breakpoint = breakpoint; // user can put debug breakpoint here to allow break + bytes = 1; + bool breakpoint = false; + //if (Breakpoints.Contains(PC)) + // breakpoint = true; + if (trace || breakpoint || step) + { + ushort addr2; + char line[27]; + char dis[13]; + DisassembleLong(PC, &conditional, &bytes, &addr2, dis, sizeof(dis), line, sizeof(line)); + char state[33]; + GetDisplayState(state, sizeof(state)); + char full_line[80]; + snprintf(full_line, sizeof(full_line), "%-30s%s\n", line, state); + #ifdef WIN32 + OutputDebugStringA(full_line); + #else + pc.printf("%s", full_line); + #endif + if (step) + step = step; // user can put debug breakpoint here to allow stepping + if (breakpoint) + breakpoint = breakpoint; // user can put debug breakpoint here to allow break + } + if (ExecutePatch != 0 && !ExecutePatch()) // allow execute to be overriden at a specific address + break; } - if (ExecutePatch != 0 && !ExecutePatch()) // allow execute to be overriden at a specific address - break; } switch (GetMemory(PC)) @@ -718,13 +740,13 @@ case 0x20: JSR(&PC, &bytes); break; case 0x21: AND(GetIndX(PC, &bytes)); break; - case 0x24: BIT(GetZP(PC, &bytes)); break; + case 0x24: BIT_OP(GetZP(PC, &bytes)); break; case 0x25: AND(GetZP(PC, &bytes)); break; case 0x26: SetZP(ROL(GetZP(PC, &bytes)), PC, &bytes); break; case 0x28: PLP(); break; case 0x29: AND(GetIM(PC, &bytes)); break; case 0x2A: SetA(ROL(A)); break; - case 0x2C: BIT(GetABS(PC, &bytes)); break; + case 0x2C: BIT_OP(GetABS(PC, &bytes)); break; case 0x2D: AND(GetABS(PC, &bytes)); break; case 0x2E: ROL(GetABS(PC, &bytes)); break; @@ -758,23 +780,23 @@ case 0x5E: SetABSX(LSR(GetABSX(PC, &bytes)), PC, &bytes); break; case 0x60: RTS(&PC, &bytes); break; - case 0x61: ADC(GetIndX(PC, &bytes)); break; - case 0x65: ADC(GetZP(PC, &bytes)); break; + case 0x61: ADC_OP(GetIndX(PC, &bytes)); break; + case 0x65: ADC_OP(GetZP(PC, &bytes)); break; case 0x66: SetZP(ROR(GetZP(PC, &bytes)), PC, &bytes); break; case 0x68: PLA(); break; - case 0x69: ADC(GetIM(PC, &bytes)); break; + case 0x69: ADC_OP(GetIM(PC, &bytes)); break; case 0x6A: SetA(ROR(A)); break; case 0x6C: JMPIND(&PC, &bytes); break; - case 0x6D: ADC(GetABS(PC, &bytes)); break; + case 0x6D: ADC_OP(GetABS(PC, &bytes)); break; case 0x6E: SetABS(ROR(GetABS(PC, &bytes)), PC, &bytes); break; case 0x70: BVS(&PC, &conditional, &bytes); break; - case 0x71: ADC(GetIndY(PC, &bytes)); break; - case 0x75: ADC(GetZPX(PC, &bytes)); break; + case 0x71: ADC_OP(GetIndY(PC, &bytes)); break; + case 0x75: ADC_OP(GetZPX(PC, &bytes)); break; case 0x76: SetZPX(ROR(GetZPX(PC, &bytes)), PC, &bytes); break; case 0x78: SEI(); break; - case 0x79: ADC(GetABSY(PC, &bytes)); break; - case 0x7D: ADC(GetABSX(PC, &bytes)); break; + case 0x79: ADC_OP(GetABSY(PC, &bytes)); break; + case 0x7D: ADC_OP(GetABSX(PC, &bytes)); break; case 0x7E: SetABSX(ROR(GetABSX(PC, &bytes)), PC, &bytes); break; case 0x81: SetIndX(A, PC, &bytes); break;