using namespace std; //6502 program counter uint16_t pc; // 6502 registers uint16_t sp, a, x, y; // 6502 flags uint16_t n, v, b, d, i, z, c; // 6502 RAM uint16_t ram[65536]; //helper variables uint32_t instructions = 0; //keep track of total instructions executed uint32_t clockticks6502 = 0; const uint16_t reset_vector = 0xFFFC; // addressing modes for instructions const uint16_t mode_imm = 1; const uint16_t mode_zp = 2; const uint16_t mode_abs = 3; const uint16_t mode_adapt = 4; const uint16_t mode_ind_idx = 5; uint16_t read16(uint16_t addr) { // read 2 bytes with wraparound return ram[addr] + ram[(uint16_t) (addr + 1)] * 0x100; } uint32_t read32(uint16_t addr) { // read 4 bytes with wraparound return ram[addr] + ram[(uint16_t) (addr + 1)] * 0x100 + ram[(uint16_t) (addr + 2)] * 0x10000 + ram[(uint16_t) (addr + 3)] * 0x01000000; } void write16(uint16_t addr, uint16_t value) { ram[addr] = value & 0xFF; ram[(uint16_t) (addr + 1)] = value >> 8; } uint16_t read_reg(uint16_t reg) { // return the value of register reg if (reg == A_reg) return a; if (reg == X_reg) return x; if (reg == Y_reg) return y; } void clear_ram() { uint16_t i = 0; do { ram[i] = 0; i++; } while(i != 0); // wrap around of uint16 } void setflags(uint16_t value) { if (value == 0) { z = 1; } else { z = 0; } if (value >= 128) { n = 1; } else { n = 0; } } void setorg(uint16_t value) { pc = value; } void print_status() { cout << "NV-BDIZC" << endl; cout << n << v << "-" << b << d << i << z << c << endl; } void print_regs() { cout << " A X Y SP PC" << endl; cout << hex(a, 2) << " " << hex(x, 2) << " " << hex(y, 2) << " " << hex(sp, 2) << " " << hex(pc, 4) << endl; } void adc(uint16_t mode, uint16_t value) { if (mode == mode_imm) { a += value + c; clockticks6502 += 2; pc += 2; } if (mode == mode_zp) { a += ram[value] + c; clockticks6502 += 3; pc += 2; } if (mode == mode_ind_idx) { a += ram[read16(value) + y] + c; clockticks6502 += 5; if (ram[value] + y > 255) clockticks6502++; pc += 2; } c = a > 255; a = a & 0xFF; setflags(a); instructions++; }
template <enum Reg REG, enum Mode MODE> static constexpr void Load(Machine& m) { m.Reg<REG>() = m.LoadEA<MODE>(); m.set<SZ>(m.Reg<REG>()); }
{ "lda", { { 0xa9, 2, Mode::IMM, Load<Reg::A, Mode::IMM>}, { 0xa5, 3, Mode::ZP, Load<Reg::A, Mode::ZP>}, { 0xb5, 4, Mode::ZPX, Load<Reg::A, Mode::ZPX>}, { 0xad, 4, Mode::ABS, Load<Reg::A, Mode::ABS>}, { 0xbd, 4, Mode::ABSX, Load<Reg::A, Mode::ABSX>}, { 0xb9, 4, Mode::ABSY, Load<Reg::A, Mode::ABSY>}, { 0xa1, 6, Mode::INDX, Load<Reg::A, Mode::INDX>}, { 0xb1, 5, Mode::INDY, Load<Reg::A, Mode::INDY>}, } },
template are invaluable for writing fast code like this (unless you want to use lot of macros).
And the CPU core is negligible on a modern box too - other things will eat a LOT more performance :)