diff --git a/src/cpu.cpp b/src/cpu.cpp index 9029c91..936c1fd 100644 --- a/src/cpu.cpp +++ b/src/cpu.cpp @@ -56,7 +56,30 @@ void CPU::WriteWord(const uint32_t address, const uint16_t value) const { void CPU::ExecuteInstruction() { // TODO: Actual Opcode decoding switch (const uint8_t opcode = bus->Read(PC++)) { - case 0xEA: NOP(); break; + // DEC - Decrement Memory + case 0x3A: DEC_Accumulator(); break; // DEC A + case 0xCE: DEC_Absolute(); break; // DEC $nnnn + case 0xDE: DEC_AbsoluteX(); break; // DEC $nnnn,X + case 0xC6: DEC_DirectPage(); break; // DEC $nn + case 0xD6: DEC_DirectPageX(); break; // DEC $nn,X + + // Single Register Decrement + case 0xCA: DEX(); break; // DEX - Decrement X Register + case 0x88: DEY(); break; // DEY - Decrement Y Register + + // INC - Increment Memory + case 0x1A: INC_Accumulator(); break; // INC A + case 0xEE: INC_Absolute(); break; // INC $nnnn + case 0xFE: INC_AbsoluteX(); break; // INC $nnnn,X + case 0xE6: INC_DirectPage(); break; // INC $nn + case 0xF6: INC_DirectPageX(); break; // INC $nn,X + + // Single Register Increment + case 0xE8: INX(); break; // INX - Increment X Register + case 0xC8: INY(); break; // INY - Increment Y Register + + // No Operation + case 0xEA: NOP(); break; //NOP // LDA - Load Accumulator case 0xA9: LDA_Immediate(); break; // LDA #$nn or #$nnnn @@ -71,7 +94,7 @@ void CPU::ExecuteInstruction() { case 0xAF: LDA_Long(); break; // LDA $nnnnnn case 0xBF: LDA_LongX(); break; // LDA $nnnnnn,X - // LDX - Load X Register + // LDX - Load X Register case 0xA2: LDX_Immediate(); break; // LDX #$nn or LDX #$nnnn case 0xAE: LDX_Absolute(); break; // LDX $nnnn case 0xBE: LDX_AbsoluteY(); break; // LDX $nnnn,Y @@ -543,7 +566,7 @@ void CPU::LDY_DirectPageX() { //Store operations implementation void CPU::STA_Absolute() { - uint32_t address = ReadWord(PC + 1) | (DB << 16); + const uint32_t address = ReadWord(PC + 1) | (DB << 16); PC += 3; if (P & FLAG_M) { // 8-bit mode @@ -556,8 +579,8 @@ void CPU::STA_Absolute() { } void CPU::STA_AbsoluteX() { - uint32_t base = ReadWord(PC + 1) | (DB << 16); - uint32_t address = base + X; + const uint32_t base = ReadWord(PC + 1) | (DB << 16); + const uint32_t address = base + X; PC += 3; if (P & FLAG_M) { // 8-bit mode @@ -570,8 +593,8 @@ void CPU::STA_AbsoluteX() { } void CPU::STA_AbsoluteY() { - uint32_t base = ReadWord(PC + 1) | (DB << 16); - uint32_t address = base + Y; + const uint32_t base = ReadWord(PC + 1) | (DB << 16); + const uint32_t address = base + Y; PC += 3; if (P & FLAG_M) { // 8-bit mode @@ -584,8 +607,8 @@ void CPU::STA_AbsoluteY() { } void CPU::STA_DirectPage() { - uint8_t offset = ReadByte(PC + 1); - uint32_t address = (D + offset) & 0xFFFF; + const uint8_t offset = ReadByte(PC + 1); + const uint32_t address = (D + offset) & 0xFFFF; PC += 2; if (P & FLAG_M) { // 8-bit mode @@ -600,8 +623,8 @@ void CPU::STA_DirectPage() { } void CPU::STA_DirectPageX() { - uint8_t offset = ReadByte(PC + 1); - uint32_t address = (D + offset + X) & 0xFFFF; + const uint8_t offset = ReadByte(PC + 1); + const uint32_t address = (D + offset + X) & 0xFFFF; PC += 2; if (P & FLAG_M) { // 8-bit mode @@ -616,9 +639,9 @@ void CPU::STA_DirectPageX() { } void CPU::STA_IndirectDirectPage() { - uint8_t offset = ReadByte(PC + 1); - uint32_t pointer = (D + offset) & 0xFFFF; - uint32_t address = ReadWord(pointer) | (DB << 16); + const uint8_t offset = ReadByte(PC + 1); + const uint32_t pointer = (D + offset) & 0xFFFF; + const uint32_t address = ReadWord(pointer) | (DB << 16); PC += 2; if (P & FLAG_M) { // 8-bit mode @@ -633,10 +656,10 @@ void CPU::STA_IndirectDirectPage() { } void CPU::STA_IndirectDirectPageY() { - uint8_t offset = ReadByte(PC + 1); - uint32_t pointer = (D + offset) & 0xFFFF; - uint32_t base = ReadWord(pointer) | (DB << 16); - uint32_t address = base + Y; + const uint8_t offset = ReadByte(PC + 1); + const uint32_t pointer = (D + offset) & 0xFFFF; + const uint32_t base = ReadWord(pointer) | (DB << 16); + const uint32_t address = base + Y; PC += 2; if (P & FLAG_M) { // 8-bit mode @@ -651,9 +674,9 @@ void CPU::STA_IndirectDirectPageY() { } void CPU::STA_DirectPageIndirectX() { - uint8_t offset = ReadByte(PC + 1); - uint32_t pointer = (D + offset + X) & 0xFFFF; - uint32_t address = ReadWord(pointer) | (DB << 16); + const uint8_t offset = ReadByte(PC + 1); + const uint32_t pointer = (D + offset + X) & 0xFFFF; + const uint32_t address = ReadWord(pointer) | (DB << 16); PC += 2; if (P & FLAG_M) { // 8-bit mode @@ -668,7 +691,7 @@ void CPU::STA_DirectPageIndirectX() { } void CPU::STA_Long() { - uint32_t address = ReadByte(PC + 1) | (ReadByte(PC + 2) << 8) | (ReadByte(PC + 3) << 16); + const uint32_t address = ReadByte(PC + 1) | (ReadByte(PC + 2) << 8) | (ReadByte(PC + 3) << 16); PC += 4; if (P & FLAG_M) { // 8-bit mode @@ -681,8 +704,8 @@ void CPU::STA_Long() { } void CPU::STA_LongX() { - uint32_t base = ReadByte(PC + 1) | (ReadByte(PC + 2) << 8) | (ReadByte(PC + 3) << 16); - uint32_t address = base + X; + const uint32_t base = ReadByte(PC + 1) | (ReadByte(PC + 2) << 8) | (ReadByte(PC + 3) << 16); + const uint32_t address = base + X; PC += 4; if (P & FLAG_M) { // 8-bit mode @@ -696,7 +719,7 @@ void CPU::STA_LongX() { // STX - Store X Register void CPU::STX_Absolute() { - uint32_t address = ReadWord(PC + 1) | (DB << 16); + const uint32_t address = ReadWord(PC + 1) | (DB << 16); PC += 3; if (P & FLAG_X) { // 8-bit mode @@ -709,8 +732,8 @@ void CPU::STX_Absolute() { } void CPU::STX_DirectPage() { - uint8_t offset = ReadByte(PC + 1); - uint32_t address = (D + offset) & 0xFFFF; + const uint8_t offset = ReadByte(PC + 1); + const uint32_t address = (D + offset) & 0xFFFF; PC += 2; if (P & FLAG_X) { // 8-bit mode @@ -755,8 +778,8 @@ void CPU::STY_Absolute() { } void CPU::STY_DirectPage() { - uint8_t offset = ReadByte(PC + 1); - uint32_t address = (D + offset) & 0xFFFF; + const uint8_t offset = ReadByte(PC + 1); + const uint32_t address = (D + offset) & 0xFFFF; PC += 2; if (P & FLAG_X) { // 8-bit mode @@ -771,8 +794,8 @@ void CPU::STY_DirectPage() { } void CPU::STY_DirectPageX() { - uint8_t offset = ReadByte(PC + 1); - uint32_t address = (D + offset + X) & 0xFFFF; + const uint8_t offset = ReadByte(PC + 1); + const uint32_t address = (D + offset + X) & 0xFFFF; PC += 2; if (P & FLAG_X) { // 8-bit mode @@ -784,4 +807,245 @@ void CPU::STY_DirectPageX() { cycles += 5; if (D & 0xFF) cycles++; // Extra cycle if D register low byte != 0 } +} + +// INC - Increment Memory +// Important to note: PC doesn't increment in accumulator mode I think +void CPU::INC_Accumulator() { + if (P & FLAG_M) { // 8-bit mode + A = (A & 0xFF00) | ((A + 1) & 0xFF); + UpdateNZ8(A & 0xFF); + cycles += 2; + } else { // 16-bit mode + A = (A + 1) & 0xFFFF; + UpdateNZ16(A); + cycles += 2; + } +} + +void CPU::INC_Absolute() { + const uint32_t address = ReadWord(PC + 1) | (DB << 16); + PC += 3; + + if (P & FLAG_M) { // 8-bit mode + uint8_t value = ReadByte(address); + value = (value + 1) & 0xFF; + WriteByte(address, value); + UpdateNZ8(value); + cycles += 6; + } else { // 16-bit mode + uint16_t value = ReadWord(address); + value = (value + 1) & 0xFFFF; + WriteWord(address, value); + UpdateNZ16(value); + cycles += 8; + } +} + +void CPU::INC_AbsoluteX() { + const uint32_t base = ReadWord(PC + 1) | (DB << 16); + const uint32_t address = base + X; + PC += 3; + + if (P & FLAG_M) { // 8-bit mode + uint8_t value = ReadByte(address); + value = (value + 1) & 0xFF; + WriteByte(address, value); + UpdateNZ8(value); + cycles += 7; + } else { // 16-bit mode + uint16_t value = ReadWord(address); + value = (value + 1) & 0xFFFF; + WriteWord(address, value); + UpdateNZ16(value); + cycles += 9; + } +} + +void CPU::INC_DirectPage() { + const uint8_t offset = ReadByte(PC + 1); + const uint32_t address = (D + offset) & 0xFFFF; + PC += 2; + + if (P & FLAG_M) { // 8-bit mode + uint8_t value = ReadByte(address); + value = (value + 1) & 0xFF; + WriteByte(address, value); + UpdateNZ8(value); + cycles += 5; + if (D & 0xFF) cycles++; // Extra cycle if D register low byte != 0 + } else { // 16-bit mode + uint16_t value = ReadWord(address); + value = (value + 1) & 0xFFFF; + WriteWord(address, value); + UpdateNZ16(value); + cycles += 7; + if (D & 0xFF) cycles++; // Extra cycle if D register low byte != 0 + } +} + +void CPU::INC_DirectPageX() { + const uint8_t offset = ReadByte(PC + 1); + const uint32_t address = (D + offset + X) & 0xFFFF; + PC += 2; + + if (P & FLAG_M) { // 8-bit mode + uint8_t value = ReadByte(address); + value = (value + 1) & 0xFF; + WriteByte(address, value); + UpdateNZ8(value); + cycles += 6; + if (D & 0xFF) cycles++; // Extra cycle if D register low byte != 0 + } else { // 16-bit mode + uint16_t value = ReadWord(address); + value = (value + 1) & 0xFFFF; + WriteWord(address, value); + UpdateNZ16(value); + cycles += 8; + if (D & 0xFF) cycles++; // Extra cycle if D register low byte != 0 + } +} + +// DEC - Decrement Memory +void CPU::DEC_Accumulator() { + if (P & FLAG_M) { // 8-bit mode + A = (A & 0xFF00) | ((A - 1) & 0xFF); + UpdateNZ8(A & 0xFF); + cycles += 2; + } else { // 16-bit mode + A = (A - 1) & 0xFFFF; + UpdateNZ16(A); + cycles += 2; + } +} + +void CPU::DEC_Absolute() { + const uint32_t address = ReadWord(PC + 1) | (DB << 16); + PC += 3; + + if (P & FLAG_M) { // 8-bit mode + uint8_t value = ReadByte(address); + value = (value - 1) & 0xFF; + WriteByte(address, value); + UpdateNZ8(value); + cycles += 6; + } else { // 16-bit mode + uint16_t value = ReadWord(address); + value = (value - 1) & 0xFFFF; + WriteWord(address, value); + UpdateNZ16(value); + cycles += 8; + } +} + +void CPU::DEC_AbsoluteX() { + const uint32_t base = ReadWord(PC + 1) | (DB << 16); + const uint32_t address = base + X; + PC += 3; + + if (P & FLAG_M) { // 8-bit mode + uint8_t value = ReadByte(address); + value = (value - 1) & 0xFF; + WriteByte(address, value); + UpdateNZ8(value); + cycles += 7; + } else { // 16-bit mode + uint16_t value = ReadWord(address); + value = (value - 1) & 0xFFFF; + WriteWord(address, value); + UpdateNZ16(value); + cycles += 9; + } +} + +void CPU::DEC_DirectPage() { + const uint8_t offset = ReadByte(PC + 1); + const uint32_t address = (D + offset) & 0xFFFF; + PC += 2; + + if (P & FLAG_M) { // 8-bit mode + uint8_t value = ReadByte(address); + value = (value - 1) & 0xFF; + WriteByte(address, value); + UpdateNZ8(value); + cycles += 5; + if (D & 0xFF) cycles++; // Extra cycle if D register low byte != 0 + } else { // 16-bit mode + uint16_t value = ReadWord(address); + value = (value - 1) & 0xFFFF; + WriteWord(address, value); + UpdateNZ16(value); + cycles += 7; + if (D & 0xFF) cycles++; // Extra cycle if D register low byte != 0 + } +} + +void CPU::DEC_DirectPageX() { + const uint8_t offset = ReadByte(PC + 1); + const uint32_t address = (D + offset + X) & 0xFFFF; + PC += 2; + + if (P & FLAG_M) { // 8-bit mode + uint8_t value = ReadByte(address); + value = (value - 1) & 0xFF; + WriteByte(address, value); + UpdateNZ8(value); + cycles += 6; + if (D & 0xFF) cycles++; // Extra cycle if D register low byte != 0 + } else { // 16-bit mode + uint16_t value = ReadWord(address); + value = (value - 1) & 0xFFFF; + WriteWord(address, value); + UpdateNZ16(value); + cycles += 8; + if (D & 0xFF) cycles++; // Extra cycle if D register low byte != 0 + } +} + +// INX - Increment X Register +void CPU::INX() { + if (P & FLAG_X) { // 8-bit mode + X = (X & 0xFF00) | ((X + 1) & 0xFF); + UpdateNZ8(X & 0xFF); + } else { // 16-bit mode + X = (X + 1) & 0xFFFF; + UpdateNZ16(X); + } + cycles += 2; +} + +// INY - Increment Y Register +void CPU::INY() { + if (P & FLAG_X) { // 8-bit mode + Y = (Y & 0xFF00) | ((Y + 1) & 0xFF); + UpdateNZ8(Y & 0xFF); + } else { // 16-bit mode + Y = (Y + 1) & 0xFFFF; + UpdateNZ16(Y); + } + cycles += 2; +} + +// DEX - Decrement X Register +void CPU::DEX() { + if (P & FLAG_X) { // 8-bit mode + X = (X & 0xFF00) | ((X - 1) & 0xFF); + UpdateNZ8(X & 0xFF); + } else { // 16-bit mode + X = (X - 1) & 0xFFFF; + UpdateNZ16(X); + } + cycles += 2; +} + +// DEY - Decrement Y Register +void CPU::DEY() { + if (P & FLAG_X) { // 8-bit mode + Y = (Y & 0xFF00) | ((Y - 1) & 0xFF); + UpdateNZ8(Y & 0xFF); + } else { // 16-bit mode + Y = (Y - 1) & 0xFFFF; + UpdateNZ16(Y); + } + cycles += 2; } \ No newline at end of file diff --git a/src/cpu.h b/src/cpu.h index 0c7b347..28e526e 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -47,7 +47,7 @@ public: [[nodiscard]] uint64_t GetCycles() const { return cycles; } // Addressing mode helpers - uint32_t GetEffectiveAddress(uint8_t mode); + //uint32_t GetEffectiveAddress(uint8_t mode); uint8_t ReadByte(uint32_t address); uint16_t ReadWord(uint32_t address); void UpdateNZ8(uint8_t value); @@ -88,7 +88,6 @@ public: void LDY_DirectPage(); void LDY_DirectPageX(); - // STA - Store Accumulator operations void STA_Absolute(); void STA_AbsoluteX(); void STA_AbsoluteY(); @@ -100,18 +99,30 @@ public: void STA_Long(); void STA_LongX(); - // STX - Store X Register operations void STX_Absolute(); void STX_DirectPage(); void STX_DirectPageY(); - // STY - Store Y Register operations void STY_Absolute(); void STY_DirectPage(); void STY_DirectPageX(); + void INC_Accumulator(); + void INC_Absolute(); + void INC_AbsoluteX(); + void INC_DirectPage(); + void INC_DirectPageX(); - void STA(); + void DEC_Accumulator(); + void DEC_Absolute(); + void DEC_AbsoluteX(); + void DEC_DirectPage(); + void DEC_DirectPageX(); + + void INX(); + void INY(); + void DEX(); + void DEY(); }; #endif //CPU_H