call stack

This commit is contained in:
2025-07-14 14:53:53 +02:00
parent 1f4815ce8c
commit 53b90af719

113
mos6502.c
View File

@@ -9,7 +9,7 @@
#define FLAG_N 0x80 #define FLAG_N 0x80
#define FLAG_V 0x40 #define FLAG_V 0x40
#define FLAG_D 0x04 #define FLAG_D 0x08
#define FLAG_I 0x04 #define FLAG_I 0x04
#define FLAG_Z 0x02 #define FLAG_Z 0x02
#define FLAG_C 0x01 #define FLAG_C 0x01
@@ -28,6 +28,7 @@ MOS6502 mos6502_create(void) {
MOS6502 m = {0}; MOS6502 m = {0};
m.pc = 0x600; m.pc = 0x600;
m.memory = calloc(1, 1 << 16); m.memory = calloc(1, 1 << 16);
m.SP = 0xFF;
return m; return m;
} }
@@ -44,35 +45,135 @@ void mos6502_set_zn(MOS6502 *m, uint8_t v) {
} }
} }
uint8_t mos6502_mem_read(MOS6502 *m, uint16_t addr) { return m->memory[addr]; }
void mos6502_mem_write(MOS6502 *m, uint16_t addr, uint8_t v) {
m->memory[addr] = v;
if (addr == 0x0400) {
putchar(m->memory[addr]);
}
}
void mos6502_step(MOS6502 *m) { void mos6502_step(MOS6502 *m) {
uint8_t op = READ_U8(); uint8_t op = READ_U8();
// printf("$%04X: %02X A: %02X X: %02X Y: %02X\n", m->pc, op, m->A, m->X,
// m->Y);
switch (op) { switch (op) {
case 0x00: { case 0x00: {
// TODO: its supposed to do some interrupt magic // TODO: its supposed to do some interrupt magic
exit(0); exit(0);
} break; } break;
case 0x20: {
uint16_t ret_addr = m->pc + 2;
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();
} break;
case 0x48: {
mos6502_mem_write(m, 0x0100 + m->SP--, m->A);
} break;
case 0x4A: {
uint8_t 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: { case 0x4C: {
m->pc = READ_U16(); m->pc = READ_U16();
} break; } break;
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);
} break;
case 0x8D: { case 0x8D: {
uint16_t addr = READ_U16(); mos6502_mem_write(m, READ_U16(), m->A);
m->memory[addr] = m->A; } break;
if (addr == 0x0400) { case 0x90: {
putchar(m->memory[addr]); int8_t offset = READ_U8();
if (!(m->P & FLAG_C)) {
m->pc += offset;
} }
} break; } break;
case 0x99: {
mos6502_mem_write(m, READ_U16() + m->Y, m->A);
} break;
case 0x9D: {
mos6502_mem_write(m, READ_U16() + m->X, m->A);
} break;
case 0xA0: { case 0xA0: {
m->Y = READ_U8(); m->Y = READ_U8();
mos6502_set_zn(m, m->Y); mos6502_set_zn(m, m->Y);
} break; } break;
case 0xA2: {
m->X = READ_U8();
mos6502_set_zn(m, m->X);
} break;
case 0xA9: {
m->A = READ_U8();
mos6502_set_zn(m, m->A);
} break;
case 0xAD: {
m->A = mos6502_mem_read(m, READ_U16());
mos6502_set_zn(m, m->A);
} break;
case 0xB0: {
int8_t offset = READ_U8();
if (m->P & FLAG_C) {
m->pc += offset;
}
} break;
case 0xB9: { case 0xB9: {
m->A = m->memory[READ_U16() + m->Y]; m->A = mos6502_mem_read(m, READ_U16() + m->Y);
mos6502_set_zn(m, m->A);
} break;
case 0xBD: {
m->A = mos6502_mem_read(m, READ_U16() + m->X);
mos6502_set_zn(m, m->A); mos6502_set_zn(m, m->A);
} break; } break;
case 0xC8: { case 0xC8: {
m->Y++; m->Y++;
mos6502_set_zn(m, m->Y); mos6502_set_zn(m, m->Y);
} break; } break;
case 0xC9: {
uint8_t oper = READ_U8();
if (m->A >= oper) {
m->P |= FLAG_C;
} else {
m->P &= ~FLAG_C;
}
mos6502_set_zn(m, m->A - oper);
} break;
case 0xCE: {
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 0xD0: {
int8_t offset = READ_U8();
if (!(m->P & FLAG_Z)) {
m->pc += offset;
}
} 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 0xE8: {
m->X++;
mos6502_set_zn(m, m->X);
} break;
case 0xF0: { case 0xF0: {
int8_t offset = READ_U8(); int8_t offset = READ_U8();
if (m->P & FLAG_Z) { if (m->P & FLAG_Z) {