summaryrefslogtreecommitdiff
path: root/main.cc
diff options
context:
space:
mode:
authorAditya <bluenerd@protonmail.com>2024-06-02 18:49:52 +0530
committerAditya <bluenerd@protonmail.com>2024-06-02 18:49:52 +0530
commit8b52d52242ea9e495b1910101cdad74e8e44e92c (patch)
tree57dd2f9aed58eff244e8db2341826167b2530e21 /main.cc
initial commit
Diffstat (limited to 'main.cc')
-rw-r--r--main.cc145
1 files changed, 145 insertions, 0 deletions
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 <cstdio>;
+import <cstdint>;
+import <cstdlib>;
+
+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;
+}