summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chip8.c399
-rw-r--r--chip8.h2
-rw-r--r--ui.c26
3 files changed, 214 insertions, 213 deletions
diff --git a/chip8.c b/chip8.c
index b27d067..504c49c 100644
--- a/chip8.c
+++ b/chip8.c
@@ -21,7 +21,6 @@
static void load_rom();
static void init_vm();
-static void vm_thread(void* v);
chip8_vm vm;
@@ -47,220 +46,206 @@ void load_rom() {
fclose(f);
}
-void vm_thread(void* v) {
- memset(&vm.screen, 0, sizeof(vm.screen));
- while (1) {
- // read 2 bytes and convert to big-endian
- u16 in = htons(vm.rom[vm.PC + 0x1]<<8 | vm.rom[vm.PC]);
+void vm_step() {
+ // read 2 bytes and convert to big-endian
+ u16 in = htons(vm.rom[vm.PC + 0x1]<<8 | vm.rom[vm.PC]);
- // 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:
- 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
- if ((vm.Vx[in>>8&0xF] + vm.Vx[in>>4&0xF]) > 0xFF) {
- vm.Vx[0xF] = 1;
- } else {
- vm.Vx[0xF] = 0;
- }
- vm.Vx[in>>8&0xF] = (vm.Vx[in>>8&0xF] + vm.Vx[in>>4&0xF])&0xFF;
- break;
- case 0x5: // SUB Vx, Vy
- if (vm.Vx[in>>8&0xF] > vm.Vx[in>>4&0xF]) {
- vm.Vx[0xF] = 1;
- } else {
- vm.Vx[0xF] = 0;
- }
- vm.Vx[in>>8&0xF] -= vm.Vx[in>>4&0xF];
- break;
- case 0x6: // SHR Vx {, Vy}
- vm.Vx[0xF] = (vm.Vx[in>>8&0xF] & 1);
- // TODO: toggle for Vx /= 2
- vm.Vx[in>>8&0xF] = vm.Vx[in>>8&0xF]>>1;
- break;
- case 0x7: // SUBN Vx, Vy
- if (vm.Vx[in>>8&0xF] < vm.Vx[in>>4&0xF]) {
- vm.Vx[0xF] = 1;
- } else {
- vm.Vx[0xF] = 0;
- }
- vm.Vx[in>>8&0xF] = vm.Vx[in>>4&0xF] - vm.Vx[in>>8&0xF];
- break;
- case 0xE: // SHL Vx {, Vy}
- vm.Vx[0xF] = ((vm.Vx[in>>8&0xF]>>7) & 1);
- // TODO: toggle for Vx *= 2;
- vm.Vx[in>>8&0xF] = vm.Vx[in>>8&0xF]<<1;
- 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[0x0]) - 0x2;
- break;
- case 0xC: // RND Vx, byte
- vm.Vx[in>>8&0xF] = (rand() % 255) & in&0xFF;
- break;
- case 0xD: // DRW Vx, Vy, nibble
- vm.Vx[0xF] = 0;
- for (int i = 0; i < (in&0xF); i++) {
- for (int s = 0; s < 8; s++) {
- u8 pix = (vm.rom[vm.I + i] & (0x80 >> s)) != 0;
-
- if (pix) {
- u8 y = (i + vm.Vx[in>>4&0xF])&0x1F;
- u8 x = ((vm.Vx[in>>8&0xF] + 7) - s)&0x3F;
+ 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
+ if ((vm.Vx[in>>8&0xF] + vm.Vx[in>>4&0xF]) > 0xFF) {
+ vm.Vx[0xF] = 1;
+ } else {
+ vm.Vx[0xF] = 0;
+ }
+ vm.Vx[in>>8&0xF] = (vm.Vx[in>>8&0xF] + vm.Vx[in>>4&0xF])&0xFF;
+ break;
+ case 0x5: // SUB Vx, Vy
+ if (vm.Vx[in>>8&0xF] > vm.Vx[in>>4&0xF]) {
+ vm.Vx[0xF] = 1;
+ } else {
+ vm.Vx[0xF] = 0;
+ }
+ vm.Vx[in>>8&0xF] -= vm.Vx[in>>4&0xF];
+ break;
+ case 0x6: // SHR Vx {, Vy}
+ vm.Vx[0xF] = (vm.Vx[in>>8&0xF] & 1);
+ // TODO: toggle for Vx /= 2
+ vm.Vx[in>>8&0xF] = vm.Vx[in>>8&0xF]>>1;
+ break;
+ case 0x7: // SUBN Vx, Vy
+ if (vm.Vx[in>>8&0xF] < vm.Vx[in>>4&0xF]) {
+ vm.Vx[0xF] = 1;
+ } else {
+ vm.Vx[0xF] = 0;
+ }
+ vm.Vx[in>>8&0xF] = vm.Vx[in>>4&0xF] - vm.Vx[in>>8&0xF];
+ break;
+ case 0xE: // SHL Vx {, Vy}
+ vm.Vx[0xF] = ((vm.Vx[in>>8&0xF]>>7) & 1);
+ // TODO: toggle for Vx *= 2;
+ vm.Vx[in>>8&0xF] = vm.Vx[in>>8&0xF]<<1;
+ 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[0x0]) - 0x2;
+ break;
+ case 0xC: // RND Vx, byte
+ vm.Vx[in>>8&0xF] = (rand() % 255) & in&0xFF;
+ break;
+ case 0xD: // DRW Vx, Vy, nibble
+ vm.Vx[0xF] = 0;
+ for (int i = 0; i < (in&0xF); i++) {
+ for (int s = 0; s < 8; s++) {
+ int pix = (vm.rom[vm.I + i] & (0x80 >> s)) != 0;
- //while (x > 0x3F) { x -= 0x3F; }
- //while (y > 0x1F) { y -= 0x1F; }
-
- u8 byte = y * 64 + x;
- u8 bit = 1 << (byte * 0x07);
+ if (pix) {
+ int y = (vm.Vx[in>>4&0xF] + i)&0x1F;
+ int x = (vm.Vx[in>>8&0xF] + s)&0x3F;
- if (vm.screen[byte>>3] & bit) {
- vm.Vx[0xF] = 1;
- }
+ //while (x > 0x3F) { x -= 0x3F; }
+ //while (y > 0x1F) { y -= 0x1F; }
+
+ int byte = y * 64 + x;
+ int bit = 1 << (byte & 0x07);
- vm.screen[byte>>3] ^= bit;
+ if (vm.screen[byte>>3] & bit) {
+ vm.Vx[0xF] = 1;
}
+
+ vm.screen[byte>>3] ^= bit;
}
}
- 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;
- }
-
- while (vm.DT > 0) {
- vm.DT--;
- usleep(1000000/60);
- }
-
- // TODO: play sound
- while(vm.ST > 0) {
- vm.ST--;
- usleep(1000000/60);
- }
-
- vm.PC += 0x2;
+ }
+ 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;
}
int main(void) {
@@ -271,7 +256,7 @@ int main(void) {
#ifdef _WIN32
HANDLE vm = CreateThread(NULL, 0, vm_thread, NULL, 0, NULL);
#else
- pthread_t vm; pthread_create(&vm, NULL, (void*)vm_thread, (void*)0);
+ //pthread_t vm; pthread_create(&vm, NULL, (void*)vm_thread, (void*)0);
#endif
init_curses();
diff --git a/chip8.h b/chip8.h
index e7a1196..400d9cd 100644
--- a/chip8.h
+++ b/chip8.h
@@ -2,6 +2,8 @@
#include "util.h"
+void vm_step();
+
typedef struct {
u8* rom;
diff --git a/ui.c b/ui.c
index 620cf8d..b7c6924 100644
--- a/ui.c
+++ b/ui.c
@@ -17,11 +17,14 @@ void init_curses() {
}
void draw() {
- for (int i = 0; i < (0x3F * 0x1F); i++) {
- if (vm.screen[i]) {
-
- // TODO: fix this lmao
- mvaddstr(i / 0x1F, (i % 0x3F) * 2, "[]");
+ erase();
+ for (int x = 0; x < 0x3F; x++) {
+ for (int y = 0; y < 0x1F; y++) {
+ int byte = y * 64 + x;
+ int bit = byte & 0x07;
+ if ((vm.screen[byte>>3] & (1 << bit)) != 0) {
+ mvaddstr(y, x * 2, "[]");
+ }
}
}
@@ -78,11 +81,22 @@ void curses_thread(void* v) {
u8 c;
while(1) {
draw();
+ vm_step();
+
+ if (vm.DT > 0) {
+ vm.DT--;
+ usleep(1000000/60);
+ }
+
+ if (vm.ST > 0) {
+ vm.ST--;
+ usleep(1000000/60);
+ }
+
c = getch();
//if ((c = ui_get_key(false)) <= 0xF) {
// vm.keyboard[c] = 1;
//}
- usleep(10);
}
}