From 7133d0491ae3244d5334ca722d6adf541869aef1 Mon Sep 17 00:00:00 2001 From: Toni Date: Fri, 11 Jul 2025 14:29:47 +0200 Subject: [PATCH] implement simple ops --- chip8.c | 228 +++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 194 insertions(+), 34 deletions(-) diff --git a/chip8.c b/chip8.c index 8895457..ade09d2 100644 --- a/chip8.c +++ b/chip8.c @@ -1,9 +1,22 @@ // http://devernay.free.fr/hacks/chip8/C8TECH10.HTM -#include #include #include #include +#define READ_INS() \ + uint8_t low = c->memory[c->pc++]; \ + uint8_t high = c->memory[c->pc++]; \ + uint16_t ins = (low << 8) | high; \ + uint16_t nnn = ins & 0x0FFF; \ + uint8_t n = ins & 0x000F; \ + uint8_t x = (ins >> 8) & 0x0F; \ + uint8_t y = (ins >> 4) & 0x0F; \ + uint8_t kk = ins & 0x00FF + +#define BAD_INS() \ + fprintf(stderr, "unrecognized instruction\n"); \ + exit(1) + typedef struct CHIP8 { uint8_t *memory; uint16_t pc; @@ -42,17 +55,9 @@ CHIP8 chip8_create() { return c; } -void chip8_disassemble(CHIP8 *c, size_t size) { - for (size_t i = 0; i < size; i++) { - uint8_t low = c->memory[c->pc++]; - uint8_t high = c->memory[c->pc++]; - uint16_t ins = (low << 8) | high; - - uint16_t nnn = ins & 0x0FFF; - uint8_t n = ins & 0x000F; - uint8_t x = (ins >> 8) & 0x0F; - uint8_t y = (ins >> 4) & 0x0F; - uint8_t kk = ins & 0x00FF; +void chip8_disassemble(CHIP8 *c, size_t ins_count) { + for (size_t i = 0; i < ins_count; i++) { + READ_INS(); switch ((ins >> 12) & 0xF) { case 0x0: { @@ -64,29 +69,29 @@ void chip8_disassemble(CHIP8 *c, size_t size) { puts("RET"); break; default: - printf("SYS %hd\n", nnn); + printf("SYS %u\n", nnn); } } break; case 0x1: { - printf("JP %hd\n", nnn); + printf("JP %u\n", nnn); } break; case 0x2: { - printf("CALL %hd\n", nnn); + printf("CALL %u\n", nnn); } break; case 0x3: { - printf("SE V%x, %hhd\n", x, kk); + printf("SE V%x, %u\n", x, kk); } break; case 0x4: { - printf("SNE V%x, %hhd\n", x, kk); + printf("SNE V%x, %u\n", x, kk); } break; case 0x5: { printf("SE V%x, V%x\n", x, y); } break; case 0x6: { - printf("LD V%x, %hhd\n", x, kk); + printf("LD V%x, %u\n", x, kk); } break; case 0x7: { - printf("ADD V%x, %hhd\n", x, kk); + printf("ADD V%x, %u\n", x, kk); } break; case 0x8: { switch (n) { @@ -118,24 +123,23 @@ void chip8_disassemble(CHIP8 *c, size_t size) { printf("SHL V%x\n", x); break; default: - fprintf(stderr, "unrecognized instruction\n"); - exit(1); + BAD_INS(); } } break; case 0x9: { printf("SNE V%x, V%x\n", x, y); } break; case 0xA: { - printf("LD I, %hd\n", nnn); + printf("LD I, %u\n", nnn); } break; case 0xB: { - printf("JP V0, %hd\n", nnn); + printf("JP V0, %u\n", nnn); } break; case 0xC: { - printf("RND V%x, %hd\n", x, kk); + printf("RND V%x, %u\n", x, kk); } break; case 0xD: { - printf("DRW V%x, V%x, %hhd\n", x, y, n); + printf("DRW V%x, V%x, %u\n", x, y, n); } break; case 0xE: { switch (kk) { @@ -146,8 +150,7 @@ void chip8_disassemble(CHIP8 *c, size_t size) { printf("SKNP V%x\n", x); break; default: - fprintf(stderr, "unrecognized instruction\n"); - exit(1); + BAD_INS(); } } break; case 0xF: { @@ -180,28 +183,185 @@ void chip8_disassemble(CHIP8 *c, size_t size) { printf("LD V%x, [I]\n", x); break; default: - fprintf(stderr, "unrecognized instruction\n"); - exit(1); + BAD_INS(); } } break; default: - fprintf(stderr, "unrecognized instruction\n"); - exit(1); + BAD_INS(); } } } +void chip8_execute(CHIP8 *c) { + while (1) { + READ_INS(); + + switch ((ins >> 12) & 0xF) { + case 0x0: { + switch (nnn) { + case 0x0E0: + puts("TODO: CLS"); + break; + case 0x0EE: + c->pc = c->stack[c->sp]; + c->sp--; + break; + default: + c->pc = nnn; + } + } break; + case 0x1: { + c->pc = nnn; + } break; + case 0x2: { + c->sp++; + c->stack[c->sp] = c->pc; + c->pc = nnn; + } break; + case 0x3: { + if (c->reg[x] == kk) { + c->pc += 2; + } + } break; + case 0x4: { + if (c->reg[x] != kk) { + c->pc += 2; + } + } break; + case 0x5: { + if (c->reg[x] == c->reg[y]) { + c->pc += 2; + } + } break; + case 0x6: { + c->reg[x] = kk; + } break; + case 0x7: { + c->reg[x] += kk; + } break; + case 0x8: { + switch (n) { + case 0x0: + c->reg[x] = c->reg[y]; + break; + case 0x1: + c->reg[x] |= c->reg[y]; + break; + case 0x2: + c->reg[x] &= c->reg[y]; + break; + case 0x3: + c->reg[x] ^= c->reg[y]; + break; + case 0x4: + printf("TODO: ADD V%x, V%x\n", x, y); + break; + case 0x5: + printf("TODO: SUB V%x, V%x\n", x, y); + break; + case 0x6: + printf("TODO: SHR V%x\n", x); + break; + case 0x7: + printf("TODO: SUBN V%x, V%x\n", x, y); + break; + case 0xE: + printf("TODO: SHL V%x\n", x); + break; + default: + BAD_INS(); + } + } break; + case 0x9: { + if (c->reg[x] != c->reg[y]) { + c->pc += 2; + } + } break; + case 0xA: { + c->I = nnn; + } break; + case 0xB: { + c->pc = nnn + c->reg[0]; + } break; + case 0xC: { + c->reg[x] = (rand() % 256) & kk; + } break; + case 0xD: { + printf("TODO: DRW V%x, V%x, %u\n", x, y, n); + } break; + case 0xE: { + switch (kk) { + case 0x9E: + printf("TODO: SKP V%x\n", x); + break; + case 0xA1: + printf("TODO: SKNP V%x\n", x); + break; + default: + BAD_INS(); + } + } break; + case 0xF: { + switch (kk) { + case 0x07: + c->reg[x] = c->delay_timer; + break; + case 0x0A: + printf("TODO: LD V%x, K\n", x); + break; + case 0x15: + c->delay_timer = c->reg[x]; + break; + case 0x18: + c->sound_timer = c->reg[x]; + break; + case 0x1E: + c->I += c->reg[x]; + break; + case 0x29: + printf("TODO: LD F, V%x\n", x); + break; + case 0x33: + c->memory[c->I] = c->reg[x] / 100; + c->memory[c->I + 1] = (c->reg[x] / 10) % 10; + c->memory[c->I + 2] = c->reg[x] % 10; + break; + case 0x55: + printf("TODO: LD [I], V%x\n", x); + break; + case 0x65: + printf("TODO: LD V%x, [I]\n", x); + break; + default: + BAD_INS(); + } + } break; + default: + BAD_INS(); + } + } +} + +void chip8_free(CHIP8 c) { free(c.memory); } + int main(int argc, char *argv[]) { + if (argc < 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + CHIP8 c = chip8_create(); - uint8_t buffer[100000]; + uint8_t buffer[4000]; FILE *f = fopen(argv[1], "rb"); - size_t n = fread(buffer, 1, 100000, f); + size_t n = fread(buffer, 1, 4000, f); fclose(f); for (size_t i = 0; i < n; i++) { c.memory[0x200 + i] = buffer[i]; } - chip8_disassemble(&c, n); + chip8_execute(&c); + + chip8_free(c); } \ No newline at end of file