Minor changes

This commit is contained in:
Loïc Guégan 2023-12-25 15:03:22 +01:00
parent 5a6aecc0f5
commit c6ddcbe2bd
13 changed files with 112 additions and 72 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -2,12 +2,18 @@
#include "mem.h" #include "mem.h"
#include "vcpu.h" #include "vcpu.h"
#include <stdio.h>
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/logo_chip8.ch8"); MemLoadROM("../roms/chip8-test-suite/3-corax+.ch8");
ScreenInit(800,400); ScreenInit(800,400);
VCPUInit(); VCPUInit();

View file

@ -15,7 +15,7 @@ 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(80); // Set game to run at 60 frames-per-second SetTargetFPS(200); // Set game to run at 60 frames-per-second
} }
void ScreenClear() { void ScreenClear() {

View file

@ -26,83 +26,109 @@ void VCPUFetch(){
void VCPUDecode(){ void VCPUDecode(){
State.X=(State.opcode>>8) & 0xF; State.X=(State.opcode>>8) & 0xF;
State.Y=(State.opcode>>4) & 0xF; State.Y=(State.opcode>>4) & 0xF;
State.N=State.opcode & 0xF; State.N=State.opcode & 0x0F;
State.NN=State.opcode & 0xFF;
State.NN=State.Y;
State.NN=State.NN<<4;
State.NN=State.NN | State.N;
State.NNN=State.opcode & 0x0FFF; State.NNN=State.opcode & 0x0FFF;
} }
void VCPUDoubleDabble(unsigned char x, unsigned char *u, unsigned char *t, unsigned char *h){
unsigned int bcd=x;
for(int i=0;i<8;i++){
bcd=bcd<<1;
unsigned char byte=bcd & 0xFF;
unsigned char units=(bcd>>8) & 0xF;
unsigned char tens=(bcd>>12) & 0xF;
unsigned char hundreds=(bcd>>16) & 0xF;
//printf("hundreds:%04b tens:%04b units:%04b byte:%08b\n",hundreds,tens,units,byte);
if(i<7){
if(units>4)
units+=3;
if(tens>4)
tens+=3;
if(hundreds>4)
hundreds+=3;
}
bcd = (hundreds<<16) | (tens << 12) | (units << 8) | byte;
}
*u=bcd>>8 & 0xF;
*t=bcd>>12 & 0xF;
*h=bcd>>16 & 0xF;
}
void VCPUExecute(){ void VCPUExecute(){
// VCPUDump(); VCPUDump();
switch(State.opcode >> 12){ switch(State.opcode >> 12){
case 0x0: // Clear screen or return from subroutine case 0x0: // Clear screen or return from subroutine
if(State.N == 0){ // Clear screen if(State.N == 0x0){ // Clear screen
ScreenClear(); ScreenClear();
} }
else { // Return from subroutine else if(State.N == 0xE) { // Return from subroutine
State.PC=State.stack[State.S]; State.PC=State.stack[State.S];
State.S--; State.S--;
} }
break break;
;;
case 0x1: // Jump case 0x1: // Jump
State.PC=State.NNN; State.PC=State.NNN;
break break;
;;
case 0x2: // Call case 0x2: // Call
State.S++; State.S++;
State.stack[State.S]=State.PC; State.stack[State.S]=State.PC;
State.PC=State.NNN; State.PC=State.NNN;
break break;
;;
case 0x3: // SE: VX, byte case 0x3: // SE: VX, byte
if(State.V[State.X]==State.NN) if(State.V[State.X]==State.NN)
State.PC+=2; State.PC+=2;
break; break;
;;
case 0x4: // SNE: VX, byte case 0x4: // SNE: VX, byte
if(State.V[State.X]!=State.NN) if(State.V[State.X]!=State.NN)
State.PC+=2; State.PC+=2;
break; break;
;;
case 0x5: // SE: VX, VY case 0x5: // SE: VX, VY
if(State.N == 0){
if(State.V[State.X]==State.V[State.Y]) if(State.V[State.X]==State.V[State.Y])
State.PC+=2; State.PC+=2;
}
break; break;
;;
case 0x6: case 0x6:
State.V[State.X]=State.NN; State.V[State.X]=State.NN;
break break;
;;
case 0x7: case 0x7:
State.V[State.X]+=State.NN; State.V[State.X]=State.V[State.X] + State.NN;
break break;
;;
case 0x8: // Register operations case 0x8: // Register operations
switch(State.N){ switch(State.N){
case 0x0: // VX = VY
State.V[State.X]=State.V[State.Y];
break;
case 0x1: // VX = VX OR VY case 0x1: // VX = VX OR VY
State.V[State.X]=State.V[State.X] | State.V[State.Y]; State.V[State.X]=State.V[State.X] | State.V[State.Y];
break; break;
;;
case 0x2: // VX = VX AND VY case 0x2: // VX = VX AND VY
State.V[State.X]=State.V[State.X] & State.V[State.Y]; State.V[State.X]=State.V[State.X] & State.V[State.Y];
break; break;
;;
case 0x3: // VX = VX XOR VY case 0x3: // VX = VX XOR VY
State.V[State.X]=State.V[State.X] ^ State.V[State.Y]; State.V[State.X]=State.V[State.X] ^ State.V[State.Y];
break; break;
;;
case 0x4: // VX = VX + VY case 0x4: // VX = VX + VY
if(State.V[State.X] + State.V[State.Y] > 255) if((State.V[State.X] + State.V[State.Y]) > 255)
State.V[REG_FLAG]=1; State.V[REG_FLAG]=1;
else else
State.V[REG_FLAG]=0; State.V[REG_FLAG]=0;
State.V[State.X]=(State.V[State.X] + State.V[State.Y]) & 0xFF; State.V[State.X]=State.V[State.X] + State.V[State.Y];
break; break;
;;
case 0x5: // VX = VX - VY case 0x5: // VX = VX - VY
if(State.V[State.X] > State.V[State.Y]) if(State.V[State.X] > State.V[State.Y])
State.V[REG_FLAG]=1; State.V[REG_FLAG]=1;
@ -110,7 +136,7 @@ void VCPUExecute(){
State.V[REG_FLAG]=0; State.V[REG_FLAG]=0;
State.V[State.X]=State.V[State.X] - State.V[State.Y]; State.V[State.X]=State.V[State.X] - State.V[State.Y];
break; break;
;;
case 0x6: // VX = VX SHR 1 case 0x6: // VX = VX SHR 1
if(State.V[State.X] & 0x1 == 1) if(State.V[State.X] & 0x1 == 1)
State.V[REG_FLAG]=1; State.V[REG_FLAG]=1;
@ -118,47 +144,49 @@ void VCPUExecute(){
State.V[REG_FLAG]=0; State.V[REG_FLAG]=0;
State.V[State.X]=State.V[State.X] >> 1; State.V[State.X]=State.V[State.X] >> 1;
break; break;
;;
case 0x7: // VX = VY - VX case 0x7: // VX = VY - VX
if(State.V[State.X] < State.V[State.Y]) if(State.V[State.Y] > State.V[State.X])
State.V[REG_FLAG]=1; State.V[REG_FLAG]=1;
else else
State.V[REG_FLAG]=0; State.V[REG_FLAG]=0;
State.V[State.X]=State.V[State.Y] - State.V[State.X]; State.V[State.X]=State.V[State.Y] - State.V[State.X];
break; break;
;;
case 0xE: // VX = VX SHL 1 case 0xE: // VX = VX SHL 1
if(State.V[State.X] >> 15 == 1) if(State.V[State.X] >> 7 == 1)
State.V[REG_FLAG]=1; State.V[REG_FLAG]=1;
else else
State.V[REG_FLAG]=0; State.V[REG_FLAG]=0;
State.V[State.X]=State.V[State.X] << 1; State.V[State.X]=State.V[State.X] << 1;
break; break;
;;
} }
break break;
;;
case 0x9: // SNE: VX, VY case 0x9: // SNE: VX, VY
if(State.N==0){
if(State.V[State.X]!=State.V[State.Y]) if(State.V[State.X]!=State.V[State.Y])
State.PC+=2; State.PC+=2;
}
break; break;
;;
case 0xA: case 0xA:
State.I=State.NNN; State.I=State.NNN;
break break;
;;
case 0xB: case 0xB:
State.PC=State.V[0]+State.NNN; State.PC=State.V[0]+State.NNN;
break break;
;;
case 0xC: case 0xC:
unsigned short n = rand() % 255 + 1; unsigned short n = rand() % 255 + 1;
State.V[State.X]=n & State.NN; State.V[State.X]=n & State.NN;
break break;
;;
case 0xD: // Draw a sprite case 0xD: // Draw a sprite
int X=State.V[State.X]%63; int X=State.V[State.X]&63;
int Y=State.V[State.Y]%31; int Y=State.V[State.Y]&31;
State.V[REG_FLAG]=0; // Set flag to 0 State.V[REG_FLAG]=0; // Set flag to 0
int width, height; int width, height;
ScreenWH(&width,&height); ScreenWH(&width,&height);
@ -166,7 +194,7 @@ void VCPUExecute(){
// Stop if row out of screen // Stop if row out of screen
if(Y+row>=height) if(Y+row>=height)
break; break;
char sprite; unsigned char sprite;
MemRead(&sprite,1,State.I+row); // Load sprite MemRead(&sprite,1,State.I+row); // Load sprite
// Draw sprite // Draw sprite
for(int shift=0;shift<8;shift++){ for(int shift=0;shift<8;shift++){
@ -178,51 +206,56 @@ void VCPUExecute(){
} }
} }
break; break;
;;
case 0xE: case 0xE:
// TODO // TODO
break;; break;
case 0xF: case 0xF:
switch(State.NN){ switch(State.NN){
case 0x07: // Get timer case 0x07: // Get timer
State.V[State.X]=State.DT; State.V[State.X]=State.DT;
break; break;
;;
case 0x0A: case 0x0A:
// TODO // TODO
break; break;
;;
case 0x15: // Set timer case 0x15: // Set timer
State.DT=State.V[State.X]; State.DT=State.V[State.X];
break; break;
;;
case 0x18: // Set sound timer case 0x18: // Set sound timer
State.ST=State.V[State.X]; State.ST=State.V[State.X];
break; break;
;;
case 0x1E: // I = I + VX case 0x1E: // I = I + VX
State.I=State.I+State.V[State.X]; State.I=State.I+State.V[State.X];
break; break;
;;
case 0x29: case 0x29:
// TODO // TODO
break; break;
;;
case 0x33: case 0x33:
// TODO unsigned char units, tens, hundreds;
VCPUDoubleDabble(State.V[State.X],&units,&tens,&hundreds);
MemCopy(&hundreds,1,State.I);
MemCopy(&tens,1,State.I+1);
MemCopy(&units,1,State.I+2);
// printf("hundreds:%d tens:%d units:%d byte:%d\n",hundreds,tens,units,State.V[State.X]);
break; break;
;;
case 0x55: case 0x55:
MemCopy(State.V,0xF,State.I); MemCopy(State.V,0xF,State.I);
break; break;
;;
case 0x65: case 0x65:
MemRead(State.V,0xF,State.I); MemRead(State.V,0xF,State.I);
break; break;
;;
} }
break; break;
;;
} }
} }

View file

@ -25,10 +25,10 @@ typedef struct VCPU_State {
// Intruction (opcode + decoded fields) // Intruction (opcode + decoded fields)
unsigned short opcode; unsigned short opcode;
char X; unsigned char X;
char Y; unsigned char Y;
char N; unsigned char N;
char NN; unsigned char NN;
unsigned short NNN; unsigned short NNN;
} VCPU_State; } VCPU_State;
@ -36,4 +36,5 @@ void VCPUInit();
void VCPUFetch(); void VCPUFetch();
void VCPUDecode(); void VCPUDecode();
void VCPUExecute(); void VCPUExecute();
void VCPUDoubleDabble(unsigned char x, unsigned char *u, unsigned char *t, unsigned char *h);
void VCPUDump(); void VCPUDump();