From 8b52d52242ea9e495b1910101cdad74e8e44e92c Mon Sep 17 00:00:00 2001 From: Aditya Date: Sun, 2 Jun 2024 18:49:52 +0530 Subject: initial commit --- main.cc | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 main.cc (limited to 'main.cc') diff --git a/main.cc b/main.cc new file mode 100644 index 0000000..3df70d8 --- /dev/null +++ b/main.cc @@ -0,0 +1,145 @@ +import ; +import ; +import ; + +using Byte = unsigned char; +using Word = uint16_t; + +struct Mem { + static constexpr uint32_t MAX_MEM = 1024 * 64; + Byte Data[MAX_MEM]; + + auto Initialise() -> void { + for (uint32_t i{}; i < MAX_MEM; ++i) { + Data[i] = 0; + } + } + + // Read 1 byte + auto operator[](uint32_t Address) const -> Byte { return Data[Address]; } + + auto operator[](uint32_t Address) -> Byte { return Data[Address]; } + + // write 2 bytes + auto WriteWord(Word Value, uint32_t Address, uint32_t &Cycles) -> void { + Data[Address] = Value & 0xFF; + Data[Address + 1] = (Value >> 8); + Cycles -= 2; + } +}; + +struct CPU { + + Word PC{}; // Program counter + Word SP{}; // Stack pointer + + Byte A{}, X{}, Y{}; // registers + + // Status flags + Byte C : 1; + Byte Z : 1; + Byte I : 1; + Byte D : 1; + Byte B : 1; + Byte V : 1; + Byte N : 1; + + auto Reset(Mem &mem) -> void { + PC = 0xFFFC; + SP = 0x0100; + C = 0; + Z = 0; + I = 0; + D = 0; + B = 0; + V = 0; + N = 0; + A = 0; + X = 0; + Y = 0; + + mem.Initialise(); + } + + auto FetchByte(uint32_t &Cycles, Mem &mem) -> Byte { + Byte Data{mem[PC]}; + ++PC; + --Cycles; + return Data; + } + + auto FetchWord(uint32_t &Cycles, Mem &mem) -> Word { + // 6502 is little endian + Word Data{mem[PC]}; + ++PC; + + Data |= (mem[PC] << 8); + ++PC; + + Cycles += 2; + + return Data; + } + + auto ReadByte(uint32_t &Cycles, Byte Address, Mem &mem) -> Byte { + Byte Data{mem[Address]}; + --Cycles; + return Data; + } + + // opcodes + static constexpr Byte INS_LDA_IM{0xA9}, INS_LDA_ZP{0xA5}, INS_LDA_ZPX{0xB5}, + INS_JSR{0x20}; + + auto LDASetStatus() -> void { + Z = (A == 0); + N = (A & 0b10'000'000) > 0; + } + + auto Execute(uint32_t Cycles, Mem &mem) -> void { + while (Cycles > 0) { + Byte Ins{FetchByte(Cycles, mem)}; + switch (Ins) { + case INS_LDA_IM: { + Byte Value{FetchByte(Cycles, mem)}; + A = Value; + LDASetStatus(); + break; + } + case INS_LDA_ZP: { + Byte ZeroPageAddress{FetchByte(Cycles, mem)}; + A = ReadByte(Cycles, ZeroPageAddress, mem); + LDASetStatus(); + break; + } + case INS_LDA_ZPX: { + Byte ZeroPageAddress{FetchByte(Cycles, mem)}; + ZeroPageAddress += X; + --Cycles; + A = ReadByte(Cycles, ZeroPageAddress, mem); + LDASetStatus(); + break; + } + case INS_JSR: { + Word SubAddr{FetchWord(Cycles, mem)}; + mem[SP] = PC - 1; + mem.WriteWord(PC - 1, SP, Cycles); + PC = SubAddr; + --Cycles; + break; + } + default: { + printf("Instruction not handled %d", Ins); + } + } + } + } +}; + +int main() { + Mem mem{}; + CPU cpu{}; + cpu.Reset(mem); + cpu.Execute(2, mem); + return 0; +} -- cgit v1.2.3