From 16be73aadb33097eeb908d12eac01e60b7564b98 Mon Sep 17 00:00:00 2001 From: Toni Date: Tue, 15 Jul 2025 15:53:18 +0200 Subject: [PATCH] cli --- mos6502.c | 184 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 168 insertions(+), 16 deletions(-) diff --git a/mos6502.c b/mos6502.c index 699510e..71ef2a8 100644 --- a/mos6502.c +++ b/mos6502.c @@ -2,6 +2,7 @@ #include #include #include +#include #define READ_U8() m->memory[m->pc++] #define READ_U16() (READ_U8() | (READ_U8() << 8)) @@ -57,20 +58,30 @@ void mos6502_mem_write(MOS6502 *m, uint16_t addr, uint8_t v) { } void mos6502_step(MOS6502 *m) { - if (0) { - printf("$%04X: ", m->pc); - uint16_t old_pc = m->pc; - mos6502_disassemble_ins(m); - m->pc = old_pc; - printf("\tA: %02X X: %02X Y: %02X\n", m->A, m->X, m->Y); - } - uint8_t op = READ_U8(); switch (op) { case 0x00: { // TODO: its supposed to do some interrupt magic exit(0); } break; + case 0x05: { + m->A |= mos6502_mem_read(m, READ_U8()); + mos6502_set_zn(m, m->A); + } break; + case 0x06: { + uint8_t addr = READ_U8(); + uint8_t oper = mos6502_mem_read(m, addr); + uint8_t res = oper << 1; + mos6502_mem_write(m, addr, res); + mos6502_set_flag(m, FLAG_C, (oper >> 7) & 1); + mos6502_set_zn(m, res); + } break; + case 0x08: { + uint8_t res = m->P; + res |= (1 << 4); + res |= (1 << 5); + mos6502_mem_write(m, 0x0100 + m->SP--, res); + } break; case 0x09: { m->A |= READ_U8(); mos6502_set_zn(m, m->A); @@ -81,6 +92,25 @@ void mos6502_step(MOS6502 *m) { mos6502_set_flag(m, FLAG_C, carry); mos6502_set_zn(m, m->A); } break; + case 0x0D: { + m->A |= mos6502_mem_read(m, READ_U16()); + mos6502_set_zn(m, m->A); + } break; + case 0x0E: { + uint16_t addr = READ_U16(); + uint8_t oper = mos6502_mem_read(m, addr); + uint8_t res = oper << 1; + + mos6502_mem_write(m, addr, res); + mos6502_set_flag(m, FLAG_C, (oper & 0x80) != 0); + mos6502_set_zn(m, res); + } break; + case 0x10: { + int8_t offset = READ_U8(); + if (!(m->P & FLAG_N)) { + m->pc += offset; + } + } break; case 0x18: { mos6502_set_flag(m, FLAG_C, 0); } break; @@ -91,6 +121,19 @@ void mos6502_step(MOS6502 *m) { mos6502_mem_write(m, 0x0100 + m->SP--, ret_addr & 0xFF); m->pc = target; } break; + case 0x24: { + uint8_t oper = mos6502_mem_read(m, READ_U8()); + mos6502_set_flag(m, FLAG_Z, (m->A & oper) == 0); + mos6502_set_flag(m, FLAG_N, oper & 0x80); + mos6502_set_flag(m, FLAG_V, oper & 0x40); + } break; + case 0x25: { + m->A &= mos6502_mem_read(m, READ_U8()); + mos6502_set_zn(m, m->A); + } break; + case 0x28: { + m->P = mos6502_mem_read(m, 0x0100 + (++m->SP)); + } break; case 0x29: { m->A &= READ_U8(); mos6502_set_zn(m, m->A); @@ -102,9 +145,38 @@ void mos6502_step(MOS6502 *m) { mos6502_set_flag(m, FLAG_C, new_carry); mos6502_set_zn(m, m->A); } break; + case 0x2C: { + uint8_t oper = mos6502_mem_read(m, READ_U16()); + mos6502_set_flag(m, FLAG_Z, (m->A & oper) == 0); + mos6502_set_flag(m, FLAG_N, oper & 0x80); + mos6502_set_flag(m, FLAG_V, oper & 0x40); + } break; + case 0x2D: { + m->A &= mos6502_mem_read(m, READ_U16()); + mos6502_set_zn(m, m->A); + } break; + case 0x2E: { + uint16_t addr = READ_U16(); + uint8_t oper = mos6502_mem_read(m, addr); + uint8_t old_carry = (m->P & FLAG_C) ? 1 : 0; + uint8_t res = (oper << 1) | old_carry; + mos6502_mem_write(m, addr, res); + mos6502_set_flag(m, FLAG_C, (oper & 0x80) >> 7); + mos6502_set_zn(m, res); + } break; + case 0x30: { + int8_t offset = READ_U8(); + if (m->P & FLAG_N) { + m->pc += offset; + } + } break; case 0x38: { mos6502_set_flag(m, FLAG_C, 1); } break; + case 0x45: { + m->A ^= mos6502_mem_read(m, READ_U8()); + mos6502_set_zn(m, m->A); + } break; case 0x48: { mos6502_mem_write(m, 0x0100 + m->SP--, m->A); } break; @@ -120,6 +192,19 @@ void mos6502_step(MOS6502 *m) { case 0x4C: { m->pc = READ_U16(); } break; + case 0x4D: { + m->A ^= mos6502_mem_read(m, READ_U16()); + mos6502_set_zn(m, m->A); + } break; + case 0x50: { + int8_t offset = READ_U8(); + if (!(m->P & FLAG_V)) { + m->pc += offset; + } + } break; + case 0x58: { + mos6502_set_flag(m, FLAG_I, 0); + } break; case 0x60: { uint16_t low = mos6502_mem_read(m, 0x0100 + (++m->SP)); uint16_t high = mos6502_mem_read(m, 0x0100 + (++m->SP)); @@ -146,10 +231,9 @@ void mos6502_step(MOS6502 *m) { m->A = res; } 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); + uint8_t carry = m->A & 0x01; + m->A = (m->A >> 1) | ((m->P & FLAG_C) << 7); + mos6502_set_flag(m, FLAG_C, carry); mos6502_set_zn(m, m->A); } break; case 0x6C: { @@ -166,6 +250,20 @@ void mos6502_step(MOS6502 *m) { mos6502_set_zn(m, res); m->A = res; } break; + case 0x6E: { + uint16_t addr = READ_U16(); + uint8_t oper = mos6502_mem_read(m, addr); + uint8_t res = (oper >> 1) | ((m->P & FLAG_C) << 7); + mos6502_mem_write(m, addr, res); + mos6502_set_flag(m, FLAG_C, oper & 0x01); + mos6502_set_zn(m, res); + } break; + case 0x70: { + int8_t offset = READ_U8(); + if (m->P & FLAG_V) { + m->pc += offset; + } + } break; case 0x78: { mos6502_set_flag(m, FLAG_I, 1); } break; @@ -177,6 +275,9 @@ void mos6502_step(MOS6502 *m) { m->A = m->X; mos6502_set_zn(m, m->A); } break; + case 0x84: { + mos6502_mem_write(m, READ_U8(), m->Y); + } break; case 0x85: { mos6502_mem_write(m, READ_U8(), m->A); } break; @@ -220,6 +321,10 @@ void mos6502_step(MOS6502 *m) { m->X = READ_U8(); mos6502_set_zn(m, m->X); } break; + case 0xA4: { + m->Y = mos6502_mem_read(m, READ_U8()); + mos6502_set_zn(m, m->Y); + } break; case 0xA5: { m->A = mos6502_mem_read(m, READ_U8()); mos6502_set_zn(m, m->A); @@ -261,6 +366,10 @@ void mos6502_step(MOS6502 *m) { m->A = mos6502_mem_read(m, addr + m->Y); mos6502_set_zn(m, m->A); } break; + case 0xB5: { + m->A = mos6502_mem_read(m, READ_U8() + m->X); + mos6502_set_zn(m, m->A); + } break; case 0xB9: { m->A = mos6502_mem_read(m, READ_U16() + m->Y); mos6502_set_zn(m, m->A); @@ -315,6 +424,18 @@ void mos6502_step(MOS6502 *m) { mos6502_set_flag(m, FLAG_C, m->X >= oper); mos6502_set_zn(m, res); } break; + case 0xE4: { + uint8_t oper = mos6502_mem_read(m, READ_U8()); + uint16_t res = m->X - oper; + mos6502_set_flag(m, FLAG_C, m->X >= oper); + mos6502_set_zn(m, res); + } break; + case 0xEC: { + uint8_t oper = mos6502_mem_read(m, READ_U16()); + 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; @@ -339,12 +460,23 @@ void mos6502_step(MOS6502 *m) { m->A = res; mos6502_set_zn(m, m->A); } break; + case 0xED: { + uint8_t oper = mos6502_mem_read(m, READ_U16()); + 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) { m->pc += offset; } } break; + case 0xF8: { + mos6502_set_flag(m, FLAG_D, 1); + } break; default: fprintf(stderr, "unrecognized opcode: $%02X\n", op); exit(1); @@ -831,15 +963,28 @@ 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 < 3) { - fprintf(stderr, "Usage: %s \n", argv[0]); + const char *path = NULL; + uint8_t disassemble = 0; + uint8_t print_cpu = 0; + for (size_t i = 1; i < argc; i++) { + if (strcmp(argv[i], "-d") == 0) { + disassemble = 1; + } else if (strcmp(argv[i], "-p") == 0) { + print_cpu = 1; + } else { + path = argv[i]; + } + } + + if (path == NULL) { + printf("Usage: %s [-d] [-p] \n", argv[0]); return 1; } MOS6502 m = mos6502_create(); uint8_t buffer[1 << 16] = {0}; - FILE *f = fopen(argv[2], "rb"); + FILE *f = fopen(path, "rb"); size_t n = fread(buffer, 1, 1 << 16, f); fclose(f); @@ -847,10 +992,17 @@ int main(int argc, char *argv[]) { m.memory[0x600 + i] = buffer[i]; } - if (argv[1][0] == 'd') { + if (disassemble) { mos6502_disassemble(&m, n); } else { while (1) { + if (print_cpu) { + printf("$%04X: ", m.pc); + uint16_t old_pc = m.pc; + mos6502_disassemble_ins(&m); + m.pc = old_pc; + printf("\tA: %02X X: %02X Y: %02X\n", m.A, m.X, m.Y); + } mos6502_step(&m); } }