chip-8

Initial commmit

Arjun Choudhary contact@arjunchoudhary.com

commit: a2e4208 parent: a2e4208
2 files changed, 173 insertions(+), 0 deletions(-)
AMakefile+2-0
Amain.c+171-0
A · Makefile +2, -0
1@@ -0,0 +1,2 @@
2+chip8: main.c
3+	$(CC) main.c -o chip8 `sdl2-config --cflags --libs` -Wall -Wextra -pedantic -std=c99
A · main.c +171, -0
  1@@ -0,0 +1,171 @@
  2+/*** includes ***/
  3+#include <SDL2/SDL.h>
  4+#include <errno.h>
  5+#include <stddef.h>
  6+#include <stdio.h>
  7+#include <sys/stat.h>
  8+#include <time.h>
  9+#include <unistd.h>
 10+
 11+/*** data ***/
 12+// opcode store
 13+// All opcodes are 2 bytes and so are unsigned short
 14+unsigned short opcode;
 15+// 4KB of RAM
 16+unsigned char memory[4096];
 17+// CPU Register
 18+// 16 general purpose 8 bit registers
 19+unsigned char V[16];
 20+// Index or Address Register
 21+unsigned short I;
 22+// Program counter | A psudo register that points to the next instruction on the
 23+// stack Instruction pointer being my preffered nomenclature
 24+unsigned short pc;
 25+// Display containing 2048 pixels in an array
 26+unsigned char gfx[64 * 32];
 27+// Timer registers that countdown to 0 at 60Hz
 28+unsigned char delay_timer;
 29+unsigned char sound_timer;
 30+//
 31+unsigned short stack[16];
 32+unsigned short stack_pointer;
 33+
 34+// Fontset used by CHIP 8
 35+// Also used to draw sprits using XOR
 36+// DEC   HEX    BIN         RESULT    DEC   HEX    BIN         RESULT
 37+// 240   0xF0   1111 0000    ****     240   0xF0   1111 0000    ****
 38+// 144   0x90   1001 0000    *  *      16   0x10   0001 0000       *
 39+// 144   0x90   1001 0000    *  *      32   0x20   0010 0000      *
 40+// 144   0x90   1001 0000    *  *      64   0x40   0100 0000     *
 41+// 240   0xF0   1111 0000    ****      64   0x40   0100 0000     *
 42+
 43+unsigned char chip8_fontset[80] = {
 44+    0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
 45+    0x20, 0x60, 0x20, 0x20, 0x70, // 1
 46+    0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2
 47+    0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3
 48+    0x90, 0x90, 0xF0, 0x10, 0x10, // 4
 49+    0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5
 50+    0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6
 51+    0xF0, 0x10, 0x20, 0x40, 0x40, // 7
 52+    0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8
 53+    0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9
 54+    0xF0, 0x90, 0xF0, 0x90, 0x90, // A
 55+    0xE0, 0x90, 0xE0, 0x90, 0xE0, // B
 56+    0xF0, 0x80, 0x80, 0x80, 0xF0, // C
 57+    0xE0, 0x90, 0x90, 0x90, 0xE0, // D
 58+    0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
 59+    0xF0, 0x80, 0xF0, 0x80, 0x80  // F
 60+};
 61+
 62+// Keypad
 63+unsigned char keypad[16];
 64+
 65+// Screen dimension constants
 66+const int SCREEN_WIDTH = 640;
 67+const int SCREEN_HEIGHT = 320;
 68+
 69+/*** initialize cpu ***/
 70+void chip8_initialize(void) {
 71+  pc = 0x200;        // program counter starts at 0x200 or 512
 72+  opcode = 0;        // reset current opcode
 73+  I = 0;             // reset current index register
 74+  stack_pointer = 0; // reset stack pointer
 75+  printf("Chip 8 Initialized successfully \n");
 76+  // Load fontset into memory 
 77+  //for (int i = 0; i < 80; i++) {
 78+  //      memory[i] = fontset[i];
 79+  //  }
 80+  memcpy(memory, chip8_fontset, sizeof(chip8_fontset));
 81+}
 82+
 83+/*** load rom ***/
 84+void chip8_load_program(char *filename) {
 85+  FILE *program = fopen(filename, "rb");
 86+
 87+  // get file size
 88+  fseek(program, 0, SEEK_END);
 89+  long buf_len = ftell(program);
 90+  rewind(program);
 91+
 92+  // load data into buffer
 93+  char *buf = malloc((buf_len + 1) * sizeof(char));
 94+  fread(buf, buf_len, 1, program);
 95+  printf("Rom loaded succesfully \n");
 96+  printf("Rom size: %zu bytes \n", buf_len);
 97+  fclose(program);
 98+
 99+  // load rom into memory
100+  for (int i = 0; i < buf_len; i++) {
101+    memory[0x200 + i] = buf[i];
102+    // Big endian so check last two values from the right
103+    printf("Byte successfully read: %08X \n", buf[i]);
104+  }
105+  // clear buffer
106+  free(buf);
107+}
108+
109+/*** initialize display ***/
110+int chip8_init_display (){
111+  SDL_Init(SDL_INIT_VIDEO);
112+  // Init Window struct
113+  SDL_Window *window;
114+  // Init window
115+   window =
116+      SDL_CreateWindow(
117+        "CHIP8", 
118+        SDL_WINDOWPOS_CENTERED, 
119+        SDL_WINDOWPOS_CENTERED,
120+        SCREEN_WIDTH,
121+        SCREEN_HEIGHT, 
122+        0);
123+  // Init renderer struct
124+  SDL_Renderer* renderer;
125+  // Init renderer
126+    renderer =  
127+      SDL_CreateRenderer(
128+        window, 
129+        -1, 
130+        SDL_RENDERER_ACCELERATED);
131+  //SDL Render color (background)
132+  SDL_SetRenderDrawColor( renderer, 0, 0, 0, 0 );
133+  // Clear the current color and use the one specified above 
134+  SDL_RenderClear( renderer );
135+  // Shape 
136+  SDL_Rect rectangle;
137+    rectangle.x = 0;
138+    rectangle.y = 0;
139+    rectangle.w = 90;
140+    rectangle.h = 100;
141+
142+  SDL_SetRenderDrawColor( renderer, 0, 0, 255, 255 );
143+  SDL_RenderFillRect( renderer, &rectangle );
144+  SDL_RenderPresent(renderer);
145+
146+
147+  if (SDL_Init(SDL_INIT_VIDEO) < 0) {
148+    printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
149+    return -1;
150+  }
151+
152+  // Check that the window was successfully created
153+  if (window == NULL) {
154+    // In the case that the window could not be made...
155+    printf("Could not create window: %s\n", SDL_GetError());
156+    return -1;
157+  }
158+  SDL_Delay(3000);
159+  // Pause execution for 3000 milliseconds, for example
160+  // Close and destroy the window
161+  SDL_DestroyWindow(window);
162+  // Clean up
163+  SDL_Quit();
164+  return 0;
165+}
166+
167+int main(int argc, char *argv[]) {
168+  chip8_initialize();
169+  chip8_load_program(argv[1]);
170+  chip8_init_display();
171+  return 0;
172+}