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

View file

@ -15,7 +15,7 @@ void ScreenInit(int width, int height){
SetTraceLogLevel(LOG_ERROR); // Disable anoying raylib logs
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() {

View file

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

View file

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