Commits

spencercw committed ce53447

Improve the accuracy in timing for enabling and disabling interrupts.

  • Participants
  • Parent commits cd3fc9a

Comments (0)

Files changed (5)

gb_emulator/gb_cpu_opcodes.cpp.inc

 	break;
 case DI:
 	cycles -= 1;
-	if (ime >= IME_ENABLING)
+	switch (ime)
 	{
-		ime = IME_DISABLING;
-		continue;
+	case IME_ENABLED:
+	case IME_ENABLING1:
+	case IME_ENABLING2:
+		ime = IME_DISABLING1;
+		break;
 	}
 	break;
 case EI:
 	cycles -= 1;
-	if (ime <= IME_DISABLING)
+	switch (ime)
 	{
-		ime = IME_ENABLING;
-		continue;
+	case IME_DISABLED:
+	case IME_DISABLING1:
+	case IME_DISABLING2:
+		ime = IME_ENABLING1;
+		break;
 	}
 	break;
 case RLCA:
 	cycles -= 4;
 	pc = gb_.mem_.read16(sp);
 	sp += 2;
-	ime = IME_ENABLING;
-	continue;
+	ime = IME_ENABLING2;
 	break;
 case MULTI_BYTE:
 	switch (gb_.mem_.read(pc++))

gb_emulator/include/gb_emulator/constants.hpp

 
 /* Interrupt master enable states */
 const uint8_t  IME_DISABLED             = 0;
-const uint8_t  IME_ENABLING             = 1;
-const uint8_t  IME_DISABLING            = 2;
-const uint8_t  IME_ENABLED              = 3;
+const uint8_t  IME_ENABLING1            = 1;
+const uint8_t  IME_ENABLING2            = 2;
+const uint8_t  IME_DISABLING1           = 3;
+const uint8_t  IME_DISABLING2           = 4;
+const uint8_t  IME_ENABLED              = 5;
 
 /* Interrupts */
 const uint8_t  VBLANK_INTR              = 0x01;

gb_emulator/ops.txt

 }
 clog << "stop: stub\n";
 f3   DI         'di'                 0 1 1
-if (ime >= IME_ENABLING)
+if (ime >= IME_ENABLING1)
 {
-	ime = IME_DISABLING;
-	continue;
+	ime = IME_DISABLING1;
 }
 fb   EI         'ei'                 0 1 1
-if (ime <= IME_DISABLING)
+if (ime <= IME_DISABLING1)
 {
-	ime = IME_ENABLING;
-	continue;
+	ime = IME_ENABLING1;
 }
 
 ; Rotates and shifts
 d9   RETI       'reti'               0 4 1
 pc = gb_.mem_.read16(sp);
 sp += 2;
-ime = IME_ENABLING;
-continue;
+ime = IME_ENABLING2;

gb_emulator/src/gb_cpu.cpp

 	while (cycles > 0 && !pause)
 	{
 		// Check the interrupt master enable flag
-		if (ime == IME_ENABLING)
+		switch (ime)
 		{
+		case IME_ENABLED:
+		case IME_DISABLED:
+			// Do nothing; we don't check for interrupts on every iteration in the interest of
+			// performance
+			break;
+
+		case IME_ENABLING1:
+			ime = IME_ENABLING2;
+			break;
+		case IME_DISABLING1:
+			ime = IME_DISABLING2;
+			break;
+
+		case IME_ENABLING2:
 			ime = IME_ENABLED;
 			handleInterrupts();
-		}
-		else if (ime == IME_DISABLING)
-		{
+			break;
+		case IME_DISABLING2:
 			ime = IME_DISABLED;
+			break;
 		}
 
 		// Update the debugger and stop execution if requested
 
 void GbCpu::handleInterrupts()
 {
-	if (ime == IME_ENABLED || ime == IME_DISABLING)
+	if (ime == IME_ENABLED || ime == IME_ENABLING2 || ime == IME_DISABLING1)
 	{
 		uint8_t interrupts = gb_.mem_.ioPorts[IF] & gb_.mem_.ie;
 		if (interrupts & 0x1f)

gb_emulator/src/gb_debugger.cpp

 	switch (gb_.cpu_.ime)
 	{
 	case IME_DISABLED:
-	case IME_ENABLING:
+	case IME_ENABLING1:
+	case IME_ENABLING2:
 		registers.ime = false;
 		break;
 
 	case IME_ENABLED:
-	case IME_DISABLING:
+	case IME_DISABLING1:
+	case IME_DISABLING2:
 		registers.ime = true;
 		break;