more opcodes
This commit is contained in:
4
chip8.c
4
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;
|
||||
}
|
||||
}
|
||||
|
||||
148
mos6502.c
148
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 <path>\n", argv[0]);
|
||||
if (argc < 3) {
|
||||
fprintf(stderr, "Usage: %s <d|r> <path>\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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user