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 0000000..09f4219 Binary files /dev/null and b/src/beep.mp3 differ 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;