#include "cpu.h" #include #include #include "log.h" #include "bus.h" struct CPU* createCPU(struct Bus* parent) { struct CPU* cpu = (struct CPU*)malloc(sizeof(struct CPU)); if (cpu == NULL) { fprintf(stderr, "Failed to create CPU, aborting.\n"); exit(1); } // TODO: THIS IS JUST FOR THE TEST ROM cpu->pc = 0xC000; cpu->status.raw = 0x34; cpu->acc = 0; cpu->x = 0; cpu->y = 0; cpu->remainingCycles = 7; cpu->totalCycles = 0; cpu->bus = parent; return cpu; } void destroyCPU(struct CPU* cpu) { free(cpu); } int tickCPU(struct CPU* cpu) { cpu->remainingCycles--; cpu->totalCycles += 1; if (cpu->remainingCycles == 0) { fetch(cpu); execute(cpu); return 1; } return 0; } void tickInstr(struct CPU* cpu) { while (!tickCPU(cpu)); } void fetch(struct CPU* cpu) { Byte opcodeVal = readBus(cpu->bus, cpu->pc++); cpu->currentOpcode = OPCODE_TABLE + opcodeVal; if (cpu->currentOpcode->op == XXX) { fprintf(stderr, "Unknown opcode: %x", opcodeVal); exit(1); } cpu->remainingCycles = cpu->currentOpcode->cycles; switch (cpu->currentOpcode->addr) { case ACC: cpu->fetchedVal = cpu->acc; break; case ABS: { Byte lo = readBus(cpu->bus, cpu->pc++); Byte hi = readBus(cpu->bus, cpu->pc++); cpu->fetchedAddress = ((Word)hi << 8) | lo; } break; case ABX: { Byte lo = readBus(cpu->bus, cpu->pc++); Byte hi = readBus(cpu->bus, cpu->pc++); Word addr = ((Word)hi << 8) | lo; cpu->fetchedAddress = addr + cpu->x; if ((cpu->fetchedAddress & 0xFF00) != (addr & 0xFF00)) cpu->remainingCycles++; } break; case ABY: { Byte lo = readBus(cpu->bus, cpu->pc++); Byte hi = readBus(cpu->bus, cpu->pc++); Word addr = ((Word)hi << 8) | lo; cpu->fetchedAddress = addr + cpu->y; if ((cpu->fetchedAddress & 0xFF00) != (addr & 0xFF00)) cpu->remainingCycles++; } break; case IMM: cpu->fetchedVal = readBus(cpu->bus, cpu->pc++); break; case IMP: break; case IND: { Byte lo = readBus(cpu->bus, cpu->pc++); Byte hi = readBus(cpu->bus, cpu->pc++); Word addr = ((Word)hi << 8) | lo; cpu->fetchedAddress = readBus(cpu->bus, addr); } break; case INDX: { Byte op = readBus(cpu->bus, cpu->pc++); Byte lo = readBus(cpu->bus, op + cpu->x); Byte hi = readBus(cpu->bus, op + cpu->x + 1); Word addr = ((Word)hi << 8) | lo; cpu->fetchedAddress = readBus(cpu->bus, addr); } break; case INDY: { Byte op = readBus(cpu->bus, cpu->pc++); Byte lo = readBus(cpu->bus, op); Byte hi = readBus(cpu->bus, op + 1); Word addr = ((Word)hi << 8) | lo; addr = readBus(cpu->bus, addr); cpu->fetchedAddress = addr + cpu->y; if ((cpu->fetchedAddress & 0xFF00) != (addr & 0xFF00)) cpu->remainingCycles++; } break; case REL: { cpu->fetchedRelAddress = readBus(cpu->bus, cpu->pc++); } break; case ZPG: cpu->fetchedAddress = readBus(cpu->bus, cpu->pc++); break; case ZPX: { cpu->fetchedAddress = readBus(cpu->bus, cpu->pc++) + cpu->x; cpu->fetchedAddress |= 0xFF; } break; case ZPY: { cpu->fetchedAddress = readBus(cpu->bus, cpu->pc++) + cpu->y; cpu->fetchedAddress |= 0xFF; } break; } } void execute(struct CPU* cpu) { LOG_BUS(cpu->bus); switch (cpu->currentOpcode->op) { case JMP: { cpu->pc = cpu->fetchedAddress; } break; default: fprintf(stderr, "Unknown instruction: %s", cpu->currentOpcode->str); exit(1); break; } }