// // Created by Selim Mustafaev on 11.08.2023. // #ifndef NES_CPU_H #define NES_CPU_H #include #include #include namespace nes { class System; enum CpuFlags: uint8_t { Carry = (1 << 0), Zero = (1 << 1), InterruptDisable = (1 << 2), DecimalMode = (1 << 3), Break = (1 << 4), Unused = (1 << 5), Overflow = (1 << 6), Negative = (1 << 7) }; class Cpu { public: struct InstructionArgs { uint16_t address; uint8_t cycles; }; struct Instruction { char name[4]; void(Cpu::*process)(InstructionArgs); InstructionArgs(Cpu::*getAddress)(); uint8_t cycles; bool variableCycles; }; static constexpr uint16_t STACK_BASE = 0x0100; public: explicit Cpu(System* system); void reset(); bool tick(); void setFlag(CpuFlags flag, bool value); bool getFlag(CpuFlags flag) const; void setStartAddress(uint16_t address); void nmi(); #ifdef NES_LOGGING std::string state() const; #endif private: size_t _ticks; System* _system; std::vector _instructions; private: // Registers uint8_t A; // Accumulator uint8_t X; // - Index registers uint8_t Y; // / uint16_t PC; // Program Counter uint8_t SP; // Stack Pointer uint8_t flags; private: // Debug info uint8_t _currentOpcode; private: void branch(InstructionArgs args); private: InstructionArgs IMM(); InstructionArgs ABSL(); InstructionArgs IMPL(); InstructionArgs REL(); InstructionArgs ZP0(); InstructionArgs IZX(); InstructionArgs IZY(); InstructionArgs IND(); InstructionArgs ABX(); InstructionArgs ABY(); InstructionArgs ZPX(); InstructionArgs ZPY(); private: void LDA(InstructionArgs args); void LDX(InstructionArgs args); void LDY(InstructionArgs args); void STA(InstructionArgs args); void STX(InstructionArgs args); void CLC(InstructionArgs args); void ADC(InstructionArgs args); void SBC(InstructionArgs args); void DEY(InstructionArgs args); void BNE(InstructionArgs args); void NOP(InstructionArgs args); void SEI(InstructionArgs args); void CLD(InstructionArgs args); void TXS(InstructionArgs args); void BPL(InstructionArgs args); void JMP(InstructionArgs args); void JSR(InstructionArgs args); void SEC(InstructionArgs args); void BCS(InstructionArgs args); void BCC(InstructionArgs args); void BEQ(InstructionArgs args); void BIT(InstructionArgs args); void BVS(InstructionArgs args); void BVC(InstructionArgs args); void RTS(InstructionArgs args); void SED(InstructionArgs args); void PHP(InstructionArgs args); void PLA(InstructionArgs args); void AND(InstructionArgs args); void CMP(InstructionArgs args); void BMI(InstructionArgs args); void PHA(InstructionArgs args); void PLP(InstructionArgs args); void ORA(InstructionArgs args); void CLV(InstructionArgs args); void EOR(InstructionArgs args); void CPY(InstructionArgs args); void CPX(InstructionArgs args); void STY(InstructionArgs args); void INY(InstructionArgs args); void INX(InstructionArgs args); void DEX(InstructionArgs args); void TAY(InstructionArgs args); void TAX(InstructionArgs args); void TYA(InstructionArgs args); void TXA(InstructionArgs args); void TSX(InstructionArgs args); void BRK(InstructionArgs args); void RTI(InstructionArgs args); void LSR_ACC(InstructionArgs args); void LSR(InstructionArgs args); void ASL_ACC(InstructionArgs args); void ASL(InstructionArgs args); void ROR_ACC(InstructionArgs args); void ROR(InstructionArgs args); void ROL_ACC(InstructionArgs args); void ROL(InstructionArgs args); void INC(InstructionArgs args); void DEC(InstructionArgs args); }; } #endif //NES_CPU_H