chip-8
chip-8 emulatorInitial commmit
ADD · Makefile +2 -0--- a/Makefile
+++ b/Makefile
@@ -0,0 +1,2 @@
+chip8: main.c
+ $(CC) main.c -o chip8 `sdl2-config --cflags --libs` -Wall -Wextra -pedantic -std=c99ADD · main.c +171 -0--- a/main.c
+++ b/main.c
@@ -0,0 +1,171 @@
+/*** includes ***/
+#include <SDL2/SDL.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <unistd.h>
+
+/*** data ***/
+// opcode store
+// All opcodes are 2 bytes and so are unsigned short
+unsigned short opcode;
+// 4KB of RAM
+unsigned char memory[4096];
+// CPU Register
+// 16 general purpose 8 bit registers
+unsigned char V[16];
+// Index or Address Register
+unsigned short I;
+// Program counter | A psudo register that points to the next instruction on the
+// stack Instruction pointer being my preffered nomenclature
+unsigned short pc;
+// Display containing 2048 pixels in an array
+unsigned char gfx[64 * 32];
+// Timer registers that countdown to 0 at 60Hz
+unsigned char delay_timer;
+unsigned char sound_timer;
+//
+unsigned short stack[16];
+unsigned short stack_pointer;
+
+// Fontset used by CHIP 8
+// Also used to draw sprits using XOR
+// DEC HEX BIN RESULT DEC HEX BIN RESULT
+// 240 0xF0 1111 0000 **** 240 0xF0 1111 0000 ****
+// 144 0x90 1001 0000 * * 16 0x10 0001 0000 *
+// 144 0x90 1001 0000 * * 32 0x20 0010 0000 *
+// 144 0x90 1001 0000 * * 64 0x40 0100 0000 *
+// 240 0xF0 1111 0000 **** 64 0x40 0100 0000 *
+
+unsigned char chip8_fontset[80] = {
+ 0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
+ 0x20, 0x60, 0x20, 0x20, 0x70, // 1
+ 0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2
+ 0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3
+ 0x90, 0x90, 0xF0, 0x10, 0x10, // 4
+ 0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5
+ 0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6
+ 0xF0, 0x10, 0x20, 0x40, 0x40, // 7
+ 0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8
+ 0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9
+ 0xF0, 0x90, 0xF0, 0x90, 0x90, // A
+ 0xE0, 0x90, 0xE0, 0x90, 0xE0, // B
+ 0xF0, 0x80, 0x80, 0x80, 0xF0, // C
+ 0xE0, 0x90, 0x90, 0x90, 0xE0, // D
+ 0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
+ 0xF0, 0x80, 0xF0, 0x80, 0x80 // F
+};
+
+// Keypad
+unsigned char keypad[16];
+
+// Screen dimension constants
+const int SCREEN_WIDTH = 640;
+const int SCREEN_HEIGHT = 320;
+
+/*** initialize cpu ***/
+void chip8_initialize(void) {
+ pc = 0x200; // program counter starts at 0x200 or 512
+ opcode = 0; // reset current opcode
+ I = 0; // reset current index register
+ stack_pointer = 0; // reset stack pointer
+ printf("Chip 8 Initialized successfully \n");
+ // Load fontset into memory
+ //for (int i = 0; i < 80; i++) {
+ // memory[i] = fontset[i];
+ // }
+ memcpy(memory, chip8_fontset, sizeof(chip8_fontset));
+}
+
+/*** load rom ***/
+void chip8_load_program(char *filename) {
+ FILE *program = fopen(filename, "rb");
+
+ // get file size
+ fseek(program, 0, SEEK_END);
+ long buf_len = ftell(program);
+ rewind(program);
+
+ // load data into buffer
+ char *buf = malloc((buf_len + 1) * sizeof(char));
+ fread(buf, buf_len, 1, program);
+ printf("Rom loaded succesfully \n");
+ printf("Rom size: %zu bytes \n", buf_len);
+ fclose(program);
+
+ // load rom into memory
+ for (int i = 0; i < buf_len; i++) {
+ memory[0x200 + i] = buf[i];
+ // Big endian so check last two values from the right
+ printf("Byte successfully read: %08X \n", buf[i]);
+ }
+ // clear buffer
+ free(buf);
+}
+
+/*** initialize display ***/
+int chip8_init_display (){
+ SDL_Init(SDL_INIT_VIDEO);
+ // Init Window struct
+ SDL_Window *window;
+ // Init window
+ window =
+ SDL_CreateWindow(
+ "CHIP8",
+ SDL_WINDOWPOS_CENTERED,
+ SDL_WINDOWPOS_CENTERED,
+ SCREEN_WIDTH,
+ SCREEN_HEIGHT,
+ 0);
+ // Init renderer struct
+ SDL_Renderer* renderer;
+ // Init renderer
+ renderer =
+ SDL_CreateRenderer(
+ window,
+ -1,
+ SDL_RENDERER_ACCELERATED);
+ //SDL Render color (background)
+ SDL_SetRenderDrawColor( renderer, 0, 0, 0, 0 );
+ // Clear the current color and use the one specified above
+ SDL_RenderClear( renderer );
+ // Shape
+ SDL_Rect rectangle;
+ rectangle.x = 0;
+ rectangle.y = 0;
+ rectangle.w = 90;
+ rectangle.h = 100;
+
+ SDL_SetRenderDrawColor( renderer, 0, 0, 255, 255 );
+ SDL_RenderFillRect( renderer, &rectangle );
+ SDL_RenderPresent(renderer);
+
+
+ if (SDL_Init(SDL_INIT_VIDEO) < 0) {
+ printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
+ return -1;
+ }
+
+ // Check that the window was successfully created
+ if (window == NULL) {
+ // In the case that the window could not be made...
+ printf("Could not create window: %s\n", SDL_GetError());
+ return -1;
+ }
+ SDL_Delay(3000);
+ // Pause execution for 3000 milliseconds, for example
+ // Close and destroy the window
+ SDL_DestroyWindow(window);
+ // Clean up
+ SDL_Quit();
+ return 0;
+}
+
+int main(int argc, char *argv[]) {
+ chip8_initialize();
+ chip8_load_program(argv[1]);
+ chip8_init_display();
+ return 0;
+}