summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chip8.c461
-rw-r--r--chip8.h4
-rw-r--r--roms/test_opcode.ch8bin0 -> 478 bytes
-rw-r--r--ui.c2
4 files changed, 231 insertions, 236 deletions
diff --git a/chip8.c b/chip8.c
index f5bed01..6cb6a55 100644
--- a/chip8.c
+++ b/chip8.c
@@ -17,29 +17,29 @@
#include "util.h"
#include "chip8.h"
-#define ROM_FILE "roms/e.ch8"
+#define ROM_FILE "roms/test_opcode.ch8"
static void load_rom();
static void init_vm();
-static void push_top_of_stack(u16 val);
static void vm_thread(void* v);
chip8_vm vm;
void init_vm() {
- memset(&vm, 0, sizeof(chip8_vm));
vm.PC = 0x200; // start of chip8 programs
}
void load_rom() {
+ memset(&vm, 0, sizeof(chip8_vm));
FILE* f = fopen(ROM_FILE, "r");
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
fseek(f, 0, SEEK_SET);
- vm.rom = malloc(fsize + 1);
- vm.rom_size = 0x200 + fsize;
- if (fread(vm.rom, 1, fsize, f) != fsize) {
+ vm.rom = (u8*)malloc(0xFFF);
+
+ memset(vm.rom, 0, 0xFFF);
+ if (fread(&vm.rom[0x200], 1, fsize, f) != fsize) {
printf("err: failed to read rom fully\n");
exit(1);
}
@@ -47,252 +47,249 @@ void load_rom() {
fclose(f);
}
-void push_top_of_stack(u16 val) {
- for (u16 i = vm.SP; i < vm.stack_count; i++) {
- if (i >= 15) {
- exit(1);
- }
- vm.stack[i+1] = vm.stack[i];
- }
- vm.stack[vm.SP] = val;
-}
-
void vm_thread(void* v) {
-
- // read 2 bytes and convert to big-endian
- u16 in = htons(vm.rom[(vm.PC) - 0x1FF]<<8 | vm.rom[(vm.PC) - 0x200]);
-
u8 buf[255];
+ while (1) {
+ // read 2 bytes and convert to big-endian
+ u16 in = htons(vm.rom[vm.PC + 0x1]<<8 | vm.rom[vm.PC]);
+ //printf("%x\n", in);
- if (in == 0xE0) {
- memset(&vm.screen, 0, sizeof(vm.screen));
- }
-
- // in>>12&0xF 0xFFFf
- // ^
- // in>>8&0xF 0xFFFf
- // ^
- // in>>4&0xF 0xFFFf
- // ^
- // in&0xF 0xFFFf
- // ^
- // in&0xFFF 0xFFFf
- // ^^^
- // in&0xFF 0xFFFf
- // ^^
- // in&0xFF 0xFFFf
- // ^^
+ // in>>12&0xF 0xFFFf
+ // ^
+ // in>>8&0xF 0xFFFf
+ // ^
+ // in>>4&0xF 0xFFFf
+ // ^
+ // in&0xF 0xFFFf
+ // ^
+ // in&0xFFF 0xFFFf
+ // ^^^
+ // in&0xFF 0xFFFf
+ // ^^
+ // in&0xFF 0xFFFf
+ // ^^
- switch ((in>>12&0xF)) {
- case 0x0:
- if (in == 0x00E0) { // CLS
- memset(&vm.screen, 0, sizeof(vm.screen));
- } else if (in == 0x00EE) { // RET
- vm.PC = vm.stack[vm.SP--];
- }
- break;
- case 0x1: // JP addr
- vm.PC = in&0xFFF;
- break;
- case 0x2: // CALL addr
- vm.SP++;
- push_top_of_stack(vm.PC);
- vm.PC = in&0xFFF;
- break;
- case 0x3: // SE Vx, byte
- if (vm.Vx[in>>8&0xF] == (in&0xFF)) {
- vm.PC += 0x2;
- }
- break;
- case 0x4: // SNE Vx, byte
- if (vm.Vx[in>>8&0xF] != (in&0xFF)) {
- vm.PC += 0x2;
- }
- break;
- case 0x5: // SE Vx, Vy
- if (vm.Vx[in>>8&0xF] == vm.Vx[in>>4&0xF]) {
- vm.PC += 0x2;
- }
- break;
- case 0x6: // LD Vx, byte
- vm.Vx[in>>8&0xF] = in&0xFF;
- break;
- case 0x7: // ADD Vx, byte
- vm.Vx[in>>8&0xF] += in&0xFF;
- break;
- case 0x8:
- switch(in&0xF) {
- case 0x0: // LD Vx, Vy
- vm.Vx[in>>8&0xF] = vm.Vx[in>>4&0xF];
- break;
- case 0x1: // OR Vx, Vy
- vm.Vx[in>>8&0xF] |= vm.Vx[in>>4&0xF];
- break;
- case 0x2: // AND Vx, Vy
- vm.Vx[in>>8&0xF] &= vm.Vx[in>>4&0xF];
- break;
- case 0x3: // XOR Vx, Vy
- vm.Vx[in>>8&0xF] ^= vm.Vx[in>>4&0xF];
- break;
- case 0x4: // ADD Vx, Vy
- vm.Vx[in>>8&0xF] += vm.Vx[in>>4&0xF];
- if (vm.Vx[in>>8&0xF] + vm.Vx[in>>4&0xF] > 255) {
- vm.Vx[15] = 1;
- vm.Vx[in>>8&0xF] &= 0xFF;
- } else {
- vm.Vx[15] = 0;
- }
- break;
- case 0x5: // SUB Vx, Vy
- if (vm.Vx[in>>8&0xF] > vm.Vx[in>>4&0xF]) {
- vm.Vx[15] = 1;
- } else {
- vm.Vx[15] = 0;
- }
- vm.Vx[in>>8&0xF] -= vm.Vx[in>>4&0xF];
- break;
- case 0x6: // SHR Vx {, Vy}
- if ((vm.Vx[in>>8&0xF] & 1) == 1) {
- vm.Vx[15] = 1;
- } else {
- vm.Vx[15] = 0;
- }
- vm.Vx[in>>8&0xF] /= 2;
- break;
- case 0x7: // SUBN Vx, Vy
- if (vm.Vx[in>>8&0xF] < vm.Vx[in>>4&0xF]) {
- vm.Vx[15] = 1;
- } else {
- vm.Vx[15] = 0;
- }
- vm.Vx[in>>8&0xF] = vm.Vx[in>>4&0xF] - vm.Vx[in>>8&0xF];
- break;
- case 0xE: // SHL Vx {, Vy}
- if ((vm.Vx[in>>8&0xF] & 1) == 1) {
- vm.Vx[15] = 1;
- } else {
- vm.Vx[15] = 0;
- }
- vm.Vx[in>>8&0xF] *= 2;
- break;
- }
- break;
- case 0x9: // SNE Vx, Vy
- if (vm.Vx[(in>>8&0xF)] != vm.Vx[(in>>4&0xF)]) {
- vm.PC += 0x2;
- }
- break;
- case 0xA: // LD I, addr
- vm.I = in&0xFFF;
- break;
- case 0xB: // JP V0, addr
- vm.PC = (in&0xFFF) + vm.Vx[0];
- break;
- case 0xC: // RND Vx, byte
- vm.Vx[in>>8&0xF] = (rand() % 255) & in&0xFF;
- break;
- case 0xD: // DRW Vx, Vy, nibble
- memcpy(buf, &vm.rom[vm.I - 0x200], in&0xF);
- for (int i = 0; i < (in&0xF); i++) {
- for (int s = 0; s < 8; s++) {
- u8 bit = (buf[i]>>s)&1;
+ switch ((in>>12&0xF)) {
+ case 0x0:
+ switch (in&0xFF) {
+ case 0xE0: // CLS
+ memset(&vm.screen, 0, sizeof(vm.screen));
+ break;
+ case 0xEE: // RET
+ vm.PC = vm.stack[vm.SP--];
+ break;
+ }
+ break;
+ case 0x1: // JP addr
+ vm.PC = (in&0xFFF) - 0x2;
+ break;
+ case 0x2: // CALL addr
+ vm.stack[++vm.SP] = vm.PC;
+ vm.PC = (in&0xFFF) - 0x2;
+ break;
+ case 0x3: // SE Vx, byte
+ if (vm.Vx[in>>8&0xF] == (in&0xFF)) {
+ vm.PC += 0x2;
+ }
+ break;
+ case 0x4: // SNE Vx, byte
+ if (vm.Vx[in>>8&0xF] != (in&0xFF)) {
+ vm.PC += 0x2;
+ }
+ break;
+ case 0x5: // SE Vx, Vy
+ if (vm.Vx[in>>8&0xF] == vm.Vx[in>>4&0xF]) {
+ vm.PC += 0x2;
+ }
+ break;
+ case 0x6: // LD Vx, byte
+ vm.Vx[in>>8&0xF] = in&0xFF;
+ break;
+ case 0x7: // ADD Vx, byte
+ vm.Vx[in>>8&0xF] += in&0xFF;
+ break;
+ case 0x8:
+ switch(in&0xF) {
+ case 0x0: // LD Vx, Vy
+ vm.Vx[in>>8&0xF] = vm.Vx[in>>4&0xF];
+ break;
+ case 0x1: // OR Vx, Vy
+ vm.Vx[in>>8&0xF] |= vm.Vx[in>>4&0xF];
+ break;
+ case 0x2: // AND Vx, Vy
+ vm.Vx[in>>8&0xF] &= vm.Vx[in>>4&0xF];
+ break;
+ case 0x3: // XOR Vx, Vy
+ vm.Vx[in>>8&0xF] ^= vm.Vx[in>>4&0xF];
+ break;
+ case 0x4: // ADD Vx, Vy
+ vm.Vx[in>>8&0xF] += vm.Vx[in>>4&0xF];
+ if (vm.Vx[in>>8&0xF] + vm.Vx[in>>4&0xF] > 255) {
+ vm.Vx[15] = 1;
+ vm.Vx[in>>8&0xF] &= 0xFF;
+ } else {
+ vm.Vx[15] = 0;
+ }
+ break;
+ case 0x5: // SUB Vx, Vy
+ if (vm.Vx[in>>8&0xF] > vm.Vx[in>>4&0xF]) {
+ vm.Vx[15] = 1;
+ } else {
+ vm.Vx[15] = 0;
+ }
+ vm.Vx[in>>8&0xF] -= vm.Vx[in>>4&0xF];
+ break;
+ case 0x6: // SHR Vx {, Vy}
+ if ((vm.Vx[in>>8&0xF] & 1) == 1) {
+ vm.Vx[15] = 1;
+ } else {
+ vm.Vx[15] = 0;
+ }
+ vm.Vx[in>>8&0xF] /= 2;
+ break;
+ case 0x7: // SUBN Vx, Vy
+ if (vm.Vx[in>>8&0xF] < vm.Vx[in>>4&0xF]) {
+ vm.Vx[15] = 1;
+ } else {
+ vm.Vx[15] = 0;
+ }
+ vm.Vx[in>>8&0xF] = vm.Vx[in>>4&0xF] - vm.Vx[in>>8&0xF];
+ break;
+ case 0xE: // SHL Vx {, Vy}
+ if ((vm.Vx[in>>8&0xF] & 1) == 1) {
+ vm.Vx[15] = 1;
+ } else {
+ vm.Vx[15] = 0;
+ }
+ vm.Vx[in>>8&0xF] *= 2;
+ break;
+ }
+ break;
+ case 0x9: // SNE Vx, Vy
+ if (vm.Vx[(in>>8&0xF)] != vm.Vx[(in>>4&0xF)]) {
+ vm.PC += 0x2;
+ }
+ break;
+ case 0xA: // LD I, addr
+ vm.I = in&0xFFF;
+ break;
+ case 0xB: // JP V0, addr
+ vm.PC = ((in&0xFFF) + vm.Vx[0]) - 0x2;
+ break;
+ case 0xC: // RND Vx, byte
+ vm.Vx[in>>8&0xF] = (rand() % 255) & in&0xFF;
+ break;
+ case 0xD: // DRW Vx, Vy, nibble
+ memcpy(buf, &vm.rom[vm.I], in&0xF);
+ for (int i = 0; i < (in&0xF); i++) {
+ for (int s = 0; s < 8; s++) {
+ u8 bit = (buf[i]>>s)&1;
- if (bit) {
- u8 x = (vm.Vx[in>>8&0xF] + 7) - s;
- u8 y = i + vm.Vx[in>>4&0xF];
-
- while (x > 63) { x -= 63; }
- while (y > 31) { y -= 31; }
+ if (bit) {
+ u8 x = (vm.Vx[in>>8&0xF] + 7) - s;
+ u8 y = i + vm.Vx[in>>4&0xF];
+
+ while (x > 63) { x -= 63; }
+ while (y > 31) { y -= 31; }
- if (vm.screen[x][y]) {
- vm.screen[x][y] = 0;
- } else {
- vm.screen[x][y] = 1;
+ if (vm.screen[x][y]) {
+ vm.screen[x][y] = 0;
+ } else {
+ vm.screen[x][y] = 1;
+ }
}
}
}
- }
- break;
- case 0xE:
- switch (in&0xFF) {
- case 0x9E:
- if (vm.keyboard[vm.Vx[in>>8&0xF]]) {
- vm.PC += 0x2;
- }
- break;
- case 0xA1:
- if (!vm.keyboard[vm.Vx[in>>8&0xF]]) {
- vm.PC += 0x2;
- }
- break;
- }
- break;
- case 0xF:
- switch (in&0xFF) {
- case 0x07:
- vm.Vx[in>>8&0xF] = vm.DT;
- break;
- case 0x0A:
- vm.Vx[in>>8&0xF] = ui_get_key(true);
- break;
- case 0x15:
- vm.DT = vm.Vx[in>>8&0xF];
- break;
- case 0x18:
- vm.ST = vm.Vx[in>>8&0xF];
- break;
- case 0x1E:
- vm.I += vm.Vx[in>>8&0xF];
- break;
- case 0x29:
- // characters
- break;
- case 0x33:
- vm.rom[vm.I - 0x200] = floor(vm.Vx[in>>8&0xF] / 100);
- vm.rom[(vm.I - 0x200)+1] = floor((vm.Vx[in>>8&0xF] % 100)/10);
- vm.rom[(vm.I - 0x200)+2] = floor(vm.Vx[in>>8&0xF] % 10);
- break;
- case 0x55:
- for (int i = 0; i < (in>>8&0xF); i++) {
- vm.rom[(vm.I - 0x200) - i] = vm.Vx[i];
- }
- break;
- case 0x65:
- for (int i = 0; i < (in>>8&0xF); i++) {
- vm.Vx[i] = vm.rom[(vm.I - 0x200) - i];
- }
- break;
- }
+ break;
+ case 0xE: switch (in&0xFF) {
+ case 0x9E: // SKP Vx
+ if (vm.keyboard[vm.Vx[in>>8&0xF]]) {
+ vm.PC += 0x2;
+ }
+ break;
+ case 0xA1: // SKNP Vx
+ if (!vm.keyboard[vm.Vx[in>>8&0xF]]) {
+ vm.PC += 0x2;
+ }
+ break;
+ }
+ break;
+ case 0xF:
+ switch (in&0xFF) {
+ case 0x07: // LD Vx, DT
+ vm.Vx[in>>8&0xF] = vm.DT;
+ break;
+ case 0x0A: // LD Vx, K
+ vm.Vx[in>>8&0xF] = 0xA;//ui_get_key(true);
+ break;
+ case 0x15: // LD DT, Vx
+ vm.DT = vm.Vx[in>>8&0xF];
+ break;
+ case 0x18: // LD ST, Vx
+ vm.ST = vm.Vx[in>>8&0xF];
+ break;
+ case 0x1E: // ADD I, Vx
+ vm.I += vm.Vx[in>>8&0xF];
+ break;
+ case 0x29: // LD F, Vx
+ // characters
+ break;
+ case 0x33: // LD B, Vx
+ vm.rom[vm.I] = (vm.Vx[in>>8&0xF] / 100);
+ vm.rom[vm.I+0x1] = ((vm.Vx[in>>8&0xF] % 100)/10);
+ vm.rom[vm.I+0x2] = (vm.Vx[in>>8&0xF] % 10);
+ break;
+ case 0x55: // LD [I], Vx
+ for (int i = 0; i < (in>>8&0xF); i++) {
+ vm.rom[(vm.I) + i] = vm.Vx[i];
+ }
+ break;
+ case 0x65: // LD Vx, [I]
+ for (int i = 0; i < (in>>8&0xF); i++) {
+ vm.Vx[i] = vm.rom[(vm.I) - i];
+ }
+ break;
+ }
+ break;
+ }
+
+ vm.PC += 0x2;
+ usleep(100);
}
+}
- vm.PC += 0x2;
+void *dt_thread(void* v) {
+ while (1) {
+ if (vm.DT > 0) {
+ vm.DT--;
+ }
+ usleep(1000/60);
+ }
+}
+
+void *st_thread(void* v) {
+ while (1) {
+ if (vm.ST > 0) {
+ vm.ST--;
+ }
+ usleep(1000/60);
+ }
}
int main(void) {
srand(time(NULL));
- init_vm();
load_rom();
+ init_vm();
#ifdef _WIN32
- DWORD WINAPI loop(void* data) {
- while(1) {
- vm_thread(0);
- sleep(1);
- }
- return 0;
- }
- HANDLE thread = CreateThread(NULL, 0, loop, NULL, 0, NULL);
+ HANDLE vm = CreateThread(NULL, 0, vm_thread, NULL, 0, NULL);
#else
- void *loop(void) {
- while(1) {
- vm_thread(0);
- usleep(1000);
- }
- return 0;
- }
- pthread_t t; pthread_create(&t, NULL, (void*)loop, (void*)0);
+ pthread_t vm; pthread_create(&vm, NULL, (void*)vm_thread, (void*)0);
+ pthread_t dt; pthread_create(&dt, NULL, (void*)dt_thread, (void*)0);
+ pthread_t st; pthread_create(&st, NULL, (void*)st_thread, (void*)0);
#endif
-
+
+ //vm_thread(0);
init_curses();
curses_thread(0);
diff --git a/chip8.h b/chip8.h
index 490ef94..7646021 100644
--- a/chip8.h
+++ b/chip8.h
@@ -8,14 +8,12 @@ typedef struct {
u16 PC;
+ u8 SP;
u16 stack[16];
- u16 stack_pos;
- u16 stack_count;
u8 DT;
u8 ST;
- u8 SP;
u16 I;
u8 Vx[16];
diff --git a/roms/test_opcode.ch8 b/roms/test_opcode.ch8
new file mode 100644
index 0000000..f540f69
--- /dev/null
+++ b/roms/test_opcode.ch8
Binary files differ
diff --git a/ui.c b/ui.c
index 3fa1a1c..13fd7d7 100644
--- a/ui.c
+++ b/ui.c
@@ -76,7 +76,7 @@ u8 ui_get_key(bool block) {
void curses_thread(void* v) {
u8 c;
while(1) {
- erase();
+ //erase();
draw();
if ((c = ui_get_key(false)) <= 0xF) {
vm.keyboard[c] = 1;