From 64917e3504c32f09a503675f3e43a362508725de Mon Sep 17 00:00:00 2001 From: Loic Guegan <loic.guegan@mailbox.org> Date: Tue, 26 Dec 2023 09:06:40 +0100 Subject: [PATCH] Minor changes --- roms/games/pong_1player.ch8 | Bin 0 -> 246 bytes src/keypad.c | 16 ++++----- src/keypad.h | 1 - src/main.c | 33 +++++++++-------- src/screen.c | 1 - src/vcpu.c | 70 +++++++++++++++++++++++++++++++----- src/vcpu.h | 11 ++++++ 7 files changed, 96 insertions(+), 36 deletions(-) create mode 100644 roms/games/pong_1player.ch8 diff --git a/roms/games/pong_1player.ch8 b/roms/games/pong_1player.ch8 new file mode 100644 index 0000000000000000000000000000000000000000..65d63106cc088da4fc0e2cfad10e01453e724620 GIT binary patch literal 246 zcmc~|%I3+j&*fS4>ejY9*YX&YuB0(%FeM~>5dFYzz#t@bT)dnk^Z%j`*9svj5*QyW ztp1n40wkFd<hz+}ZR;&Kz*YOtfuWWufgwS@m+8(mkm|OU_9+SWZA^*s?Lux$LKSZI zLQU@Sng87xG8wNG3Tb69B{Mb@G;9^>%J`Se1!P^dXB1kL$kZSTq<4YI6JYXCg2D$0 zr7L|VK$qDWGXh=r&zLcTNl2{nzvsWq|3W7!89kXY853AONR%<UIh6eq%31X3pYf;E akD4hWsSH;_OGH0uUI}G**8l+wAOHX*Vqww% literal 0 HcmV?d00001 diff --git a/src/keypad.c b/src/keypad.c index d106642..f26c5e2 100644 --- a/src/keypad.c +++ b/src/keypad.c @@ -19,21 +19,19 @@ int map[]={ KEY_V // F }; -int KeypadIsPressed(unsigned char c){ - if(c<=0xF){ - if(IsKeyPressed(map[c])) - return 1; +int KeypadKeycodeValid(int keycode){ + for(int i=0;i<16;i++){ + if(map[i]==keycode) + return i; } - return 0; + return -1; } + int KeypadGetPressed(){ int keycode=GetKeyPressed(); if(keycode){ - for(int i=0;i<16;i++){ - if(map[i]==keycode) - return 1; - } + return KeypadKeycodeValid(keycode); } return -1; } diff --git a/src/keypad.h b/src/keypad.h index 9339280..922d2a8 100644 --- a/src/keypad.h +++ b/src/keypad.h @@ -2,6 +2,5 @@ #include "raylib.h" -int KeypadIsPressed(unsigned char c); int KeypadGetPressed(); diff --git a/src/main.c b/src/main.c index 7591627..ea8d606 100644 --- a/src/main.c +++ b/src/main.c @@ -1,34 +1,33 @@ #include "screen.h" #include "mem.h" #include "vcpu.h" - #include <stdio.h> + +#define ROM "../roms/chip8-test-suite/6-keypad.ch8" +//#define ROM "../roms/games/pong_1player.ch8" + int main(int argc, char *argv[]) { - /* unsigned char byte=137; */ - /* unsigned char u,t,h; */ - /* VCPUDoubleDabble(byte,&u,&t,&h); */ - /* printf("%d: %01d%01d%01d\n",byte,h,t,u); */ - /* return 0; */ // Initialize MemInit(); - MemLoadROM("../roms/games/paddles.ch8"); - + MemLoadROM(ROM); ScreenInit(800,400); VCPUInit(); - // MemDump(); - int i=0; + // Set game to run at very high FPS (prevent raylib to interfer with emulator FPS) + SetTargetFPS(VCPU_FREQ*100); + + // Emulator main loop + int i=0; while (!WindowShouldClose()){ - for(int i=0;i<30;i++){ - VCPUFetch(); - VCPUDecode(); - VCPUExecute(); - } - ScreenUpdate(); + VCPUTick(); + if(i%600 == 0) + printf("tick\n"); + i++; } - + + // Close screen ScreenClose(); return 0; diff --git a/src/screen.c b/src/screen.c index 2e77ba9..a445bd8 100644 --- a/src/screen.c +++ b/src/screen.c @@ -15,7 +15,6 @@ void ScreenInit(int width, int height){ SetTraceLogLevel(LOG_ERROR); // Disable anoying raylib logs InitWindow(width, height, "Chip-8 Emulator"); - SetTargetFPS(60); // Set game to run at 60 frames-per-second } void ScreenClear() { diff --git a/src/vcpu.c b/src/vcpu.c index 67dea13..1f36b68 100644 --- a/src/vcpu.c +++ b/src/vcpu.c @@ -5,6 +5,7 @@ #include <stdio.h> #include <stdlib.h> +#include <unistd.h> #include <time.h> // Current VCPU state @@ -13,6 +14,9 @@ VCPU_State State; void VCPUInit(){ State.PC=ADDR_ROM; State.S=0; + State.dtst_ticks=0; + State.screen_ticks=0; + State.keypress=-1; srand(time(NULL)); } @@ -204,11 +208,20 @@ void VCPUExecute(){ case 0xE: if(State.NN==0x9E){ // Skip if keypress in VX - if(KeypadIsPressed(State.V[State.X]&0x0F)){ - State.PC+=2; + if(State.keypress >= 0){ + if(State.V[State.X]&0x0F == State.keypress&0xF){ + State.PC+=2; + } + State.keypress=-1; } }else if(State.NN==0xA1){ // Skip if not keypress in VX - if(!KeypadIsPressed(State.V[State.X]&0x0F)) + if(State.keypress >=0){ + if(State.V[State.X]&0x0F != State.keypress&0xF){ + State.PC+=2; + } + State.keypress=-1; + } + else State.PC+=2; } break; @@ -220,13 +233,15 @@ void VCPUExecute(){ break; case 0x0A: - int key=KeypadGetPressed(); - if(key >= 0){ - State.V[State.X]=key&0x0F; + if(State.keypress >=0){ + State.V[State.X]=State.keypress&0xF; + if(State.V[State.X]&0x0F != State.keypress&0xF){ + State.PC+=2; + State.keypress=-1; + } } else - State.PC-=2; // Go back to last instruction (loop until key is pressed) - + State.PC-=2; // Go back to last instruction (loop until key is pressed) break; case 0x15: // Set timer @@ -267,6 +282,45 @@ void VCPUExecute(){ } } +void VCPUTick(){ + struct timespec start, stop; + double duration, delay; + + // Run and benchmark CPU pipeline + clock_gettime(CLOCK_REALTIME, &start); + VCPUFetch(); + VCPUDecode(); + VCPUExecute(); + State.dtst_ticks++; + State.screen_ticks++; + clock_gettime(CLOCK_REALTIME, &stop); + + // Adjust pipeline duration + duration=(stop.tv_sec - start.tv_sec) + (stop.tv_nsec - start.tv_nsec)*1e-9; + delay=1.0/VCPU_FREQ-duration; + if(delay>0){ + usleep(delay*1e6); + } + + // Update Delay Timer and Sound Timer + if(State.dtst_ticks>=(1.0*VCPU_FREQ/DTST_FREQ)){ + State.dtst_ticks=0; + if(State.DT>0) + State.DT--; + } + + // Refresh screen + if(State.screen_ticks>=(1.0*VCPU_FREQ/SCREEN_FREQ)){ + State.screen_ticks=0; + ScreenUpdate(); + } + + // Update keypressed + int keypress=KeypadGetPressed(); + if(keypress>=0) + State.keypress=keypress; +} + void VCPUDump(){ printf("opcode: 0x%04x\n",State.opcode&0xFFFF); printf("X: 0x%01x\n",State.X); diff --git a/src/vcpu.h b/src/vcpu.h index fccd397..3da6b37 100644 --- a/src/vcpu.h +++ b/src/vcpu.h @@ -1,5 +1,8 @@ #pragma once +#define VCPU_FREQ 600 +#define DTST_FREQ 60 +#define SCREEN_FREQ 60 #define REG_FLAG 0xF typedef struct VCPU_State { @@ -30,11 +33,19 @@ typedef struct VCPU_State { unsigned char N; unsigned char NN; unsigned short NNN; + + // Keypressed + int keypress; + + // Count VCPU ticks + int dtst_ticks; + int screen_ticks; } VCPU_State; void VCPUInit(); void VCPUFetch(); void VCPUDecode(); void VCPUExecute(); +void VCPUTick(); void VCPUDoubleDabble(unsigned char x, unsigned char *u, unsigned char *t, unsigned char *h); void VCPUDump();