summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoic Guegan <loic.guegan@mailbox.org>2023-12-26 19:27:23 +0100
committerLoic Guegan <loic.guegan@mailbox.org>2023-12-26 19:27:23 +0100
commitf7b1fedfb43f7c4b702bf22b32cbc9aa722f3c8e (patch)
tree8f3842a8f921a597f06f38185db5a85e5c1a95e1
parentc3b9b472bf9a993a89121b8989e4cc9dbc786f2c (diff)
Cleaning code
-rw-r--r--src/main.c13
-rw-r--r--src/mem.c11
-rw-r--r--src/vcpu.c45
-rw-r--r--src/vcpu.h8
4 files changed, 53 insertions, 24 deletions
diff --git a/src/main.c b/src/main.c
index de3ae0d..2f2f9d0 100644
--- a/src/main.c
+++ b/src/main.c
@@ -5,6 +5,9 @@
#include <stdio.h>
+#define SCREEN_WIDTH 1000
+#define SCREEN_HEIGHT 500
+
int main(int argc, char *argv[])
{
// Parse argument
@@ -17,11 +20,8 @@ int main(int argc, char *argv[])
}
// Initialize
- MemInit();
- MemLoadROM(argv[1]);
- ScreenInit(1000,500);
- VCPUInit();
- SpeakerInit();
+ VCPUInit(SCREEN_WIDTH, SCREEN_HEIGHT);
+ MemLoadROM(argv[1]); // Load ROM into main memory
// Set game to run at very high FPS (prevent raylib to interfer with emulator CPU frequency)
SetTargetFPS(VCPU_FREQ*100);
@@ -32,8 +32,7 @@ int main(int argc, char *argv[])
}
// Finish
- SpeakerFinish();
- ScreenClose();
+ VCPUFinish();
return 0;
}
diff --git a/src/mem.c b/src/mem.c
index ec34750..aba34fc 100644
--- a/src/mem.c
+++ b/src/mem.c
@@ -16,13 +16,22 @@ void MemSet(int addr, unsigned char value, int size){
}
void MemStore(unsigned char *data, int size, int addr){
- for(int i=0;i<size;i++)
+ for(int i=0;i<size;i++){
+ if(addr+i>4096){
+ printf("Illegal memory access (store): addr=%d\n",addr+i);
+ return;
+ }
memory[addr+i]=data[i];
+ }
}
void MemLoad(unsigned char *data, int size, int addr){
int location=addr;
for(int i=0;i<size;i++){
+ if(addr+i>4096){
+ printf("Illegal memory access (load): addr=%d\n",addr+i);
+ return;
+ }
data[i]=memory[addr+i];
}
}
diff --git a/src/vcpu.c b/src/vcpu.c
index 4bfd86b..fb73eeb 100644
--- a/src/vcpu.c
+++ b/src/vcpu.c
@@ -12,7 +12,11 @@
// Current VCPU state
VCPU_State State;
-void VCPUInit(){
+void VCPUInit(int width, int height){
+ MemInit();
+ ScreenInit(width,height);
+ SpeakerInit();
+
State.PC=ADDR_ROM;
State.S=0;
State.dt_ticks=0;
@@ -22,6 +26,11 @@ void VCPUInit(){
srand(time(NULL));
}
+void VCPUFinish(){
+ SpeakerFinish();
+ ScreenClose();
+}
+
void VCPUFetch(){
unsigned char byte[2];
MemLoad(byte,2,State.PC); // Little indian to -1 no +1
@@ -64,7 +73,7 @@ void VCPUDoubleDabble(unsigned char x, unsigned char *u, unsigned char *t, unsig
}
void VCPUExecute(){
- // VCPUDump();
+ // Very big switch case... Thinking about it, ifelse would have been cleaner for the reader
switch(State.opcode >> 12){
case 0x0: // Clear screen or return from subroutine
if(State.N == 0x0){ // Clear screen
@@ -259,7 +268,7 @@ void VCPUExecute(){
MemStore(&hundreds,1,State.I);
MemStore(&tens,1,State.I+1);
MemStore(&units,1,State.I+2);
- //printf("hundreds:%d tens:%d units:%d byte:%d\n",hundreds,tens,units,State.V[State.X]);
+ // printf("hundreds:%d tens:%d units:%d byte:%d\n",hundreds,tens,units,State.V[State.X]);
break;
case 0x55:
@@ -279,32 +288,29 @@ void VCPUTick(){
struct timespec start, stop;
double duration, delay;
+ // Start CPU pipeline instrumentation
+ clock_gettime(CLOCK_REALTIME, &start);
+
// Update keypressed
int key=KeypadGetPressed();
if(key>=0){
State.keypressed=1;
State.key=key&0xF;
- //printf("Keypressed: %x\n",State.key);
+ // printf("Keypressed: %x\n",State.key);
}
- else
+ else{
State.keypressed=0;
+ }
- // Run and benchmark CPU pipeline
- clock_gettime(CLOCK_REALTIME, &start);
+ // Execute next instruction
VCPUFetch();
VCPUDecode();
VCPUExecute();
+
+ // Update ticks
State.dt_ticks++;
State.st_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
if(State.dt_ticks>=(1.0*VCPU_FREQ/DTST_FREQ)){
@@ -330,6 +336,15 @@ void VCPUTick(){
ScreenUpdate();
}
+ // End instrumentation
+ 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);
+ }
}
void VCPUDump(){
diff --git a/src/vcpu.h b/src/vcpu.h
index 4266ac4..09bfd4e 100644
--- a/src/vcpu.h
+++ b/src/vcpu.h
@@ -51,7 +51,7 @@ typedef struct VCPU_State {
* @brief Must be called first!
*
*/
-void VCPUInit();
+void VCPUInit(int width, int height);
/**
* @brief Fetch instruction from memory
@@ -92,3 +92,9 @@ void VCPUDoubleDabble(unsigned char x, unsigned char *u, unsigned char *t, unsig
*
*/
void VCPUDump();
+
+/**
+ * @brief To call before terminating the application
+ *
+ */
+void VCPUFinish();