Skip to content

Commit

Permalink
Separate div register from cycleIndex to avoid errors when games rese…
Browse files Browse the repository at this point in the history
…t the div register. Fixing the major problem in #7. (Also refactor emergency stops in opcodes.c)
  • Loading branch information
Staacks committed Jan 9, 2023
1 parent c90df9d commit d4cb27b
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 21 deletions.
4 changes: 2 additions & 2 deletions firmware/cpubus.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ uint8_t volatile * extra = (uint8_t*)(&rawBusData) + 3;
uint32_t history[256]; //Buffer for memory events
uint volatile cycleIndex; // Just counting cycles. Lowest byte can be used as index to the cyclic history array and the second byte is used as the Game Boy's DIV register
uint8_t volatile * historyIndex = (uint8_t *)&cycleIndex; //Index for history array, lowest byte of cycleIndex
uint8_t volatile * div = ((uint8_t *)&cycleIndex) + 1; //DIV register, second byte of cycleIndex
uint volatile div; //cycle that corresponds to DIV register equaling zero
uint8_t readAheadIndex;

mutex_t cpubusMutex;
Expand Down Expand Up @@ -118,7 +118,7 @@ void dmaToOAM(uint16_t source) {
void reset() {
cycleIndex = 0;
readAheadIndex = HISTORY_READAHEAD;
*div = 0xab;
div = cycleIndex - 0x0000ab00u; //Starts at 0xab

ignoreCycles = 0;

Expand Down
4 changes: 3 additions & 1 deletion firmware/cpubus.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ extern uint8_t volatile * extra;
extern uint32_t history[];
extern uint volatile cycleIndex;
extern uint8_t volatile * historyIndex; //Index for history array, lowest byte of cycleIndex
extern uint8_t volatile * div;
extern uint volatile div;

extern uint ignoreCycles;
extern bool cartridgeDMA;
Expand Down Expand Up @@ -66,4 +66,6 @@ void getNextFromBus();

void dmaToOAM(uint16_t source);

void stop(const char* errorMsg);

#endif
28 changes: 10 additions & 18 deletions firmware/opcodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ void toMemory(uint16_t address, uint8_t data) {
if (address >= 0xff00) {
switch (address) {
case 0xff04: //Reset DIV register
*div = 0;
div = cycleIndex;
break;
case 0xff40: //LCDC
bgAndWindowDisplay = (data & 0x01) != 0;
Expand Down Expand Up @@ -81,7 +81,7 @@ void toMemory(uint16_t address, uint8_t data) {
uint8_t static inline fromMemory(uint16_t addr) {
DEBUG_TRIGGER_BREAKPOINT_AT_READ_FROM_ADDRESS
switch (addr) {
case 0xff04: return *div; //DIV register
case 0xff04: return (uint8_t)((uint)(cycleIndex - div) >> 8); //DIV register
case 0xff41:
//STAT register. Since this is usually only used for conditional jumps done in the real Game Boy, emulating the correct value is not ciritcally here.
//Instead we use it to synchronize our PPU to the real one:
Expand Down Expand Up @@ -346,8 +346,7 @@ void call6() {
getNextFromBus();
getNextFromBus();
if (*address != sp) {
running = false;
error = "SP desynchronized.";
stop("SP desynchronized.");
}
getNextFromBus();
}
Expand All @@ -364,8 +363,7 @@ void call3_6() {
getNextFromBus();
getNextFromBus();
if (*address != sp) {
running = false;
error = "SP desynchronized.";
stop("SP desynchronized.");
}
getNextFromBus();
}
Expand Down Expand Up @@ -948,8 +946,7 @@ void pop_r16() {
uint32_t whichOpcode = rawBusData & 0x00300000;
getNextFromBus();
if (*address != sp) {
running = false;
error = "SP desynchronized.";
stop("SP desynchronized.");
}
uint16_t v = fromMemory(sp);
sp++;
Expand Down Expand Up @@ -1001,8 +998,7 @@ void push_r16() {
getNextFromBus();
getNextFromBus();
if (*address != sp) {
running = false;
error = "SP desynchronized.";
stop("SP desynchronized.");
}
getNextFromBus();
}
Expand All @@ -1012,8 +1008,7 @@ void push_r16() {
void ret4() {
getNextFromBus();
if (*address != sp) {
running = false;
error = "SP desynchronized.";
stop("SP desynchronized.");
}
getNextFromBus();
getNextFromBus();
Expand All @@ -1024,8 +1019,7 @@ void ret4() {
void reti4() {
getNextFromBus();
if (*address != sp) {
running = false;
error = "SP desynchronized.";
stop("SP desynchronized.");
}
getNextFromBus();
getNextFromBus();
Expand All @@ -1042,8 +1036,7 @@ void ret2_5() {
if (nextPC != *address) { //If these are equal, a jump was not taken but the next code was fetched.
//If not equal, burn three more cycles and pop the sp register.
if (*address != sp) {
running = false;
error = "SP desynchronized.";
stop("SP desynchronized.");
}
getNextFromBus();
getNextFromBus();
Expand Down Expand Up @@ -1466,9 +1459,8 @@ void xCB() {
// UNKNOWN / ERROR STATE //

void unknown() {
error = "Unknown opcode.";
stop("Unknown opcode.");
errorOpcode = *opcode;
running = false;
}

void (*opcodes[256])() = {
Expand Down

0 comments on commit d4cb27b

Please sign in to comment.