Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Created by https://www.toptal.com/developers/gitignore/api/macos,c++
# Edit at https://www.toptal.com/developers/gitignore?templates=macos,c++

### C++ ###
# Prerequisites
*.d

# Compiled Object files
*.slo
*.lo
*.o
*.obj

# Precompiled Headers
*.gch
*.pch

# Compiled Dynamic libraries
*.so
*.dylib
*.dll

# Fortran module files
*.mod
*.smod

# Compiled Static libraries
*.lai
*.la
*.a
*.lib

# Executables
*.exe
*.out
*.app

### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon


# Thumbnails
._*

/bin/*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

### macOS Patch ###
# iCloud generated files
*.icloud

# End of https://www.toptal.com/developers/gitignore/api/macos,c++
15 changes: 9 additions & 6 deletions src/chip8.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,20 @@ static void chip8_execute_extended_eight(struct chip8 *chip8, unsigned short opc

// 8xy1 - OR Vx, Vy. Perform a bitwise OR on Vx and Vy stores then result in Vx
case 0x01:
chip8->registers.V[x] = chip8->registers.V[x] | chip8->registers.V[y];
// chip8->registers.V[x] = chip8->registers.V[x] | chip8->registers.V[y];
chip8->registers.V[x] |= chip8->registers.V[y];
break;

// 8xy2 - AND Vx, Vy. Perform a bitwise AND on Vx and Vy stores the result in Vx
case 0x02:
chip8->registers.V[x] = chip8->registers.V[x] & chip8->registers.V[y];
// chip8->registers.V[x] = chip8->registers.V[x] & chip8->registers.V[y];
chip8->registers.V[x] &= chip8->registers.V[y];
break;

// 8xy3 - AND Vx, Vy. perform a bitwise XOR on Vx and Vy then store result in Vx
case 0x03:
chip8->registers.V[x] = chip8->registers.V[x] ^ chip8->registers.V[y];
// chip8->registers.V[x] = chip8->registers.V[x] ^ chip8->registers.V[y];
chip8->registers.V[x] ^= chip8->registers.V[y];
break;

// 8xy4 - ADD Vx, Vy. Set Vx = Vx + Vy, set VF = carry
Expand All @@ -86,13 +89,13 @@ static void chip8_execute_extended_eight(struct chip8 *chip8, unsigned short opc
{
chip8->registers.V[0x0f] = true;
}
chip8->registers.V[x] = chip8->registers.V[x] - chip8->registers.V[y];
chip8->registers.V[x] -= chip8->registers.V[y];
break;

// 8xy6 - SHR Vx {, Vy}
case 0x06:
chip8->registers.V[0x0f] = chip8->registers.V[x] & 0x01;
chip8->registers.V[x] = chip8->registers.V[x] / 2;
chip8->registers.V[0x0f] = chip8->registers.V[x] & 0b00000001;
chip8->registers.V[x] /= 2;
break;

// 8xy7 - SUBN Vx, Vy
Expand Down
8 changes: 4 additions & 4 deletions src/chip8keyboard.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#include "chip8keyboard.h"
#include <assert.h>

static void chip8_keyboard_ensure_in_bounds(int key)
{
assert(key >= 0 && key < CHIP8_TOTAL_KEYS);
}
// static void chip8_keyboard_ensure_in_bounds(int key)
// {
// assert(key >= 0 && key < CHIP8_TOTAL_KEYS);
// }

void chip8_keyboard_set_map(struct chip8_keyboard* keyboard, const char* map)
{
Expand Down
49 changes: 37 additions & 12 deletions src/chip8screen.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,26 +24,51 @@ bool chip8_screen_is_set(struct chip8_screen* screen, int x, int y)
return screen->pixels[y][x];
}

void chip8_screen_xor(struct chip8_screen* screen, int x, int y)
{
chip8_screen_check_bounds(x, y);
screen->pixels[y][x] ^= true;
}

bool chip8_screen_draw_sprite(struct chip8_screen* screen, int x, int y, const char* sprite, int num)
{
bool pixel_collision = false;
// bool pixel_collision = false;

for (int ly = 0; ly < num; ly++)
{
char c = sprite[ly];
for (int lx = 0; lx < 8; lx++)
{
if ((c & (0b10000000 >> lx)) == 0)
continue;
// for (int ly = 0; ly < num; ly++)
// {
// char c = sprite[ly];
// for (int lx = 0; lx < 8; lx++)
// {
// if ((c & (0b10000000 >> lx)) == 0)
// continue;

// if (screen->pixels[(ly + y) % CHIP8_HEIGHT][(lx + x) % CHIP8_WIDTH])
// {
// pixel_collision = true;
// }

if (screen->pixels[(ly + y) % CHIP8_HEIGHT][(lx + x) % CHIP8_WIDTH])
// screen->pixels[(ly + y) % CHIP8_HEIGHT][(lx + x) % CHIP8_WIDTH] ^= true;
// }
// }

// return pixel_collision;

bool pixel_collision = false;
for (int ly = 0; ly < num; ly++) {
char c = sprite[ly];
for (int lx = 0; lx < 8; lx++) {
if ((c & (0b10000000 >> lx)) == 0)
{
continue;
}

int drawx = (lx+x) % CHIP8_WIDTH;
int drawy = (ly+y) % CHIP8_HEIGHT;
if (chip8_screen_is_set(screen, drawx, drawy)) {
pixel_collision = true;
}

screen->pixels[(ly + y) % CHIP8_HEIGHT][(lx + x) % CHIP8_WIDTH] ^= true;
chip8_screen_xor(screen, drawx, drawy);
}
}

return pixel_collision;
}
2 changes: 0 additions & 2 deletions src/chip8stack.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,12 @@ void chip8_stack_push(struct chip8* chip8, unsigned short val)
{
chip8->registers.SP += 1;
chip8_stack_in_bounds(chip8);

chip8->stack.stack[chip8->registers.SP] = val;
}

unsigned short chip8_stack_pop(struct chip8* chip8)
{
chip8_stack_in_bounds(chip8);

unsigned short result = chip8->stack.stack[chip8->registers.SP];
chip8->registers.SP -=1;
return result;
Expand Down
86 changes: 53 additions & 33 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,54 @@ const char keyboard_map[CHIP8_TOTAL_KEYS] = {
SDLK_6, SDLK_7, SDLK_8, SDLK_9, SDLK_a, SDLK_b,
SDLK_c, SDLK_d, SDLK_e, SDLK_f};

void drawScreen(struct chip8_screen *screen, struct SDL_Renderer *renderer)
{
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 0);

for (int x = 0; x < CHIP8_WIDTH; x++)
{
for (int y = 0; y < CHIP8_HEIGHT; y++)
{
if (chip8_screen_is_set(screen, x, y))
{
SDL_Rect r;
r.x = x * CHIP8_WINDOW_MULTIPLIER;
r.y = y * CHIP8_WINDOW_MULTIPLIER;
r.w = CHIP8_WINDOW_MULTIPLIER;
r.h = CHIP8_WINDOW_MULTIPLIER;
SDL_RenderFillRect(renderer, &r);
}
}
}

SDL_RenderPresent(renderer);
}

int main(int argc, char **argv)
{
// a clock to keep track of every 60hz tick
clock_t renderTimer = 0;
// the desired render refresh rate
int renderHz = 60;

// the amount of time the last render too
clock_t lastRenderTime = 0;
// number of milliseconds to delay (moderated by lastRenderTime) - 1/120th of a second
int loopDelayUsec = 120000;

if (argc < 2)
{
printf("You must provide a file to load");
return -1;
}

const char* filename = argv[1];
const char *filename = argv[1];
printf("The filename to load is: %s\n", filename);

// rb - reading binary
FILE* f = fopen(filename, "rb");
FILE *f = fopen(filename, "rb");
if (!f)
{
printf("Failed to open the file");
Expand All @@ -37,6 +72,7 @@ int main(int argc, char **argv)

char buf[size];
int res = fread(buf, size, 1, f);

if (res != 1)
{
printf("Failed to read from file");
Expand All @@ -48,19 +84,19 @@ int main(int argc, char **argv)
chip8_load(&chip8, buf, size);
chip8_keyboard_set_map(&chip8.keyboard, keyboard_map);


SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window *window = SDL_CreateWindow(
EMULATOR_WINDOW_TITLE,
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
CHIP8_WIDTH * CHIP8_WINDOW_MULTIPLIER,
CHIP8_HEIGHT * CHIP8_WINDOW_MULTIPLIER, SDL_WINDOW_SHOWN);
CHIP8_HEIGHT * CHIP8_WINDOW_MULTIPLIER, SDL_WINDOW_SHOWN | SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_OPENGL);

SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_TEXTUREACCESS_TARGET);

while (1)
{
clock_t start = clock();
SDL_Event event;

while (SDL_PollEvent(&event))
Expand Down Expand Up @@ -95,43 +131,27 @@ int main(int argc, char **argv)
};
}

SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 0);

for (int x = 0; x < CHIP8_WIDTH; x++)
if ((clock() - renderTimer) >= (CLOCKS_PER_SEC / (renderHz * 10)))
{
for (int y = 0; y < CHIP8_HEIGHT; y++)
if (chip8.registers.delay_timer > 0)
{
if (chip8_screen_is_set(&chip8.screen, x, y))
{
SDL_Rect r;
r.x = x * CHIP8_WINDOW_MULTIPLIER;
r.y = y * CHIP8_WINDOW_MULTIPLIER;
r.w = CHIP8_WINDOW_MULTIPLIER;
r.h = CHIP8_WINDOW_MULTIPLIER;
SDL_RenderFillRect(renderer, &r);
}
chip8.registers.delay_timer -= 1;
}
}

SDL_RenderPresent(renderer);

if (chip8.registers.delay_timer > 0)
{
sleep(1);
chip8.registers.delay_timer -=1;
}

if (chip8.registers.sound_timer > 0)
{
// Beep(15000, 100 * chip8.registers.sound_timer);
chip8.registers.sound_timer = 0;
if (chip8.registers.sound_timer > 0)
{
chip8.registers.sound_timer -= 1;
}
drawScreen(&chip8.screen, renderer);
renderTimer = clock();
}

unsigned short opcode = chip8_memory_get_short(&chip8.memory, chip8.registers.PC);
chip8.registers.PC += 2;
chip8_exec(&chip8, opcode);

lastRenderTime = clock() - start;
float sleep_for = loopDelayUsec / (lastRenderTime >= 1 ? lastRenderTime : 1);
usleep(sleep_for);
}

out:
Expand Down