/** * Opcode #0x76. * * HALT * * @param \GameBoy\Core $core * @throws Exception */ public static function opcode118(Core $core) { if ($core->untilEnable == 1) { /*VBA-M says this fixes Torpedo Range (Seems to work): Involves an edge case where an EI is placed right before a HALT. EI in this case actually is immediate, so we adjust (Hacky?).*/ $core->programCounter = $core->nswtuw($core->programCounter - 1); } else { if (!$core->halt && !$core->IME && !$core->cGBC && ($core->memory[0xff0f] & $core->memory[0xffff] & 0x1f) > 0) { $core->skipPCIncrement = true; } $core->halt = true; while ($core->halt && ($core->stopEmulator & 1) === 0) { /*We're hijacking the main interpreter loop to do this dirty business in order to not slow down the main interpreter loop code with halt state handling.*/ $bitShift = 0; $testbit = 1; $interrupts = $core->memory[0xffff] & $core->memory[0xff0f]; while ($bitShift < 5) { //Check to see if an interrupt is enabled AND requested. if (($testbit & $interrupts) === $testbit) { $core->halt = false; //Get out of halt state if in halt state. return; //Let the main interrupt handler compute the interrupt. } $testbit = 1 << ++$bitShift; } $core->CPUTicks = 1; //1 machine cycle under HALT... //Timing: $core->updateCore(); } //Throw an error on purpose to exit out of the loop. throw new Exception('HALT_OVERRUN'); } }