diff --git a/include/chip8.h b/include/chip8.h index f5e984f..b983f78 100644 --- a/include/chip8.h +++ b/include/chip8.h @@ -13,6 +13,15 @@ #define FONT_SIZE 16 #define REG_SIZE 16 #define STACK_SIZE 16 +#define KEYMAP_SIZE 16 + +int keymap[KEYMAP_SIZE] = { + 49, 50, 51,67, // 1 2 3 C + 52, 68, 55, 56, // 4 5 6 D + 57, 58, 59, 69, // 7 8 9 E + 65,79, 66, 70,// A O B F +}; + int font[FONT_SIZE][SPRITE_SIZE] = { {0xF0, 0x90, 0x90, 0x90, 0xF0}, // 0 @@ -33,7 +42,6 @@ int font[FONT_SIZE][SPRITE_SIZE] = { {0xF0, 0x80, 0xF0, 0x80, 0x80}, // F }; -typedef uint16_t* stack; typedef struct Chip8{ uint8_t RAM[MEM_SIZE]; @@ -43,8 +51,14 @@ typedef struct Chip8{ uint8_t sound_timer; uint16_t I; uint16_t PC; - uint16_t SP; - stack chip8_stack; + int SP; + uint16_t* chip8_stack; + uint8_t key; }Chip8; +void push(Chip8* chip8, uint16_t value); +uint16_t pop(Chip8* chip8); +void set_key(Chip8 *chip8, uint8_t key_pressed); +void reset_key(Chip8 *chip8); + #endif // __CHIP8_H__ \ No newline at end of file diff --git a/include/instructions.h b/include/instructions.h index c5786fc..6f22578 100644 --- a/include/instructions.h +++ b/include/instructions.h @@ -24,7 +24,7 @@ extern void __9XY0(Chip8 *chip8, uint8_t x, uint8_t y); extern void __ANNN(Chip8 *chip8, uint8_t nnn); extern void __BNNN(Chip8 *chip8, uint8_t nnn); - extern void __CXNN(Chip8 *chip8, uint8_t nn); + extern void __CXNN(Chip8 *chip8, uint8_t x, uint8_t nn); extern void __DXYN(Chip8 *chip8, uint8_t x, uint8_t y, uint8_t n); extern void __EX9E(Chip8 *chip8, uint8_t x); extern void __EXA1(Chip8 *chip8, uint8_t x); diff --git a/src/chip8.c b/src/chip8.c index 640c4b1..f975366 100644 --- a/src/chip8.c +++ b/src/chip8.c @@ -1,4 +1,4 @@ -#include "../include/chip8.h" +#include "../include/instructions.h" #include #include @@ -12,11 +12,25 @@ Chip8 *init_cpu() chip8->sound_timer = 0x00; chip8->PC = PROGRAM_ADDRESS; - chip8->chip8_stack = (stack)malloc(STACK_SIZE*sizeof(stack)); + chip8->chip8_stack = (uint16_t*)malloc(STACK_SIZE*sizeof(uint16_t)); return chip8; } +void push(Chip8* chip8, uint16_t value) +{ + chip8->chip8_stack[chip8->SP++] = value; +} + +uint16_t pop(Chip8* chip8) +{ + if(chip8->PC > 0){ + return chip8->chip8_stack[--chip8->SP]; + }else{ + perror("Stack is empty!"); + } +} + void start_cpu(Chip8 *chip8, uint8_t instructions[], int size) { int ram_index = 0; @@ -61,46 +75,58 @@ void run(Chip8 *chip8, uint16_t instruction) switch (instruction & 0x00FF) { case 0xE0: - + __00E0(chip8); // Display clear break; case 0xEE: + __00EE(chip8); // Returns from a subroutine break; default: panic("Invalid Instruction!"); - break; } break; case 0x1000: - + nnn = instruction & 0x0FFF; + __1NNN(chip8, nnn); break; case 0x2000: - + nnn = instruction & 0x0FFF; + __2NNN(chip8, nnn); break; case 0x3000: - + x = (instruction & 0x0F00) >> 8; + nn = instruction & 0x00FF; + __3XNN(chip8, x, nn); break; case 0x4000: - + x = (instruction & 0x0F00) >> 8; + nn = instruction & 0x00FF; + __4XNN(chip8,x,nn); break; case 0x5000: - + x = (instruction & 0x0F00) >> 8; + y = (instruction & 0x00F0) >> 4; + __5XY0(chip8,x,y); break; case 0x6000: - + x = (instruction & 0x0F00) >> 8; + y = (instruction & 0x00F0) >> 4; + __6XNN(chip8, x, nn); break; case 0x7000: - + x = (instruction & 0x0F00) >> 8; + nn = instruction & 0x00FF; + __7XNN(chip8, x, nn); break; case 0x8000: @@ -108,52 +134,92 @@ void run(Chip8 *chip8, uint16_t instruction) switch (instruction & 0x000F) { case 0x0: + x = (instruction & 0x0F00) >> 8; + y = (instruction & 0x00F0) >> 4; + __8XY0(chip8, x, y); break; case 0x1: + x = (instruction & 0x0F00) >> 8; + y = (instruction & 0x00F0) >> 4; + __8XY1(chip8, x, y); break; case 0x2: + x = (instruction & 0x0F00) >> 8; + y = (instruction & 0x00F0) >> 4; + __8XY2(chip8, x, y); break; case 0x3: + x = (instruction & 0x0F00) >> 8; + y = (instruction & 0x00F0) >> 4; + __8XY3(chip8, x, y); break; case 0x4: + x = (instruction & 0x0F00) >> 8; + y = (instruction & 0x00F0) >> 4; + __8XY4(chip8, x, y); break; case 0x5: + x = (instruction & 0x0F00) >> 8; + y = (instruction & 0x00F0) >> 4; + __8XY5(chip8, x, y); break; case 0x6: + x = (instruction & 0x0F00) >> 8; + y = (instruction & 0x00F0) >> 4; + __8XY6(chip8, x, y); break; case 0x7: + x = (instruction & 0x0F00) >> 8; + y = (instruction & 0x00F0) >> 4; + __8XY7(chip8, x, y); break; case 0xE: + x = (instruction & 0x0F00) >> 8; + y = (instruction & 0x00F0) >> 4; + __8XYE(chip8, x, y); break; default: panic("Invalid Instruction!"); - break; } break; case 0x9000: + x = (instruction & 0x0F00) >> 8; + y = (instruction & 0x00F0) >> 4; + __9XY0(chip8, x, y); break; case 0xA000: + nnn = instruction & 0x0FFF; + __ANNN(chip8, nnn); break; case 0xB000: + nnn = instruction & 0x0FFF; + __BNNN(chip8, nnn); break; case 0xC000: + x = (instruction & 0x0F00) >> 8; + nn = instruction & 0x00FF; + __CXNN(chip8, x, nn); break; case 0xD000: + x = (instruction & 0x0F00) >> 8; + y = (instruction & 0x00F0) >> 4; + n = (instruction & 0x000F); + __DXYN(chip8, x, y, n); break; case 0xE000: @@ -161,14 +227,17 @@ void run(Chip8 *chip8, uint16_t instruction) switch (instruction & 0x00FF) { case 0x9E: + x = (instruction & 0x0F00) >> 8; + __EX9E(chip8, x); break; case 0xA1: + x = (instruction & 0x0F00) >> 8; + __EXA1(chip8, x); break; default: panic("Invalid Instruction!"); - break; } break; @@ -177,38 +246,156 @@ void run(Chip8 *chip8, uint16_t instruction) switch (instruction & 0x00FF) { case 0x07: + x = (instruction & 0x0F00) >> 8; + __FX07(chip8, x); break; case 0x0A: + x = (instruction & 0x0F00) >> 8; + __FX0A(chip8, x); break; case 0x15: + x = (instruction & 0x0F00) >> 8; + __FX15(chip8, x); break; case 0x18: + x = (instruction & 0x0F00) >> 8; + __FX18(chip8, x); break; case 0x1E: + x = (instruction & 0x0F00) >> 8; + __FX15(chip8, x); break; case 0x29: + x = (instruction & 0x0F00) >> 8; + __FX29(chip8, x); break; case 0x33: + x = (instruction & 0x0F00) >> 8; + __FX33(chip8, x); break; case 0x55: + x = (instruction & 0x0F00) >> 8; + __FX55(chip8, x); break; case 0x65: + x = (instruction & 0x0F00) >> 8; + __FX65(chip8, x); break; default: - panic("Invalid Instruction!") - break; + panic("Invalid Instruction!"); } - + break; + + default: + panic("Invalid Instruction!"); } +} + +void set_key(Chip8 *chip8,uint8_t key_pressed) +{ + switch (key_pressed) { + + case 0x31: + chip8->key = keymap[0]; + break; + case 0x32: + chip8->key = keymap[1]; + break; + case 0x33: + chip8->key = keymap[2]; + break; + case 0x34: + chip8->key = keymap[3]; + break; + case 0x51: + chip8->key = keymap[4]; + break; + case 0x71: + chip8->key = keymap[4]; + break; + case 0x57: + chip8->key = keymap[5]; + break; + case 0x77: + chip8->key = keymap[5]; + break; + case 0x45: + chip8->key = keymap[6]; + break; + case 0x65: + chip8->key = keymap[6]; + break; + case 0x52: + chip8->key = keymap[7]; + break; + case 0x72: + chip8->key = keymap[7]; + break; + case 0x41: + chip8->key = keymap[8]; + break; + case 0x61: + chip8->key = keymap[8]; + break; + case 0x53: + chip8->key = keymap[9]; + break; + case 0x73: + chip8->key = keymap[9]; + break; + case 0x44: + chip8->key = keymap[10]; + break; + case 0x64: + chip8->key = keymap[10]; + break; + case 0x46: + chip8->key = keymap[11]; + break; + case 0x66: + chip8->key = keymap[11]; + break; + case 0x5A: + chip8->key = keymap[12]; + break; + case 0x7A: + chip8->key = keymap[12]; + break; + case 0x58: + chip8->key = keymap[13]; + break; + case 0x78: + chip8->key = keymap[13]; + break; + case 0x43: + chip8->key = keymap[14]; + break; + case 0X63: + chip8->key = keymap[14]; + break; + case 0x56: + chip8->key = keymap[15]; + break; + case 0X76: + chip8->key = keymap[15]; + break; + default: + panic("Key pressed is invalid!"); + } +} + +void reset_key(Chip8 *chip8) +{ + chip8->key = 0; } \ No newline at end of file diff --git a/src/instructions.c b/src/instructions.c index 7ff3831..5f69fda 100644 --- a/src/instructions.c +++ b/src/instructions.c @@ -1,5 +1,8 @@ #include "../include/instructions.h" +#include +#include + void __00E0(Chip8 *chip8) { for(int y = 0; y < DISPLAY_HEIGHT; y++) @@ -13,147 +16,173 @@ void __00E0(Chip8 *chip8) void __00EE(Chip8 *chip8) { - + chip8->PC = pop(chip8); } void __1NNN(Chip8 *chip8, uint8_t nnn) { - + chip8->PC = nnn; } void __2NNN(Chip8 *chip8, uint8_t nnn) { - + push(chip8, chip8->PC); + chip8->PC = nnn; } void __3XNN(Chip8 *chip8, uint8_t x, uint8_t nn) { - + if(chip8->V[x] == nn){ chip8->PC += 2; } } void __4XNN(Chip8 *chip8, uint8_t x, uint8_t nn) { - + if(chip8->V[x] != nn){ chip8->PC += 2; } } void __5XY0(Chip8 *chip8, uint8_t x, uint8_t y) { - + if(chip8->V[x] == chip8->V[y]){ chip8->PC += 2; } } void __6XNN(Chip8 *chip8, uint8_t x, uint8_t nn) { - + chip8->V[x] = nn; } void __7XNN(Chip8 *chip8, uint8_t x, uint8_t nn) { - + chip8->V[x] += nn; } void __8XY0(Chip8 *chip8, uint8_t x, uint8_t y) { - + chip8->V[x] = chip8->V[y]; } void __8XY1(Chip8 *chip8, uint8_t x, uint8_t y) { - + chip8->V[x] |= chip8->V[y]; } void __8XY2(Chip8 *chip8, uint8_t x, uint8_t y) { - + chip8->V[x] &= chip8->V[y]; } void __8XY3(Chip8 *chip8, uint8_t x, uint8_t y) { - + chip8->V[x] ^= chip8->V[y]; } void __8XY4(Chip8 *chip8, uint8_t x, uint8_t y) { - + chip8->V[x] += chip8->V[y]; } void __8XY5(Chip8 *chip8, uint8_t x, uint8_t y) { - + chip8->V[x] -= chip8->V[y]; } void __8XY6(Chip8 *chip8, uint8_t x, uint8_t y) { - + chip8->V[x] = chip8->V[x] >> 1; } void __8XY7(Chip8 *chip8, uint8_t x, uint8_t y) { + chip8->V[x] = chip8->V[y] - chip8->V[x]; + if(chip8->V[y] >= chip8->V[x]) + { + chip8->V[F] = 1; + }else{ + chip8->V[F] = 0; + } } void __8XYE(Chip8 *chip8, uint8_t x, uint8_t y) { - + chip8->V[x] = chip8->V[x] >> 1; } void __9XY0(Chip8 *chip8, uint8_t x, uint8_t y) { - + if(chip8->V[x] != chip8->V[y]){ chip8->PC += 2; } } void __ANNN(Chip8 *chip8, uint8_t nnn) { - + chip8->I = nnn; } void __BNNN(Chip8 *chip8, uint8_t nnn) { - + chip8->PC = chip8->V[0] + nnn; } -void __CXNN(Chip8 *chip8, uint8_t nn) +void __CXNN(Chip8 *chip8, uint8_t x, uint8_t nn) { - + chip8->V[x] = (rand() % 255) & nn; } void __DXYN(Chip8 *chip8, uint8_t x, uint8_t y, uint8_t n) { + uint8_t x_coord = (chip8->V[x] % DISPLAY_WIDTH); + uint8_t y_coord = (chip8->V[y] % DISPLAY_HEIGHT); + chip8->V[F] = 0; + + for(int i = 0; i < n; i++) + { + uint8_t pixel = chip8->RAM[chip8->I + n]; + + for(int j = 0; j < 8; j++) + { + if(pixel == 1 && chip8->display[y_coord + i][x_coord + j] == 1) + { + chip8->display[y_coord + i][x_coord + j] == 0; + chip8->V[F] = 1; + } + } + } + } void __EX9E(Chip8 *chip8, uint8_t x) { - + if(chip8->key == chip8->V[x]){ chip8->PC += 2; } } void __EXA1(Chip8 *chip8, uint8_t x) { - + if(chip8->key != chip8->V[x]){ chip8->PC += 2; } } void __FX07(Chip8 *chip8, uint8_t x) { - + chip8->V[x] = chip8->delay_timer; } void __FX0A(Chip8 *chip8, uint8_t x) { - + chip8->V[x] = chip8->key; } void __FX15(Chip8 *chip8, uint8_t x) { - + chip8->delay_timer = chip8->V[x]; } void __FX18(Chip8 *chip8, uint8_t x) { - + chip8->sound_timer = chip8->V[x]; } void __FX1E(Chip8 *chip8, uint8_t x) { - + chip8->I = chip8->V[x]; } void __FX29(Chip8 *chip8, uint8_t x) @@ -168,12 +197,18 @@ void __FX33(Chip8 *chip8, uint8_t x) void __FX55(Chip8 *chip8, uint8_t x) { - + for(int i = 0; i <= x; i++) + { + chip8->RAM[chip8->I + i] = chip8->V[i]; + } } void __FX65(Chip8 *chip8, uint8_t x) { - + for(int i = 0; i <= x; i++) + { + chip8->V[i] = chip8->RAM[chip8->I + i]; + } } diff --git a/src/main.c b/src/main.c index e69de29..23e468c 100644 --- a/src/main.c +++ b/src/main.c @@ -0,0 +1,50 @@ +#include "../include/chip8.h" +#include +#include +#include +#include + +noreturn void get_graphics() +{ + while(true) + { + + } +} + +uint8_t load_rom(char* rom_path) +{ + FILE *file; + char* buffer; + long file_size; + + file = fopen(rom_path,"rb"); + + if(file == NULL) + { + perror("File can not be opened!"); + return 1; + } + + fseek(file, 0, SEEK_END); + file_size = ftell(file); + rewind(file); + + buffer = (char*)malloc(file_size*sizeof(char*)); + + size_t bytes_read = fread(buffer, 1, file_size, file); +} + +int main(int argc, char** argv) +{ + + if(argc > 1) + { + load_rom(argv[1]); + }else + { + perror("ROM not specified!"); + } + + return 0; +} \ No newline at end of file