diff --git a/chip8.c b/chip8.c index 493c6fc..537a649 100644 --- a/chip8.c +++ b/chip8.c @@ -344,11 +344,11 @@ void chip8_step(CHIP8 *c) { c->reg[x] = c->delay_timer; break; case 0x0A: { - bool key_pressed = false; + uint8_t key_pressed = 0; while (!key_pressed && WindowShouldClose()) { for (size_t i = 0; i < 16; i++) { if (IsKeyDown(keyboard_map[i])) { - key_pressed = true; + key_pressed = 1; break; } } diff --git a/mos6502.c b/mos6502.c index 2e284ed..310193d 100644 --- a/mos6502.c +++ b/mos6502.c @@ -32,17 +32,17 @@ MOS6502 mos6502_create(void) { return m; } +void mos6502_set_flag(MOS6502 *m, uint8_t flag, uint8_t value) { + if (value) { + m->P |= flag; + } else { + m->P &= ~flag; + } +} + 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; - } + mos6502_set_flag(m, FLAG_Z, v == 0); + mos6502_set_flag(m, FLAG_N, v & 0x80); } uint8_t mos6502_mem_read(MOS6502 *m, uint16_t addr) { return m->memory[addr]; } @@ -57,33 +57,58 @@ void mos6502_mem_write(MOS6502 *m, uint16_t addr, uint8_t v) { void mos6502_step(MOS6502 *m) { uint8_t op = READ_U8(); - // printf("$%04X: %02X A: %02X X: %02X Y: %02X\n", m->pc, op, m->A, m->X, - // m->Y); + // printf("$%04X: %02X A: %02X X: %02X Y: %02X\n", m->pc - 1, op, m->A, + // m->X, m->Y); switch (op) { case 0x00: { // TODO: its supposed to do some interrupt magic - exit(0); + m->pc--; + } break; + case 0x09: { + m->A |= READ_U8(); + mos6502_set_zn(m, m->A); + } break; + case 0x0A: { + uint8_t carry = (m->A & 0x80) != 0; + m->A <<= 1; + mos6502_set_flag(m, FLAG_C, carry); + mos6502_set_zn(m, m->A); + } break; + case 0x18: { + mos6502_set_flag(m, FLAG_C, 0); } break; case 0x20: { - uint16_t ret_addr = m->pc + 2; + uint16_t target = READ_U16(); + uint16_t ret_addr = m->pc - 1; mos6502_mem_write(m, 0x0100 + m->SP--, (ret_addr >> 8) & 0xFF); mos6502_mem_write(m, 0x0100 + m->SP--, ret_addr & 0xFF); - m->pc = READ_U16(); + m->pc = target; + } break; + case 0x29: { + m->A &= READ_U8(); + mos6502_set_zn(m, m->A); + } break; + case 0x2A: { + uint8_t old_carry = m->P & FLAG_C; + uint8_t new_carry = (m->A & 0x80) >> 7; + m->A = ((m->A << 1) & 0xFE) | old_carry; + mos6502_set_flag(m, FLAG_C, new_carry); + mos6502_set_zn(m, m->A); + } break; + case 0x38: { + mos6502_set_flag(m, FLAG_C, 1); } break; case 0x48: { mos6502_mem_write(m, 0x0100 + m->SP--, m->A); } break; + case 0x49: { + m->A ^= READ_U8(); + mos6502_set_zn(m, m->A); + } break; case 0x4A: { - uint8_t c = m->A & 0x01; - + mos6502_set_flag(m, FLAG_C, m->A & 0x01); m->A >>= 1; - - if (c) { - m->P |= FLAG_C; - } else { - m->P &= ~FLAG_C; - } mos6502_set_zn(m, m->A); } break; case 0x4C: { @@ -92,7 +117,30 @@ void mos6502_step(MOS6502 *m) { case 0x60: { uint16_t low = mos6502_mem_read(m, 0x0100 + (++m->SP)); uint16_t high = mos6502_mem_read(m, 0x0100 + (++m->SP)); - m->pc = (((uint16_t)high << 8) | low); + m->pc = (((uint16_t)high << 8) | low) + 1; + } break; + case 0x68: { + m->A = mos6502_mem_read(m, 0x0100 + (++m->SP)); + mos6502_set_zn(m, m->A); + } break; + case 0x69: { + uint8_t oper = READ_U8(); + uint16_t res = m->A + oper + (m->P & FLAG_C); + mos6502_set_flag(m, FLAG_C, res > 0xFF); + mos6502_set_flag(m, FLAG_V, (~(m->A ^ oper) & (m->A ^ res) & 0x80) != 0); + m->A = res; + mos6502_set_zn(m, m->A); + } break; + case 0x6A: { + uint8_t old_carry = m->P & FLAG_C; + uint8_t new_carry = m->A & 0x01; + m->A = (m->A >> 1) | (old_carry << 7); + mos6502_set_flag(m, FLAG_C, new_carry); + mos6502_set_zn(m, m->A); + } break; + case 0x8A: { + m->A = m->X; + mos6502_set_zn(m, m->A); } break; case 0x8D: { mos6502_mem_write(m, READ_U16(), m->A); @@ -103,6 +151,10 @@ void mos6502_step(MOS6502 *m) { m->pc += offset; } } break; + case 0x98: { + m->A = m->Y; + mos6502_set_zn(m, m->A); + } break; case 0x99: { mos6502_mem_write(m, READ_U16() + m->Y, m->A); } break; @@ -117,10 +169,18 @@ void mos6502_step(MOS6502 *m) { m->X = READ_U8(); mos6502_set_zn(m, m->X); } break; + case 0xA8: { + m->X = m->A; + mos6502_set_zn(m, m->X); + } break; case 0xA9: { m->A = READ_U8(); mos6502_set_zn(m, m->A); } break; + case 0xAA: { + m->X = m->A; + mos6502_set_zn(m, m->X); + } break; case 0xAD: { m->A = mos6502_mem_read(m, READ_U16()); mos6502_set_zn(m, m->A); @@ -145,13 +205,13 @@ void mos6502_step(MOS6502 *m) { } break; case 0xC9: { uint8_t oper = READ_U8(); - if (m->A >= oper) { - m->P |= FLAG_C; - } else { - m->P &= ~FLAG_C; - } + mos6502_set_flag(m, FLAG_C, m->A >= oper); mos6502_set_zn(m, m->A - oper); } break; + case 0xCA: { + m->X--; + mos6502_set_zn(m, m->X); + } break; case 0xCE: { uint16_t addr = READ_U16(); uint8_t res = mos6502_mem_read(m, addr) - 1; @@ -164,6 +224,12 @@ void mos6502_step(MOS6502 *m) { m->pc += offset; } } break; + case 0xE0: { + uint8_t oper = READ_U8(); + uint16_t res = m->X - oper; + mos6502_set_flag(m, FLAG_C, m->X >= oper); + mos6502_set_zn(m, res); + } break; case 0xEE: { uint16_t addr = READ_U16(); uint8_t res = mos6502_mem_read(m, addr) + 1; @@ -174,6 +240,14 @@ void mos6502_step(MOS6502 *m) { m->X++; mos6502_set_zn(m, m->X); } break; + case 0xE9: { + uint8_t oper = READ_U8(); + uint16_t res = m->A - oper - ((m->P & FLAG_C) ? 0 : 1); + mos6502_set_flag(m, FLAG_C, res < 0x100); + mos6502_set_flag(m, FLAG_V, (m->A ^ oper) & (m->A ^ res) & 0x80); + m->A = res; + mos6502_set_zn(m, m->A); + } break; case 0xF0: { int8_t offset = READ_U8(); if (m->P & FLAG_Z) { @@ -188,7 +262,7 @@ void mos6502_step(MOS6502 *m) { void mos6502_disassemble(MOS6502 *m, size_t program_size) { while (m->pc < 0x600 + program_size) { - printf("%04X: ", m->pc); + printf("$%04X: ", m->pc); uint8_t op = READ_U8(); switch (op) { @@ -662,15 +736,15 @@ void mos6502_disassemble(MOS6502 *m, size_t program_size) { void mos6502_free(MOS6502 m) { free(m.memory); } int main(int argc, char *argv[]) { - if (argc < 2) { - fprintf(stderr, "Usage: %s \n", argv[0]); + if (argc < 3) { + fprintf(stderr, "Usage: %s \n", argv[0]); return 1; } MOS6502 m = mos6502_create(); uint8_t buffer[1 << 16] = {0}; - FILE *f = fopen(argv[1], "rb"); + FILE *f = fopen(argv[2], "rb"); size_t n = fread(buffer, 1, 1 << 16, f); fclose(f); @@ -678,7 +752,11 @@ int main(int argc, char *argv[]) { m.memory[0x600 + i] = buffer[i]; } - while (1) { - mos6502_step(&m); + if (argv[1][0] == 'd') { + mos6502_disassemble(&m, n); + } else { + while (1) { + mos6502_step(&m); + } } }