diff --git a/mos6502.c b/mos6502.c index e7d5ad1..d815ae4 100644 --- a/mos6502.c +++ b/mos6502.c @@ -7,15 +7,21 @@ #define READ_U8() m->memory[m->pc++] #define READ_U16() (READ_U8() | (READ_U8() << 8)) +#define FLAG_N 0x80 +#define FLAG_V 0x40 +#define FLAG_D 0x04 +#define FLAG_I 0x04 +#define FLAG_Z 0x02 +#define FLAG_C 0x01 + typedef struct MOS6502 { uint8_t *memory; uint16_t pc; - // TODO - // uint8_t A; - // uint8_t X; - // uint8_t Y; - // uint8_t SP; - // uint8_t P; + uint8_t A; + uint8_t X; + uint8_t Y; + uint8_t SP; + uint8_t P; } MOS6502; MOS6502 mos6502_create(void) { @@ -25,6 +31,60 @@ MOS6502 mos6502_create(void) { return m; } +void mos6502_set_zn(MOS6502 *m, uint8_t v) { + if (v == 0) { + m->P |= FLAG_Z; + } else { + m->P &= ~FLAG_Z; + } + if (v & 0x80) { + m->P |= FLAG_N; + } else { + m->P &= ~FLAG_N; + } +} + +void mos6502_step(MOS6502 *m) { + uint8_t op = READ_U8(); + switch (op) { + case 0x00: { + // TODO: its supposed to do some interrupt magic + exit(0); + } break; + case 0x4C: { + m->pc = READ_U16(); + } break; + case 0x8D: { + uint16_t addr = READ_U16(); + m->memory[addr] = m->A; + if (addr == 0x0400) { + putchar(m->memory[addr]); + } + } break; + case 0xA0: { + m->Y = READ_U8(); + mos6502_set_zn(m, m->Y); + } break; + case 0xB9: { + m->A = m->memory[READ_U16() + m->Y]; + mos6502_set_zn(m, m->A); + } break; + case 0xC8: { + m->Y++; + mos6502_set_zn(m, m->Y); + } break; + case 0xF0: { + int8_t offset = READ_U8(); + if (m->P & FLAG_Z) { + m->pc += offset; + } + } break; + default: + fprintf(stderr, "unrecognized opcode: $%02X\n", op); + exit(1); + } +} + void mos6502_disassemble(MOS6502 *m, size_t program_size) { while (m->pc < 0x600 + program_size) { printf("%04X: ", m->pc); @@ -517,7 +577,7 @@ int main(int argc, char *argv[]) { m.memory[0x600 + i] = buffer[i]; } - mos6502_disassemble(&m, n); - - mos6502_free(m); + while (1) { + mos6502_step(&m); + } }