--- /dev/null
+#ifndef FONT_H
+#define FONT_H
+
+const uint8_t font[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
+};
+
+#endif
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include "font.h"
+#include "processor.h"
+
+int init(ch8_ctx * context, char * rom_name){
+ FILE * rom_file = fopen(rom_name, "r");
+ if (rom_file == NULL){
+ printf("Could not open the file <%s>\n", rom_name);
+ fclose(rom_file);
+ return 1;
+ }
+ context->RAM = calloc(0x1000, 1);
+ if (context->RAM == NULL){
+ printf("Could not allocate enough space (4KB)\n");
+ fclose(rom_file);
+ return 1;
+ }
+ // The font is located at address 0, so that program can access it
+ memcpy(context->RAM, font, 80);
+
+ // Next we load the rom at address 0x200
+ fread((context->RAM + 0x200), 1, 0xDFF, rom_file);
+
+ fclose(rom_file);
+ return 0;
+}
+
+
+int main(int argc, char * argv[]){
+ if (argc!=2){
+ printf("Usage: ./chipy8 <path of the rom>\n");
+ return 1;
+ }
+ printf("Welcome to the Chipy 8 emulator!\n");
+
+ ch8_ctx context = {NULL, {0}, 0, 0, 0, 0x200, 0, {0}};
+ if(init(&context, argv[1])){ // If error in init
+ free(context.RAM);
+ return 1;
+ }
+ int running = 1;
+ while (running){
+ ;
+ }
+ free(context.RAM);
+ return 0;
+}
--- /dev/null
+#include <stdint.h>
+#include <stdio.h>
+#include "processor.h"
+
+void execute_instruction(ch8_ctx * ctx){
+ // The two instruction bytes
+ uint8_t b1=*(ctx->RAM + ctx->PC), b2=*(ctx->RAM + ctx->PC + 1);
+ if(b1==0 && b2 == 0xE0){
+ ins_CLS(ctx);
+ ctx->PC++;
+ return;
+ }if(b1==0 && b2 == 0xEE){
+ ins_RET(ctx);
+ return;
+ }
+ // First nimble (4 bits)
+ uint8_t n1 = (b1&0xF0)>>4;
+ switch (n1){
+ //case 0:
+ //Sys instr, deprecated
+ //break;
+ case 1:
+ ins_JP(ctx);
+ return;
+ case 2:
+ ins_CALL(ctx);
+ return;
+ case 3:
+ ins_SE(ctx);
+ break;
+ case 4:
+ ins_SNE(ctx);
+ break;
+ case 5:
+ ins_SEV(ctx);
+ break;
+ case 6:
+ ins_LD(ctx);
+ break;
+ case 7:
+ ins_ADD(ctx);
+ break;
+ case 8:
+ // Last nimble
+ uint8_t n4=b2&0xF;
+ switch (n4){
+ case 0:
+ ins_LDV(ctx);
+ break;
+ case 1:
+ ins_OR(ctx);
+ break;
+ case 2:
+ ins_ANDV(ctx);
+ break;
+ case 3:
+ ins_XOR(ctx);
+ break;
+ case 4:
+ ins_ADDV(ctx);
+ break;
+ case 5:
+ ins_SUB(ctx);
+ break;
+ case 6:
+ ins_SHR(ctx);
+ break;
+ case 7:
+ ins_SUBN(ctx);
+ break;
+ case 0xE:
+ ins_SHL(ctx);
+ break;
+ default:
+ printf("Unknown 8xxx instruction b1: %X b2: %X\n", b1, b2);
+ break;
+ }
+ break;
+ case 9:
+ ins_SNEV(ctx);
+ break;
+ case 0xA:
+ ins_LDI(ctx);
+ break;
+ case 0xB:
+ ins_JPV(ctx);
+ break;
+ case 0xC:
+ ins_RND(ctx);
+ break;
+ case 0xD:
+ ins_DRW(ctx);
+ break;
+ case 0xE:
+ if(b2==0x9E)
+ ins_SKP(ctx);
+ else if(b2==0xA1)
+ ins_SKNP(ctx);
+ else
+ printf("Unknown Exxx instruction b1: %X b2: %X\n", b1, b2);
+ break;
+ default: // 0xF
+ switch (b2){
+ case 7:
+ ins_LDVDT(ctx);
+ break;
+ case 0xA:
+ ins_LDK(ctx);
+ break;
+ case 0x15:
+ ins_LDDTV(ctx);
+ break;
+ case 0x18:
+ ins_LDST(ctx);
+ break;
+ case 0x1E:
+ ins_ADDI(ctx);
+ break;
+ case 0x29:
+ ins_LDF(ctx);
+ break;
+ case 0x33:
+ ins_LDB(ctx);
+ break;
+ case 0x55:
+ ins_LD_Rng_IV(ctx);
+ break;
+ case 0x65:
+ ins_LD_Rng_VI(ctx);
+ break;
+ default:
+ printf("Unknown Fxxx instruction b1: %X b2: %X\n", b1, b2);
+ }
+ break;
+ }
+ // Goes to next instruction.
+ // Note: we do not implement the Super Chip 48 instruction set
+ ctx->PC++;
+}