Cleaning code
This commit is contained in:
parent
c3b9b472bf
commit
f7b1fedfb4
4 changed files with 53 additions and 24 deletions
13
src/main.c
13
src/main.c
|
@ -5,6 +5,9 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define SCREEN_WIDTH 1000
|
||||||
|
#define SCREEN_HEIGHT 500
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
// Parse argument
|
// Parse argument
|
||||||
|
@ -17,11 +20,8 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize
|
// Initialize
|
||||||
MemInit();
|
VCPUInit(SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||||
MemLoadROM(argv[1]);
|
MemLoadROM(argv[1]); // Load ROM into main memory
|
||||||
ScreenInit(1000,500);
|
|
||||||
VCPUInit();
|
|
||||||
SpeakerInit();
|
|
||||||
|
|
||||||
// Set game to run at very high FPS (prevent raylib to interfer with emulator CPU frequency)
|
// Set game to run at very high FPS (prevent raylib to interfer with emulator CPU frequency)
|
||||||
SetTargetFPS(VCPU_FREQ*100);
|
SetTargetFPS(VCPU_FREQ*100);
|
||||||
|
@ -32,8 +32,7 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finish
|
// Finish
|
||||||
SpeakerFinish();
|
VCPUFinish();
|
||||||
ScreenClose();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
11
src/mem.c
11
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){
|
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];
|
memory[addr+i]=data[i];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MemLoad(unsigned char *data, int size, int addr){
|
void MemLoad(unsigned char *data, int size, int addr){
|
||||||
int location=addr;
|
int location=addr;
|
||||||
for(int i=0;i<size;i++){
|
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];
|
data[i]=memory[addr+i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
41
src/vcpu.c
41
src/vcpu.c
|
@ -12,7 +12,11 @@
|
||||||
// Current VCPU state
|
// Current VCPU state
|
||||||
VCPU_State State;
|
VCPU_State State;
|
||||||
|
|
||||||
void VCPUInit(){
|
void VCPUInit(int width, int height){
|
||||||
|
MemInit();
|
||||||
|
ScreenInit(width,height);
|
||||||
|
SpeakerInit();
|
||||||
|
|
||||||
State.PC=ADDR_ROM;
|
State.PC=ADDR_ROM;
|
||||||
State.S=0;
|
State.S=0;
|
||||||
State.dt_ticks=0;
|
State.dt_ticks=0;
|
||||||
|
@ -22,6 +26,11 @@ void VCPUInit(){
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VCPUFinish(){
|
||||||
|
SpeakerFinish();
|
||||||
|
ScreenClose();
|
||||||
|
}
|
||||||
|
|
||||||
void VCPUFetch(){
|
void VCPUFetch(){
|
||||||
unsigned char byte[2];
|
unsigned char byte[2];
|
||||||
MemLoad(byte,2,State.PC); // Little indian to -1 no +1
|
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(){
|
void VCPUExecute(){
|
||||||
// VCPUDump();
|
// Very big switch case... Thinking about it, ifelse would have been cleaner for the reader
|
||||||
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 == 0x0){ // Clear screen
|
if(State.N == 0x0){ // Clear screen
|
||||||
|
@ -279,6 +288,9 @@ void VCPUTick(){
|
||||||
struct timespec start, stop;
|
struct timespec start, stop;
|
||||||
double duration, delay;
|
double duration, delay;
|
||||||
|
|
||||||
|
// Start CPU pipeline instrumentation
|
||||||
|
clock_gettime(CLOCK_REALTIME, &start);
|
||||||
|
|
||||||
// Update keypressed
|
// Update keypressed
|
||||||
int key=KeypadGetPressed();
|
int key=KeypadGetPressed();
|
||||||
if(key>=0){
|
if(key>=0){
|
||||||
|
@ -286,25 +298,19 @@ void VCPUTick(){
|
||||||
State.key=key&0xF;
|
State.key=key&0xF;
|
||||||
// printf("Keypressed: %x\n",State.key);
|
// printf("Keypressed: %x\n",State.key);
|
||||||
}
|
}
|
||||||
else
|
else{
|
||||||
State.keypressed=0;
|
State.keypressed=0;
|
||||||
|
}
|
||||||
|
|
||||||
// Run and benchmark CPU pipeline
|
// Execute next instruction
|
||||||
clock_gettime(CLOCK_REALTIME, &start);
|
|
||||||
VCPUFetch();
|
VCPUFetch();
|
||||||
VCPUDecode();
|
VCPUDecode();
|
||||||
VCPUExecute();
|
VCPUExecute();
|
||||||
|
|
||||||
|
// Update ticks
|
||||||
State.dt_ticks++;
|
State.dt_ticks++;
|
||||||
State.st_ticks++;
|
State.st_ticks++;
|
||||||
State.screen_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
|
// Update Delay Timer
|
||||||
if(State.dt_ticks>=(1.0*VCPU_FREQ/DTST_FREQ)){
|
if(State.dt_ticks>=(1.0*VCPU_FREQ/DTST_FREQ)){
|
||||||
|
@ -330,6 +336,15 @@ void VCPUTick(){
|
||||||
ScreenUpdate();
|
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(){
|
void VCPUDump(){
|
||||||
|
|
|
@ -51,7 +51,7 @@ typedef struct VCPU_State {
|
||||||
* @brief Must be called first!
|
* @brief Must be called first!
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void VCPUInit();
|
void VCPUInit(int width, int height);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Fetch instruction from memory
|
* @brief Fetch instruction from memory
|
||||||
|
@ -92,3 +92,9 @@ void VCPUDoubleDabble(unsigned char x, unsigned char *u, unsigned char *t, unsig
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void VCPUDump();
|
void VCPUDump();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief To call before terminating the application
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void VCPUFinish();
|
||||||
|
|
Loading…
Add table
Reference in a new issue