chip8/src/chip8.c

401 lines
9.8 KiB
C

#include "../include/instructions.h"
#include <stdint.h>
#include <stdlib.h>
Chip8 *init_cpu()
{
Chip8 *chip8 = (Chip8*)malloc(sizeof(Chip8));
chip8->I = 0x00;
chip8->SP = 0x00;
chip8->delay_timer = 0x00;
chip8->sound_timer = 0x00;
chip8->PC = PROGRAM_ADDRESS;
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;
// insert sprites on the memory
for(int i = 0; i < FONT_SIZE; i++)
{
for(int j = 0; j < SPRITE_SIZE; j++)
{
chip8->RAM[ram_index++] = font[i][j];
}
}
// insert instructions on the memory
for(int i = 0; i < size; i++)
{
chip8->RAM[PROGRAM_ADDRESS + i] = instructions[i];
}
}
uint16_t fetch(Chip8 *chip8)
{
uint16_t instruction;
uint8_t msb_instruction = chip8->RAM[chip8->PC];
uint8_t lsb_instruction = chip8->RAM[chip8->PC + 1];
instruction = ((instruction | msb_instruction) << 8) | lsb_instruction;
return instruction;
}
void run(Chip8 *chip8, uint16_t instruction)
{
uint8_t nn, nnn, n, x, y = 0x00;
switch (instruction & 0xF000) {
case 0x0000:
switch (instruction & 0x00FF) {
case 0xE0:
__00E0(chip8); // Display clear
break;
case 0xEE:
__00EE(chip8); // Returns from a subroutine
break;
default:
panic("Invalid Instruction!");
}
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:
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;
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:
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;
case 0xF000:
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;
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;
}