diff options
| author | 2019-09-09 20:25:22 -0400 | |
|---|---|---|
| committer | 2019-09-09 20:25:22 -0400 | |
| commit | 1ea493d0d11d19dd3777f3e2646bce19929f786a (patch) | |
| tree | 902cd31cbce3f2b76d44e1cac3b597ef9c966ea1 | |
| download | chip8-1ea493d0d11d19dd3777f3e2646bce19929f786a.tar.gz chip8-1ea493d0d11d19dd3777f3e2646bce19929f786a.tar.bz2 chip8-1ea493d0d11d19dd3777f3e2646bce19929f786a.zip | |
initial commit
| -rw-r--r-- | .gitignore | 1 | ||||
| -rwxr-xr-x | Makefile | 19 | ||||
| -rw-r--r-- | chip8.c | 150 | ||||
| -rw-r--r-- | chip8.h | 24 | ||||
| -rw-r--r-- | roms/Breakout [Carmelo Cortez, 1979].ch8 | bin | 0 -> 232 bytes | |||
| -rw-r--r-- | roms/a.ch8 | bin | 0 -> 27 bytes | |||
| -rw-r--r-- | roms/e.asm | 22 | ||||
| -rw-r--r-- | roms/e.ch8 | bin | 0 -> 25 bytes | |||
| -rw-r--r-- | ui.c | 35 | ||||
| -rw-r--r-- | ui.h | 4 | ||||
| -rw-r--r-- | util.c | 14 | ||||
| -rw-r--r-- | util.h | 9 |
12 files changed, 278 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1062ad7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +chip8 diff --git a/Makefile b/Makefile new file mode 100755 index 0000000..b504d98 --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ +all: CC=gcc
+win: CC=x86_64-w64-mingw32-gcc
+
+CFLAGS = -O3 -Wall -std=c99 $(shell pkg-config --cflags ncursesw)
+
+all: BIN = chip8
+win: BIN = chip8.exe
+
+all: executable
+win: executable
+
+all: LDFLAGS = -lncursesw -ltinfow -lpthread
+win: LDFLAGS = ./win/pdcurses.a
+
+executable: chip8.c ui.c util.c
+ $(CC) $(CFLAGS) -o $(BIN) chip8.c ui.c util.c $(LDFLAGS)
+
+clean:
+ $(RM) chip8
@@ -0,0 +1,150 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <arpa/inet.h> + +#ifdef _WIN32 +#include <window.h> +#else +#include <unistd.h> +#include <pthread.h> +#endif + +#include "ui.h" +#include "util.h" +#include "chip8.h" + +#define ROM_FILE "roms/a.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() { + 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) { + printf("err: failed to read rom fully\n"); + exit(1); + } + + 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) { + if (vm.PC > vm.rom_size) { + return; + } + + // read 2 bytes and convert to big-endian + u16 instr = htons(vm.rom[(vm.PC) - 0x1FF]<<8 | vm.rom[(vm.PC) - 0x200]); + + char str[5]; + sprintf(str, "%x", instr); + + switch (*str) { + case '0': + if (instr == 0x00E0) { + //clearscreen + } else if (instr == 0x00EE) { + vm.PC = vm.stack[vm.SP--]; + } + break; + case '1': + vm.PC = hex_str(str+1); + break; + case '2': + vm.SP++; + push_top_of_stack(vm.PC); + vm.PC = hex_str(str+1); + break; + case '3': + if (vm.Vx[hex_char(str[1])] == hex_str(str+2)) { + vm.PC += 0x2; + } + break; + case '4': + if (vm.Vx[hex_char(str[1])] != hex_str(str+2)) { + vm.PC += 0x2; + } + break; + case '5': + if (vm.Vx[hex_char(str[1])] == vm.Vx[hex_char(str[2])]) { + vm.PC += 0x2; + } + break; + case '6': + vm.Vx[hex_char(str[1])] = hex_str(str+2); + break; + case '7': + vm.Vx[hex_char(str[1])] += hex_str(str+2); + break; + case '8': + switch(str[3]) { + case '0': + vm.Vx[hex_char(str[1])] = vm.Vx[hex_char(str[2])]; + break; + case '1': + vm.Vx[hex_char(str[1])] |= vm.Vx[hex_char(str[2])]; + break; + case '2': + vm.Vx[hex_char(str[1])] &= vm.Vx[hex_char(str[2])]; + break; + } + } + + vm.PC += 0x2; +} + +int main(void) { + init_vm(); + load_rom(); + +#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); +#else + void *loop(void) { + while(1) { + vm_thread(0); + usleep(100); + } + return 0; + } + pthread_t t; pthread_create(&t, NULL, (void*)loop, (void*)0); +#endif + + init_curses(); + curses_thread(0); + + return 0; +} @@ -0,0 +1,24 @@ +#pragma once + +#include "util.h" + +typedef struct { + u8* rom; + u16 rom_size; + + u16 PC; + + u16 stack[16]; + u16 stack_pos; + u16 stack_count; + + u8 DT; + u8 ST; + + u8 SP; + u16 I; + + u8 Vx[16]; +} chip8_vm; + +extern chip8_vm vm; diff --git a/roms/Breakout [Carmelo Cortez, 1979].ch8 b/roms/Breakout [Carmelo Cortez, 1979].ch8 Binary files differnew file mode 100644 index 0000000..70b50db --- /dev/null +++ b/roms/Breakout [Carmelo Cortez, 1979].ch8 diff --git a/roms/a.ch8 b/roms/a.ch8 Binary files differnew file mode 100644 index 0000000..f445d49 --- /dev/null +++ b/roms/a.ch8 diff --git a/roms/e.asm b/roms/e.asm new file mode 100644 index 0000000..2dd3761 --- /dev/null +++ b/roms/e.asm @@ -0,0 +1,22 @@ +CLS + +LD V0, 0 +LD V1, 0 +LD V2, 0 + +loop: + +LD F, V0 +LD I, esprite +DRW V1, V2, 5 +ADD V1, 5 +ADD V2, 6 + +JP loop + +esprite: +db %11110000, + %10000000, + %11110000, + %10000000, + %11110000, diff --git a/roms/e.ch8 b/roms/e.ch8 Binary files differnew file mode 100644 index 0000000..e890b81 --- /dev/null +++ b/roms/e.ch8 @@ -0,0 +1,35 @@ +#include <ncurses.h> +#include <string.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> + +#include "chip8.h" + +void init_curses() { + initscr(); + curs_set(0); + noecho(); + nodelay(stdscr, 1); + clear(); +} + +void curses_thread(void* v) { + char c; + while(1) { + c = getch(); + if (c == 'q') { + endwin(); + exit(1); + } + mvaddstr(0, 0, "V0 V1 V2 V3 V4 V5 V6 V7 V8 V9 VA VB VC VD VE VF"); + char buf[5]; + for (int i = 0; i < 16; i++) { + sprintf(buf, "%i", vm.Vx[i]); + mvaddstr(1, i * 4, buf); + } + usleep(100); + } +} + + @@ -0,0 +1,4 @@ +#pragma once + +void curses_thread(void* v); +void init_curses(); @@ -0,0 +1,14 @@ +#include <stdlib.h> +#include <stdio.h> + +#include "util.h" + +u16 hex_str(char* str) { + return (u16)strtol(str, NULL, 16); +} + +u16 hex_char(char c) { + char buf[2]; + sprintf(buf, "%c", c); + return (u16)strtol(buf, NULL, 16); +} @@ -0,0 +1,9 @@ +#include <stdint.h> + +#define u8 uint8_t +#define u16 uint16_t +#define s8 int8_t +#define s16 int16_t + +u16 hex_char(char c); +u16 hex_str(char* str); |