Minor changes

This commit is contained in:
Loïc Guégan 2023-12-26 09:06:40 +01:00
parent f1c3a67294
commit 64917e3504
7 changed files with 96 additions and 36 deletions

BIN
roms/games/pong_1player.ch8 Normal file

Binary file not shown.

View file

@ -19,21 +19,19 @@ int map[]={
KEY_V // F KEY_V // F
}; };
int KeypadIsPressed(unsigned char c){ int KeypadKeycodeValid(int keycode){
if(c<=0xF){ for(int i=0;i<16;i++){
if(IsKeyPressed(map[c])) if(map[i]==keycode)
return 1; return i;
} }
return 0; return -1;
} }
int KeypadGetPressed(){ int KeypadGetPressed(){
int keycode=GetKeyPressed(); int keycode=GetKeyPressed();
if(keycode){ if(keycode){
for(int i=0;i<16;i++){ return KeypadKeycodeValid(keycode);
if(map[i]==keycode)
return 1;
}
} }
return -1; return -1;
} }

View file

@ -2,6 +2,5 @@
#include "raylib.h" #include "raylib.h"
int KeypadIsPressed(unsigned char c);
int KeypadGetPressed(); int KeypadGetPressed();

View file

@ -1,34 +1,33 @@
#include "screen.h" #include "screen.h"
#include "mem.h" #include "mem.h"
#include "vcpu.h" #include "vcpu.h"
#include <stdio.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[]) 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 // Initialize
MemInit(); MemInit();
MemLoadROM("../roms/games/paddles.ch8"); MemLoadROM(ROM);
ScreenInit(800,400); ScreenInit(800,400);
VCPUInit(); 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()){ while (!WindowShouldClose()){
for(int i=0;i<30;i++){ VCPUTick();
VCPUFetch(); if(i%600 == 0)
VCPUDecode(); printf("tick\n");
VCPUExecute(); i++;
}
ScreenUpdate();
} }
// Close screen
ScreenClose(); ScreenClose();
return 0; return 0;

View file

@ -15,7 +15,6 @@ void ScreenInit(int width, int height){
SetTraceLogLevel(LOG_ERROR); // Disable anoying raylib logs SetTraceLogLevel(LOG_ERROR); // Disable anoying raylib logs
InitWindow(width, height, "Chip-8 Emulator"); InitWindow(width, height, "Chip-8 Emulator");
SetTargetFPS(60); // Set game to run at 60 frames-per-second
} }
void ScreenClear() { void ScreenClear() {

View file

@ -5,6 +5,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h>
#include <time.h> #include <time.h>
// Current VCPU state // Current VCPU state
@ -13,6 +14,9 @@ VCPU_State State;
void VCPUInit(){ void VCPUInit(){
State.PC=ADDR_ROM; State.PC=ADDR_ROM;
State.S=0; State.S=0;
State.dtst_ticks=0;
State.screen_ticks=0;
State.keypress=-1;
srand(time(NULL)); srand(time(NULL));
} }
@ -204,11 +208,20 @@ void VCPUExecute(){
case 0xE: case 0xE:
if(State.NN==0x9E){ // Skip if keypress in VX if(State.NN==0x9E){ // Skip if keypress in VX
if(KeypadIsPressed(State.V[State.X]&0x0F)){ if(State.keypress >= 0){
State.PC+=2; 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 }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; State.PC+=2;
} }
break; break;
@ -220,13 +233,15 @@ void VCPUExecute(){
break; break;
case 0x0A: case 0x0A:
int key=KeypadGetPressed(); if(State.keypress >=0){
if(key >= 0){ State.V[State.X]=State.keypress&0xF;
State.V[State.X]=key&0x0F; if(State.V[State.X]&0x0F != State.keypress&0xF){
State.PC+=2;
State.keypress=-1;
}
} }
else 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; break;
case 0x15: // Set timer 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(){ void VCPUDump(){
printf("opcode: 0x%04x\n",State.opcode&0xFFFF); printf("opcode: 0x%04x\n",State.opcode&0xFFFF);
printf("X: 0x%01x\n",State.X); printf("X: 0x%01x\n",State.X);

View file

@ -1,5 +1,8 @@
#pragma once #pragma once
#define VCPU_FREQ 600
#define DTST_FREQ 60
#define SCREEN_FREQ 60
#define REG_FLAG 0xF #define REG_FLAG 0xF
typedef struct VCPU_State { typedef struct VCPU_State {
@ -30,11 +33,19 @@ typedef struct VCPU_State {
unsigned char N; unsigned char N;
unsigned char NN; unsigned char NN;
unsigned short NNN; unsigned short NNN;
// Keypressed
int keypress;
// Count VCPU ticks
int dtst_ticks;
int screen_ticks;
} VCPU_State; } VCPU_State;
void VCPUInit(); void VCPUInit();
void VCPUFetch(); void VCPUFetch();
void VCPUDecode(); void VCPUDecode();
void VCPUExecute(); void VCPUExecute();
void VCPUTick();
void VCPUDoubleDabble(unsigned char x, unsigned char *u, unsigned char *t, unsigned char *h); void VCPUDoubleDabble(unsigned char x, unsigned char *u, unsigned char *t, unsigned char *h);
void VCPUDump(); void VCPUDump();