Minor changes
This commit is contained in:
parent
f1c3a67294
commit
64917e3504
7 changed files with 96 additions and 36 deletions
BIN
roms/games/pong_1player.ch8
Normal file
BIN
roms/games/pong_1player.ch8
Normal file
Binary file not shown.
16
src/keypad.c
16
src/keypad.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,5 @@
|
||||||
|
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
|
|
||||||
int KeypadIsPressed(unsigned char c);
|
|
||||||
int KeypadGetPressed();
|
int KeypadGetPressed();
|
||||||
|
|
||||||
|
|
33
src/main.c
33
src/main.c
|
@ -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;
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
70
src/vcpu.c
70
src/vcpu.c
|
@ -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);
|
||||||
|
|
11
src/vcpu.h
11
src/vcpu.h
|
@ -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();
|
||||||
|
|
Loading…
Add table
Reference in a new issue