diff --git a/mmu.cpp b/mmu.cpp index 78ba9e1..84be1ce 100644 --- a/mmu.cpp +++ b/mmu.cpp @@ -32,248 +32,248 @@ //========================================== MEMORY MAPPED SOFT SWITCHES HANDLER uint8_t Mmu::softSwitches(uint16_t address, uint8_t value, bool WRT) { - static uint8_t dLatch = 0; // disk ][ I/O register + static uint8_t dLatch = 0; // disk ][ I/O register - switch (address) { + switch (address) { - // MEMORY MANAGEMENT (and KEYBOARD) - case 0xC000: if (WRT) STORE80 = false; else return KBD; break; // cause PAGE2 on to select AUX -- KEYBOARD return key code - if hi-bit is set the key code (7 lo-bits) is valid - case 0xC001: if (WRT) STORE80 = true; break; // allow PAGE2 to switch MAIN / AUX - case 0xC002: if (WRT) RAMRD = false; break; // read from MAIN - case 0xC003: if (WRT) RAMRD = true; break; // read from AUX - case 0xC004: if (WRT) RAMWRT = false; break; // write to MAIN - case 0xC005: if (WRT) RAMWRT = true; break; // write to AUX - case 0xC006: if (WRT) INTCXROM = false; break; // set peripheral roms for peripherals ($C100-$CFFF) - case 0xC007: if (WRT) INTCXROM = true; break; // set internal rom for peripherals ($C100-$CFFF) - case 0xC008: if (WRT) ALTZP = false; break; // MAIN stack & rero page - case 0xC009: if (WRT) ALTZP = true; break; // AUX stack & rero page - case 0xC00A: if (WRT) SLOTC3ROM = false; break; // ROM in Slot 3 - case 0xC00B: if (WRT) SLOTC3ROM = true; break; // ROM in AUX Slot - case 0xC00C: if (WRT) COL80 = false; break; // 80 COL OFF -> 40 COL - case 0xC00D: if (WRT) COL80 = true; break; // 80 COL ON - case 0xC00E: if (WRT) ALTCHARSET = false; break; // primary character set - case 0xC00F: if (WRT) ALTCHARSET = true; break; // alternate character set - case 0xC010: KBD &= 0x7F; return KBD; // KBDSTROBE, clear hi-bit and return key code + // MEMORY MANAGEMENT (and KEYBOARD) + case 0xC000: if (WRT) STORE80 = false; else return KBD; break; // cause PAGE2 on to select AUX -- KEYBOARD return key code - if hi-bit is set the key code (7 lo-bits) is valid + case 0xC001: if (WRT) STORE80 = true; break; // allow PAGE2 to switch MAIN / AUX + case 0xC002: if (WRT) RAMRD = false; break; // read from MAIN + case 0xC003: if (WRT) RAMRD = true; break; // read from AUX + case 0xC004: if (WRT) RAMWRT = false; break; // write to MAIN + case 0xC005: if (WRT) RAMWRT = true; break; // write to AUX + case 0xC006: if (WRT) INTCXROM = false; break; // set peripheral roms for peripherals ($C100-$CFFF) + case 0xC007: if (WRT) INTCXROM = true; break; // set internal rom for peripherals ($C100-$CFFF) + case 0xC008: if (WRT) ALTZP = false; break; // MAIN stack & rero page + case 0xC009: if (WRT) ALTZP = true; break; // AUX stack & rero page + case 0xC00A: if (WRT) SLOTC3ROM = false; break; // ROM in Slot 3 + case 0xC00B: if (WRT) SLOTC3ROM = true; break; // ROM in AUX Slot + case 0xC00C: if (WRT) COL80 = false; break; // 80 COL OFF -> 40 COL + case 0xC00D: if (WRT) COL80 = true; break; // 80 COL ON + case 0xC00E: if (WRT) ALTCHARSET = false; break; // primary character set + case 0xC00F: if (WRT) ALTCHARSET = true; break; // alternate character set + case 0xC010: KBD &= 0x7F; return KBD; // KBDSTROBE, clear hi-bit and return key code - // SOFT SWITCH STATUS FLAGS - case 0xC011: return (0x80 * LCBK2); - case 0xC012: return (0x80 * LCRD); - case 0xC013: return (0x80 * RAMRD); // 0x80 if reads from AUX - case 0xC014: return (0x80 * RAMWRT); // 0x80 if writes from AUX - case 0xC015: return (0x80 * INTCXROM); - case 0xC016: return (0x80 * ALTZP); // 0x80 if using stack and zero page from AUX - case 0xC017: return (0x80 * SLOTC3ROM); - case 0xC018: return (0x80 * STORE80); // do we store 80 col page 2 on MAIN or AUX - case 0xC019: return (0x80 * VERTBLANK); + // SOFT SWITCH STATUS FLAGS + case 0xC011: return (0x80 * LCBK2); + case 0xC012: return (0x80 * LCRD); + case 0xC013: return (0x80 * RAMRD); // 0x80 if reads from AUX + case 0xC014: return (0x80 * RAMWRT); // 0x80 if writes from AUX + case 0xC015: return (0x80 * INTCXROM); + case 0xC016: return (0x80 * ALTZP); // 0x80 if using stack and zero page from AUX + case 0xC017: return (0x80 * SLOTC3ROM); + case 0xC018: return (0x80 * STORE80); // do we store 80 col page 2 on MAIN or AUX + case 0xC019: return (0x80 * VERTBLANK); - case 0xC01A: return (0x80 * TEXT); // read text switch - case 0xC01B: return (0x80 * MIXED); // read mixed switch - case 0xC01C: return (0x80 * PAGE2); // read page 2 switch - case 0xC01D: return (0x80 * HIRES); // read HiRes switch - case 0xC01E: return (0x80 * ALTCHARSET); // alternate character set ? - case 0xC01F: return (0x80 * COL80); // 80 columns on ? + case 0xC01A: return (0x80 * TEXT); // read text switch + case 0xC01B: return (0x80 * MIXED); // read mixed switch + case 0xC01C: return (0x80 * PAGE2); // read page 2 switch + case 0xC01D: return (0x80 * HIRES); // read HiRes switch + case 0xC01E: return (0x80 * ALTCHARSET); // alternate character set ? + case 0xC01F: return (0x80 * COL80); // 80 columns on ? - // SOUND - case 0xC020: // TAPEOUT (shall we listen it ? - try SAVE from applesoft) - case 0xC030: // SPEAKER - case 0xC033: speaker->play(); break; // apple invader uses $C033 to output sound ! + // SOUND + case 0xC020: // TAPEOUT (shall we listen it ? - try SAVE from applesoft) + case 0xC030: // SPEAKER + case 0xC033: speaker->play(); break; // apple invader uses $C033 to output sound ! - // GAME I/O STROBE OUT - case 0xC040: break; + // GAME I/O STROBE OUT + case 0xC040: break; - // VIDEO MODES - case 0xC050: TEXT = false; video->clearCache(); break; // set Graphics - case 0xC051: TEXT = true; video->clearCache(); break; // set Text - case 0xC052: MIXED = false; video->clearCache(); break; // set Mixed to off - case 0xC053: MIXED = true; video->clearCache(); break; // set Mixed to on - case 0xC054: PAGE2 = false; video->clearCache(); break; // select page 1 - case 0xC055: PAGE2 = true; video->clearCache(); break; // select page 2 - case 0xC056: HIRES = false; video->clearCache(); break; // set HiRes to off - case 0xC057: HIRES = true; video->clearCache(); break; // set HiRes to on + // VIDEO MODES + case 0xC050: TEXT = false; video->clearCache(); break; // set Graphics + case 0xC051: TEXT = true; video->clearCache(); break; // set Text + case 0xC052: MIXED = false; video->clearCache(); break; // set Mixed to off + case 0xC053: MIXED = true; video->clearCache(); break; // set Mixed to on + case 0xC054: PAGE2 = false; video->clearCache(); break; // select page 1 + case 0xC055: PAGE2 = true; video->clearCache(); break; // select page 2 + case 0xC056: HIRES = false; video->clearCache(); break; // set HiRes to off + case 0xC057: HIRES = true; video->clearCache(); break; // set HiRes to on - // ANNUNCIATORS - case 0xC058: if (!IOUDIS) AN0 = false; break; // If IOUDIS off: Annunciator 0 Off - case 0xC059: if (!IOUDIS) AN0 = true; break; // If IOUDIS off: Annunciator 0 On - case 0xC05A: if (!IOUDIS) AN1 = false; break; // If IOUDIS off: Annunciator 1 Off - case 0xC05B: if (!IOUDIS) AN1 = true; break; // If IOUDIS off: Annunciator 1 On - case 0xC05C: if (!IOUDIS) AN2 = false; break; // If IOUDIS off: Annunciator 2 Off - case 0xC05D: if (!IOUDIS) AN2 = true; break; // If IOUDIS off: Annunciator 2 On - case 0xC05E: if (!IOUDIS) AN3 = false; DHIRES = true; break; // If IOUDIS off: Annunciator 3 Off - case 0xC05F: if (!IOUDIS) AN3 = true; DHIRES = false; break; // If IOUDIS off: Annunciator 2 On + // ANNUNCIATORS + case 0xC058: if (!IOUDIS) AN0 = false; break; // If IOUDIS off: Annunciator 0 Off + case 0xC059: if (!IOUDIS) AN0 = true; break; // If IOUDIS off: Annunciator 0 On + case 0xC05A: if (!IOUDIS) AN1 = false; break; // If IOUDIS off: Annunciator 1 Off + case 0xC05B: if (!IOUDIS) AN1 = true; break; // If IOUDIS off: Annunciator 1 On + case 0xC05C: if (!IOUDIS) AN2 = false; break; // If IOUDIS off: Annunciator 2 Off + case 0xC05D: if (!IOUDIS) AN2 = true; break; // If IOUDIS off: Annunciator 2 On + case 0xC05E: if (!IOUDIS) AN3 = false; DHIRES = true; break; // If IOUDIS off: Annunciator 3 Off + case 0xC05F: if (!IOUDIS) AN3 = true; DHIRES = false; break; // If IOUDIS off: Annunciator 2 On - // TAPE - case 0xC060: break; // TAPE IN + // TAPE + case 0xC060: break; // TAPE IN - // PADDLES - case 0xC061: return paddles->PB0; // Push Button 0 / Open Apple - case 0xC062: return paddles->PB1; // Push Button 1 / Solid Apple - case 0xC063: return paddles->PB2; // Push Button 2 / Shift - case 0xC064: return paddles->read(0); // Paddle 0 - case 0xC065: return paddles->read(1); // Paddle 1 - case 0xC066: return paddles->read(2); // Paddle 2 - case 0xC067: return paddles->read(3); // Paddle 3 - case 0xC070: paddles->reset(); break; // paddles timer reset + // PADDLES + case 0xC061: return paddles->PB0; // Push Button 0 / Open Apple + case 0xC062: return paddles->PB1; // Push Button 1 / Solid Apple + case 0xC063: return paddles->PB2; // Push Button 2 / Shift + case 0xC064: return paddles->read(0); // Paddle 0 + case 0xC065: return paddles->read(1); // Paddle 1 + case 0xC066: return paddles->read(2); // Paddle 2 + case 0xC067: return paddles->read(3); // Paddle 3 + case 0xC070: paddles->reset(); break; // paddles timer reset - // IOUDIS - case 0xC07E: if (WRT) IOUDIS = false; else return (0x80 * IOUDIS); break; - case 0xC07F: if (WRT) IOUDIS = true; else return (0x80 * DHIRES); break; + // IOUDIS + case 0xC07E: if (WRT) IOUDIS = false; else return (0x80 * IOUDIS); break; + case 0xC07F: if (WRT) IOUDIS = true; else return (0x80 * DHIRES); break; - // LANGUAGE CARD (used with MAIN and AUX) + // LANGUAGE CARD (used with MAIN and AUX) case 0xC080: - case 0xC084: LCBK2 = 1; LCRD = 1; LCWR = 0; LCWFF = 0; break; // LC2RD - case 0xC081: - case 0xC085: LCBK2 = 1; LCRD = 0; LCWR |= LCWFF; LCWFF = !WRT; break; // LC2WR - case 0xC082: - case 0xC086: LCBK2 = 1; LCRD = 0; LCWR = 0; LCWFF = 0; break; // ROMONLY2 - case 0xC083: - case 0xC087: LCBK2 = 1; LCRD = 1; LCWR |= LCWFF; LCWFF = !WRT; break; // LC2RW - case 0xC088: - case 0xC08C: LCBK2 = 0; LCRD = 1; LCWR = 0; LCWFF = 0; break; // LC1RD - case 0xC089: - case 0xC08D: LCBK2 = 0; LCRD = 0; LCWR |= LCWFF; LCWFF = !WRT; break; // LC1WR - case 0xC08A: - case 0xC08E: LCBK2 = 0; LCRD = 0; LCWR = 0; LCWFF = 0; break; // ROMONLY1 - case 0xC08B: - case 0xC08F: LCBK2 = 0; LCRD = 1; LCWR |= LCWFF; LCWFF = !WRT; break; // LC1RW + case 0xC084: LCBK2 = 1; LCRD = 1; LCWR = 0; LCWFF = 0; break; // LC2RD + case 0xC081: + case 0xC085: LCBK2 = 1; LCRD = 0; LCWR |= LCWFF; LCWFF = !WRT; break; // LC2WR + case 0xC082: + case 0xC086: LCBK2 = 1; LCRD = 0; LCWR = 0; LCWFF = 0; break; // ROMONLY2 + case 0xC083: + case 0xC087: LCBK2 = 1; LCRD = 1; LCWR |= LCWFF; LCWFF = !WRT; break; // LC2RW + case 0xC088: + case 0xC08C: LCBK2 = 0; LCRD = 1; LCWR = 0; LCWFF = 0; break; // LC1RD + case 0xC089: + case 0xC08D: LCBK2 = 0; LCRD = 0; LCWR |= LCWFF; LCWFF = !WRT; break; // LC1WR + case 0xC08A: + case 0xC08E: LCBK2 = 0; LCRD = 0; LCWR = 0; LCWFF = 0; break; // ROMONLY1 + case 0xC08B: + case 0xC08F: LCBK2 = 0; LCRD = 1; LCWR |= LCWFF; LCWFF = !WRT; break; // LC1RW - // SLOT 1 - case 0xC090 ... 0xC09F: break; + // SLOT 1 + case 0xC090 ... 0xC09F: break; - // SLOT 2 - case 0xC0A0 ... 0xC0AF: break; + // SLOT 2 + case 0xC0A0 ... 0xC0AF: break; - // SLOT 3 - case 0xC0B0 ... 0xC0BF: break; + // SLOT 3 + case 0xC0B0 ... 0xC0BF: break; - // SLOT 4 - case 0xC0C0 ... 0xC0CF: break; + // SLOT 4 + case 0xC0C0 ... 0xC0CF: break; - // SLOT 5 - case 0xC0D0 ... 0xC0DF: break; + // SLOT 5 + case 0xC0D0 ... 0xC0DF: break; - // SLOT 6 DISK ][ + // SLOT 6 DISK ][ case 0xC0E0 ... 0xC0E7: disk->stepMotor(address); break; // MOVE DRIVE HEAD - case 0xC0E8: disk->unit[disk->curDrv].motorOn = false; break; // MOTOROFF - case 0xC0E9: disk->unit[disk->curDrv].motorOn = true; break; // MOTORON - case 0xC0EA: disk->setDrv(0); break; // DRIVE0EN - case 0xC0EB: disk->setDrv(1); break; // DRIVE1EN - case 0xC0EC: // Shift Data Latch - if (disk->unit[disk->curDrv].writeMode) // writting - disk->unit[disk->curDrv].data[disk->unit[disk->curDrv].track * 0x1A00 + disk->unit[disk->curDrv].nibble] = dLatch; // good luck gcc - else // reading - dLatch = disk->unit[disk->curDrv].data[disk->unit[disk->curDrv].track * 0x1A00 + disk->unit[disk->curDrv].nibble]; // easy peasy - disk->unit[disk->curDrv].nibble = (disk->unit[disk->curDrv].nibble + 1) % 0x1A00; // turn floppy of 1 nibble - return dLatch; - case 0xC0ED: dLatch = value; break; // Load Data Latch - case 0xC0EE: // latch for READ - disk->unit[disk->curDrv].writeMode = false; - return disk->unit[disk->curDrv].readOnly ? 0x80 : 0; // check protection - case 0xC0EF: disk->unit[disk->curDrv].writeMode = true; break; // latch for WRITE + case 0xC0E8: disk->unit[disk->curDrv].motorOn = false; break; // MOTOROFF + case 0xC0E9: disk->unit[disk->curDrv].motorOn = true; break; // MOTORON + case 0xC0EA: disk->setDrv(0); break; // DRIVE0EN + case 0xC0EB: disk->setDrv(1); break; // DRIVE1EN + case 0xC0EC: // Shift Data Latch + if (disk->unit[disk->curDrv].writeMode) // writting + disk->unit[disk->curDrv].data[disk->unit[disk->curDrv].track * 0x1A00 + disk->unit[disk->curDrv].nibble] = dLatch; // good luck gcc + else // reading + dLatch = disk->unit[disk->curDrv].data[disk->unit[disk->curDrv].track * 0x1A00 + disk->unit[disk->curDrv].nibble]; // easy peasy + disk->unit[disk->curDrv].nibble = (disk->unit[disk->curDrv].nibble + 1) % 0x1A00; // turn floppy of 1 nibble + return dLatch; + case 0xC0ED: dLatch = value; break; // Load Data Latch + case 0xC0EE: // latch for READ + disk->unit[disk->curDrv].writeMode = false; + return disk->unit[disk->curDrv].readOnly ? 0x80 : 0; // check protection + case 0xC0EF: disk->unit[disk->curDrv].writeMode = true; break; // latch for WRITE - // SLOT 7 - case 0xC0F0 ... 0xC0FF: break; + // SLOT 7 + case 0xC0F0 ... 0xC0FF: break; - } - return cpu->ticks%256; // catch all, gives a floating value + } + return cpu->ticks%256; // catch all, gives a floating value } //================================================================== MEMORY READ uint8_t Mmu::readMem(uint16_t address) { - switch (address) { - case 0x0000 ... 0x01FF: // STACK and Zero Page in AUX or MAIN - if (ALTZP) { - video->auxHeatmap[address] |= 0xFF00FF00; - return aux[address]; - } - video->ramHeatmap[address] |= 0xFF00FF00; - return ram[address]; - break; + switch (address) { + case 0x0000 ... 0x01FF: // STACK and Zero Page in AUX or MAIN + if (ALTZP) { + video->auxHeatmap[address] |= 0xFF00FF00; + return aux[address]; + } + video->ramHeatmap[address] |= 0xFF00FF00; + return ram[address]; + break; - case 0x0200 ... 0x03FF: // MAIN or AUX - if (RAMRD) { - video->auxHeatmap[address] |= 0xFF00FF00; - return aux[address]; - } - video->ramHeatmap[address] |= 0xFF00FF00; - return ram[address]; - break; + case 0x0200 ... 0x03FF: // MAIN or AUX + if (RAMRD) { + video->auxHeatmap[address] |= 0xFF00FF00; + return aux[address]; + } + video->ramHeatmap[address] |= 0xFF00FF00; + return ram[address]; + break; - case 0x0400 ... 0x07FF: // TEXT PAGE 1 in AUX or MAIN - if (STORE80) { - if (PAGE2) { - video->auxHeatmap[address] |= 0xFF00FF00; - return aux[address]; - } - video->ramHeatmap[address] |= 0xFF00FF00; - return ram[address]; - } - if (RAMRD) { - video->auxHeatmap[address] |= 0xFF00FF00; - return aux[address]; - } - video->ramHeatmap[address] |= 0xFF00FF00; - return ram[address]; - break; + case 0x0400 ... 0x07FF: // TEXT PAGE 1 in AUX or MAIN + if (STORE80) { + if (PAGE2) { + video->auxHeatmap[address] |= 0xFF00FF00; + return aux[address]; + } + video->ramHeatmap[address] |= 0xFF00FF00; + return ram[address]; + } + if (RAMRD) { + video->auxHeatmap[address] |= 0xFF00FF00; + return aux[address]; + } + video->ramHeatmap[address] |= 0xFF00FF00; + return ram[address]; + break; - case 0x0800 ... 0x0BFF: // TEXT PAGE 2 in AUX or MAIN - if (RAMRD) { - video->auxHeatmap[address] |= 0xFF00FF00; - return aux[address]; - } - video->ramHeatmap[address] |= 0xFF00FF00; - return ram[address]; - break; + case 0x0800 ... 0x0BFF: // TEXT PAGE 2 in AUX or MAIN + if (RAMRD) { + video->auxHeatmap[address] |= 0xFF00FF00; + return aux[address]; + } + video->ramHeatmap[address] |= 0xFF00FF00; + return ram[address]; + break; - case 0x0C00 ... 0x1FFF: // AUX or MAIN - if (RAMRD) { - video->auxHeatmap[address] |= 0xFF00FF00; - return aux[address]; - } - video->ramHeatmap[address] |= 0xFF00FF00; - return ram[address]; - break; + case 0x0C00 ... 0x1FFF: // AUX or MAIN + if (RAMRD) { + video->auxHeatmap[address] |= 0xFF00FF00; + return aux[address]; + } + video->ramHeatmap[address] |= 0xFF00FF00; + return ram[address]; + break; - case 0x2000 ... 0x3FFF: // HIRES PAGE 1 - if (STORE80) { - if (PAGE2 && HIRES) { - video->auxHeatmap[address] |= 0xFF00FF00; - return aux[address]; - } - video->ramHeatmap[address] |= 0xFF00FF00; - return ram[address]; - } - if (RAMRD) { - video->auxHeatmap[address] |= 0xFF00FF00; - return aux[address]; - } - video->ramHeatmap[address] |= 0xFF00FF00; - return ram[address]; - break; + case 0x2000 ... 0x3FFF: // HIRES PAGE 1 + if (STORE80) { + if (PAGE2 && HIRES) { + video->auxHeatmap[address] |= 0xFF00FF00; + return aux[address]; + } + video->ramHeatmap[address] |= 0xFF00FF00; + return ram[address]; + } + if (RAMRD) { + video->auxHeatmap[address] |= 0xFF00FF00; + return aux[address]; + } + video->ramHeatmap[address] |= 0xFF00FF00; + return ram[address]; + break; - case 0x4000 ... 0x5FFF: // HIRES PAGE 2 in AUX or MAIN - if (RAMRD) { - video->auxHeatmap[address] |= 0xFF00FF00; - return aux[address]; - } - video->ramHeatmap[address] |= 0xFF00FF00; - return ram[address]; - break; + case 0x4000 ... 0x5FFF: // HIRES PAGE 2 in AUX or MAIN + if (RAMRD) { + video->auxHeatmap[address] |= 0xFF00FF00; + return aux[address]; + } + video->ramHeatmap[address] |= 0xFF00FF00; + return ram[address]; + break; - case 0x6000 ... 0xBFFF: // AUX or MAIN - if (RAMRD) { - video->auxHeatmap[address] |= 0xFF00FF00; - return aux[address]; - } - video->ramHeatmap[address] |= 0xFF00FF00; - return ram[address]; - break; + case 0x6000 ... 0xBFFF: // AUX or MAIN + if (RAMRD) { + video->auxHeatmap[address] |= 0xFF00FF00; + return aux[address]; + } + video->ramHeatmap[address] |= 0xFF00FF00; + return ram[address]; + break; - case 0xC000 ... 0xC0FF: // SOFT SWITCHES - video->ramHeatmap[address] |= 0xFF00FF00; - return softSwitches(address, 0, false); - break; + case 0xC000 ... 0xC0FF: // SOFT SWITCHES + video->ramHeatmap[address] |= 0xFF00FF00; + return softSwitches(address, 0, false); + break; case 0xC100 ... 0xC1FF: // SLOT 1 ROM or ROM video->ramHeatmap[address] |= 0xFF00FF00; @@ -315,70 +315,70 @@ uint8_t Mmu::readMem(uint16_t address) { return sl5[address - SL5START]; break; - case 0xC600 ... 0xC6FF: // SLOT 6 ROM : DISK ][ or ROM - video->ramHeatmap[address] |= 0xFF00FF00; - if (INTCXROM) { - return rom[address - ROMSTART]; - } - return sl6[address - SL6START]; - break; + case 0xC600 ... 0xC6FF: // SLOT 6 ROM : DISK ][ or ROM + video->ramHeatmap[address] |= 0xFF00FF00; + if (INTCXROM) { + return rom[address - ROMSTART]; + } + return sl6[address - SL6START]; + break; - case 0xC700 ... 0xC7FF: // SLOT 7 ROM or ROM - video->ramHeatmap[address] |= 0xFF00FF00; - if (INTCXROM) { - return rom[address - ROMSTART]; - } - return sl7[address - SL7START]; - break; + case 0xC700 ... 0xC7FF: // SLOT 7 ROM or ROM + video->ramHeatmap[address] |= 0xFF00FF00; + if (INTCXROM) { + return rom[address - ROMSTART]; + } + return sl7[address - SL7START]; + break; - case 0xC800 ... 0xCFFE: // SHARED EXANSION SLOTS ROM AREA or ROM - video->ramHeatmap[address] |= 0xFF00FF00; - if (INTCXROM || !SLOTC3ROM) { - return rom[address - ROMSTART]; - } - return slrom[(address & 0x0F00) >> 2 & 0xF][address - SLROMSTART]; - break; + case 0xC800 ... 0xCFFE: // SHARED EXANSION SLOTS ROM AREA or ROM + video->ramHeatmap[address] |= 0xFF00FF00; + if (INTCXROM || !SLOTC3ROM) { + return rom[address - ROMSTART]; + } + return slrom[(address & 0x0F00) >> 2 & 0xF][address - SLROMSTART]; + break; - case 0xCFFF: // turn off all slots expansion ROMs - TODO : NEEDS REWORK - disk->unit[disk->curDrv].motorOn = false; - return 0; - break; + case 0xCFFF: // turn off all slots expansion ROMs - TODO : NEEDS REWORK + disk->unit[disk->curDrv].motorOn = false; + return 0; + break; - case 0xD000 ... 0xDFFF: // ROM, MAIN-BK1, RAM-BK2, AUX-BK1 or AUX-BK2 - if (LCRD) { - if (LCBK2) { - if (ALTZP) { - video->auxHeatmap[address] |= 0xFF00FF00; - return auxbk2[address - BK2START]; // AUX Bank 2 - } - video->ramHeatmap[address] |= 0xFF00FF00; - return rambk2[address - BK2START]; // MAIN Bank 2 - } - if (ALTZP) { - video->auxHeatmap[address] |= 0xFF00FF00; - return auxlgc[address - LGCSTART]; // AUX Bank 1 - } - video->ramHeatmap[address] |= 0xFF00FF00; - return ramlgc[address - LGCSTART]; // MAIN Bank 1 - } - video->ramHeatmap[address] |= 0xFF00FF00; - return rom[address - ROMSTART]; // ROM - break; + case 0xD000 ... 0xDFFF: // ROM, MAIN-BK1, RAM-BK2, AUX-BK1 or AUX-BK2 + if (LCRD) { + if (LCBK2) { + if (ALTZP) { + video->auxHeatmap[address] |= 0xFF00FF00; + return auxbk2[address - BK2START]; // AUX Bank 2 + } + video->ramHeatmap[address] |= 0xFF00FF00; + return rambk2[address - BK2START]; // MAIN Bank 2 + } + if (ALTZP) { + video->auxHeatmap[address] |= 0xFF00FF00; + return auxlgc[address - LGCSTART]; // AUX Bank 1 + } + video->ramHeatmap[address] |= 0xFF00FF00; + return ramlgc[address - LGCSTART]; // MAIN Bank 1 + } + video->ramHeatmap[address] |= 0xFF00FF00; + return rom[address - ROMSTART]; // ROM + break; - case 0xE000 ... 0xFFFF: // ROM, MAIN-BK1 or AUX-BK1 - if (LCRD) { - if (ALTZP) { - video->auxHeatmap[address] |= 0xFF00FF00; - return auxlgc[address - LGCSTART]; // AUX Bank 1 - } - video->ramHeatmap[address] |= 0xFF00FF00; - return ramlgc[address - LGCSTART]; // MAIN Bank 1 - } - video->ramHeatmap[address] |= 0xFF00FF00; - return rom[address - ROMSTART]; // ROM - break; - } - return cpu->ticks%256; // returns a floating value + case 0xE000 ... 0xFFFF: // ROM, MAIN-BK1 or AUX-BK1 + if (LCRD) { + if (ALTZP) { + video->auxHeatmap[address] |= 0xFF00FF00; + return auxlgc[address - LGCSTART]; // AUX Bank 1 + } + video->ramHeatmap[address] |= 0xFF00FF00; + return ramlgc[address - LGCSTART]; // MAIN Bank 1 + } + video->ramHeatmap[address] |= 0xFF00FF00; + return rom[address - ROMSTART]; // ROM + break; + } + return cpu->ticks%256; // returns a floating value } @@ -386,181 +386,181 @@ uint8_t Mmu::readMem(uint16_t address) { void Mmu::writeMem(uint16_t address, uint8_t value) { - switch (address) { - case 0x0000 ... 0x01FF: // STACK and Zero Page in AUX or MAIN - if (ALTZP) { - video->auxHeatmap[address] |= 0xFF0000FF; - aux[address] = value; - return; - } - video->ramHeatmap[address] |= 0xFF0000FF; - ram[address] = value; - return; - break; + switch (address) { + case 0x0000 ... 0x01FF: // STACK and Zero Page in AUX or MAIN + if (ALTZP) { + video->auxHeatmap[address] |= 0xFF0000FF; + aux[address] = value; + return; + } + video->ramHeatmap[address] |= 0xFF0000FF; + ram[address] = value; + return; + break; - case 0x0200 ... 0x03FF: // MAIN or AUX - if (RAMWRT) { - video->auxHeatmap[address] |= 0xFF0000FF; - aux[address] = value; - return; - } - video->ramHeatmap[address] |= 0xFF0000FF; - ram[address] = value; - return; - break; + case 0x0200 ... 0x03FF: // MAIN or AUX + if (RAMWRT) { + video->auxHeatmap[address] |= 0xFF0000FF; + aux[address] = value; + return; + } + video->ramHeatmap[address] |= 0xFF0000FF; + ram[address] = value; + return; + break; - case 0x0400 ... 0x07FF: // TEXT PAGE 1 in AUX or MAIN - if (STORE80) { - if (PAGE2) { - video->auxHeatmap[address] |= 0xFF0000FF; - aux[address] = value; - return; - } - video->ramHeatmap[address] |= 0xFF0000FF; - ram[address] = value; - return; - } - if (RAMWRT) { - video->auxHeatmap[address] |= 0xFF0000FF; - aux[address] = value; - return; - } - video->ramHeatmap[address] |= 0xFF0000FF; - ram[address] = value; - return; - break; + case 0x0400 ... 0x07FF: // TEXT PAGE 1 in AUX or MAIN + if (STORE80) { + if (PAGE2) { + video->auxHeatmap[address] |= 0xFF0000FF; + aux[address] = value; + return; + } + video->ramHeatmap[address] |= 0xFF0000FF; + ram[address] = value; + return; + } + if (RAMWRT) { + video->auxHeatmap[address] |= 0xFF0000FF; + aux[address] = value; + return; + } + video->ramHeatmap[address] |= 0xFF0000FF; + ram[address] = value; + return; + break; - case 0x0800 ... 0x0BFF: // TEXT PAGE 2 in AUX or MAIN - if (RAMWRT) { - video->auxHeatmap[address] |= 0xFF0000FF; - aux[address] = value; - return; - } - video->ramHeatmap[address] |= 0xFF0000FF; - ram[address] = value; - return; - break; + case 0x0800 ... 0x0BFF: // TEXT PAGE 2 in AUX or MAIN + if (RAMWRT) { + video->auxHeatmap[address] |= 0xFF0000FF; + aux[address] = value; + return; + } + video->ramHeatmap[address] |= 0xFF0000FF; + ram[address] = value; + return; + break; - case 0x0C00 ... 0x1FFF: // MAIN or AUX - if (RAMWRT) { - video->auxHeatmap[address] |= 0xFF0000FF; - aux[address] = value; - return; - } - video->ramHeatmap[address] |= 0xFF0000FF; - ram[address] = value; - return; - break; + case 0x0C00 ... 0x1FFF: // MAIN or AUX + if (RAMWRT) { + video->auxHeatmap[address] |= 0xFF0000FF; + aux[address] = value; + return; + } + video->ramHeatmap[address] |= 0xFF0000FF; + ram[address] = value; + return; + break; - case 0x2000 ... 0x3FFF: // HIRES PAGE 1 - if (STORE80) { - if (PAGE2 && HIRES) { - video->auxHeatmap[address] |= 0xFF0000FF; - aux[address] = value; - return; - } - video->ramHeatmap[address] |= 0xFF0000FF; - ram[address] = value; - return; - } - if (RAMWRT) { - video->auxHeatmap[address] |= 0xFF0000FF; - aux[address] = value; - return; - } - video->ramHeatmap[address] |= 0xFF0000FF; - ram[address] = value; - return; - break; + case 0x2000 ... 0x3FFF: // HIRES PAGE 1 + if (STORE80) { + if (PAGE2 && HIRES) { + video->auxHeatmap[address] |= 0xFF0000FF; + aux[address] = value; + return; + } + video->ramHeatmap[address] |= 0xFF0000FF; + ram[address] = value; + return; + } + if (RAMWRT) { + video->auxHeatmap[address] |= 0xFF0000FF; + aux[address] = value; + return; + } + video->ramHeatmap[address] |= 0xFF0000FF; + ram[address] = value; + return; + break; - case 0x4000 ... 0x5FFF: // HIRES PAGE 2 in AUX or MAIN - if (RAMWRT) { - video->auxHeatmap[address] |= 0xFF0000FF; - aux[address] = value; - return; - } - video->ramHeatmap[address] |= 0xFF0000FF; - ram[address] = value; - return; - break; + case 0x4000 ... 0x5FFF: // HIRES PAGE 2 in AUX or MAIN + if (RAMWRT) { + video->auxHeatmap[address] |= 0xFF0000FF; + aux[address] = value; + return; + } + video->ramHeatmap[address] |= 0xFF0000FF; + ram[address] = value; + return; + break; - case 0x6000 ... 0xBFFF: // AUX or MAIN - if (RAMWRT) { - video->auxHeatmap[address] |= 0xFF0000FF; - aux[address] = value; - return; - } - video->ramHeatmap[address] |= 0xFF0000FF; - ram[address] = value; - return; - break; + case 0x6000 ... 0xBFFF: // AUX or MAIN + if (RAMWRT) { + video->auxHeatmap[address] |= 0xFF0000FF; + aux[address] = value; + return; + } + video->ramHeatmap[address] |= 0xFF0000FF; + ram[address] = value; + return; + break; - case 0xC000 ... 0xC0FF: // softSwitches - video->ramHeatmap[address] |= 0xFF0000FF; - softSwitches(address, 0, true); - return; - break; + case 0xC000 ... 0xC0FF: // softSwitches + video->ramHeatmap[address] |= 0xFF0000FF; + softSwitches(address, 0, true); + return; + break; - case 0xC100 ... 0xCFFE: // readonly area - return; - break; + case 0xC100 ... 0xCFFE: // readonly area + return; + break; - case 0xCFFF: // turn off all slots expansion ROMs - NEEDS REWORK soft switch ? - disk->unit[disk->curDrv].motorOn = false; - return; - break; + case 0xCFFF: // turn off all slots expansion ROMs - NEEDS REWORK soft switch ? + disk->unit[disk->curDrv].motorOn = false; + return; + break; - case 0xD000 ... 0xDFFF: // ROM, MAIN-BK1, RAM-BK2, AUX-BK1 or AUX-BK2 - if (LCWR) { - if (LCBK2) { - if (ALTZP) { - video->auxHeatmap[address] |= 0xFF0000FF; - auxbk2[address - BK2START] = value; // AUX Bank 2 - return; - } - video->ramHeatmap[address] |= 0xFF0000FF; - rambk2[address - BK2START] = value; // MAIN Bank 2 - return; - } - if (ALTZP) { - video->auxHeatmap[address] |= 0xFF0000FF; - auxlgc[address - LGCSTART] = value; // AUX Bank 1 - return; - } - video->ramHeatmap[address] |= 0xFF0000FF; - ramlgc[address - LGCSTART] = value; // MAIN Bank 1 - return; - } - video->ramHeatmap[address] |= 0xFF0000FF; - return; - break; + case 0xD000 ... 0xDFFF: // ROM, MAIN-BK1, RAM-BK2, AUX-BK1 or AUX-BK2 + if (LCWR) { + if (LCBK2) { + if (ALTZP) { + video->auxHeatmap[address] |= 0xFF0000FF; + auxbk2[address - BK2START] = value; // AUX Bank 2 + return; + } + video->ramHeatmap[address] |= 0xFF0000FF; + rambk2[address - BK2START] = value; // MAIN Bank 2 + return; + } + if (ALTZP) { + video->auxHeatmap[address] |= 0xFF0000FF; + auxlgc[address - LGCSTART] = value; // AUX Bank 1 + return; + } + video->ramHeatmap[address] |= 0xFF0000FF; + ramlgc[address - LGCSTART] = value; // MAIN Bank 1 + return; + } + video->ramHeatmap[address] |= 0xFF0000FF; + return; + break; - case 0xE000 ... 0xFFFF: // ROM, MAIN-BK1 or AUX-BK1 - if (LCWR) { - if (ALTZP) { - video->auxHeatmap[address] |= 0xFF0000FF; - auxlgc[address - LGCSTART] = value; // AUX Bank 1 - return; - } - video->ramHeatmap[address] |= 0xFF0000FF; - ramlgc[address - LGCSTART] = value; // MAIN Bank 1 - return; - } - video->ramHeatmap[address] |= 0xFF0000FF; - return; - break; - } + case 0xE000 ... 0xFFFF: // ROM, MAIN-BK1 or AUX-BK1 + if (LCWR) { + if (ALTZP) { + video->auxHeatmap[address] |= 0xFF0000FF; + auxlgc[address - LGCSTART] = value; // AUX Bank 1 + return; + } + video->ramHeatmap[address] |= 0xFF0000FF; + ramlgc[address - LGCSTART] = value; // MAIN Bank 1 + return; + } + video->ramHeatmap[address] |= 0xFF0000FF; + return; + break; + } } Mmu::Mmu() { - // TODO : give user the choice of the rom version - + // TODO : give user the choice of the rom version + // pick one ROM file - // FILE* f = fopen("rom/appleII.rom", "rb"); // load the Apple II ROM - // FILE* f = fopen("rom/appleII+.rom", "rb"); // load the Apple II+ ROM - // FILE* f = fopen("rom/appleIIe.rom", "rb"); // load the Apple IIe ROM - FILE* f = fopen("rom/appleIIee.rom", "rb"); // load the Apple IIee ROM + // FILE* f = fopen("rom/appleII.rom", "rb"); // load the Apple II ROM + // FILE* f = fopen("rom/appleII+.rom", "rb"); // load the Apple II+ ROM + // FILE* f = fopen("rom/appleIIe.rom", "rb"); // load the Apple IIe ROM + FILE* f = fopen("rom/appleIIee.rom", "rb"); // load the Apple IIee ROM fread(rom, 1, ROMSIZE, f); fclose(f); @@ -569,52 +569,52 @@ Mmu::Mmu() { fread(sl6, 1, 256, f); fclose(f); - init(); + init(); } Mmu::~Mmu() { - // release the memory arrays ? + // release the memory arrays ? } void Mmu::init() { - KBD = 0; // $C000, $C010 ascii value of keyboard input - PAGE2 = false; // $C054 PAGE1 / $C055 PAGE2 - TEXT = true; // $C050 CLRTEXT / $C051 SETTEXT - MIXED = false; // $C052 CLRMIXED / $C053 SETMIXED - HIRES = false; // $C056 GR / $C057 HGR - DHIRES = false; // 0xC05E / 0xC05F DOUBLE HIRES - COL80 = false; // 80 COLUMNS - ALTCHARSET = false; - LCWR = true; // Language Card writable - LCRD = false; // Language Card readable - LCBK2 = true; // Language Card bank 2 enabled - LCWFF = false; // Language Card pre-write flip flop - AN0 = false; - AN1 = false; - AN2 = true; - AN3 = true; + KBD = 0; // $C000, $C010 ascii value of keyboard input + PAGE2 = false; // $C054 PAGE1 / $C055 PAGE2 + TEXT = true; // $C050 CLRTEXT / $C051 SETTEXT + MIXED = false; // $C052 CLRMIXED / $C053 SETMIXED + HIRES = false; // $C056 GR / $C057 HGR + DHIRES = false; // 0xC05E / 0xC05F DOUBLE HIRES + COL80 = false; // 80 COLUMNS + ALTCHARSET = false; + LCWR = true; // Language Card writable + LCRD = false; // Language Card readable + LCBK2 = true; // Language Card bank 2 enabled + LCWFF = false; // Language Card pre-write flip flop + AN0 = false; + AN1 = false; + AN2 = true; + AN3 = true; - RAMRD = false; - RAMWRT = false; - ALTZP = false; - STORE80 = false; + RAMRD = false; + RAMWRT = false; + ALTZP = false; + STORE80 = false; - INTCXROM = false; // use slots roms - SLOTC3ROM = false; // use AUX Slot rom + INTCXROM = false; // use slots roms + SLOTC3ROM = false; // use AUX Slot rom - IOUDIS = false; - VERTBLANK = true; + IOUDIS = false; + VERTBLANK = true; - memset(ram, 0, sizeof(ram)); // 48K of MAIN in $000-$BFFF - memset(aux, 0, sizeof(aux)); // 48K of AUX memory - memset(ramlgc, 0, sizeof(ramlgc)); // MAIN Language Card 12K in $D000-$FFFF - memset(rambk2, 0, sizeof(rambk2)); // MAIN bank 2 of Language Card 4K in $D000-$DFFF - memset(auxlgc, 0, sizeof(auxlgc)); // AUX Language Card 12K in $D000-$FFFF - memset(auxbk2, 0, sizeof(auxbk2)); // AUX bank 2 of Language Card 4K in $D000-$DFFF + memset(ram, 0, sizeof(ram)); // 48K of MAIN in $000-$BFFF + memset(aux, 0, sizeof(aux)); // 48K of AUX memory + memset(ramlgc, 0, sizeof(ramlgc)); // MAIN Language Card 12K in $D000-$FFFF + memset(rambk2, 0, sizeof(rambk2)); // MAIN bank 2 of Language Card 4K in $D000-$DFFF + memset(auxlgc, 0, sizeof(auxlgc)); // AUX Language Card 12K in $D000-$FFFF + memset(auxbk2, 0, sizeof(auxbk2)); // AUX bank 2 of Language Card 4K in $D000-$DFFF - // dirty hacks - fix when I know why + // dirty hacks - fix when I know why ram[0x4D] = 0xAA; // Joust won't work if this memory location equals zero - ram[0xD0] = 0xAA; // Planetoids won't work if this memory location equals zero + ram[0xD0] = 0xAA; // Planetoids won't work if this memory location equals zero } diff --git a/puce65c02.cpp b/puce65c02.cpp index f00f6cd..703fc0f 100644 --- a/puce65c02.cpp +++ b/puce65c02.cpp @@ -1,5 +1,6 @@ /* puce65c02, a WDC 65c02 cpu emulator, based on puce6502 by the same author + Last modified 1st of July 2021 Copyright (c) 2021 Arthur Ferreira (arthur.ferreira2@gmail.com) @@ -9,7 +10,7 @@ in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions : + furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. @@ -23,77 +24,71 @@ THE SOFTWARE. */ -#include "puce65c02.h" +/* + This version is slightly modified for reinette IIe, a french Apple IIe + emulator using SDL2 (https://github.com/ArthurFerreira2/reinette-IIe). + Please download the latest version from + https://github.com/ArthurFerreira2/puce65c02 +*/ - -#if __TESTS__ - - // functionnal and timing tests - see also bottom of file - - // Theses tests require 65C02_extended_opcodes_test.bin and 6502_functional_test.bin - // from https://github.com/Klaus2m5/6502_65C02_functional_tests - // and timingtest-1.bin from http://forum.6502.org/viewtopic.php?f=8&t=3340 - - // compile and run : - - // g++ -Wall -O3 -D __TESTS__ puce65c02.cpp -o puce65c02 && ./puce65c02 - // or, slower but with detailled info : - // g++ -Wall -O3 -D __TESTS__ -D VERBOSE puce65c02.cpp -o puce65c02 && ./puce65c02 - // or, if you just want to check the cycle accuracy : - // g++ -Wall -O3 -D __TESTS__ -D TIMING puce65c02.cpp -o puce65c02 && ./puce65c02 - - uint8_t RAM[65536]; - inline uint8_t readMem(uint16_t address) { return RAM[address]; } - inline void writeMem(uint16_t address, uint8_t value8) { RAM[address] = value8; } - -#else - // user is supposed to provide these two functions - extern uint8_t readMem(uint16_t address); - extern void writeMem(uint16_t address, uint8_t value8); - -#endif +#include "reinette.h" // provides mmu->readMem and mmu->writeMem void puce65c02::RST() { - PC = readMem(0xFFFC) | (readMem(0xFFFD) << 8); + PC = mmu->readMem(0xFFFC) | (mmu->readMem(0xFFFD) << 8); SP = 0xFF; - P.I = 1; - P.U = 1; + P.bits.I = 1; + P.bits.U = 1; state = run; ticks += 7; } void puce65c02::IRQ() { - state = run; // always ?? - if (!P.I) return; // consume clock cycles ? + state = run; // always ? + if (!P.bits.I) return; // consume 0 clock cycle ? PC++; - writeMem(0x100 + SP, (PC >> 8) & 0xFF); + mmu->writeMem(0x100 + SP, (PC >> 8) & 0xFF); SP--; - writeMem(0x100 + SP, PC & 0xFF); + mmu->writeMem(0x100 + SP, PC & 0xFF); SP--; - writeMem(0x100 + SP, P.byte & ~BREAK); + mmu->writeMem(0x100 + SP, P.byte & ~BREAK); SP--; - PC = readMem(0xFFFE) | (readMem(0xFFFF) << 8); + PC = mmu->readMem(0xFFFE) | (mmu->readMem(0xFFFF) << 8); ticks += 7; } void puce65c02::NMI() { state = run; - P.I = 1; // ??? + P.bits.I = 1; // ??? PC++; - writeMem(0x100 + SP, (PC >> 8) & 0xFF); + mmu->writeMem(0x100 + SP, (PC >> 8) & 0xFF); SP--; - writeMem(0x100 + SP, PC & 0xFF); + mmu->writeMem(0x100 + SP, PC & 0xFF); SP--; - writeMem(0x100 + SP, P.byte & ~BREAK); + mmu->writeMem(0x100 + SP, P.byte & ~BREAK); SP--; - PC = readMem(0xFFFA) | (readMem(0xFFFB) << 8); + PC = mmu->readMem(0xFFFA) | (mmu->readMem(0xFFFB) << 8); ticks += 7; } +puce65c02::puce65c02() { + ticks = 0LL; +} + + +uint16_t puce65c02::getPC() { + return PC; +} + + +void puce65c02::setPC(uint16_t address) { + PC = address; +} + + /* Addressing modes abreviations used in the comments below : @@ -117,7 +112,6 @@ void puce65c02::NMI() { uint16_t puce65c02::exec(unsigned long long int cycleCount) { - cycleCount += ticks; // cycleCount becomes the targeted ticks value8 while (ticks < cycleCount) { if (state == run || state == step) { @@ -126,31 +120,31 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { uint16_t value16; uint16_t address; - switch(readMem(PC++)) { // fetch instruction and increment Program Counter + switch(mmu->readMem(PC++)) { // fetch instruction and increment Program Counter case 0x00 : // IMP BRK PC++; - writeMem(0x100 + SP, ((PC) >> 8) & 0xFF); + mmu->writeMem(0x100 + SP, ((PC) >> 8) & 0xFF); SP--; - writeMem(0x100 + SP, PC & 0xFF); + mmu->writeMem(0x100 + SP, PC & 0xFF); SP--; - writeMem(0x100 + SP, P.byte | BREAK); + mmu->writeMem(0x100 + SP, P.byte | BREAK); SP--; - P.I = 1; - P.D = 0; - PC = readMem(0xFFFE) | (readMem(0xFFFF) << 8); + P.bits.I = 1; + P.bits.D = 0; + PC = mmu->readMem(0xFFFE) | (mmu->readMem(0xFFFF) << 8); ticks += 7; break; case 0x01 : // IZX ORA - value8 = readMem(PC) + X; + value8 = mmu->readMem(PC) + X; PC++; - address = readMem(value8); + address = mmu->readMem(value8); value8++; - address |= readMem(value8) << 8; - A |= readMem(address); - P.Z = A == 0; - P.S = A > 0x7F; + address |= mmu->readMem(value8) << 8; + A |= mmu->readMem(address); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 6; break; @@ -164,61 +158,61 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x04 : // ZPG TSB - address = readMem(PC); + address = mmu->readMem(PC); PC++; - value8 = readMem(address); - P.Z = (value8 & A) == 0; - writeMem(address, value8 | A); + value8 = mmu->readMem(address); + P.bits.Z = (value8 & A) == 0; + mmu->writeMem(address, value8 | A); ticks += 5; break; case 0x05 : // ZPG ORA - A |= readMem(readMem(PC)); + A |= mmu->readMem(mmu->readMem(PC)); PC++; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 3; break; case 0x06 : // ZPG ASL - address = readMem(PC); + address = mmu->readMem(PC); PC++; - value16 = readMem(address) << 1; - P.C = value16 > 0xFF; + value16 = mmu->readMem(address) << 1; + P.bits.C = value16 > 0xFF; value16 &= 0xFF; - writeMem(address, value16); - P.Z = value16 == 0; - P.S = value16 > 0x7F; + mmu->writeMem(address, value16); + P.bits.Z = value16 == 0; + P.bits.S = value16 > 0x7F; ticks += 5; break; case 0x07 : // ZPG RMB - address = readMem(PC); + address = mmu->readMem(PC); PC++; - writeMem(address, readMem(address) & ~1); + mmu->writeMem(address, mmu->readMem(address) & ~1); ticks += 5; break; case 0x08 : // IMP PHP - writeMem(0x100 + SP, P.byte | BREAK); + mmu->writeMem(0x100 + SP, P.byte | BREAK); SP--; ticks += 3; break; case 0x09 : // IMM ORA - A |= readMem(PC); + A |= mmu->readMem(PC); PC++; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 2; break; case 0x0A : // ACC ASL value16 = A << 1; A = value16 & 0xFF; - P.C = value16 > 0xFF; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.C = value16 > 0xFF; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 2; break; @@ -227,45 +221,45 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x0C : // ABS TSB - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; - value8 = readMem(address); - P.Z = (value8 & A) == 0; - writeMem(address, value8 | A); + value8 = mmu->readMem(address); + P.bits.Z = (value8 & A) == 0; + mmu->writeMem(address, value8 | A); ticks += 6; break; case 0x0D : // ABS ORA - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; - A |= readMem(address); - P.Z = A == 0; - P.S = A > 0x7F; + A |= mmu->readMem(address); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 4; break; case 0x0E : // ABS ASL - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; - value16 = readMem(address) << 1; - P.C = value16 > 0xFF; + value16 = mmu->readMem(address) << 1; + P.bits.C = value16 > 0xFF; value16 &= 0xFF; - writeMem(address, value16); - P.Z = value16 == 0; - P.S = value16 > 0x7F; + mmu->writeMem(address, value16); + P.bits.Z = value16 == 0; + P.bits.S = value16 > 0x7F; ticks += 6; break; case 0x0F : // ZPR BBR - value8 = readMem(readMem(PC)); + value8 = mmu->readMem(mmu->readMem(PC)); PC++; - address = readMem(PC); + address = mmu->readMem(PC); PC++; if (address & SIGN) address |= 0xFF00; // jump backward @@ -275,9 +269,9 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x10 : // REL BPL - address = readMem(PC); + address = mmu->readMem(PC); PC++; - if (!P.S) { // jump taken + if (!P.bits.S) { // jump taken ticks++; if (address & SIGN) address |= 0xFF00; // jump backward @@ -289,27 +283,27 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x11 : // IZY ORA - value8 = readMem(PC); + value8 = mmu->readMem(PC); PC++; - address = readMem(value8); + address = mmu->readMem(value8); value8++; - address |= readMem(value8) << 8; + address |= mmu->readMem(value8) << 8; ticks += (((address & 0xFF) + Y) & 0xFF00) ? 6 : 5; // page crossing address += Y; - A |= readMem(address); - P.Z = A == 0; - P.S = A > 0x7F; + A |= mmu->readMem(address); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; break; case 0x12 : // IZP ORA - value8 = readMem(PC); + value8 = mmu->readMem(PC); PC++; - address = readMem(value8); + address = mmu->readMem(value8); value8++; - address |= readMem(value8) << 8; - A |= readMem(address); - P.Z = A == 0; - P.S = A > 0x7F; + address |= mmu->readMem(value8) << 8; + A |= mmu->readMem(address); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 5; break; @@ -318,61 +312,61 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x14 : // ZPG TRB - address = readMem(PC); + address = mmu->readMem(PC); PC++; - value8 = readMem(address); - writeMem(address, value8 & ~A); - P.Z = (value8 & A) == 0; + value8 = mmu->readMem(address); + mmu->writeMem(address, value8 & ~A); + P.bits.Z = (value8 & A) == 0; ticks += 5; break; case 0x15 : // ZPX ORA - A |= readMem(readMem(PC) + X); + A |= mmu->readMem(mmu->readMem(PC) + X); PC++; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 4; break; case 0x16 : // ZPX ASL - address = readMem(PC) + X; + address = mmu->readMem(PC) + X; PC++; - value16 = readMem(address) << 1; - writeMem(address, value16 & 0xFF); - P.C = value16 > 0xFF; - P.Z = value16 == 0; - P.S = (value16 & 0xFF) > 0x7F; + value16 = mmu->readMem(address) << 1; + mmu->writeMem(address, value16 & 0xFF); + P.bits.C = value16 > 0xFF; + P.bits.Z = value16 == 0; + P.bits.S = (value16 & 0xFF) > 0x7F; ticks += 6; break; case 0x17 : // ZPG RMB - address = readMem(PC); + address = mmu->readMem(PC); PC++; - writeMem(address, readMem(address) & ~2); + mmu->writeMem(address, mmu->readMem(address) & ~2); ticks += 5; break; case 0x18 : // IMP CLC - P.C = 0; + P.bits.C = 0; ticks += 2; break; case 0x19 : // ABY ORA - address = readMem(PC); + address = mmu->readMem(PC); PC++; ticks += ((address + Y) & 0xFF00) ? 5 : 4; // page crossing - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; address += Y; - A |= readMem(address); - P.Z = A == 0; - P.S = A > 0x7F; + A |= mmu->readMem(address); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; break; case 0x1A : // ACC INC A++; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 2; break; @@ -381,47 +375,47 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x1C : // ABS TRB - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; - value8 = readMem(address); - P.Z = (value8 & A) == 0; - writeMem(address, value8 & ~A); + value8 = mmu->readMem(address); + P.bits.Z = (value8 & A) == 0; + mmu->writeMem(address, value8 & ~A); ticks += 6; break; case 0x1D : // ABX ORA - address = readMem(PC); + address = mmu->readMem(PC); PC++; ticks += ((address + X) & 0xFF00) ? 5 : 4; // page crossing - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; address += X; - A |= readMem(address); - P.Z = A == 0; - P.S = A > 0x7F; + A |= mmu->readMem(address); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; break; case 0x1E : // ABX ASL - address = readMem(PC); + address = mmu->readMem(PC); PC++; ticks += address + X > 0xFF ? 7 : 6; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; address += X; - value16 = readMem(address) << 1; - P.C = value16 > 0xFF; + value16 = mmu->readMem(address) << 1; + P.bits.C = value16 > 0xFF; value16 &= 0xFF; - writeMem(address, value16); - P.Z = value16 == 0; - P.S = value16 > 0x7F; + mmu->writeMem(address, value16); + P.bits.Z = value16 == 0; + P.bits.S = value16 > 0x7F; break; case 0x1F : // ZPR BBR - value8 = readMem(readMem(PC)); + value8 = mmu->readMem(mmu->readMem(PC)); PC++; - address = readMem(PC); + address = mmu->readMem(PC); PC++; if (address & SIGN) address |= 0xFF00; // jump backward @@ -431,26 +425,26 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x20 : // ABS JSR - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; - writeMem(0x100 + SP, (PC >> 8) & 0xFF); + address |= mmu->readMem(PC) << 8; + mmu->writeMem(0x100 + SP, (PC >> 8) & 0xFF); SP--; - writeMem(0x100 + SP, PC & 0xFF); + mmu->writeMem(0x100 + SP, PC & 0xFF); SP--; PC = address; ticks += 6; break; case 0x21 : // IZX AND - value8 = readMem(PC) + X; + value8 = mmu->readMem(PC) + X; PC++; - address = readMem(value8); + address = mmu->readMem(value8); value8++; - address |= readMem(value8) << 8; - A &= readMem(address); - P.Z = A == 0; - P.S = A > 0x7F; + address |= mmu->readMem(value8) << 8; + A &= mmu->readMem(address); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 6; break; @@ -464,61 +458,61 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x24 : // ZPG BIT - address = readMem(PC); + address = mmu->readMem(PC); PC++; - value8 = readMem(address); - P.Z = (A & value8) == 0; + value8 = mmu->readMem(address); + P.bits.Z = (A & value8) == 0; P.byte = (P.byte & 0x3F) | (value8 & 0xC0); ticks += 3; break; case 0x25 : // ZPG AND - A &= readMem(readMem(PC)); + A &= mmu->readMem(mmu->readMem(PC)); PC++; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 3; break; case 0x26 : // ZPG ROL - address = readMem(PC); + address = mmu->readMem(PC); PC++; - value16 = (readMem(address) << 1) | P.C; - P.C = (value16 & 0x100) != 0; + value16 = (mmu->readMem(address) << 1) | P.bits.C; + P.bits.C = (value16 & 0x100) != 0; value16 &= 0xFF; - writeMem(address, value16); - P.Z = value16 == 0; - P.S = value16 > 0x7F; + mmu->writeMem(address, value16); + P.bits.Z = value16 == 0; + P.bits.S = value16 > 0x7F; ticks += 5; break; case 0x27 : // ZPG RMB - address = readMem(PC); + address = mmu->readMem(PC); PC++; - writeMem(address, readMem(address) & ~4); + mmu->writeMem(address, mmu->readMem(address) & ~4); ticks += 5; break; case 0x28 : // IMP PLP SP++; - P.byte = readMem(0x100 + SP) | UNDEF; + P.byte = mmu->readMem(0x100 + SP) | UNDEF; ticks += 4; break; case 0x29 : // IMM AND - A &= readMem(PC); + A &= mmu->readMem(PC); PC++; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 2; break; case 0x2A : // ACC ROL - value16 = (A << 1) | P.C; - P.C = (value16 & 0x100) != 0; + value16 = (A << 1) | P.bits.C; + P.bits.C = (value16 & 0x100) != 0; A = value16 & 0xFF; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 2; break; @@ -527,45 +521,45 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x2C : // ABS BIT - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; - value8 = readMem(address); - P.Z = (A & value8) == 0; + value8 = mmu->readMem(address); + P.bits.Z = (A & value8) == 0; P.byte = (P.byte & 0x3F) | (value8 & 0xC0); ticks += 4; break; case 0x2D : // ABS AND - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; - A &= readMem(address); - P.Z = A == 0; - P.S = A > 0x7F; + A &= mmu->readMem(address); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 4; break; case 0x2E : // ABS ROL - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; - value16 = (readMem(address) << 1) | P.C; - P.C = (value16 & 0x100) != 0; + value16 = (mmu->readMem(address) << 1) | P.bits.C; + P.bits.C = (value16 & 0x100) != 0; value16 &= 0xFF; - writeMem(address, value16); - P.Z = value16 == 0; - P.S = value16 > 0x7F; + mmu->writeMem(address, value16); + P.bits.Z = value16 == 0; + P.bits.S = value16 > 0x7F; ticks += 6; break; case 0x2F : // ZPR BBR - value8 = readMem(readMem(PC)); + value8 = mmu->readMem(mmu->readMem(PC)); PC++; - address = readMem(PC); + address = mmu->readMem(PC); PC++; if (address & SIGN) address |= 0xFF00; // jump backward @@ -575,9 +569,9 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x30 : // REL BMI - address = readMem(PC); + address = mmu->readMem(PC); PC++; - if (P.S) { // branch taken + if (P.bits.S) { // branch taken ticks++; if (address & SIGN) address |= 0xFF00; // jump backward @@ -589,27 +583,27 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x31 : // IZY AND - value8 = readMem(PC); + value8 = mmu->readMem(PC); PC++; - address = readMem(value8); + address = mmu->readMem(value8); value8++; - address |= readMem(value8) << 8; + address |= mmu->readMem(value8) << 8; ticks += (((address & 0xFF) + Y) & 0xFF00) ? 6 : 5; // page crossing address += Y; - A &= readMem(address); - P.Z = A == 0; - P.S = A > 0x7F; + A &= mmu->readMem(address); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; break; case 0x32 : // IZP AND - value8 = readMem(PC); + value8 = mmu->readMem(PC); PC++; - address = readMem(value8); + address = mmu->readMem(value8); value8++; - address |= readMem(value8) << 8; - A &= readMem(address); - P.Z = A == 0; - P.S = A > 0x7F; + address |= mmu->readMem(value8) << 8; + A &= mmu->readMem(address); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 5; break; @@ -618,63 +612,63 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x34 : // ZPX BIT - address = (readMem(PC) + X) & 0xFF; + address = (mmu->readMem(PC) + X) & 0xFF; PC++; - value8 = readMem(address); - P.Z = (A & value8) == 0; + value8 = mmu->readMem(address); + P.bits.Z = (A & value8) == 0; P.byte = (P.byte & 0x3F) | (value8 & 0xC0); ticks += 4; break; case 0x35 : // ZPX AND - address = (readMem(PC) + X) & 0xFF; + address = (mmu->readMem(PC) + X) & 0xFF; PC++; - A &= readMem(address); - P.Z = A == 0; - P.S = A > 0x7F; + A &= mmu->readMem(address); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 4; break; case 0x36 : // ZPX ROL - address = (readMem(PC) + X) & 0xFF; + address = (mmu->readMem(PC) + X) & 0xFF; PC++; - value16 = (readMem(address) << 1) | P.C; - P.C = value16 > 0xFF; + value16 = (mmu->readMem(address) << 1) | P.bits.C; + P.bits.C = value16 > 0xFF; value16 &= 0xFF; - writeMem(address, value16); - P.Z = value16 == 0; - P.S = value16 > 0x7F; + mmu->writeMem(address, value16); + P.bits.Z = value16 == 0; + P.bits.S = value16 > 0x7F; ticks += 6; break; case 0x37 : // ZPG RMB - address = readMem(PC); + address = mmu->readMem(PC); PC++; - writeMem(address, readMem(address) & ~8); + mmu->writeMem(address, mmu->readMem(address) & ~8); ticks += 5; break; case 0x38 : // IMP SEC - P.C = 1; + P.bits.C = 1; ticks += 2; break; case 0x39 : // ABY AND - address = readMem(PC); + address = mmu->readMem(PC); PC++; ticks += ((address + Y) & 0xFF00) ? 5 : 4; // page crossing - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; address += Y; - A &= readMem(address); - P.Z = A == 0; - P.S = A > 0x7F; + A &= mmu->readMem(address); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; break; case 0x3A : // ACC DEC --A; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 2; break; @@ -683,47 +677,47 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x3C : // ABX BIT - ticks += readMem(PC) + X > 0xFF ? 5 : 4; - address = readMem(PC); + ticks += mmu->readMem(PC) + X > 0xFF ? 5 : 4; + address = mmu->readMem(PC); PC++; - address |= (readMem(PC) << 8) + X; + address |= (mmu->readMem(PC) << 8) + X; PC++; - value8 = readMem(address); - P.Z = (A & value8) == 0; + value8 = mmu->readMem(address); + P.bits.Z = (A & value8) == 0; P.byte = (P.byte & 0x3F) | (value8 & 0xC0); break; case 0x3D : // ABX AND - address = readMem(PC); + address = mmu->readMem(PC); PC++; ticks += ((address + X) & 0xFF00) ? 5 : 4; // page crossing - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; address += X; - A &= readMem(address); - P.Z = A == 0; - P.S = A > 0x7F; + A &= mmu->readMem(address); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; break; case 0x3E : // ABX ROL - address = readMem(PC); + address = mmu->readMem(PC); PC++; ticks += address + X > 0xFF ? 7 : 6; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; address += X; - value16 = (readMem(address) << 1) | P.C; - P.C = value16 > 0xFF; + value16 = (mmu->readMem(address) << 1) | P.bits.C; + P.bits.C = value16 > 0xFF; value16 &= 0xFF; - writeMem(address, value16); - P.Z = value16 == 0; - P.S = value16 > 0x7F; + mmu->writeMem(address, value16); + P.bits.Z = value16 == 0; + P.bits.S = value16 > 0x7F; break; case 0x3F : // ZPR BBR - value8 = readMem(readMem(PC)); + value8 = mmu->readMem(mmu->readMem(PC)); PC++; - address = readMem(PC); + address = mmu->readMem(PC); PC++; if (address & SIGN) address |= 0xFF00; // jump backward @@ -734,23 +728,23 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { case 0x40 : // IMP RTI SP++; - P.byte = readMem(0x100 + SP); + P.byte = mmu->readMem(0x100 + SP); SP++; - PC = readMem(0x100 + SP); + PC = mmu->readMem(0x100 + SP); SP++; - PC |= readMem(0x100 + SP) << 8; + PC |= mmu->readMem(0x100 + SP) << 8; ticks += 6; break; case 0x41 : // IZX EOR - value8 = readMem(PC) + X; + value8 = mmu->readMem(PC) + X; PC++; - address = readMem(value8); + address = mmu->readMem(value8); value8++; - address |= readMem(value8) << 8; - A ^= readMem(address); - P.Z = A == 0; - P.S = A > 0x7F; + address |= mmu->readMem(value8) << 8; + A ^= mmu->readMem(address); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 6; break; @@ -769,52 +763,52 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x45 : // ZPG EOR - address = readMem(PC); + address = mmu->readMem(PC); PC++; - A ^= readMem(address); - P.Z = A == 0; - P.S = A > 0x7F; + A ^= mmu->readMem(address); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 3; break; case 0x46 : // ZPG LSR - address = readMem(PC); + address = mmu->readMem(PC); PC++; - value8 = readMem(address); - P.C = (value8 & 1) != 0; + value8 = mmu->readMem(address); + P.bits.C = (value8 & 1) != 0; value8 = value8 >> 1; - writeMem(address, value8); - P.Z = value8 == 0; - P.S = value8 > 0x7F; + mmu->writeMem(address, value8); + P.bits.Z = value8 == 0; + P.bits.S = value8 > 0x7F; ticks += 5; break; case 0x47 : // ZPG RMB - address = readMem(PC); + address = mmu->readMem(PC); PC++; - writeMem(address, readMem(address) & ~16); + mmu->writeMem(address, mmu->readMem(address) & ~16); ticks += 5; break; case 0x48 : // IMP PHA - writeMem(0x100 + SP, A); + mmu->writeMem(0x100 + SP, A); SP--; ticks += 3; break; case 0x49 : // IMM EOR - A ^= readMem(PC); + A ^= mmu->readMem(PC); PC++; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 2; break; case 0x4A : // ACC LSR - P.C = (A & 1) != 0; + P.bits.C = (A & 1) != 0; A = A >> 1; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 2; break; @@ -823,39 +817,39 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x4C : // ABS JMP - PC = readMem(PC) | (readMem(PC + 1) << 8); + PC = mmu->readMem(PC) | (mmu->readMem(PC + 1) << 8); ticks += 3; break; case 0x4D : // ABS EOR - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; - A ^= readMem(address); - P.Z = A == 0; - P.S = A > 0x7F; + A ^= mmu->readMem(address); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 4; break; case 0x4E : // ABS LSR - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; - value8 = readMem(address); - P.C = (value8 & 1) != 0; + value8 = mmu->readMem(address); + P.bits.C = (value8 & 1) != 0; value8 = value8 >> 1; - writeMem(address, value8); - P.Z = value8 == 0; - P.S = value8 > 0x7F; + mmu->writeMem(address, value8); + P.bits.Z = value8 == 0; + P.bits.S = value8 > 0x7F; ticks += 6; break; case 0x4F : // ZPR BBR - value8 = readMem(readMem(PC)); + value8 = mmu->readMem(mmu->readMem(PC)); PC++; - address = readMem(PC); + address = mmu->readMem(PC); PC++; if (address & SIGN) address |= 0xFF00; // jump backward @@ -865,9 +859,9 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x50 : // REL BVC - address = readMem(PC); + address = mmu->readMem(PC); PC++; - if (!P.V) { // branch taken + if (!P.bits.V) { // branch taken ticks++; if (address & SIGN) address |= 0xFF00; // jump backward @@ -879,26 +873,26 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x51 : // IZY EOR - value8 = readMem(PC); + value8 = mmu->readMem(PC); PC++; - address = readMem(value8); + address = mmu->readMem(value8); value8++; - address |= readMem(value8) << 8; + address |= mmu->readMem(value8) << 8; ticks += (((address & 0xFF) + Y) & 0xFF00) ? 6 : 5; // page crossing - A ^= readMem(address + Y); - P.Z = A == 0; - P.S = A > 0x7F; + A ^= mmu->readMem(address + Y); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; break; case 0x52 : // IZP EOR - value8 = readMem(PC); + value8 = mmu->readMem(PC); PC++; - address = readMem(value8); + address = mmu->readMem(value8); value8++; - address |= readMem(value8) << 8; - A ^= readMem(address); - P.Z = A == 0; - P.S = A > 0x7F; + address |= mmu->readMem(value8) << 8; + A ^= mmu->readMem(address); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 5; break; @@ -912,52 +906,52 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x55 : // ZPX EOR - address = (readMem(PC) + X) & 0xFF; + address = (mmu->readMem(PC) + X) & 0xFF; PC++; - A ^= readMem(address); - P.Z = A == 0; - P.S = A > 0x7F; + A ^= mmu->readMem(address); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 4; break; case 0x56 : // ZPX LSR - address = (readMem(PC) + X) & 0xFF; + address = (mmu->readMem(PC) + X) & 0xFF; PC++; - value8 = readMem(address); - P.C = (value8 & 1) != 0; + value8 = mmu->readMem(address); + P.bits.C = (value8 & 1) != 0; value8 = value8 >> 1; - writeMem(address, value8); - P.Z = value8 == 0; - P.S = value8 > 0x7F; + mmu->writeMem(address, value8); + P.bits.Z = value8 == 0; + P.bits.S = value8 > 0x7F; ticks += 6; break; case 0x57 : // ZPG RMB - address = readMem(PC); + address = mmu->readMem(PC); PC++; - writeMem(address, readMem(address) & ~32); + mmu->writeMem(address, mmu->readMem(address) & ~32); ticks += 5; break; case 0x58 : // IMP CLI - P.I = 0; + P.bits.I = 0; ticks += 2; break; case 0x59 : // ABY EOR - address = readMem(PC); + address = mmu->readMem(PC); PC++; ticks += ((address + Y) & 0xFF00) ? 5 : 4; // page crossing - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; address += Y; - A ^= readMem(address); - P.Z = A == 0; - P.S = A > 0x7F; + A ^= mmu->readMem(address); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; break; case 0x5A : // IMP PHY - writeMem(0x100 + SP, Y); + mmu->writeMem(0x100 + SP, Y); SP--; ticks += 3; break; @@ -972,36 +966,36 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x5D : // ABX EOR - address = readMem(PC); + address = mmu->readMem(PC); PC++; ticks += ((address + X) & 0xFF00) ? 5 : 4; // page crossing - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; address += X; - A ^= readMem(address); - P.Z = A == 0; - P.S = A > 0x7F; + A ^= mmu->readMem(address); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; break; case 0x5E : // ABX LSR - address = readMem(PC); + address = mmu->readMem(PC); PC++; ticks += address + X > 0xFF ? 7 : 6; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; address += X; - value8 = readMem(address); - P.C = (value8 & 1) != 0; + value8 = mmu->readMem(address); + P.bits.C = (value8 & 1) != 0; value8 = value8 >> 1; - writeMem(address, value8); - P.Z = value8 == 0; - P.S = value8 > 0x7F; + mmu->writeMem(address, value8); + P.bits.Z = value8 == 0; + P.bits.S = value8 > 0x7F; break; case 0x5F : // ZPR BBR - value8 = readMem(readMem(PC)); + value8 = mmu->readMem(mmu->readMem(PC)); PC++; - address = readMem(PC); + address = mmu->readMem(PC); PC++; if (address & SIGN) address |= 0xFF00; // jump backward @@ -1012,28 +1006,28 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { case 0x60 : // IMP RTS SP++; - PC = readMem(0x100 + SP); + PC = mmu->readMem(0x100 + SP); SP++; - PC |= readMem(0x100 + SP) << 8; + PC |= mmu->readMem(0x100 + SP) << 8; PC++; ticks += 6; break; case 0x61 : // IZX ADC - value8 = readMem(PC) + X; + value8 = mmu->readMem(PC) + X; PC++; - address = readMem(value8); + address = mmu->readMem(value8); value8++; - address |= readMem(value8) << 8; - value8 = readMem(address); - value16 = A + value8 + P.C; - P.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; - if (P.D) + address |= mmu->readMem(value8) << 8; + value8 = mmu->readMem(address); + value16 = A + value8 + P.bits.C; + P.bits.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; + if (P.bits.D) value16 += ((((value16 + 0x66) ^ A ^ value8) >> 3) & 0x22) * 3; - P.C = value16 > 0xFF; + P.bits.C = value16 > 0xFF; A = value16 & 0xFF; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 6; break; @@ -1047,74 +1041,74 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x64 : // ZPG STZ - writeMem(readMem(PC), 0x00); + mmu->writeMem(mmu->readMem(PC), 0x00); PC++; ticks += 3; break; case 0x65 : // ZPG ADC - address = readMem(PC); + address = mmu->readMem(PC); PC++; - value8 = readMem(address); - value16 = A + value8 + P.C; - P.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; - if (P.D) + value8 = mmu->readMem(address); + value16 = A + value8 + P.bits.C; + P.bits.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; + if (P.bits.D) value16 += ((((value16 + 0x66) ^ A ^ value8) >> 3) & 0x22) * 3; - P.C = value16 > 0xFF; + P.bits.C = value16 > 0xFF; A = value16 & 0xFF; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 3; break; case 0x66 : // ZPG ROR - address = readMem(PC); + address = mmu->readMem(PC); PC++; - value8 = readMem(address); - value16 = (value8 >> 1) | (P.C << 7); - P.C = (value8 & 0x1) != 0; + value8 = mmu->readMem(address); + value16 = (value8 >> 1) | (P.bits.C << 7); + P.bits.C = (value8 & 0x1) != 0; value16 &= 0xFF; - writeMem(address, value16); - P.Z = value16 == 0; - P.S = value16 > 0x7F; + mmu->writeMem(address, value16); + P.bits.Z = value16 == 0; + P.bits.S = value16 > 0x7F; ticks += 5; break; case 0x67 : // ZPG RMB - address = readMem(PC); + address = mmu->readMem(PC); PC++; - writeMem(address, readMem(address) & ~64); + mmu->writeMem(address, mmu->readMem(address) & ~64); ticks += 5; break; case 0x68 : // IMP PLA SP++; - A = readMem(0x100 + SP); - P.Z = A == 0; - P.S = A > 0x7F; + A = mmu->readMem(0x100 + SP); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 4; break; case 0x69 : // IMM ADC - value8 = readMem(PC); + value8 = mmu->readMem(PC); PC++; - value16 = A + value8 + P.C; - P.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; - if (P.D) + value16 = A + value8 + P.bits.C; + P.bits.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; + if (P.bits.D) value16 += ((((value16 + 0x66) ^ A ^ value8) >> 3) & 0x22) * 3; - P.C = value16 > 0xFF; + P.bits.C = value16 > 0xFF; A = value16 & 0xFF; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 2; break; case 0x6A : // ACC ROR - value16 = (A >> 1) | (P.C << 7); - P.C = (A & 0x1) != 0; + value16 = (A >> 1) | (P.bits.C << 7); + P.bits.C = (A & 0x1) != 0; A = value16 & 0xFF; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 2; break; @@ -1123,47 +1117,47 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x6C : // IND JMP - address = readMem(PC) | readMem(PC + 1) << 8; - PC = readMem(address) | (readMem(address + 1) << 8); + address = mmu->readMem(PC) | mmu->readMem(PC + 1) << 8; + PC = mmu->readMem(address) | (mmu->readMem(address + 1) << 8); ticks += 5; break; case 0x6D : // ABS ADC - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; - value8 = readMem(address); - value16 = A + value8 + P.C; - P.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; - if (P.D) + value8 = mmu->readMem(address); + value16 = A + value8 + P.bits.C; + P.bits.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; + if (P.bits.D) value16 += ((((value16 + 0x66) ^ A ^ value8) >> 3) & 0x22) * 3; - P.C = value16 > 0xFF; + P.bits.C = value16 > 0xFF; A = value16 & 0xFF; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 4; break; case 0x6E : // ABS ROR - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; - value8 = readMem(address); - value16 = (value8 >> 1) | (P.C << 7); - P.C = (value8 & 0x1) != 0; + value8 = mmu->readMem(address); + value16 = (value8 >> 1) | (P.bits.C << 7); + P.bits.C = (value8 & 0x1) != 0; value16 = value16 & 0xFF; - writeMem(address, value16); - P.Z = value16 == 0; - P.S = value16 > 0x7F; + mmu->writeMem(address, value16); + P.bits.Z = value16 == 0; + P.bits.S = value16 > 0x7F; ticks += 6; break; case 0x6F : // ZPR BBR - value8 = readMem(readMem(PC)); + value8 = mmu->readMem(mmu->readMem(PC)); PC++; - address = readMem(PC); + address = mmu->readMem(PC); PC++; if (address & SIGN) address |= 0xFF00; // jump backward @@ -1173,9 +1167,9 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x70 : // REL BVS - address = readMem(PC); + address = mmu->readMem(PC); PC++; - if (P.V) { // branch taken + if (P.bits.V) { // branch taken ticks++; if (((PC & 0xFF) + address) & 0xFF00) // page crossing ticks++; @@ -1187,41 +1181,41 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x71 : // IZY ADC - value8 = readMem(PC); + value8 = mmu->readMem(PC); PC++; - address = readMem(value8); + address = mmu->readMem(value8); if ((address + Y) & 0xFF00) // page crossing ticks++; value8++; - address |= readMem(value8) << 8; + address |= mmu->readMem(value8) << 8; address += Y; - value8 = readMem(address); - value16 = A + value8 + P.C; - P.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; - if (P.D) + value8 = mmu->readMem(address); + value16 = A + value8 + P.bits.C; + P.bits.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; + if (P.bits.D) value16 += ((((value16 + 0x66) ^ A ^ value8) >> 3) & 0x22) * 3; - P.C = value16 > 0xFF; + P.bits.C = value16 > 0xFF; A = value16 & 0xFF; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 5; break; case 0x72 : // IZP ADC - value8 = readMem(PC); + value8 = mmu->readMem(PC); PC++; - address = readMem(value8); + address = mmu->readMem(value8); value8++; - address |= readMem(value8) << 8; - value8 = readMem(address); - value16 = A + value8 + P.C; - P.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; - if (P.D) + address |= mmu->readMem(value8) << 8; + value8 = mmu->readMem(address); + value16 = A + value8 + P.bits.C; + P.bits.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; + if (P.bits.D) value16 += ((((value16 + 0x66) ^ A ^ value8) >> 3) & 0x22) * 3; - P.C = value16 > 0xFF; + P.bits.C = value16 > 0xFF; A = value16 & 0xFF; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 5; break; @@ -1230,77 +1224,77 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x74 : // ZPX STZ - value8 = readMem(PC) + X; // 8bit -> zp wrap around + value8 = mmu->readMem(PC) + X; // 8bit -> zp wrap around PC++; - writeMem(value8, 0x00); + mmu->writeMem(value8, 0x00); ticks += 4; break; case 0x75 : // ZPX ADC - address = (readMem(PC) + X) & 0xFF; + address = (mmu->readMem(PC) + X) & 0xFF; PC++; - value8 = readMem(address); - value16 = A + value8 + P.C; - P.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; - if (P.D) + value8 = mmu->readMem(address); + value16 = A + value8 + P.bits.C; + P.bits.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; + if (P.bits.D) value16 += ((((value16 + 0x66) ^ A ^ value8) >> 3) & 0x22) * 3; - P.C = value16 > 0xFF; + P.bits.C = value16 > 0xFF; A = value16 & 0xFF; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 4; break; case 0x76 : // ZPX ROR - address = (readMem(PC) + X) & 0xFF; + address = (mmu->readMem(PC) + X) & 0xFF; PC++; - value8 = readMem(address); - value16 = (value8 >> 1) | (P.C << 7); - P.C = (value8 & 0x1) != 0; + value8 = mmu->readMem(address); + value16 = (value8 >> 1) | (P.bits.C << 7); + P.bits.C = (value8 & 0x1) != 0; value16 = value16 & 0xFF; - writeMem(address, value16); - P.Z = value16 == 0; - P.S = value16 > 0x7F; + mmu->writeMem(address, value16); + P.bits.Z = value16 == 0; + P.bits.S = value16 > 0x7F; ticks += 6; break; case 0x77 : // ZPG RMB - address = readMem(PC); + address = mmu->readMem(PC); PC++; - writeMem(address, readMem(address) & ~128); + mmu->writeMem(address, mmu->readMem(address) & ~128); ticks += 5; break; case 0x78 : // IMP SEI - P.I = 1; + P.bits.I = 1; ticks += 2; break; case 0x79 : // ABY ADC - if ((readMem(PC) + Y) & 0xFF00) + if ((mmu->readMem(PC) + Y) & 0xFF00) ticks++; - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; address += Y; - value8 = readMem(address); - value16 = A + value8 + P.C; - P.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; - if (P.D) + value8 = mmu->readMem(address); + value16 = A + value8 + P.bits.C; + P.bits.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; + if (P.bits.D) value16 += ((((value16 + 0x66) ^ A ^ value8) >> 3) & 0x22) * 3; - P.C = value16 > 0xFF; + P.bits.C = value16 > 0xFF; A = value16 & 0xFF; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 4; break; case 0x7A : // IMP PLY SP++; - Y = readMem(0x100 + SP); - P.Z = Y == 0; - P.S = Y > 0x7F; + Y = mmu->readMem(0x100 + SP); + P.bits.Z = Y == 0; + P.bits.S = Y > 0x7F; ticks += 4; break; @@ -1310,50 +1304,50 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { case 0x7C : // IAX JMP ticks += ((PC & 0xFF) + X) > 0xFF ? 7 : 6; - address = (readMem((PC + 1) & 0xFFFF) << 8) + readMem(PC) + X; - PC = (readMem(address) | (readMem((address + 1) & 0xFFFF) << 8)); + address = (mmu->readMem((PC + 1) & 0xFFFF) << 8) + mmu->readMem(PC) + X; + PC = (mmu->readMem(address) | (mmu->readMem((address + 1) & 0xFFFF) << 8)); break; case 0x7D : // ABX ADC - if ((readMem(PC) + X) & 0xFF00) + if ((mmu->readMem(PC) + X) & 0xFF00) ticks++; - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; address += X; - value8 = readMem(address); - value16 = A + value8 + P.C; - P.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; - if (P.D) + value8 = mmu->readMem(address); + value16 = A + value8 + P.bits.C; + P.bits.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; + if (P.bits.D) value16 += ((((value16 + 0x66) ^ A ^ value8) >> 3) & 0x22) * 3; - P.C = value16 > 0xFF; + P.bits.C = value16 > 0xFF; A = value16 & 0xFF; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 4; break; case 0x7E : // ABX ROR - address = readMem(PC); + address = mmu->readMem(PC); PC++; ticks += address + X > 0xFF ? 7 : 6; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; address += X; - value8 = readMem(address); - value16 = (value8 >> 1) | (P.C << 7); - P.C = (value8 & 0x1) != 0; + value8 = mmu->readMem(address); + value16 = (value8 >> 1) | (P.bits.C << 7); + P.bits.C = (value8 & 0x1) != 0; value16 = value16 & 0xFF; - writeMem(address, value16); - P.Z = value16 == 0; - P.S = value16 > 0x7F; + mmu->writeMem(address, value16); + P.bits.Z = value16 == 0; + P.bits.S = value16 > 0x7F; break; case 0x7F : // ZPR BBR - value8 = readMem(readMem(PC)); + value8 = mmu->readMem(mmu->readMem(PC)); PC++; - address = readMem(PC); + address = mmu->readMem(PC); PC++; if (address & SIGN) address |= 0xFF00; // jump backward @@ -1363,7 +1357,7 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x80 : // REL BRA - address = readMem(PC); + address = mmu->readMem(PC); PC++; if (address & SIGN) address |= 0xFF00; // jump backward @@ -1372,12 +1366,12 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x81 : // IZX STA - value8 = readMem(PC) + X; + value8 = mmu->readMem(PC) + X; PC++; - address = readMem(value8); + address = mmu->readMem(value8); value8++; - address |= readMem(value8) << 8; - writeMem(address, A); + address |= mmu->readMem(value8) << 8; + mmu->writeMem(address, A); ticks += 6; break; @@ -1391,47 +1385,47 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x84 : // ZPG STY - writeMem(readMem(PC), Y); + mmu->writeMem(mmu->readMem(PC), Y); PC++; ticks += 3; break; case 0x85 : // ZPG STA - writeMem(readMem(PC), A); + mmu->writeMem(mmu->readMem(PC), A); PC++; ticks += 3; break; case 0x86 : // ZPG STX - writeMem(readMem(PC), X); + mmu->writeMem(mmu->readMem(PC), X); PC++; ticks += 3; break; case 0x87 : // ZPG SMB - address = readMem(PC); + address = mmu->readMem(PC); PC++; - writeMem(address, readMem(address) | 1); + mmu->writeMem(address, mmu->readMem(address) | 1); ticks += 5; break; case 0x88 : // IMP DEY Y--; - P.Z = (Y & 0xFF) == 0; - P.S = (Y & SIGN) != 0; + P.bits.Z = (Y & 0xFF) == 0; + P.bits.S = (Y & SIGN) != 0; ticks += 2; break; case 0x89 : // IMM BIT - P.Z = (A & readMem(PC)) == 0; + P.bits.Z = (A & mmu->readMem(PC)) == 0; PC++; ticks += 2; break; case 0x8A : // IMP TXA A = X; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 2; break; @@ -1440,36 +1434,36 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x8C : // ABS STY - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; - writeMem(address, Y); + mmu->writeMem(address, Y); ticks += 4; break; case 0x8D : // ABS STA - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; - writeMem(address, A); + mmu->writeMem(address, A); ticks += 4; break; case 0x8E : // ABS STX - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; - writeMem(address, X); + mmu->writeMem(address, X); ticks += 4; break; case 0x8F : // ZPR BBS - value8 = readMem(readMem(PC)); + value8 = mmu->readMem(mmu->readMem(PC)); PC++; - address = readMem(PC); + address = mmu->readMem(PC); PC++; if (address & SIGN) address |= 0xFF00; // jump backward @@ -1479,9 +1473,9 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x90 : // REL BCC - address = readMem(PC); + address = mmu->readMem(PC); PC++; - if (!P.C) { // branch taken + if (!P.bits.C) { // branch taken ticks++; if (((PC & 0xFF) + address) & 0xFF00) // page crossing ticks++; @@ -1493,23 +1487,23 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x91 : // IZY STA - value8 = readMem(PC); + value8 = mmu->readMem(PC); PC++; - address = readMem(value8); + address = mmu->readMem(value8); value8++; - address |= readMem(value8) << 8; + address |= mmu->readMem(value8) << 8; address += Y; - writeMem(address, A); + mmu->writeMem(address, A); ticks += 6; break; case 0x92 : // IZP STA - value8 = readMem(PC); + value8 = mmu->readMem(PC); PC++; - address = readMem(value8); + address = mmu->readMem(value8); value8++; - address |= readMem(value8) << 8; - writeMem(address, A); + address |= mmu->readMem(value8) << 8; + mmu->writeMem(address, A); ticks += 5; break; @@ -1518,45 +1512,45 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x94 : // ZPX STY - address = (readMem(PC) + X) & 0xFF; + address = (mmu->readMem(PC) + X) & 0xFF; PC++; - writeMem(address, Y); + mmu->writeMem(address, Y); ticks += 4; break; case 0x95 : // ZPX STA - writeMem((readMem(PC) + X) & 0xFF, A); + mmu->writeMem((mmu->readMem(PC) + X) & 0xFF, A); PC++; ticks += 4; break; case 0x96 : // ZPY STX - writeMem((readMem(PC) + Y) & 0xFF, X); + mmu->writeMem((mmu->readMem(PC) + Y) & 0xFF, X); PC++; ticks += 4; break; case 0x97 : // ZPG SMB - address = readMem(PC); + address = mmu->readMem(PC); PC++; - writeMem(address, readMem(address) | 2); + mmu->writeMem(address, mmu->readMem(address) | 2); ticks += 5; break; case 0x98 : // IMP TYA A = Y; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 2; break; case 0x99 : // ABY STA - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; address += Y; - writeMem(address, A); + mmu->writeMem(address, A); ticks += 5; break; @@ -1570,38 +1564,38 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0x9C : // ABS STZ - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; - writeMem(address, 0x00); + mmu->writeMem(address, 0x00); ticks += 4; break; case 0x9D : // ABX STA - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; address += X; - writeMem(address, A); + mmu->writeMem(address, A); ticks += 5; break; case 0x9E : // ABX STZ - ticks += readMem(PC) + X > 0xFF ? 6 : 5; - address = readMem(PC); + ticks += mmu->readMem(PC) + X > 0xFF ? 6 : 5; + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; address += X; - writeMem(address, 0x00); + mmu->writeMem(address, 0x00); break; case 0x9F : // ZPR BBS - value8 = readMem(readMem(PC)); + value8 = mmu->readMem(mmu->readMem(PC)); PC++; - address = readMem(PC); + address = mmu->readMem(PC); PC++; if (address & SIGN) address |= 0xFF00; // jump backward @@ -1611,84 +1605,84 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0xA0 : // IMM LDY - Y = readMem(PC); + Y = mmu->readMem(PC); PC++; - P.Z = Y == 0; - P.S = Y > 0x7F; + P.bits.Z = Y == 0; + P.bits.S = Y > 0x7F; ticks += 2; break; case 0xA1 : // IZX LDA - value8 = readMem(PC) + X; + value8 = mmu->readMem(PC) + X; PC++; - address = readMem(value8); + address = mmu->readMem(value8); value8++; - address |= readMem(value8) << 8; - A = readMem(address); - P.Z = A == 0; - P.S = A > 0x7F; + address |= mmu->readMem(value8) << 8; + A = mmu->readMem(address); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 6; break; case 0xA2 : // IMM LDX address = PC; PC++; - X = readMem(address); - P.Z = X == 0; - P.S = X > 0x7F; + X = mmu->readMem(address); + P.bits.Z = X == 0; + P.bits.S = X > 0x7F; ticks += 2; break; case 0xA4 : // ZPG LDY - Y = readMem(readMem(PC)); + Y = mmu->readMem(mmu->readMem(PC)); PC++; - P.Z = Y == 0; - P.S = Y > 0x7F; + P.bits.Z = Y == 0; + P.bits.S = Y > 0x7F; ticks += 3; break; case 0xA5 : // ZPG LDA - A = readMem(readMem(PC)); + A = mmu->readMem(mmu->readMem(PC)); PC++; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 3; break; case 0xA6 : // ZPG LDX - X = readMem(readMem(PC)); + X = mmu->readMem(mmu->readMem(PC)); PC++; - P.Z = X == 0; - P.S = X > 0x7F; + P.bits.Z = X == 0; + P.bits.S = X > 0x7F; ticks += 3; break; case 0xA7 : // ZPG SMB - address = readMem(PC); + address = mmu->readMem(PC); PC++; - writeMem(address, readMem(address) | 4); + mmu->writeMem(address, mmu->readMem(address) | 4); ticks += 5; break; case 0xA8 : // IMP TAY Y = A; - P.Z = Y == 0; - P.S = Y > 0x7F; + P.bits.Z = Y == 0; + P.bits.S = Y > 0x7F; ticks += 2; break; case 0xA9 : // IMM LDA - A = readMem(PC); + A = mmu->readMem(PC); PC++; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 2; break; case 0xAA : // IMP TAX X = A; - P.Z = X == 0; - P.S = X > 0x7F; + P.bits.Z = X == 0; + P.bits.S = X > 0x7F; ticks += 2; break; @@ -1697,42 +1691,42 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0xAC : // ABS LDY - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; - Y = readMem(address); - P.Z = Y == 0; - P.S = Y > 0x7F; + Y = mmu->readMem(address); + P.bits.Z = Y == 0; + P.bits.S = Y > 0x7F; ticks += 4; break; case 0xAD : // ABS LDA - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; - A = readMem(address); - P.Z = A == 0; - P.S = A > 0x7F; + A = mmu->readMem(address); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 4; break; case 0xAE : // ABS LDX - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; - X = readMem(address); - P.Z = X == 0; - P.S = X > 0x7F; + X = mmu->readMem(address); + P.bits.Z = X == 0; + P.bits.S = X > 0x7F; ticks += 4; break; case 0xAF : // ZPR BBS - value8 = readMem(readMem(PC)); + value8 = mmu->readMem(mmu->readMem(PC)); PC++; - address = readMem(PC); + address = mmu->readMem(PC); PC++; if (address & SIGN) address |= 0xFF00; // jump backward @@ -1742,9 +1736,9 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0xB0 : // REL BCS - address = readMem(PC); + address = mmu->readMem(PC); PC++; - if (P.C) { // branch taken + if (P.bits.C) { // branch taken ticks++; if (address & SIGN) address |= 0xFF00; // jump backward @@ -1756,26 +1750,26 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0xB1 : // IZY LDA - value8 = readMem(PC); + value8 = mmu->readMem(PC); PC++; - address = readMem(value8); + address = mmu->readMem(value8); value8++; - address |= readMem(value8) << 8; - A = readMem(address + Y); + address |= mmu->readMem(value8) << 8; + A = mmu->readMem(address + Y); ticks += (((address & 0xFF) + Y) & 0xFF00) ? 6 : 5; // page crossing - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; break; case 0xB2 : // IZP LDA - value8 = readMem(PC); + value8 = mmu->readMem(PC); PC++; - address = readMem(value8); + address = mmu->readMem(value8); value8++; - address |= readMem(value8) << 8; - A = readMem(address); - P.Z = A == 0; - P.S = A > 0x7F; + address |= mmu->readMem(value8) << 8; + A = mmu->readMem(address); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 5; break; @@ -1784,60 +1778,60 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0xB4 : // ZPX LDY - address = (readMem(PC) + X) & 0xFF; + address = (mmu->readMem(PC) + X) & 0xFF; PC++; - Y = readMem(address); - P.Z = Y == 0; - P.S = Y > 0x7F; + Y = mmu->readMem(address); + P.bits.Z = Y == 0; + P.bits.S = Y > 0x7F; ticks += 4; break; case 0xB5 : // ZPX LDA - address = (readMem(PC) + X) & 0xFF; + address = (mmu->readMem(PC) + X) & 0xFF; PC++; - A = readMem(address); - P.Z = A == 0; - P.S = A > 0x7F; + A = mmu->readMem(address); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 4; break; case 0xB6 : // ZPY LDX - address = (readMem(PC) + Y) & 0xFF; + address = (mmu->readMem(PC) + Y) & 0xFF; PC++; - X = readMem(address); - P.Z = X == 0; - P.S = X > 0x7F; + X = mmu->readMem(address); + P.bits.Z = X == 0; + P.bits.S = X > 0x7F; ticks += 4; break; case 0xB7 : // ZPG SMB - address = readMem(PC); + address = mmu->readMem(PC); PC++; - writeMem(address, readMem(address) | 8); + mmu->writeMem(address, mmu->readMem(address) | 8); ticks += 5; break; case 0xB8 : // IMP CLV - P.V = 0; + P.bits.V = 0; ticks += 2; break; case 0xB9 : // ABY LDA - address = readMem(PC); + address = mmu->readMem(PC); PC++; ticks += ((address + Y) & 0xFF00) ? 5 : 4; // page crossing - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; address += Y; - A = readMem(address); - P.Z = A == 0; - P.S = A > 0x7F; + A = mmu->readMem(address); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; break; case 0xBA : // IMP TSX X = SP; - P.Z = X == 0; - P.S = X > 0x7F; + P.bits.Z = X == 0; + P.bits.S = X > 0x7F; ticks += 2; break; @@ -1846,45 +1840,45 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0xBC : // ABX LDY - address = readMem(PC); + address = mmu->readMem(PC); PC++; ticks += ((address + X) & 0xFF00) ? 5 : 4; // page crossing - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; address += X; - Y = readMem(address); - P.Z = Y == 0; - P.S = Y > 0x7F; + Y = mmu->readMem(address); + P.bits.Z = Y == 0; + P.bits.S = Y > 0x7F; break; case 0xBD : // ABX LDA - address = readMem(PC); + address = mmu->readMem(PC); PC++; ticks += ((address + X) & 0xFF00) ? 5 : 4; // page crossing - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; address += X; - A = readMem(address); - P.Z = A == 0; - P.S = A > 0x7F; + A = mmu->readMem(address); + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; break; case 0xBE : // ABY LDX - address = readMem(PC); + address = mmu->readMem(PC); PC++; ticks += ((address + Y) & 0xFF00) ? 5 : 4; // page crossing - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; address += Y; - X = readMem(address); - P.Z = X == 0; - P.S = X > 0x7F; + X = mmu->readMem(address); + P.bits.Z = X == 0; + P.bits.S = X > 0x7F; break; case 0xBF : // ZPR BBS - value8 = readMem(readMem(PC)); + value8 = mmu->readMem(mmu->readMem(PC)); PC++; - address = readMem(PC); + address = mmu->readMem(PC); PC++; if (address & SIGN) address |= 0xFF00; // jump backward @@ -1894,24 +1888,24 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0xC0 : // IMM CPY - value8 = readMem(PC); + value8 = mmu->readMem(PC); PC++; - P.Z = ((Y - value8) & 0xFF) == 0; - P.S = ((Y - value8) & SIGN) != 0; - P.C = (Y >= value8) != 0; + P.bits.Z = ((Y - value8) & 0xFF) == 0; + P.bits.S = ((Y - value8) & SIGN) != 0; + P.bits.C = (Y >= value8) != 0; ticks += 2; break; case 0xC1 : // IZX CMP - value8 = readMem(PC) + X; + value8 = mmu->readMem(PC) + X; PC++; - address = readMem(value8); + address = mmu->readMem(value8); value8++; - address |= readMem(value8) << 8; - value8 = readMem(address); - P.Z = ((A - value8) & 0xFF) == 0; - P.S = ((A - value8) & SIGN) != 0; - P.C = (A >= value8) != 0; + address |= mmu->readMem(value8) << 8; + value8 = mmu->readMem(address); + P.bits.Z = ((A - value8) & 0xFF) == 0; + P.bits.S = ((A - value8) & SIGN) != 0; + P.bits.C = (A >= value8) != 0; ticks += 6; break; @@ -1925,61 +1919,61 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0xC4 : // ZPG CPY - value8 = readMem(readMem(PC)); + value8 = mmu->readMem(mmu->readMem(PC)); PC++; - P.Z = ((Y - value8) & 0xFF) == 0; - P.S = ((Y - value8) & SIGN) != 0; - P.C = (Y >= value8) != 0; + P.bits.Z = ((Y - value8) & 0xFF) == 0; + P.bits.S = ((Y - value8) & SIGN) != 0; + P.bits.C = (Y >= value8) != 0; ticks += 3; break; case 0xC5 : // ZPG CMP - value8 = readMem(readMem(PC)); + value8 = mmu->readMem(mmu->readMem(PC)); PC++; - P.Z = ((A - value8) & 0xFF) == 0; - P.S = ((A - value8) & SIGN) != 0; - P.C = (A >= value8) != 0; + P.bits.Z = ((A - value8) & 0xFF) == 0; + P.bits.S = ((A - value8) & SIGN) != 0; + P.bits.C = (A >= value8) != 0; ticks += 3; break; case 0xC6 : // ZPG DEC - address = readMem(PC); + address = mmu->readMem(PC); PC++; - value8 = readMem(address); + value8 = mmu->readMem(address); --value8; - writeMem(address, value8); - P.Z = value8 == 0; - P.S = value8 > 0x7F; + mmu->writeMem(address, value8); + P.bits.Z = value8 == 0; + P.bits.S = value8 > 0x7F; ticks += 5; break; case 0xC7 : // ZPG SMB - address = readMem(PC); + address = mmu->readMem(PC); PC++; - writeMem(address, readMem(address) | 16); + mmu->writeMem(address, mmu->readMem(address) | 16); ticks += 5; break; case 0xC8 : // IMP INY Y++; - P.Z = Y == 0; - P.S = Y > 0x7F; + P.bits.Z = Y == 0; + P.bits.S = Y > 0x7F; ticks += 2; break; case 0xC9 : // IMM CMP - value8 = readMem(PC); + value8 = mmu->readMem(PC); PC++; - P.Z = ((A - value8) & 0xFF) == 0; - P.S = ((A - value8) & SIGN) != 0; - P.C = (A >= value8) != 0; + P.bits.Z = ((A - value8) & 0xFF) == 0; + P.bits.S = ((A - value8) & SIGN) != 0; + P.bits.C = (A >= value8) != 0; ticks += 2; break; case 0xCA : // IMP DEX X--; - P.Z = (X & 0xFF) == 0; - P.S = X > 0x7F; + P.bits.Z = (X & 0xFF) == 0; + P.bits.S = X > 0x7F; ticks += 2; break; @@ -1989,46 +1983,46 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0xCC : // ABS CPY - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; - value8 = readMem(address); - P.Z = ((Y - value8) & 0xFF) == 0; - P.S = ((Y - value8) & SIGN) != 0; - P.C = (Y >= value8) != 0; + value8 = mmu->readMem(address); + P.bits.Z = ((Y - value8) & 0xFF) == 0; + P.bits.S = ((Y - value8) & SIGN) != 0; + P.bits.C = (Y >= value8) != 0; ticks += 4; break; case 0xCD : // ABS CMP - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; - value8 = readMem(address); - P.Z = ((A - value8) & 0xFF) == 0; - P.S = ((A - value8) & SIGN) != 0; - P.C = (A >= value8) != 0; + value8 = mmu->readMem(address); + P.bits.Z = ((A - value8) & 0xFF) == 0; + P.bits.S = ((A - value8) & SIGN) != 0; + P.bits.C = (A >= value8) != 0; ticks += 4; break; case 0xCE : // ABS DEC - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; - value8 = readMem(address); + value8 = mmu->readMem(address); value8--; - writeMem(address, value8); - P.Z = value8 == 0; - P.S = value8 > 0x7F; + mmu->writeMem(address, value8); + P.bits.Z = value8 == 0; + P.bits.S = value8 > 0x7F; ticks += 3; break; case 0xCF : // ZPR BBS - value8 = readMem(readMem(PC)); + value8 = mmu->readMem(mmu->readMem(PC)); PC++; - address = readMem(PC); + address = mmu->readMem(PC); PC++; if (address & SIGN) address |= 0xFF00; // jump backward @@ -2038,9 +2032,9 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0xD0 : // REL BNE - address = readMem(PC); + address = mmu->readMem(PC); PC++; - if (!P.Z) { // branch taken + if (!P.bits.Z) { // branch taken ticks++; if (address & SIGN) address |= 0xFF00; // jump backward @@ -2052,29 +2046,29 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0xD1 : // IZY CMP - value8 = readMem(PC); + value8 = mmu->readMem(PC); PC++; - address = readMem(value8); + address = mmu->readMem(value8); ticks += ((address + Y) & 0xFF00) ? 6 : 5; // page crossing value8++; - address |= readMem(value8) << 8; + address |= mmu->readMem(value8) << 8; address += Y; - value8 = readMem(address); - P.Z = ((A - value8) & 0xFF) == 0; - P.S = ((A - value8) & SIGN) != 0; - P.C = (A >= value8) != 0; + value8 = mmu->readMem(address); + P.bits.Z = ((A - value8) & 0xFF) == 0; + P.bits.S = ((A - value8) & SIGN) != 0; + P.bits.C = (A >= value8) != 0; break; case 0xD2 : // IZP CMP - value8 = readMem(PC); + value8 = mmu->readMem(PC); PC++; - address = readMem(value8); + address = mmu->readMem(value8); value8++; - address |= readMem(value8) << 8; - value8 = readMem(address); - P.Z = ((A - value8) & 0xFF) == 0; - P.S = ((A - value8) & SIGN) != 0; - P.C = (A >= value8) != 0; + address |= mmu->readMem(value8) << 8; + value8 = mmu->readMem(address); + P.bits.Z = ((A - value8) & 0xFF) == 0; + P.bits.S = ((A - value8) & SIGN) != 0; + P.bits.C = (A >= value8) != 0; ticks += 5; break; @@ -2088,53 +2082,53 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0xD5 : // ZPX CMP - address = (readMem(PC) + X) & 0xFF; + address = (mmu->readMem(PC) + X) & 0xFF; PC++; - value8 = readMem(address); - P.Z = ((A - value8) & 0xFF) == 0; - P.S = ((A - value8) & SIGN) != 0; - P.C = (A >= value8) != 0; + value8 = mmu->readMem(address); + P.bits.Z = ((A - value8) & 0xFF) == 0; + P.bits.S = ((A - value8) & SIGN) != 0; + P.bits.C = (A >= value8) != 0; ticks += 4; break; case 0xD6 : // ZPX DEC - address = (readMem(PC) + X) & 0xFF; + address = (mmu->readMem(PC) + X) & 0xFF; PC++; - value8 = readMem(address); + value8 = mmu->readMem(address); value8--; - writeMem(address, value8); - P.Z = value8 == 0; - P.S = value8 > 0x7F; + mmu->writeMem(address, value8); + P.bits.Z = value8 == 0; + P.bits.S = value8 > 0x7F; ticks += 6; break; case 0xD7 : // ZPG SMB - address = readMem(PC); + address = mmu->readMem(PC); PC++; - writeMem(address, readMem(address) | 32); + mmu->writeMem(address, mmu->readMem(address) | 32); ticks += 5; break; case 0xD8 : // IMP CLD - P.D = 0; + P.bits.D = 0; ticks += 2; break; case 0xD9 : // ABY CMP - address = readMem(PC); + address = mmu->readMem(PC); PC++; ticks += ((address + Y) & 0xFF00) ? 5 : 4; // page crossing - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; address += Y; - value8 = readMem(address); - P.Z = ((A - value8) & 0xFF) == 0; - P.S = ((A - value8) & SIGN) != 0; - P.C = (A >= value8) != 0; + value8 = mmu->readMem(address); + P.bits.Z = ((A - value8) & 0xFF) == 0; + P.bits.S = ((A - value8) & SIGN) != 0; + P.bits.C = (A >= value8) != 0; break; case 0xDA : // IMP PHX - writeMem(0x100 + SP, X); + mmu->writeMem(0x100 + SP, X); SP--; ticks += 3; break; @@ -2150,36 +2144,36 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0xDD : // ABX CMP - address = readMem(PC); + address = mmu->readMem(PC); PC++; ticks += ((address + X) & 0xFF00) ? 5 : 4; // page crossing - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; address += X; - value8 = readMem(address); - P.Z = ((A - value8) & 0xFF) == 0; - P.S = ((A - value8) & SIGN) != 0; - P.C = (A >= value8) != 0; + value8 = mmu->readMem(address); + P.bits.Z = ((A - value8) & 0xFF) == 0; + P.bits.S = ((A - value8) & SIGN) != 0; + P.bits.C = (A >= value8) != 0; break; case 0xDE : // ABX DEC - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; address += X; - value8 = readMem(address); + value8 = mmu->readMem(address); value8--; - writeMem(address, value8); - P.Z = value8 == 0; - P.S = (value8 & SIGN) != 0; + mmu->writeMem(address, value8); + P.bits.Z = value8 == 0; + P.bits.S = (value8 & SIGN) != 0; ticks += 7; break; case 0xDF : // ZPR BBS - value8 = readMem(readMem(PC)); + value8 = mmu->readMem(mmu->readMem(PC)); PC++; - address = readMem(PC); + address = mmu->readMem(PC); PC++; if (address & SIGN) address |= 0xFF00; // jump backward @@ -2189,32 +2183,32 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0xE0 : // IMM CPX - value8 = readMem(PC); + value8 = mmu->readMem(PC); PC++; - P.Z = ((X - value8) & 0xFF) == 0; - P.S = ((X - value8) & SIGN) != 0; - P.C = (X >= value8) != 0; + P.bits.Z = ((X - value8) & 0xFF) == 0; + P.bits.S = ((X - value8) & SIGN) != 0; + P.bits.C = (X >= value8) != 0; ticks += 2; break; case 0xE1 : // IZX SBC - value8 = readMem(PC) + X; + value8 = mmu->readMem(PC) + X; PC++; - address = readMem(value8); + address = mmu->readMem(value8); value8++; - address |= readMem(value8) << 8; - value8 = readMem(address); + address |= mmu->readMem(value8) << 8; + value8 = mmu->readMem(address); value8 ^= 0xFF; - if (P.D) + if (P.bits.D) value8 -= 0x0066; - value16 = A + value8 + P.C; - P.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; - if (P.D) + value16 = A + value8 + P.bits.C; + P.bits.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; + if (P.bits.D) value16 += ((((value16 + 0x66) ^ A ^ value8) >> 3) & 0x22) * 3; - P.C = value16 > 0xFF; + P.bits.C = value16 > 0xFF; A = value16 & 0xFF; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 6; break; @@ -2228,70 +2222,70 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0xE4 : // ZPG CPX - value8 = readMem(readMem(PC)); + value8 = mmu->readMem(mmu->readMem(PC)); PC++; - P.Z = ((X - value8) & 0xFF) == 0; - P.S = ((X - value8) & SIGN) != 0; - P.C = (X >= value8) != 0; + P.bits.Z = ((X - value8) & 0xFF) == 0; + P.bits.S = ((X - value8) & SIGN) != 0; + P.bits.C = (X >= value8) != 0; ticks += 3; break; case 0xE5 : // ZPG SBC - value8 = readMem(readMem(PC)); + value8 = mmu->readMem(mmu->readMem(PC)); PC++; value8 ^= 0xFF; - if (P.D) + if (P.bits.D) value8 -= 0x0066; - value16 = A + value8 + P.C; - P.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; - if (P.D) + value16 = A + value8 + P.bits.C; + P.bits.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; + if (P.bits.D) value16 += ((((value16 + 0x66) ^ A ^ value8) >> 3) & 0x22) * 3; - P.C = value16 > 0xFF; + P.bits.C = value16 > 0xFF; A = value16 & 0xFF; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 3; break; case 0xE6 : // ZPG INC - address = readMem(PC); + address = mmu->readMem(PC); PC++; - value8 = readMem(address); + value8 = mmu->readMem(address); value8++; - writeMem(address, value8); - P.Z = value8 == 0; - P.S = value8 > 0x7F; + mmu->writeMem(address, value8); + P.bits.Z = value8 == 0; + P.bits.S = value8 > 0x7F; ticks += 5; break; case 0xE7 : // ZPG SMB - address = readMem(PC); + address = mmu->readMem(PC); PC++; - writeMem(address, readMem(address) | 64); + mmu->writeMem(address, mmu->readMem(address) | 64); ticks += 5; break; case 0xE8 : // IMP INX X++; - P.Z = X == 0; - P.S = X > 0x7F; + P.bits.Z = X == 0; + P.bits.S = X > 0x7F; ticks += 2; break; case 0xE9 : // IMM SBC - value8 = readMem(PC); + value8 = mmu->readMem(PC); PC++; value8 ^= 0xFF; - if (P.D) + if (P.bits.D) value8 -= 0x0066; - value16 = A + value8 + (P.C); - P.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; - if (P.D) + value16 = A + value8 + (P.bits.C); + P.bits.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; + if (P.bits.D) value16 += ((((value16 + 0x66) ^ A ^ value8) >> 3) & 0x22) * 3; - P.C = value16 > 0xFF; + P.bits.C = value16 > 0xFF; A = value16 & 0xFF; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 2; break; @@ -2304,54 +2298,54 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0xEC : // ABS CPX - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; - value8 = readMem(address); - P.Z = ((X - value8) & 0xFF) == 0; - P.S = ((X - value8) & SIGN) != 0; - P.C = (X >= value8) != 0; + value8 = mmu->readMem(address); + P.bits.Z = ((X - value8) & 0xFF) == 0; + P.bits.S = ((X - value8) & SIGN) != 0; + P.bits.C = (X >= value8) != 0; ticks += 4; break; case 0xED : // ABS SBC - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; - value8 = readMem(address); + value8 = mmu->readMem(address); value8 ^= 0xFF; - if (P.D) + if (P.bits.D) value8 -= 0x0066; - value16 = A + value8 + P.C; - P.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; - if (P.D) + value16 = A + value8 + P.bits.C; + P.bits.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; + if (P.bits.D) value16 += ((((value16 + 0x66) ^ A ^ value8) >> 3) & 0x22) * 3; - P.C = value16 > 0xFF; + P.bits.C = value16 > 0xFF; A = value16 & 0xFF; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 4; break; case 0xEE : // ABS INC - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; - value8 = readMem(address); + value8 = mmu->readMem(address); value8++; - writeMem(address, value8); - P.Z = value8 == 0; - P.S = value8 > 0x7F; + mmu->writeMem(address, value8); + P.bits.Z = value8 == 0; + P.bits.S = value8 > 0x7F; ticks += 6; break; case 0xEF : // ZPR BBS - value8 = readMem(readMem(PC)); + value8 = mmu->readMem(mmu->readMem(PC)); PC++; - address = readMem(PC); + address = mmu->readMem(PC); PC++; if (address & SIGN) address |= 0xFF00; // jump backward @@ -2361,9 +2355,9 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0xF0 : // REL BEQ - address = readMem(PC); + address = mmu->readMem(PC); PC++; - if (P.Z) { // branch taken + if (P.bits.Z) { // branch taken ticks++; if (address & SIGN) address |= 0xFF00; // jump backward @@ -2375,47 +2369,47 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0xF1 : // IZY SBC - value8 = readMem(PC); + value8 = mmu->readMem(PC); PC++; - address = readMem(value8); + address = mmu->readMem(value8); if ((address + Y) & 0xFF00) // page crossing ticks++; value8++; - address |= readMem(value8) << 8; + address |= mmu->readMem(value8) << 8; address += Y; - value8 = readMem(address); + value8 = mmu->readMem(address); value8 ^= 0xFF; - if (P.D) + if (P.bits.D) value8 -= 0x0066; - value16 = A + value8 + P.C; - P.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; - if (P.D) + value16 = A + value8 + P.bits.C; + P.bits.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; + if (P.bits.D) value16 += ((((value16 + 0x66) ^ A ^ value8) >> 3) & 0x22) * 3; - P.C = value16 > 0xFF; + P.bits.C = value16 > 0xFF; A = value16 & 0xFF; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 5; break; case 0xF2 : // IZP SBC - value8 = readMem(PC); + value8 = mmu->readMem(PC); PC++; - address = readMem(value8); + address = mmu->readMem(value8); value8++; - address |= readMem(value8) << 8; - value8 = readMem(address); + address |= mmu->readMem(value8) << 8; + value8 = mmu->readMem(address); value8 ^= 0xFF; - if (P.D) + if (P.bits.D) value8 -= 0x0066; - value16 = A + value8 + P.C; - P.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; - if (P.D) + value16 = A + value8 + P.bits.C; + P.bits.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; + if (P.bits.D) value16 += ((((value16 + 0x66) ^ A ^ value8) >> 3) & 0x22) * 3; - P.C = value16 > 0xFF; + P.bits.C = value16 > 0xFF; A = value16 & 0xFF; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 5; break; @@ -2429,74 +2423,74 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0xF5 : // ZPX SBC - address = (readMem(PC) + X) & 0xFF; + address = (mmu->readMem(PC) + X) & 0xFF; PC++; - value8 = readMem(address); + value8 = mmu->readMem(address); value8 ^= 0xFF; - if (P.D) + if (P.bits.D) value8 -= 0x0066; - value16 = A + value8 + P.C; - P.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; - if (P.D) + value16 = A + value8 + P.bits.C; + P.bits.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; + if (P.bits.D) value16 += ((((value16 + 0x66) ^ A ^ value8) >> 3) & 0x22) * 3; - P.C = value16 > 0xFF; + P.bits.C = value16 > 0xFF; A = value16 & 0xFF; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 4; break; case 0xF6 : // ZPX INC - address = (readMem(PC) + X) & 0xFF; + address = (mmu->readMem(PC) + X) & 0xFF; PC++; - value8 = readMem(address); + value8 = mmu->readMem(address); value8++; - writeMem(address, value8); - P.Z = value8 == 0; - P.S = value8 > 0x7F; + mmu->writeMem(address, value8); + P.bits.Z = value8 == 0; + P.bits.S = value8 > 0x7F; ticks += 6; break; case 0xF7 : // ZPG SMB - address = readMem(PC); + address = mmu->readMem(PC); PC++; - writeMem(address, readMem(address) | 128); + mmu->writeMem(address, mmu->readMem(address) | 128); ticks += 5; break; case 0xF8 : // IMP SED - P.D = 1; + P.bits.D = 1; ticks += 2; break; case 0xF9 : // ABY SBC - address = readMem(PC); + address = mmu->readMem(PC); PC++; if ((address + Y) & 0xFF00) // page crossing ticks++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; address += Y; - value8 = readMem(address); + value8 = mmu->readMem(address); value8 ^= 0xFF; - if (P.D) + if (P.bits.D) value8 -= 0x0066; - value16 = A + value8 + P.C; - P.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; - if (P.D) + value16 = A + value8 + P.bits.C; + P.bits.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; + if (P.bits.D) value16 += ((((value16 + 0x66) ^ A ^ value8) >> 3) & 0x22) * 3; - P.C = value16 > 0xFF; + P.bits.C = value16 > 0xFF; A = value16 & 0xFF; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 4; break; case 0xFA : // IMP PLX SP++; - X = readMem(0x100 + SP); - P.Z = X == 0; - P.S = X > 0x7F; + X = mmu->readMem(0x100 + SP); + P.bits.Z = X == 0; + P.bits.S = X > 0x7F; ticks += 4; break; @@ -2510,46 +2504,46 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { break; case 0xFD : // ABX SBC - address = readMem(PC); + address = mmu->readMem(PC); PC++; if ((address + X) & 0xFF00) // page crossing ticks++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; address += X; - value8 = readMem(address); + value8 = mmu->readMem(address); value8 ^= 0xFF; - if (P.D) + if (P.bits.D) value8 -= 0x0066; - value16 = A + value8 + P.C; - P.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; - if (P.D) + value16 = A + value8 + P.bits.C; + P.bits.V = ((value16 ^ A) & (value16 ^ value8) & 0x0080) != 0; + if (P.bits.D) value16 += ((((value16 + 0x66) ^ A ^ value8) >> 3) & 0x22) * 3; - P.C = (value16 & 0xFF00) != 0; + P.bits.C = (value16 & 0xFF00) != 0; A = value16 & 0xFF; - P.Z = A == 0; - P.S = A > 0x7F; + P.bits.Z = A == 0; + P.bits.S = A > 0x7F; ticks += 4; break; case 0xFE : // ABX INC - address = readMem(PC); + address = mmu->readMem(PC); PC++; - address |= readMem(PC) << 8; + address |= mmu->readMem(PC) << 8; PC++; address += X; - value8 = readMem(address); + value8 = mmu->readMem(address); value8++; - writeMem(address, value8); - P.Z = value8 == 0; - P.S = value8 > 0x7F; + mmu->writeMem(address, value8); + P.bits.Z = value8 == 0; + P.bits.S = value8 > 0x7F; ticks += 7; break; case 0xFF : // ZPR BBS - value8 = readMem(readMem(PC)); + value8 = mmu->readMem(mmu->readMem(PC)); PC++; - address = readMem(PC); + address = mmu->readMem(PC); PC++; if (address & SIGN) address |= 0xFF00; // jump backward @@ -2565,249 +2559,81 @@ uint16_t puce65c02::exec(unsigned long long int cycleCount) { } +// utilities // to be moved into gui ?? -//============================================================================== -// Everything down below are optionnal utilities used during devellopment -// mostly using Klaus Dormann's functonnal tests published at -// https://github.com/Klaus2m5/6502_65C02_functional_tests -// but also BigEd's timing tests code published at -// https://github.com/BigEd/6502timing -// and http://forum.6502.org/viewtopic.php?f=8&t=3340 -// -// for functionnal tests : -// g++ -Wall -O3 -D __TESTS__ puce65c02.cpp -o puce65c02 && ./puce65c02 -// or, for detailled info -// g++ -Wall -O3 -D __TESTS__ -D VERBOSE puce65c02.cpp -o puce65c02 && ./puce65c02 -// or, if you want to check the cycle accuracy : -// g++ -Wall -O3 -D __TESTS__ -D TIMING puce65c02.cpp -o puce65c02 && ./puce65c02 -// and see bottom of file for more info +#include +static const char* mn[256] = { + "BRK","ORA","NOP","NOP","TSB","ORA","ASL","RMB","PHP","ORA","ASL","NOP","TSB","ORA","ASL","BBR", + "BPL","ORA","ORA","NOP","TRB","ORA","ASL","RMB","CLC","ORA","INC","NOP","TRB","ORA","ASL","BBR", + "JSR","AND","NOP","NOP","BIT","AND","ROL","RMB","PLP","AND","ROL","NOP","BIT","AND","ROL","BBR", + "BMI","AND","AND","NOP","BIT","AND","ROL","RMB","SEC","AND","DEC","NOP","BIT","AND","ROL","BBR", + "RTI","EOR","NOP","NOP","NOP","EOR","LSR","RMB","PHA","EOR","LSR","NOP","JMP","EOR","LSR","BBR", + "BVC","EOR","EOR","NOP","NOP","EOR","LSR","RMB","CLI","EOR","PHY","NOP","NOP","EOR","LSR","BBR", + "RTS","ADC","NOP","NOP","STZ","ADC","ROR","RMB","PLA","ADC","ROR","NOP","JMP","ADC","ROR","BBR", + "BVS","ADC","ADC","NOP","STZ","ADC","ROR","RMB","SEI","ADC","PLY","NOP","JMP","ADC","ROR","BBR", + "BRA","STA","NOP","NOP","STY","STA","STX","SMB","DEY","BIT","TXA","NOP","STY","STA","STX","BBS", + "BCC","STA","STA","NOP","STY","STA","STX","SMB","TYA","STA","TXS","NOP","STZ","STA","STZ","BBS", + "LDY","LDA","LDX","NOP","LDY","LDA","LDX","SMB","TAY","LDA","TAX","NOP","LDY","LDA","LDX","BBS", + "BCS","LDA","LDA","NOP","LDY","LDA","LDX","SMB","CLV","LDA","TSX","NOP","LDY","LDA","LDX","BBS", + "CPY","CMP","NOP","NOP","CPY","CMP","DEC","SMB","INY","CMP","DEX","WAI","CPY","CMP","DEC","BBS", + "BNE","CMP","CMP","NOP","NOP","CMP","DEC","SMB","CLD","CMP","PHX","STP","NOP","CMP","DEC","BBS", + "CPX","SBC","NOP","NOP","CPX","SBC","INC","SMB","INX","SBC","NOP","NOP","CPX","SBC","INC","BBS", + "BEQ","SBC","SBC","NOP","NOP","SBC","INC","SMB","SED","SBC","PLX","NOP","NOP","SBC","INC","BBS" +}; -#if __TESTS__ - #include +static const int am[256] = { + 0x0 , 0xC , 0x2 , 0x0 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x2 , 0x1 , 0x0 , 0x7 , 0x7 , 0x7 , 0xE, + 0x6 , 0xD , 0xB , 0x0 , 0x3 , 0x4 , 0x4 , 0x3 , 0x0 , 0x9 , 0x1 , 0x0 , 0x7 , 0x8 , 0x8 , 0xE, + 0x7 , 0xC , 0x2 , 0x0 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x2 , 0x1 , 0x0 , 0x7 , 0x7 , 0x7 , 0xE, + 0x6 , 0xD , 0xB , 0x0 , 0x4 , 0x4 , 0x4 , 0x3 , 0x0 , 0x9 , 0x1 , 0x0 , 0x8 , 0x8 , 0x8 , 0xE, + 0x0 , 0xC , 0x2 , 0x0 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x2 , 0x1 , 0x0 , 0x7 , 0x7 , 0x7 , 0xE, + 0x6 , 0xD , 0xB , 0x0 , 0x4 , 0x4 , 0x4 , 0x3 , 0x0 , 0x9 , 0x0 , 0x0 , 0x7 , 0x8 , 0x8 , 0xE, + 0x0 , 0xC , 0x2 , 0x0 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x2 , 0x1 , 0x0 , 0xA , 0x7 , 0x7 , 0xE, + 0x6 , 0xD , 0xB , 0x0 , 0x4 , 0x4 , 0x4 , 0x3 , 0x0 , 0x9 , 0x0 , 0x0 , 0xF , 0x8 , 0x8 , 0xE, + 0x6 , 0xC , 0x2 , 0x0 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x2 , 0x0 , 0x0 , 0x7 , 0x7 , 0x7 , 0xE, + 0x6 , 0xD , 0xB , 0x0 , 0x4 , 0x4 , 0x5 , 0x3 , 0x0 , 0x9 , 0x0 , 0x0 , 0x7 , 0x8 , 0x8 , 0xE, + 0x2 , 0xC , 0x2 , 0x0 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x2 , 0x0 , 0x0 , 0x7 , 0x7 , 0x7 , 0xE, + 0x6 , 0xD , 0xB , 0x0 , 0x4 , 0x4 , 0x5 , 0x3 , 0x0 , 0x9 , 0x0 , 0x0 , 0x8 , 0x8 , 0x9 , 0xE, + 0x2 , 0xC , 0x2 , 0x0 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x2 , 0x0 , 0x0 , 0x7 , 0x7 , 0x7 , 0xE, + 0x6 , 0xD , 0xB , 0x0 , 0x4 , 0x4 , 0x4 , 0x3 , 0x0 , 0x9 , 0x0 , 0x0 , 0x7 , 0x8 , 0x8 , 0xE, + 0x2 , 0xC , 0x2 , 0x0 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x2 , 0x0 , 0x0 , 0x7 , 0x7 , 0x7 , 0xE, + 0x6 , 0xD , 0xB , 0x0 , 0x4 , 0x4 , 0x4 , 0x3 , 0x0 , 0x9 , 0x0 , 0x0 , 0x7 , 0x8 , 0x8 , 0xE + }; - static const char* mn[256] = { - "BRK","ORA","NOP","NOP","TSB","ORA","ASL","RMB","PHP","ORA","ASL","NOP","TSB","ORA","ASL","BBR", - "BPL","ORA","ORA","NOP","TRB","ORA","ASL","RMB","CLC","ORA","INC","NOP","TRB","ORA","ASL","BBR", - "JSR","AND","NOP","NOP","BIT","AND","ROL","RMB","PLP","AND","ROL","NOP","BIT","AND","ROL","BBR", - "BMI","AND","AND","NOP","BIT","AND","ROL","RMB","SEC","AND","DEC","NOP","BIT","AND","ROL","BBR", - "RTI","EOR","NOP","NOP","NOP","EOR","LSR","RMB","PHA","EOR","LSR","NOP","JMP","EOR","LSR","BBR", - "BVC","EOR","EOR","NOP","NOP","EOR","LSR","RMB","CLI","EOR","PHY","NOP","NOP","EOR","LSR","BBR", - "RTS","ADC","NOP","NOP","STZ","ADC","ROR","RMB","PLA","ADC","ROR","NOP","JMP","ADC","ROR","BBR", - "BVS","ADC","ADC","NOP","STZ","ADC","ROR","RMB","SEI","ADC","PLY","NOP","JMP","ADC","ROR","BBR", - "BRA","STA","NOP","NOP","STY","STA","STX","SMB","DEY","BIT","TXA","NOP","STY","STA","STX","BBS", - "BCC","STA","STA","NOP","STY","STA","STX","SMB","TYA","STA","TXS","NOP","STZ","STA","STZ","BBS", - "LDY","LDA","LDX","NOP","LDY","LDA","LDX","SMB","TAY","LDA","TAX","NOP","LDY","LDA","LDX","BBS", - "BCS","LDA","LDA","NOP","LDY","LDA","LDX","SMB","CLV","LDA","TSX","NOP","LDY","LDA","LDX","BBS", - "CPY","CMP","NOP","NOP","CPY","CMP","DEC","SMB","INY","CMP","DEX","WAI","CPY","CMP","DEC","BBS", - "BNE","CMP","CMP","NOP","NOP","CMP","DEC","SMB","CLD","CMP","PHX","STP","NOP","CMP","DEC","BBS", - "CPX","SBC","NOP","NOP","CPX","SBC","INC","SMB","INX","SBC","NOP","NOP","CPX","SBC","INC","BBS", - "BEQ","SBC","SBC","NOP","NOP","SBC","INC","SMB","SED","SBC","PLX","NOP","NOP","SBC","INC","BBS" - }; +int puce65c02::getCode(uint16_t address, char* buffer, int size, int numLines) { + int consumed = 0; - static const int am[256] = { - 0x0 , 0xC , 0x2 , 0x0 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x2 , 0x1 , 0x0 , 0x7 , 0x7 , 0x7 , 0xE , - 0x6 , 0xD , 0xB , 0x0 , 0x3 , 0x4 , 0x4 , 0x3 , 0x0 , 0x9 , 0x1 , 0x0 , 0x7 , 0x8 , 0x8 , 0xE , - 0x7 , 0xC , 0x2 , 0x0 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x2 , 0x1 , 0x0 , 0x7 , 0x7 , 0x7 , 0xE , - 0x6 , 0xD , 0xB , 0x0 , 0x4 , 0x4 , 0x4 , 0x3 , 0x0 , 0x9 , 0x1 , 0x0 , 0x8 , 0x8 , 0x8 , 0xE , - 0x0 , 0xC , 0x2 , 0x0 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x2 , 0x1 , 0x0 , 0x7 , 0x7 , 0x7 , 0xE , - 0x6 , 0xD , 0xB , 0x0 , 0x4 , 0x4 , 0x4 , 0x3 , 0x0 , 0x9 , 0x0 , 0x0 , 0x7 , 0x8 , 0x8 , 0xE , - 0x0 , 0xC , 0x2 , 0x0 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x2 , 0x1 , 0x0 , 0xA , 0x7 , 0x7 , 0xE , - 0x6 , 0xD , 0xB , 0x0 , 0x4 , 0x4 , 0x4 , 0x3 , 0x0 , 0x9 , 0x0 , 0x0 , 0xF , 0x8 , 0x8 , 0xE , - 0x6 , 0xC , 0x2 , 0x0 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x2 , 0x0 , 0x0 , 0x7 , 0x7 , 0x7 , 0xE , - 0x6 , 0xD , 0xB , 0x0 , 0x4 , 0x4 , 0x5 , 0x3 , 0x0 , 0x9 , 0x0 , 0x0 , 0x7 , 0x8 , 0x8 , 0xE , - 0x2 , 0xC , 0x2 , 0x0 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x2 , 0x0 , 0x0 , 0x7 , 0x7 , 0x7 , 0xE , - 0x6 , 0xD , 0xB , 0x0 , 0x4 , 0x4 , 0x5 , 0x3 , 0x0 , 0x9 , 0x0 , 0x0 , 0x8 , 0x8 , 0x9 , 0xE , - 0x2 , 0xC , 0x2 , 0x0 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x2 , 0x0 , 0x0 , 0x7 , 0x7 , 0x7 , 0xE , - 0x6 , 0xD , 0xB , 0x0 , 0x4 , 0x4 , 0x4 , 0x3 , 0x0 , 0x9 , 0x0 , 0x0 , 0x7 , 0x8 , 0x8 , 0xE , - 0x2 , 0xC , 0x2 , 0x0 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x2 , 0x0 , 0x0 , 0x7 , 0x7 , 0x7 , 0xE , - 0x6 , 0xD , 0xB , 0x0 , 0x4 , 0x4 , 0x4 , 0x3 , 0x0 , 0x9 , 0x0 , 0x0 , 0x7 , 0x8 , 0x8 , 0xE - }; - - void puce65c02::dasm(uint16_t address) { // TODO : give the bit# for BBR, BSS, RMB and SMB - uint8_t op = readMem(address); - uint8_t b1 = readMem((address + 1) & 0xFFFF); - uint8_t b2 = readMem((address + 2) & 0xFFFF); - printf("%04X %02X ", address, op); - switch(am[op]) { - case 0x0: printf(" %s ", mn[op] ); break; // implied - case 0x1: printf(" %s A ", mn[op] ); break; // accumulator - case 0x2: printf("%02X %s #$%02X ", b1, mn[op],b1 ); break; // immediate - case 0x3: printf("%02X %s $%02X ", b1, mn[op],b1 ); break; // zero page - case 0x4: printf("%02X %s $%02X,X ", b1, mn[op],b1 ); break; // zero page, X indexed - case 0x5: printf("%02X %s $%02X,Y ", b1, mn[op],b1 ); break; // zero page, Y indexed - case 0x6: printf("%02X %s $%02X ", b1, mn[op],b1 ); break; // relative - case 0xB: printf("%02X %s ($%02X) ", b1, mn[op],b1 ); break; // izp ($00) - case 0xC: printf("%02X %s ($%02X,X) ", b1, mn[op],b1 ); break; // X indexed, indirect - case 0xD: printf("%02X %s ($%02X),Y ", b1, mn[op],b1 ); break; // indirect, Y indexed - case 0x7: printf("%02X%02X %s $%02X%02X ",b1,b2,mn[op],b2,b1); break; // absolute - case 0x8: printf("%02X%02X %s $%02X%02X,X ",b1,b2,mn[op],b2,b1); break; // absolute, X indexed - case 0x9: printf("%02X%02X %s $%02X%02X,Y ",b1,b2,mn[op],b2,b1); break; // absolute, Y indexed - case 0xA: printf("%02X%02X %s ($%02X%02X) ",b1,b2,mn[op],b2,b1); break; // indirect - case 0xF: printf("%02X%02X %s ($%02X%02X,X)",b1,b2,mn[op],b2,b1); break; // iax ($0000,X) - case 0xE: printf("%02X%02X %s $%02X,$%02X ",b1,b2,mn[op],b2,b1); break; // zpr $00,$00 - } - return; + for (int i=0; ireadMem(address); + uint8_t b1 = mmu->readMem((address + 1) & 0xFFFF); + uint8_t b2 = mmu->readMem((address + 2) & 0xFFFF); + consumed += snprintf(buffer + consumed, size - consumed, "%04X %02X ", address, op); + switch(am[op]) { + case 0x0: consumed += snprintf(buffer + consumed, size - consumed, " %s ", mn[op] ); address+=1; break; // implied + case 0x1: consumed += snprintf(buffer + consumed, size - consumed, " %s A ", mn[op] ); address+=1; break; // accumulator + case 0x2: consumed += snprintf(buffer + consumed, size - consumed, "%02X %s #$%02X ", b1, mn[op],b1 ); address+=2; break; // immediate + case 0x3: consumed += snprintf(buffer + consumed, size - consumed, "%02X %s $%02X ", b1, mn[op],b1 ); address+=2; break; // zero page + case 0x4: consumed += snprintf(buffer + consumed, size - consumed, "%02X %s $%02X,X ", b1, mn[op],b1 ); address+=2; break; // zero page, X indexed + case 0x5: consumed += snprintf(buffer + consumed, size - consumed, "%02X %s $%02X,Y ", b1, mn[op],b1 ); address+=2; break; // zero page, Y indexed + case 0x6: consumed += snprintf(buffer + consumed, size - consumed, "%02X %s $%02X ", b1, mn[op],b1 ); address+=2; break; // relative + case 0xB: consumed += snprintf(buffer + consumed, size - consumed, "%02X %s ($%02X) ", b1, mn[op],b1 ); address+=2; break; // izp ($00) + case 0xC: consumed += snprintf(buffer + consumed, size - consumed, "%02X %s ($%02X,X) ", b1, mn[op],b1 ); address+=2; break; // X indexed, indirect + case 0xD: consumed += snprintf(buffer + consumed, size - consumed, "%02X %s ($%02X),Y ", b1, mn[op],b1 ); address+=2; break; // indirect, Y indexed + case 0x7: consumed += snprintf(buffer + consumed, size - consumed, "%02X%02X %s $%02X%02X ",b1,b2,mn[op],b2,b1); address+=3; break; // absolute + case 0x8: consumed += snprintf(buffer + consumed, size - consumed, "%02X%02X %s $%02X%02X,X ",b1,b2,mn[op],b2,b1); address+=3; break; // absolute, X indexed + case 0x9: consumed += snprintf(buffer + consumed, size - consumed, "%02X%02X %s $%02X%02X,Y ",b1,b2,mn[op],b2,b1); address+=3; break; // absolute, Y indexed + case 0xA: consumed += snprintf(buffer + consumed, size - consumed, "%02X%02X %s ($%02X%02X) ",b1,b2,mn[op],b2,b1); address+=3; break; // indirect + case 0xF: consumed += snprintf(buffer + consumed, size - consumed, "%02X%02X %s ($%02X%02X,X)",b1,b2,mn[op],b2,b1); address+=3; break; // iax ($0000,X) + case 0xE: consumed += snprintf(buffer + consumed, size - consumed, "%02X%02X %s $%02X,$%02X ",b1,b2,mn[op],b2,b1); address+=3; break; // zpr $00,$00 } + consumed += snprintf(buffer + consumed, size - consumed, "\n"); + } + return consumed; +} - - int puce65c02::getCode(uint16_t address, char* buffer, int size, int numLines) { - int consumed = 0; - int remaining = size; - - for (int i=0; iticks = 0; // we won't measure the 7 ticks the RESET took above - unsigned long long int oldticks = cpu->ticks; - - do { - cpu->dasm(cpu->PC); - printf(" "); - cpu->exec(1); - cpu->printRegs(); - printf(" Cycles: %llu Total: %llu\n", cpu->ticks - oldticks, cpu->ticks); - - oldticks = cpu->ticks; - } while(cpu->ticks < 1143); - -#else - // Running the two functionnal tests : - const char *filename = "6502_functional_test.bin"; - FILE *f = fopen(filename, "rb"); - if (!f || fread(RAM, 1, 65536, f) != 65536) { - printf("ERROR : can't load Klaus Dormann's functonnal tests binary file %s\n", filename); - return(0); - } - fclose(f); - - puce65c02 *cpu = new puce65c02(0x400); // instantiate, reset the cpu and set PC to 0x400 - -#if VERBOSE - unsigned long long int oldticks = cpu->ticks; -#endif - - uint16_t oldPC = 0x400, newPC = 0x400; // to detect loops (BNE $FE) when error occurs - - while(newPC != 0x3469) { - -#if VERBOSE - cpu->dasm(newPC); - printf(" "); -#endif - - newPC = cpu->exec(1); - -#if VERBOSE - cpu->printRegs(); - printf(" Cycles: %llu Total: %llu\n", cpu->ticks - oldticks, cpu->ticks); - oldticks = cpu->ticks; -#endif - - if (newPC == oldPC ) { - printf("\n\nLoop detected @ %04X - Press ENTER to proceed with next test or CTRL to abort\n\n", newPC); - getchar(); - cpu->setPC(newPC + 2); // step out the loop - } - oldPC = newPC; - } - printf("\nSUCCESS : Reached end of 6502_functional_test @ 0x3469 after %llu clock cycles\n", cpu->ticks); - - - const char *filename2 = "65C02_extended_opcodes_test.bin"; - f = fopen(filename2, "rb"); - if (!f || fread(RAM, 1, 65536, f) != 65536) { - printf("ERROR : can't load 65c02 Klaus Dormann's functonnal tests binary file %s\n", filename2); - return(0); - } - fclose(f); - - cpu->RST(); - cpu->setPC(0x400); - oldPC = newPC = 0x400; -#if VERBOSE - oldticks = cpu->ticks; -#endif - - while(newPC != 0x24f1) { -#if VERBOSE - cpu->dasm(newPC); - printf(" "); -#endif - newPC = cpu->exec(1); -#if VERBOSE - cpu->printRegs(); - printf(" Cycles: %llu Total: %llu\n", cpu->ticks - oldticks, cpu->ticks); - oldticks = cpu->ticks; -#endif - if (newPC == oldPC ) { - printf("\n\nLoop detected @ %04X - Press ENTER to proceed with next test or CTRL to abort\n\n", newPC); - getchar(); - cpu->setPC(newPC + 2); // step out the loop - } - oldPC = newPC; - } - printf("\nSUCCESS : Reached end of 65C02_extended_opcodes_test @ 0x24f1 after %llu clock cycles\n", cpu->ticks); - -#endif - return(0); - } -#endif +int puce65c02::getRegs(char* buffer) { + return (snprintf(buffer, 100, "A=%02X X=%02X Y=%02X S=%02X *S=%02X\nPC=%04X P=%c%c%c%c%c%c%c%c", \ + A, X, Y, SP, mmu->readMem(0x100 + SP), PC, \ + P.bits.S?'N':'-', P.bits.V?'V':'-', P.bits.U?'U':'.', P.bits.B?'B':'-', P.bits.D?'D':'-', P.bits.I?'I':'-', P.bits.Z?'Z':'-', P.bits.C?'C':'-')); +} diff --git a/puce65c02.h b/puce65c02.h index 9a0141f..f4f5f0e 100644 --- a/puce65c02.h +++ b/puce65c02.h @@ -1,5 +1,6 @@ /* puce65c02, a WDC 65c02 cpu emulator, based on puce6502 by the same author + Last modified 1st of July 2021 Copyright (c) 2021 Arthur Ferreira (arthur.ferreira2@gmail.com) @@ -9,7 +10,7 @@ in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions : + furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. @@ -23,12 +24,17 @@ THE SOFTWARE. */ +/* + This version is slightly modified for reinette IIe, a french Apple IIe + emulator using SDL2 (https://github.com/ArthurFerreira2/reinette-IIe). + Please download the latest version from + https://github.com/ArthurFerreira2/puce65c02 +*/ + #ifndef _PUCE65C02_H #define _PUCE65C02_H -#include - typedef enum {run, step, stop, wait} status; #define CARRY 0x01 @@ -40,49 +46,45 @@ typedef enum {run, step, stop, wait} status; #define OFLOW 0x40 #define SIGN 0x80 +typedef struct Pbits_t { + uint8_t C : 1; // Carry + uint8_t Z : 1; // Zero + uint8_t I : 1; // Interupt disabled + uint8_t D : 1; // Decimal + uint8_t B : 1; // Break + uint8_t U : 1; // Undefined + uint8_t V : 1; // Overflow + uint8_t S : 1; // Sign +} Pbits; + class puce65c02 { -public: - - unsigned long long int ticks; -// private: - status state; - uint16_t PC; // Program Counter - uint8_t A, X, Y, SP; // Accumulator, X and y indexes and Stack Pointer +private: + uint16_t PC; // Program Counter + uint8_t A, X, Y, SP; // Accumulator, X and y indexes and Stack Pointer union { uint8_t byte; - struct { - uint8_t C : 1; // Carry - uint8_t Z : 1; // Zero - uint8_t I : 1; // Interupt disabled - uint8_t D : 1; // Decimal - uint8_t B : 1; // Break - uint8_t U : 1; // Undefined - uint8_t V : 1; // Overflow - uint8_t S : 1; // Sign - }; - } P; // Processor Status + Pbits bits; + } P; // Processor Status public: - puce65c02() { ticks = 0; RST(); } - puce65c02(uint16_t address) { ticks = 0; RST(); PC = address; } - ~puce65c02(); + unsigned long long int ticks; - uint16_t getPC() { return PC; }; - void setPC(uint16_t address) { PC = address; }; + status state; + + puce65c02(); + ~puce65c02(); void RST(); void IRQ(); void NMI(); uint16_t exec(unsigned long long int cycleCount); -#if __TESTS__ - void dasm(uint16_t address); - void printRegs(); + uint16_t getPC(); + void setPC(uint16_t address); + int getRegs(char* buffer); int getCode(uint16_t address, char* buffer, int size, int numLines); -#endif - }; #endif diff --git a/video.cpp b/video.cpp index 0a7544c..721bb2c 100644 --- a/video.cpp +++ b/video.cpp @@ -209,10 +209,10 @@ void Video::update() { }; const uint32_t hcolor[16] = { // the high res colors (light & dark levels) - 0xFF000000, 0xFF31C090, 0xFFAD6E7E, 0xFFFFFFFF, - 0xFF000000, 0xFF156CEA, 0xFFE4A856, 0xFFFFFFFF, - 0xFF000000, 0xFF56373f, 0xFF196048, 0xFFFFFFFF, - 0xFF000000, 0xFF72542B, 0xFF0A3675, 0xFFFFFFFF + 0xFF000000, 0xFF31C090, 0xFFAD6E7E, 0xFFFFFFFF, + 0xFF000000, 0xFF156CEA, 0xFFE4A856, 0xFFFFFFFF, + 0xFF000000, 0xFF56373f, 0xFF196048, 0xFFFFFFFF, + 0xFF000000, 0xFF72542B, 0xFF0A3675, 0xFFFFFFFF }; const uint32_t dhcolor[16] = { @@ -223,99 +223,99 @@ void Video::update() { }; const uint16_t offsetGR[24] = { // base addresses for each line in TEXT or GR - 0x000, 0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380, // lines 0-7 - 0x028, 0x0A8, 0x128, 0x1A8, 0x228, 0x2A8, 0x328, 0x3A8, // lines 8-15 - 0x050, 0x0D0, 0x150, 0x1D0, 0x250, 0x2D0, 0x350, 0x3D0 // lines 16-23 + 0x000, 0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380, // lines 0-7 + 0x028, 0x0A8, 0x128, 0x1A8, 0x228, 0x2A8, 0x328, 0x3A8, // lines 8-15 + 0x050, 0x0D0, 0x150, 0x1D0, 0x250, 0x2D0, 0x350, 0x3D0 // lines 16-23 }; const uint16_t offsetHGR[192] = { // base addresses for each line in HGR - 0x0000, 0x0400, 0x0800, 0x0C00, 0x1000, 0x1400, 0x1800, 0x1C00, // lines 0-7 - 0x0080, 0x0480, 0x0880, 0x0C80, 0x1080, 0x1480, 0x1880, 0x1C80, // lines 8-15 - 0x0100, 0x0500, 0x0900, 0x0D00, 0x1100, 0x1500, 0x1900, 0x1D00, // lines 16-23 - 0x0180, 0x0580, 0x0980, 0x0D80, 0x1180, 0x1580, 0x1980, 0x1D80, - 0x0200, 0x0600, 0x0A00, 0x0E00, 0x1200, 0x1600, 0x1A00, 0x1E00, - 0x0280, 0x0680, 0x0A80, 0x0E80, 0x1280, 0x1680, 0x1A80, 0x1E80, - 0x0300, 0x0700, 0x0B00, 0x0F00, 0x1300, 0x1700, 0x1B00, 0x1F00, - 0x0380, 0x0780, 0x0B80, 0x0F80, 0x1380, 0x1780, 0x1B80, 0x1F80, - 0x0028, 0x0428, 0x0828, 0x0C28, 0x1028, 0x1428, 0x1828, 0x1C28, - 0x00A8, 0x04A8, 0x08A8, 0x0CA8, 0x10A8, 0x14A8, 0x18A8, 0x1CA8, - 0x0128, 0x0528, 0x0928, 0x0D28, 0x1128, 0x1528, 0x1928, 0x1D28, - 0x01A8, 0x05A8, 0x09A8, 0x0DA8, 0x11A8, 0x15A8, 0x19A8, 0x1DA8, - 0x0228, 0x0628, 0x0A28, 0x0E28, 0x1228, 0x1628, 0x1A28, 0x1E28, - 0x02A8, 0x06A8, 0x0AA8, 0x0EA8, 0x12A8, 0x16A8, 0x1AA8, 0x1EA8, - 0x0328, 0x0728, 0x0B28, 0x0F28, 0x1328, 0x1728, 0x1B28, 0x1F28, - 0x03A8, 0x07A8, 0x0BA8, 0x0FA8, 0x13A8, 0x17A8, 0x1BA8, 0x1FA8, - 0x0050, 0x0450, 0x0850, 0x0C50, 0x1050, 0x1450, 0x1850, 0x1C50, - 0x00D0, 0x04D0, 0x08D0, 0x0CD0, 0x10D0, 0x14D0, 0x18D0, 0x1CD0, - 0x0150, 0x0550, 0x0950, 0x0D50, 0x1150, 0x1550, 0x1950, 0x1D50, - 0x01D0, 0x05D0, 0x09D0, 0x0DD0, 0x11D0, 0x15D0, 0x19D0, 0x1DD0, - 0x0250, 0x0650, 0x0A50, 0x0E50, 0x1250, 0x1650, 0x1A50, 0x1E50, - 0x02D0, 0x06D0, 0x0AD0, 0x0ED0, 0x12D0, 0x16D0, 0x1AD0, 0x1ED0, // lines 168-183 - 0x0350, 0x0750, 0x0B50, 0x0F50, 0x1350, 0x1750, 0x1B50, 0x1F50, // lines 176-183 - 0x03D0, 0x07D0, 0x0BD0, 0x0FD0, 0x13D0, 0x17D0, 0x1BD0, 0x1FD0 // lines 184-191 + 0x0000, 0x0400, 0x0800, 0x0C00, 0x1000, 0x1400, 0x1800, 0x1C00, // lines 0-7 + 0x0080, 0x0480, 0x0880, 0x0C80, 0x1080, 0x1480, 0x1880, 0x1C80, // lines 8-15 + 0x0100, 0x0500, 0x0900, 0x0D00, 0x1100, 0x1500, 0x1900, 0x1D00, // lines 16-23 + 0x0180, 0x0580, 0x0980, 0x0D80, 0x1180, 0x1580, 0x1980, 0x1D80, + 0x0200, 0x0600, 0x0A00, 0x0E00, 0x1200, 0x1600, 0x1A00, 0x1E00, + 0x0280, 0x0680, 0x0A80, 0x0E80, 0x1280, 0x1680, 0x1A80, 0x1E80, + 0x0300, 0x0700, 0x0B00, 0x0F00, 0x1300, 0x1700, 0x1B00, 0x1F00, + 0x0380, 0x0780, 0x0B80, 0x0F80, 0x1380, 0x1780, 0x1B80, 0x1F80, + 0x0028, 0x0428, 0x0828, 0x0C28, 0x1028, 0x1428, 0x1828, 0x1C28, + 0x00A8, 0x04A8, 0x08A8, 0x0CA8, 0x10A8, 0x14A8, 0x18A8, 0x1CA8, + 0x0128, 0x0528, 0x0928, 0x0D28, 0x1128, 0x1528, 0x1928, 0x1D28, + 0x01A8, 0x05A8, 0x09A8, 0x0DA8, 0x11A8, 0x15A8, 0x19A8, 0x1DA8, + 0x0228, 0x0628, 0x0A28, 0x0E28, 0x1228, 0x1628, 0x1A28, 0x1E28, + 0x02A8, 0x06A8, 0x0AA8, 0x0EA8, 0x12A8, 0x16A8, 0x1AA8, 0x1EA8, + 0x0328, 0x0728, 0x0B28, 0x0F28, 0x1328, 0x1728, 0x1B28, 0x1F28, + 0x03A8, 0x07A8, 0x0BA8, 0x0FA8, 0x13A8, 0x17A8, 0x1BA8, 0x1FA8, + 0x0050, 0x0450, 0x0850, 0x0C50, 0x1050, 0x1450, 0x1850, 0x1C50, + 0x00D0, 0x04D0, 0x08D0, 0x0CD0, 0x10D0, 0x14D0, 0x18D0, 0x1CD0, + 0x0150, 0x0550, 0x0950, 0x0D50, 0x1150, 0x1550, 0x1950, 0x1D50, + 0x01D0, 0x05D0, 0x09D0, 0x0DD0, 0x11D0, 0x15D0, 0x19D0, 0x1DD0, + 0x0250, 0x0650, 0x0A50, 0x0E50, 0x1250, 0x1650, 0x1A50, 0x1E50, + 0x02D0, 0x06D0, 0x0AD0, 0x0ED0, 0x12D0, 0x16D0, 0x1AD0, 0x1ED0, // lines 168-183 + 0x0350, 0x0750, 0x0B50, 0x0F50, 0x1350, 0x1750, 0x1B50, 0x1F50, // lines 176-183 + 0x03D0, 0x07D0, 0x0BD0, 0x0FD0, 0x13D0, 0x17D0, 0x1BD0, 0x1FD0 // lines 184-191 }; // HIGH RES GRAPHICS - if (!mmu->TEXT && mmu->HIRES && !mmu->DHIRES) { + if (!mmu->TEXT && mmu->HIRES && !mmu->DHIRES) { gfxmode = 40; uint8_t colorIdx; // index to the color array - uint16_t word; - uint8_t bits[16], bit, pbit, colorSet, even; + uint16_t word; + uint8_t bits[16], bit, pbit, colorSet, even; int vRamBase = 0x2000 + mmu->PAGE2 * 0x2000; - int endRaw = mmu->MIXED ? 160 : 192; + int endRaw = mmu->MIXED ? 160 : 192; - for (int line = 0; line < endRaw; line++) { // for every line - for (int col = 0; col < 40; col += 2) { // for every 7 horizontal dots - word = (uint16_t)(mmu->ram[vRamBase + offsetHGR[line] + col + 1]) << 8; // store the two next bytes into 'word' - word += mmu->ram[vRamBase + offsetHGR[line] + col]; // in reverse order + for (int line = 0; line < endRaw; line++) { // for every line + for (int col = 0; col < 40; col += 2) { // for every 7 horizontal dots + word = (uint16_t)(mmu->ram[vRamBase + offsetHGR[line] + col + 1]) << 8; // store the two next bytes into 'word' + word += mmu->ram[vRamBase + offsetHGR[line] + col]; // in reverse order - if (previousDots[line][col] != word) { // check if this group of 7 dots need a redraw + if (previousDots[line][col] != word) { // check if this group of 7 dots need a redraw - int x = col * 7; - even = 0; + int x = col * 7; + even = 0; - for (bit = 0; bit < 16; bit++) // store all bits 'word' into 'bits' - bits[bit] = (word >> bit) & 1; - colorSet = bits[7] * 4; // select the right color set - pbit = previousBit[line][col]; // the bit value of the left dot - bit = 0; // starting at 1st bit of 1st byte + for (bit = 0; bit < 16; bit++) // store all bits 'word' into 'bits' + bits[bit] = (word >> bit) & 1; + colorSet = bits[7] * 4; // select the right color set + pbit = previousBit[line][col]; // the bit value of the left dot + bit = 0; // starting at 1st bit of 1st byte - while (bit < 15) { // until we reach bit7 of 2nd byte - if (bit == 7) { // moving into the second byte - colorSet = bits[15] * 4; // update the color set - bit++; // skip bit 7 - } + while (bit < 15) { // until we reach bit7 of 2nd byte + if (bit == 7) { // moving into the second byte + colorSet = bits[15] * 4; // update the color set + bit++; // skip bit 7 + } colorIdx = even + colorSet + (bits[bit] << 1) + (pbit); screenPixels[line * 280 + x] = hcolor[colorIdx]; - x++; - pbit = bits[bit++]; // proceed to the next pixel - even = even ? 0 : 8; // one pixel every two is darker - } + x++; + pbit = bits[bit++]; // proceed to the next pixel + even = even ? 0 : 8; // one pixel every two is darker + } - previousDots[line][col] = word; // update the video cache - if ((col < 37) && (previousBit[line][col + 2] != pbit)) { // check color franging effect on the dot after - previousBit[line][col + 2] = pbit; // set pbit and clear the - previousDots[line][col + 2] = -1; // video cache for next dot - } - } // if (previousDots[line][col] ... - } - } - } + previousDots[line][col] = word; // update the video cache + if ((col < 37) && (previousBit[line][col + 2] != pbit)) { // check color franging effect on the dot after + previousBit[line][col + 2] = pbit; // set pbit and clear the + previousDots[line][col + 2] = -1; // video cache for next dot + } + } // if (previousDots[line][col] ... + } + } + } // DOUBLE HIGH RES GRAPHICS - else if (!mmu->TEXT && mmu->HIRES && mmu->DHIRES) { + else if (!mmu->TEXT && mmu->HIRES && mmu->DHIRES) { gfxmode = 80; // int vRamBase = 0x2000 + PAGE2 * 0x2000; int vRamBase = mmu->STORE80 ? 0x2000 : mmu->PAGE2 * 0x2000 + 0x2000; // TODO : CHECK THIS ! - int endRaw = mmu->MIXED ? 160 : 192; + int endRaw = mmu->MIXED ? 160 : 192; uint32_t color; uint32_t dword; - for (int line = 0; line < endRaw; line++) { - for (int col = 0, x = 0; col < 39; col+=2) { + for (int line = 0; line < endRaw; line++) { + for (int col = 0, x = 0; col < 39; col+=2) { int address = vRamBase + offsetHGR[line] + col; @@ -336,55 +336,55 @@ void Video::update() { screenPixels80[offset2 + x] = color; } } - } + } } - } + } - // lOW RES GRAPHICS - else if (!mmu->TEXT && !mmu->HIRES && !mmu->DHIRES) { // and not in HIRES + // lOW RES GRAPHICS + else if (!mmu->TEXT && !mmu->HIRES && !mmu->DHIRES) { // and not in HIRES gfxmode = 40; - int vRamBase = mmu->PAGE2 * 0x0400 + 0x400; - int endRaw = mmu->MIXED ? 20 : 24; + int vRamBase = mmu->PAGE2 * 0x0400 + 0x400; + int endRaw = mmu->MIXED ? 20 : 24; uint32_t color; - for (int col = 0; col < 40; col++) { // for each column - int x = col * 7; - for (int line = 0; line < endRaw; line++) { // for each row + for (int col = 0; col < 40; col++) { // for each column + int x = col * 7; + for (int line = 0; line < endRaw; line++) { // for each row - glyph = mmu->ram[vRamBase + offsetGR[line] + col]; // read video memory + glyph = mmu->ram[vRamBase + offsetGR[line] + col]; // read video memory if (previousBlocks[line][col] != glyph) { // check if this block need a redraw previousBlocks[line][col] = glyph; int y = line * 8; // first block - color = lcolor[glyph & 0x0F]; // first nibble + color = lcolor[glyph & 0x0F]; // first nibble for (int a=0; a<7; a++) for (int b=0; b<4; b++) screenPixels[(y+b) * 280 + x + a] = color; - y += 4; // second block - color = lcolor[(glyph & 0xF0) >> 4]; // second nibble + y += 4; // second block + color = lcolor[(glyph & 0xF0) >> 4]; // second nibble for (int a=0; a<7; a++) for (int b=0; b<4; b++) screenPixels[(y+b) * 280 + x + a] = color; } - } - } - } + } + } + } // DOUBLE lOW RES GRAPHICS - else if (!mmu->TEXT && !mmu->HIRES && mmu->DHIRES) { + else if (!mmu->TEXT && !mmu->HIRES && mmu->DHIRES) { gfxmode = 80; int vRamBase = mmu->PAGE2 * 0x0400 + 0x400; // TODO : CHECK THIS ! - int endRaw = mmu->MIXED ? 20 : 24; + int endRaw = mmu->MIXED ? 20 : 24; int x, y; uint32_t color; - for (int col = 0; col < 40; col++) { // for each column + for (int col = 0; col < 40; col++) { // for each column x = col * 14; - for (int line = 0; line < endRaw; line++) { // for each row + for (int line = 0; line < endRaw; line++) { // for each row y = line * 16; // first block - glyph = mmu->aux[vRamBase + offsetGR[line] + col]; // read AUX video memory - color = lcolor[glyph & 0x0F]; // first nibble + glyph = mmu->aux[vRamBase + offsetGR[line] + col]; // read AUX video memory + color = lcolor[glyph & 0x0F]; // first nibble for (int a=0; a<7; a++) for (int b=0; b<8; b++) screenPixels80[(y+b) * 560 + (x+a)] = color; @@ -404,19 +404,19 @@ void Video::update() { for (int a=7; a<14; a++) for (int b=8; b<16; b++) screenPixels80[(y+b) * 560 + (x+a)] = color; - } - } - } + } + } + } // TEXT 40 COLUMNS - if (!mmu->COL80 && (mmu->TEXT || mmu->MIXED)) { + if (!mmu->COL80 && (mmu->TEXT || mmu->MIXED)) { gfxmode = 40; int vRamBase = mmu->PAGE2 * 0x0400 + 0x400; - int startRaw = mmu->TEXT ? 0 : 20; - for (int col = 0; col < 40; col++) { // for each column - for (int line = startRaw; line < 24; line++) { // for each row + int startRaw = mmu->TEXT ? 0 : 20; + for (int col = 0; col < 40; col++) { // for each column + for (int line = startRaw; line < 24; line++) { // for each row - glyph = mmu->ram[vRamBase + offsetGR[line] + col]; // read video memory + glyph = mmu->ram[vRamBase + offsetGR[line] + col]; // read video memory if (glyph > 0x7F) glyphAttr = A_NORMAL; // is NORMAL ? else if (glyph < 0x40) glyphAttr = A_INVERSE; // is INVERSE ? @@ -453,16 +453,16 @@ void Video::update() { } } } - } + } // TEXT 80 COLUMNS - else if (mmu->COL80 && (mmu->TEXT || mmu->MIXED)) { + else if (mmu->COL80 && (mmu->TEXT || mmu->MIXED)) { gfxmode = 80; int startRaw = mmu->TEXT ? 0 : 20; int vRamBase = 0x0400; // + PAGE2 * 0x400; - for (int col = 0; col < 40; col++) { // for each column - for (int line = startRaw; line < 24; line++) { // for each row + for (int col = 0; col < 40; col++) { // for each column + for (int line = startRaw; line < 24; line++) { // for each row glyph = mmu->ram[vRamBase + offsetGR[line] + col]; // read video memory in Main memory if (glyph > 0x7F) glyphAttr = A_NORMAL; // is NORMAL ? @@ -544,7 +544,7 @@ void Video::update() { } } } - } + } // update ram & aux HEATMAPS (fade out green and red components) for (int address=0; address<65536; address++){