more opcodes

This commit is contained in:
2025-07-15 12:38:46 +02:00
parent 53b90af719
commit df162fd642
2 changed files with 115 additions and 37 deletions

View File

@@ -344,11 +344,11 @@ void chip8_step(CHIP8 *c) {
c->reg[x] = c->delay_timer; c->reg[x] = c->delay_timer;
break; break;
case 0x0A: { case 0x0A: {
bool key_pressed = false; uint8_t key_pressed = 0;
while (!key_pressed && WindowShouldClose()) { while (!key_pressed && WindowShouldClose()) {
for (size_t i = 0; i < 16; i++) { for (size_t i = 0; i < 16; i++) {
if (IsKeyDown(keyboard_map[i])) { if (IsKeyDown(keyboard_map[i])) {
key_pressed = true; key_pressed = 1;
break; break;
} }
} }

144
mos6502.c
View File

@@ -32,17 +32,17 @@ MOS6502 mos6502_create(void) {
return m; 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) { void mos6502_set_zn(MOS6502 *m, uint8_t v) {
if (v == 0) { mos6502_set_flag(m, FLAG_Z, v == 0);
m->P |= FLAG_Z; mos6502_set_flag(m, FLAG_N, v & 0x80);
} else {
m->P &= ~FLAG_Z;
}
if (v & 0x80) {
m->P |= FLAG_N;
} else {
m->P &= ~FLAG_N;
}
} }
uint8_t mos6502_mem_read(MOS6502 *m, uint16_t addr) { return m->memory[addr]; } 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) { 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, // printf("$%04X: %02X A: %02X X: %02X Y: %02X\n", m->pc - 1, op, m->A,
// m->Y); // 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); 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; } break;
case 0x20: { 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 >> 8) & 0xFF);
mos6502_mem_write(m, 0x0100 + m->SP--, ret_addr & 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; } break;
case 0x48: { case 0x48: {
mos6502_mem_write(m, 0x0100 + m->SP--, m->A); mos6502_mem_write(m, 0x0100 + m->SP--, m->A);
} break; } break;
case 0x49: {
m->A ^= READ_U8();
mos6502_set_zn(m, m->A);
} break;
case 0x4A: { case 0x4A: {
uint8_t c = m->A & 0x01; mos6502_set_flag(m, FLAG_C, m->A & 0x01);
m->A >>= 1; m->A >>= 1;
if (c) {
m->P |= FLAG_C;
} else {
m->P &= ~FLAG_C;
}
mos6502_set_zn(m, m->A); mos6502_set_zn(m, m->A);
} break; } break;
case 0x4C: { case 0x4C: {
@@ -92,7 +117,30 @@ void mos6502_step(MOS6502 *m) {
case 0x60: { case 0x60: {
uint16_t low = mos6502_mem_read(m, 0x0100 + (++m->SP)); uint16_t low = mos6502_mem_read(m, 0x0100 + (++m->SP));
uint16_t high = 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; } break;
case 0x8D: { case 0x8D: {
mos6502_mem_write(m, READ_U16(), m->A); mos6502_mem_write(m, READ_U16(), m->A);
@@ -103,6 +151,10 @@ void mos6502_step(MOS6502 *m) {
m->pc += offset; m->pc += offset;
} }
} break; } break;
case 0x98: {
m->A = m->Y;
mos6502_set_zn(m, m->A);
} break;
case 0x99: { case 0x99: {
mos6502_mem_write(m, READ_U16() + m->Y, m->A); mos6502_mem_write(m, READ_U16() + m->Y, m->A);
} break; } break;
@@ -117,10 +169,18 @@ void mos6502_step(MOS6502 *m) {
m->X = READ_U8(); m->X = READ_U8();
mos6502_set_zn(m, m->X); mos6502_set_zn(m, m->X);
} break; } break;
case 0xA8: {
m->X = m->A;
mos6502_set_zn(m, m->X);
} break;
case 0xA9: { case 0xA9: {
m->A = READ_U8(); m->A = READ_U8();
mos6502_set_zn(m, m->A); mos6502_set_zn(m, m->A);
} break; } break;
case 0xAA: {
m->X = m->A;
mos6502_set_zn(m, m->X);
} break;
case 0xAD: { case 0xAD: {
m->A = mos6502_mem_read(m, READ_U16()); m->A = mos6502_mem_read(m, READ_U16());
mos6502_set_zn(m, m->A); mos6502_set_zn(m, m->A);
@@ -145,13 +205,13 @@ void mos6502_step(MOS6502 *m) {
} break; } break;
case 0xC9: { case 0xC9: {
uint8_t oper = READ_U8(); uint8_t oper = READ_U8();
if (m->A >= oper) { mos6502_set_flag(m, FLAG_C, m->A >= oper);
m->P |= FLAG_C;
} else {
m->P &= ~FLAG_C;
}
mos6502_set_zn(m, m->A - oper); mos6502_set_zn(m, m->A - oper);
} break; } break;
case 0xCA: {
m->X--;
mos6502_set_zn(m, m->X);
} break;
case 0xCE: { case 0xCE: {
uint16_t addr = READ_U16(); uint16_t addr = READ_U16();
uint8_t res = mos6502_mem_read(m, addr) - 1; uint8_t res = mos6502_mem_read(m, addr) - 1;
@@ -164,6 +224,12 @@ void mos6502_step(MOS6502 *m) {
m->pc += offset; m->pc += offset;
} }
} break; } 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: { case 0xEE: {
uint16_t addr = READ_U16(); uint16_t addr = READ_U16();
uint8_t res = mos6502_mem_read(m, addr) + 1; uint8_t res = mos6502_mem_read(m, addr) + 1;
@@ -174,6 +240,14 @@ void mos6502_step(MOS6502 *m) {
m->X++; m->X++;
mos6502_set_zn(m, m->X); mos6502_set_zn(m, m->X);
} break; } 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: { case 0xF0: {
int8_t offset = READ_U8(); int8_t offset = READ_U8();
if (m->P & FLAG_Z) { if (m->P & FLAG_Z) {
@@ -188,7 +262,7 @@ void mos6502_step(MOS6502 *m) {
void mos6502_disassemble(MOS6502 *m, size_t program_size) { void mos6502_disassemble(MOS6502 *m, size_t program_size) {
while (m->pc < 0x600 + program_size) { while (m->pc < 0x600 + program_size) {
printf("%04X: ", m->pc); printf("$%04X: ", m->pc);
uint8_t op = READ_U8(); uint8_t op = READ_U8();
switch (op) { switch (op) {
@@ -662,15 +736,15 @@ void mos6502_disassemble(MOS6502 *m, size_t program_size) {
void mos6502_free(MOS6502 m) { free(m.memory); } void mos6502_free(MOS6502 m) { free(m.memory); }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
if (argc < 2) { if (argc < 3) {
fprintf(stderr, "Usage: %s <path>\n", argv[0]); fprintf(stderr, "Usage: %s <d|r> <path>\n", argv[0]);
return 1; return 1;
} }
MOS6502 m = mos6502_create(); MOS6502 m = mos6502_create();
uint8_t buffer[1 << 16] = {0}; 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); size_t n = fread(buffer, 1, 1 << 16, f);
fclose(f); fclose(f);
@@ -678,7 +752,11 @@ int main(int argc, char *argv[]) {
m.memory[0x600 + i] = buffer[i]; m.memory[0x600 + i] = buffer[i];
} }
if (argv[1][0] == 'd') {
mos6502_disassemble(&m, n);
} else {
while (1) { while (1) {
mos6502_step(&m); mos6502_step(&m);
} }
} }
}