From e9ec67945034935931c975ddb9522a5dbb69e6a9 Mon Sep 17 00:00:00 2001 From: Loic Guegan Date: Tue, 26 Dec 2023 13:17:52 +0100 Subject: [PATCH] Minor changes --- src/Makefile | 2 +- src/beep.mp3 | Bin 0 -> 5320 bytes src/keypad.c | 8 +++---- src/main.c | 16 +++++++++---- src/speaker.c | 20 ++++++++++++++++ src/speaker.h | 8 +++++++ src/vcpu.c | 65 ++++++++++++++++++++++++++++++-------------------- src/vcpu.h | 6 +++-- 8 files changed, 87 insertions(+), 38 deletions(-) create mode 100644 src/beep.mp3 create mode 100644 src/speaker.c create mode 100644 src/speaker.h diff --git a/src/Makefile b/src/Makefile index d4e52d0..1a073e1 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,7 +1,7 @@ EXEC=chip-8 -$(EXEC): main.c screen.c mem.c vcpu.c keypad.c +$(EXEC): main.c screen.c mem.c vcpu.c keypad.c speaker.c gcc -lraylib $^ -o $@ clean: diff --git a/src/beep.mp3 b/src/beep.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..09f4219ff37fa18139270102340b46e08a285c77 GIT binary patch literal 5320 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 literal 0 HcmV?d00001 diff --git a/src/keypad.c b/src/keypad.c index f26c5e2..2ff7be4 100644 --- a/src/keypad.c +++ b/src/keypad.c @@ -19,7 +19,7 @@ int map[]={ KEY_V // F }; -int KeypadKeycodeValid(int keycode){ +int KeypadGetKey(int keycode){ for(int i=0;i<16;i++){ if(map[i]==keycode) return i; @@ -29,9 +29,9 @@ int KeypadKeycodeValid(int keycode){ int KeypadGetPressed(){ - int keycode=GetKeyPressed(); - if(keycode){ - return KeypadKeycodeValid(keycode); + for(int i=0;i<16;i++){ + if(IsKeyDown(map[i])) + return i; } return -1; } diff --git a/src/main.c b/src/main.c index 88d12bf..4a3beec 100644 --- a/src/main.c +++ b/src/main.c @@ -1,10 +1,14 @@ #include "screen.h" #include "mem.h" #include "vcpu.h" +#include "speaker.h" + #include -#define ROM "../roms/chip8-test-suite/5-quirks.ch8" -//#define ROM "../roms/games/pong_1player.ch8" +//#define ROM "../roms/chip8-test-suite/5-quirks.ch8" +//#define ROM "../roms/chip8-test-suite/8-scrolling.ch8" +#define ROM "../roms/games/pong_1player.ch8" +//#define ROM "../roms/ibm.ch8" int main(int argc, char *argv[]) { @@ -14,8 +18,9 @@ int main(int argc, char *argv[]) MemLoadROM(ROM); ScreenInit(800,400); VCPUInit(); + SpeakerInit(); - // Set game to run at very high FPS (prevent raylib to interfer with emulator FPS) + // Set game to run at very high FPS (prevent raylib to interfer with emulator CPU frequency) SetTargetFPS(VCPU_FREQ*100); // Emulator main loop @@ -27,8 +32,9 @@ int main(int argc, char *argv[]) i++; } - // Close screen + // Finish + SpeakerFinish(); ScreenClose(); - + return 0; } diff --git a/src/speaker.c b/src/speaker.c new file mode 100644 index 0000000..b4bef73 --- /dev/null +++ b/src/speaker.c @@ -0,0 +1,20 @@ +#include "speaker.h" + +Sound s; + +void SpeakerInit(){ + InitAudioDevice(); // Initialize audio device + s=LoadSound(SPEAKER_AUDIO_FILE); +} + +void SpeakerOn(){ + PlaySound(s); +} + +void SpeakerOff(){ + StopSound(s); +} + +void SpeakerFinish(){ + CloseAudioDevice(); +} diff --git a/src/speaker.h b/src/speaker.h new file mode 100644 index 0000000..3c36fef --- /dev/null +++ b/src/speaker.h @@ -0,0 +1,8 @@ +#include "raylib.h" + +#define SPEAKER_AUDIO_FILE "beep.mp3" + +void SpeakerInit(); +void SpeakerOn(); +void SpeakerOff(); +void SpeakerFinish(); diff --git a/src/vcpu.c b/src/vcpu.c index 11181f0..4682f0b 100644 --- a/src/vcpu.c +++ b/src/vcpu.c @@ -2,6 +2,7 @@ #include "mem.h" #include "screen.h" #include "keypad.h" +#include "speaker.h" #include #include @@ -14,9 +15,10 @@ VCPU_State State; void VCPUInit(){ State.PC=ADDR_ROM; State.S=0; - State.dtst_ticks=0; + State.dt_ticks=0; + State.st_ticks=0; State.screen_ticks=0; - State.keypress=-1; + State.keypressed=0; srand(time(NULL)); } @@ -208,19 +210,16 @@ void VCPUExecute(){ case 0xE: if(State.NN==0x9E){ // Skip if keypress in VX - if(State.keypress >= 0){ - if(State.V[State.X]&0x0F == State.keypress&0xF){ + if(State.keypressed){ + if(State.V[State.X] == State.key) State.PC+=2; - } } - State.keypress=-1; }else if(State.NN==0xA1){ // Skip if not keypress in VX - State.PC+=2; // First skip - if(State.keypress >=0){ - if(State.V[State.X]&0x0F == State.keypress&0x0F) - State.PC+=2; // Ignore skip if pressed + State.PC+=2; + if(State.keypressed){ + if(State.V[State.X] == State.key) + State.PC+=4; } - State.keypress=-1; } break; @@ -231,12 +230,8 @@ void VCPUExecute(){ break; case 0x0A: - 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; + if(State.keypressed){ + State.V[State.X]=State.key; } else State.PC-=2; // Go back to last instruction (loop until key is pressed) @@ -284,12 +279,23 @@ void VCPUTick(){ struct timespec start, stop; double duration, delay; + // Update keypressed + int key=KeypadGetPressed(); + if(key>=0){ + State.keypressed=1; + State.key=key&0xF; + //printf("Keypressed: %x\n",State.key); + } + else + State.keypressed=0; + // Run and benchmark CPU pipeline - clock_gettime(CLOCK_REALTIME, &start); + clock_gettime(CLOCK_REALTIME, &start); VCPUFetch(); VCPUDecode(); VCPUExecute(); - State.dtst_ticks++; + State.dt_ticks++; + State.st_ticks++; State.screen_ticks++; clock_gettime(CLOCK_REALTIME, &stop); @@ -300,23 +306,30 @@ void VCPUTick(){ usleep(delay*1e6); } - // Update Delay Timer and Sound Timer - if(State.dtst_ticks>=(1.0*VCPU_FREQ/DTST_FREQ)){ - State.dtst_ticks=0; + // Update Delay Timer + if(State.dt_ticks>=(1.0*VCPU_FREQ/DTST_FREQ)){ + State.dt_ticks=0; if(State.DT>0) State.DT--; } + // Update Sound Timer + if(State.st_ticks>=(1.0*VCPU_FREQ/DTST_FREQ)){ + State.st_ticks=0; + if(State.ST>0) + State.ST--; + } + + // Play sound + if(State.ST>0) + SpeakerOn(); + // 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(){ diff --git a/src/vcpu.h b/src/vcpu.h index 3da6b37..16de017 100644 --- a/src/vcpu.h +++ b/src/vcpu.h @@ -35,10 +35,12 @@ typedef struct VCPU_State { unsigned short NNN; // Keypressed - int keypress; + int keypressed; // Not 0 if a key was pressed + unsigned char key; // Count VCPU ticks - int dtst_ticks; + int dt_ticks; + int st_ticks; int screen_ticks; } VCPU_State;