diff --git a/M6502/inc/mos6502.h b/M6502/inc/mos6502.h index 4a61ff2..0bfaba0 100644 --- a/M6502/inc/mos6502.h +++ b/M6502/inc/mos6502.h @@ -163,15 +163,19 @@ namespace EightBit { return m_memory.reference(); } - uint8_t& AM_AbsoluteX() { + uint8_t& AM_AbsoluteX(bool read = true) { Address_AbsoluteX(); m_memory.ADDRESS() = m_memptr; + if (read && (m_memory.ADDRESS().low == 0xff)) + ++cycles; return m_memory.reference(); } - uint8_t& AM_AbsoluteY() { + uint8_t& AM_AbsoluteY(bool read = true) { Address_AbsoluteY(); m_memory.ADDRESS() = m_memptr; + if (read && (m_memory.ADDRESS().low == 0xff)) + ++cycles; return m_memory.reference(); } @@ -193,9 +197,11 @@ namespace EightBit { return m_memory.reference(); } - uint8_t& AM_IndirectIndexedY() { + uint8_t& AM_IndirectIndexedY(bool read = true) { Address_IndirectIndexedY(); m_memory.ADDRESS() = m_memptr; + if (read && (m_memory.ADDRESS().low == 0xff)) + ++cycles; return m_memory.reference(); } @@ -203,7 +209,7 @@ namespace EightBit { #pragma region 6502 addressing mode switching - uint8_t& AM_00(int bbb) { + uint8_t& AM_00(int bbb, bool read = true) { switch (bbb) { case 0b000: return AM_Immediate(); @@ -214,7 +220,7 @@ namespace EightBit { case 0b101: return AM_ZeroPageX(); case 0b111: - return AM_AbsoluteX(); + return AM_AbsoluteX(read); case 0b010: case 0b100: case 0b110: @@ -224,7 +230,7 @@ namespace EightBit { } } - uint8_t& AM_01(int bbb) { + uint8_t& AM_01(int bbb, bool read = true) { switch (bbb) { case 0b000: return AM_IndexedIndirectX(); @@ -235,19 +241,19 @@ namespace EightBit { case 0b011: return AM_Absolute(); case 0b100: - return AM_IndirectIndexedY(); + return AM_IndirectIndexedY(read); case 0b101: return AM_ZeroPageX(); case 0b110: - return AM_AbsoluteY(); + return AM_AbsoluteY(read); case 0b111: - return AM_AbsoluteX(); + return AM_AbsoluteX(read); default: __assume(0); } } - uint8_t& AM_10(int bbb) { + uint8_t& AM_10(int bbb, bool read = true) { switch (bbb) { case 0b000: return AM_Immediate(); @@ -260,7 +266,7 @@ namespace EightBit { case 0b101: return AM_ZeroPageX(); case 0b111: - return AM_AbsoluteX(); + return AM_AbsoluteX(read); case 0b100: case 0b110: throw std::domain_error("Illegal addressing mode"); @@ -269,7 +275,7 @@ namespace EightBit { } } - uint8_t& AM_10_x(int bbb) { + uint8_t& AM_10_x(int bbb, bool read = true) { switch (bbb) { case 0b000: return AM_Immediate(); @@ -282,7 +288,7 @@ namespace EightBit { case 0b101: return AM_ZeroPageY(); case 0b111: - return AM_AbsoluteY(); + return AM_AbsoluteY(read); case 0b100: case 0b110: throw std::domain_error("Illegal addressing mode"); @@ -356,5 +362,7 @@ namespace EightBit { uint8_t p; // processor status register16_t m_memptr; + + std::array m_timings; }; } \ No newline at end of file diff --git a/M6502/src/mos6502.cpp b/M6502/src/mos6502.cpp index fa74780..0d3d1e1 100644 --- a/M6502/src/mos6502.cpp +++ b/M6502/src/mos6502.cpp @@ -3,6 +3,25 @@ EightBit::MOS6502::MOS6502(Memory& memory) : Processor(memory) { + m_timings = { + //// 0 1 2 3 4 5 6 7 8 9 A B C D E F + /* 0 */ 7, 6, 0, 0, 0, 4, 5, 0, 3, 2, 2, 0, 0, 4, 6, 0, + /* 1 */ 2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0, + /* 2 */ 6, 6, 0, 0, 3, 3, 5, 0, 4, 2, 2, 0, 4, 4, 6, 0, + /* 3 */ 2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0, + /* 4 */ 6, 6, 0, 0, 0, 3, 5, 0, 3, 2, 2, 0, 3, 4, 6, 0, + /* 5 */ 2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0, + /* 6 */ 6, 6, 0, 0, 0, 3, 5, 0, 4, 2, 2, 0, 5, 4, 6, 0, + /* 7 */ 2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0, + /* 8 */ 0, 6, 0, 0, 3, 3, 3, 0, 2, 0, 2, 0, 4, 4, 4, 0, + /* 9 */ 2, 6, 0, 0, 4, 4, 4, 0, 2, 5, 2, 0, 0, 5, 0, 0, + /* A */ 2, 6, 2, 0, 3, 3, 3, 0, 2, 2, 2, 0, 4, 4, 4, 0, + /* B */ 2, 5, 0, 0, 4, 4, 4, 0, 2, 4, 2, 0, 4, 4, 4, 0, + /* C */ 2, 6, 0, 0, 3, 3, 5, 0, 2, 2, 2, 0, 4, 4, 6, 0, + /* D */ 2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0, + /* E */ 2, 6, 0, 0, 3, 3, 5, 0, 2, 2, 2, 0, 4, 4, 6, 0, + /* F */ 2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0, + }; } void EightBit::MOS6502::initialise() { @@ -61,7 +80,7 @@ void EightBit::MOS6502::Interrupt(uint16_t vector) { int EightBit::MOS6502::Execute(uint8_t cell) { - cycles = 1; + cycles = m_timings[cell]; // http://www.llx.com/~nparker/a2/opcodes.html @@ -110,7 +129,7 @@ int EightBit::MOS6502::Execute(uint8_t cell) { setFlag(P(), CF); break; default: // BIT - BIT(AM_00(bbb)); + BIT(AM_00(bbb, false)); break; } break; @@ -168,7 +187,7 @@ int EightBit::MOS6502::Execute(uint8_t cell) { UpdateZeroNegativeFlags(A() = Y()); break; default: // STY - AM_00(bbb) = Y(); + AM_00(bbb, false) = Y(); break; } break; @@ -237,7 +256,7 @@ int EightBit::MOS6502::Execute(uint8_t cell) { ADC(AM_01(bbb)); break; case 0b100: // STA - AM_01(bbb) = A(); + AM_01(bbb, false) = A(); break; case 0b101: // LDA LDA(AM_01(bbb)); @@ -255,16 +274,16 @@ int EightBit::MOS6502::Execute(uint8_t cell) { case 0b10: switch (aaa) { case 0b000: // ASL - ASL(AM_10(bbb)); + ASL(AM_10(bbb, false)); break; case 0b001: // ROL - ROL(AM_10(bbb)); + ROL(AM_10(bbb, false)); break; case 0b010: // LSR - LSR(AM_10(bbb)); + LSR(AM_10(bbb, false)); break; case 0b011: // ROR - ROR(AM_10(bbb)); + ROR(AM_10(bbb, false)); break; case 0b100: switch (bbb) { @@ -275,7 +294,7 @@ int EightBit::MOS6502::Execute(uint8_t cell) { S() = X(); break; default: // STX - AM_10_x(bbb) = X(); + AM_10_x(bbb, false) = X(); break; } break; @@ -295,7 +314,7 @@ int EightBit::MOS6502::Execute(uint8_t cell) { DEC(X()); break; default: // DEC - DEC(AM_10(bbb)); + DEC(AM_10(bbb, false)); break; } break; @@ -304,7 +323,7 @@ int EightBit::MOS6502::Execute(uint8_t cell) { case 0b010: // NOP break; default: // INC - INC(AM_10(bbb)); + INC(AM_10(bbb, false)); break; } break; @@ -510,7 +529,11 @@ void EightBit::MOS6502::ADC_d(uint8_t data) { //// void EightBit::MOS6502::Branch(int8_t displacement) { + auto page = PC().high; PC().word += displacement; + if (PC().high != page) + cycles++; + cycles++; } void EightBit::MOS6502::Branch(bool flag) {