almost there

This commit is contained in:
2025-07-15 17:26:40 +02:00
parent 16be73aadb
commit 442b775cec

239
mos6502.c
View File

@@ -24,7 +24,7 @@ typedef struct MOS6502 {
uint8_t P;
} MOS6502;
void mos6502_disassemble_ins(MOS6502 *m);
void mos6502_disassemble(MOS6502 *m);
MOS6502 mos6502_create(void) {
MOS6502 m = {0};
@@ -64,6 +64,13 @@ void mos6502_step(MOS6502 *m) {
// TODO: its supposed to do some interrupt magic
exit(0);
} break;
case 0x01: {
uint16_t oper = READ_U8() + m->X;
uint16_t addr =
mos6502_mem_read(m, oper) | (mos6502_mem_read(m, oper + 1) << 8);
m->A |= mos6502_mem_read(m, addr);
mos6502_set_zn(m, m->A);
} break;
case 0x05: {
m->A |= mos6502_mem_read(m, READ_U8());
mos6502_set_zn(m, m->A);
@@ -86,6 +93,13 @@ void mos6502_step(MOS6502 *m) {
m->A |= READ_U8();
mos6502_set_zn(m, m->A);
} break;
case 0x11: {
uint16_t oper = READ_U8();
uint16_t addr =
mos6502_mem_read(m, oper) | (mos6502_mem_read(m, oper + 1) << 8);
m->A |= mos6502_mem_read(m, addr + m->Y);
mos6502_set_zn(m, m->A);
} break;
case 0x0A: {
uint8_t carry = (m->A & 0x80) != 0;
m->A <<= 1;
@@ -121,6 +135,13 @@ void mos6502_step(MOS6502 *m) {
mos6502_mem_write(m, 0x0100 + m->SP--, ret_addr & 0xFF);
m->pc = target;
} break;
case 0x21: {
uint16_t oper = READ_U8() + m->X;
uint16_t addr =
mos6502_mem_read(m, oper) | (mos6502_mem_read(m, oper + 1) << 8);
m->A &= mos6502_mem_read(m, addr);
mos6502_set_zn(m, m->A);
} break;
case 0x24: {
uint8_t oper = mos6502_mem_read(m, READ_U8());
mos6502_set_flag(m, FLAG_Z, (m->A & oper) == 0);
@@ -158,8 +179,7 @@ void mos6502_step(MOS6502 *m) {
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;
uint8_t res = (oper << 1) | ((m->P & FLAG_C) ? 1 : 0);
mos6502_mem_write(m, addr, res);
mos6502_set_flag(m, FLAG_C, (oper & 0x80) >> 7);
mos6502_set_zn(m, res);
@@ -170,9 +190,35 @@ void mos6502_step(MOS6502 *m) {
m->pc += offset;
}
} break;
case 0x31: {
uint16_t oper = READ_U8();
uint16_t addr =
mos6502_mem_read(m, oper) | (mos6502_mem_read(m, oper + 1) << 8);
m->A &= mos6502_mem_read(m, addr + m->Y);
mos6502_set_zn(m, m->A);
} break;
case 0x35: {
m->A &= mos6502_mem_read(m, READ_U8() + m->X);
mos6502_set_zn(m, m->A);
} break;
case 0x38: {
mos6502_set_flag(m, FLAG_C, 1);
} break;
case 0x39: {
m->A &= mos6502_mem_read(m, READ_U16() + m->Y);
mos6502_set_zn(m, m->A);
} break;
case 0x3D: {
m->A &= mos6502_mem_read(m, READ_U16() + m->X);
mos6502_set_zn(m, m->A);
} break;
case 0x41: {
uint16_t oper = READ_U8() + m->X;
uint16_t addr =
mos6502_mem_read(m, oper) | (mos6502_mem_read(m, oper + 1) << 8);
m->A ^= mos6502_mem_read(m, addr);
mos6502_set_zn(m, m->A);
} break;
case 0x45: {
m->A ^= mos6502_mem_read(m, READ_U8());
mos6502_set_zn(m, m->A);
@@ -202,9 +248,28 @@ void mos6502_step(MOS6502 *m) {
m->pc += offset;
}
} break;
case 0x51: {
uint16_t oper = READ_U8();
uint16_t addr =
mos6502_mem_read(m, oper) | (mos6502_mem_read(m, oper + 1) << 8);
m->A ^= mos6502_mem_read(m, addr + m->Y);
mos6502_set_zn(m, m->A);
} break;
case 0x55: {
m->A ^= mos6502_mem_read(m, READ_U8() + m->X);
mos6502_set_zn(m, m->A);
} break;
case 0x58: {
mos6502_set_flag(m, FLAG_I, 0);
} break;
case 0x59: {
m->A ^= mos6502_mem_read(m, READ_U16() + m->Y);
mos6502_set_zn(m, m->A);
} break;
case 0x5D: {
m->A ^= mos6502_mem_read(m, READ_U16() + m->X);
mos6502_set_zn(m, m->A);
} break;
case 0x60: {
uint16_t low = mos6502_mem_read(m, 0x0100 + (++m->SP));
uint16_t high = mos6502_mem_read(m, 0x0100 + (++m->SP));
@@ -281,6 +346,12 @@ void mos6502_step(MOS6502 *m) {
case 0x85: {
mos6502_mem_write(m, READ_U8(), m->A);
} break;
case 0x86: {
mos6502_mem_write(m, READ_U8(), m->X);
} break;
case 0x8C: {
mos6502_mem_write(m, READ_U16(), m->Y);
} break;
case 0x8D: {
mos6502_mem_write(m, READ_U16(), m->A);
} break;
@@ -293,6 +364,15 @@ void mos6502_step(MOS6502 *m) {
m->pc += offset;
}
} break;
case 0x94: {
mos6502_mem_write(m, READ_U8() + m->X, m->Y);
} break;
case 0x95: {
mos6502_mem_write(m, READ_U8() + m->X, m->A);
} break;
case 0x96: {
mos6502_mem_write(m, READ_U8() + m->Y, m->X);
} break;
case 0x98: {
m->A = m->Y;
mos6502_set_zn(m, m->A);
@@ -345,6 +425,10 @@ void mos6502_step(MOS6502 *m) {
m->X = m->A;
mos6502_set_zn(m, m->X);
} break;
case 0xAC: {
m->Y = mos6502_mem_read(m, READ_U16());
mos6502_set_zn(m, m->Y);
} break;
case 0xAD: {
m->A = mos6502_mem_read(m, READ_U16());
mos6502_set_zn(m, m->A);
@@ -366,24 +450,51 @@ void mos6502_step(MOS6502 *m) {
m->A = mos6502_mem_read(m, addr + m->Y);
mos6502_set_zn(m, m->A);
} break;
case 0xB4: {
m->Y = mos6502_mem_read(m, READ_U8() + m->X);
mos6502_set_zn(m, m->Y);
} break;
case 0xB5: {
m->A = mos6502_mem_read(m, READ_U8() + m->X);
mos6502_set_zn(m, m->A);
} break;
case 0xB6: {
m->X = mos6502_mem_read(m, READ_U8() + m->Y);
mos6502_set_zn(m, m->X);
} break;
case 0xB9: {
m->A = mos6502_mem_read(m, READ_U16() + m->Y);
mos6502_set_zn(m, m->A);
} break;
case 0xBC: {
m->Y = mos6502_mem_read(m, READ_U16() + m->X);
mos6502_set_zn(m, m->Y);
} break;
case 0xBD: {
m->A = mos6502_mem_read(m, READ_U16() + m->X);
mos6502_set_zn(m, m->A);
} break;
case 0xBE: {
m->X = mos6502_mem_read(m, READ_U16() + m->Y);
mos6502_set_zn(m, m->X);
} break;
case 0xC0: {
uint8_t oper = READ_U8();
uint16_t res = m->Y - oper;
mos6502_set_flag(m, FLAG_C, m->Y >= oper);
mos6502_set_zn(m, res);
} break;
case 0xC4: {
uint8_t oper = mos6502_mem_read(m, READ_U8());
uint16_t res = m->Y - oper;
mos6502_set_flag(m, FLAG_C, m->Y >= oper);
mos6502_set_zn(m, res);
} break;
case 0xC5: {
uint8_t oper = mos6502_mem_read(m, READ_U8());
mos6502_set_flag(m, FLAG_C, m->A >= oper);
mos6502_set_zn(m, m->A - oper);
} break;
case 0xC6: {
uint16_t addr = READ_U8();
uint8_t res = mos6502_mem_read(m, addr) - 1;
@@ -403,6 +514,17 @@ void mos6502_step(MOS6502 *m) {
m->X--;
mos6502_set_zn(m, m->X);
} break;
case 0xCC: {
uint8_t oper = mos6502_mem_read(m, READ_U16());
uint16_t res = m->Y - oper;
mos6502_set_flag(m, FLAG_C, m->Y >= oper);
mos6502_set_zn(m, res);
} break;
case 0xCD: {
uint8_t oper = mos6502_mem_read(m, READ_U16());
mos6502_set_flag(m, FLAG_C, m->A >= oper);
mos6502_set_zn(m, m->A - oper);
} break;
case 0xCE: {
uint16_t addr = READ_U16();
uint8_t res = mos6502_mem_read(m, addr) - 1;
@@ -415,9 +537,36 @@ void mos6502_step(MOS6502 *m) {
m->pc += offset;
}
} break;
case 0xD5: {
uint8_t oper = mos6502_mem_read(m, READ_U8() + m->X);
mos6502_set_flag(m, FLAG_C, m->A >= oper);
mos6502_set_zn(m, m->A - oper);
} break;
case 0xD6: {
uint16_t addr = READ_U8() + m->X;
uint8_t res = mos6502_mem_read(m, addr) - 1;
mos6502_mem_write(m, addr, res);
mos6502_set_zn(m, res);
} break;
case 0xD8: {
mos6502_set_flag(m, FLAG_D, 0);
} break;
case 0xD9: {
uint8_t oper = mos6502_mem_read(m, READ_U16() + m->Y);
mos6502_set_flag(m, FLAG_C, m->A >= oper);
mos6502_set_zn(m, m->A - oper);
} break;
case 0xDD: {
uint8_t oper = mos6502_mem_read(m, READ_U16() + m->X);
mos6502_set_flag(m, FLAG_C, m->A >= oper);
mos6502_set_zn(m, m->A - oper);
} break;
case 0xDE: {
uint16_t addr = READ_U16() + m->X;
uint8_t res = mos6502_mem_read(m, addr) - 1;
mos6502_mem_write(m, addr, res);
mos6502_set_zn(m, res);
} break;
case 0xE0: {
uint8_t oper = READ_U8();
uint16_t res = m->X - oper;
@@ -430,17 +579,13 @@ void mos6502_step(MOS6502 *m) {
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;
mos6502_mem_write(m, addr, res);
mos6502_set_zn(m, res);
case 0xE5: {
uint8_t oper = mos6502_mem_read(m, 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 0xE6: {
uint16_t addr = READ_U8();
@@ -460,6 +605,14 @@ void mos6502_step(MOS6502 *m) {
m->A = res;
mos6502_set_zn(m, m->A);
} break;
case 0xEA: {
} 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 0xED: {
uint8_t oper = mos6502_mem_read(m, READ_U16());
uint16_t res = m->A - oper - ((m->P & FLAG_C) ? 0 : 1);
@@ -468,22 +621,58 @@ void mos6502_step(MOS6502 *m) {
m->A = res;
mos6502_set_zn(m, m->A);
} break;
case 0xEE: {
uint16_t addr = READ_U16();
uint8_t res = mos6502_mem_read(m, addr) + 1;
mos6502_mem_write(m, addr, res);
mos6502_set_zn(m, res);
} break;
case 0xF0: {
int8_t offset = READ_U8();
if (m->P & FLAG_Z) {
m->pc += offset;
}
} break;
case 0xF5: {
uint8_t oper = mos6502_mem_read(m, READ_U8() + m->X);
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 0xF8: {
mos6502_set_flag(m, FLAG_D, 1);
} break;
case 0xF9: {
uint8_t oper = mos6502_mem_read(m, READ_U16() + m->Y);
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 0xFD: {
uint8_t oper = mos6502_mem_read(m, READ_U16() + m->X);
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 0xFE: {
uint16_t addr = READ_U16() + m->X;
uint8_t res = mos6502_mem_read(m, addr) + 1;
mos6502_mem_write(m, addr, res);
mos6502_set_zn(m, res);
} break;
default:
fprintf(stderr, "unrecognized opcode: $%02X\n", op);
exit(1);
}
}
void mos6502_disassemble_ins(MOS6502 *m) {
void mos6502_disassemble(MOS6502 *m) {
uint8_t op = READ_U8();
switch (op) {
case 0x00: {
@@ -952,21 +1141,13 @@ void mos6502_disassemble_ins(MOS6502 *m) {
}
}
void mos6502_disassemble(MOS6502 *m, size_t program_size) {
while (m->pc < 0x600 + program_size) {
printf("$%04X: ", m->pc);
mos6502_disassemble_ins(m);
printf("\n");
}
}
void mos6502_free(MOS6502 m) { free(m.memory); }
int main(int argc, char *argv[]) {
const char *path = NULL;
uint8_t disassemble = 0;
uint8_t print_cpu = 0;
for (size_t i = 1; i < argc; i++) {
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-d") == 0) {
disassemble = 1;
} else if (strcmp(argv[i], "-p") == 0) {
@@ -977,7 +1158,7 @@ int main(int argc, char *argv[]) {
}
if (path == NULL) {
printf("Usage: %s [-d] [-p] <path>\n", argv[0]);
fprintf(stderr, "Usage: %s [-d] [-p] <path>\n", argv[0]);
return 1;
}
@@ -993,13 +1174,17 @@ int main(int argc, char *argv[]) {
}
if (disassemble) {
mos6502_disassemble(&m, n);
while (m.pc < 0x600 + n) {
printf("$%04X: ", m.pc);
mos6502_disassemble(&m);
printf("\n");
}
} else {
while (1) {
if (print_cpu) {
printf("$%04X: ", m.pc);
uint16_t old_pc = m.pc;
mos6502_disassemble_ins(&m);
mos6502_disassemble(&m);
m.pc = old_pc;
printf("\tA: %02X X: %02X Y: %02X\n", m.A, m.X, m.Y);
}