From eea5d7275656329326a6fb0a2cc1ef7ad0b94446 Mon Sep 17 00:00:00 2001 From: Thomas Curley Date: Fri, 24 Feb 2023 09:25:22 +0000 Subject: [PATCH] fix delay issue --- .gitignore | 73 ++++++++++++++++++++++++++++++++++++++ src/chip8.c | 15 ++++---- src/chip8keyboard.c | 8 ++--- src/chip8screen.c | 49 +++++++++++++++++++------- src/chip8stack.c | 2 -- src/main.c | 86 ++++++++++++++++++++++++++++----------------- 6 files changed, 176 insertions(+), 57 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2e358e1 --- /dev/null +++ b/.gitignore @@ -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++ \ No newline at end of file diff --git a/src/chip8.c b/src/chip8.c index 28e4b46..a88bf90 100644 --- a/src/chip8.c +++ b/src/chip8.c @@ -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 @@ -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 diff --git a/src/chip8keyboard.c b/src/chip8keyboard.c index 6a56f4f..451cc1f 100644 --- a/src/chip8keyboard.c +++ b/src/chip8keyboard.c @@ -1,10 +1,10 @@ #include "chip8keyboard.h" #include -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) { diff --git a/src/chip8screen.c b/src/chip8screen.c index cee2c6e..9a82cb9 100644 --- a/src/chip8screen.c +++ b/src/chip8screen.c @@ -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; } \ No newline at end of file diff --git a/src/chip8stack.c b/src/chip8stack.c index 2ad1f65..4ab1f83 100644 --- a/src/chip8stack.c +++ b/src/chip8stack.c @@ -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; diff --git a/src/main.c b/src/main.c index fbb612e..9f99918 100644 --- a/src/main.c +++ b/src/main.c @@ -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"); @@ -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"); @@ -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)) @@ -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: