diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Gameboy/Core.php | 546 | ||||
-rw-r--r-- | src/Gameboy/DrawContext.php | 2 | ||||
-rw-r--r-- | src/Gameboy/Opcode.php | 48 |
3 files changed, 59 insertions, 537 deletions
diff --git a/src/Gameboy/Core.php b/src/Gameboy/Core.php index ace9c70..50cb254 100644 --- a/src/Gameboy/Core.php +++ b/src/Gameboy/Core.php @@ -231,132 +231,12 @@ class Core public $RTCHALT = false; // - //Sound variables: - // - - //Audio object or the WAV PCM generator wrapper - public $audioHandle = null; - - //Buffering counter for the WAVE PCM output. - public $outTracker = 0; - - //Buffering limiter for WAVE PCM output. - public $outTrackerLimit = 0; - - //Length of the sound buffers. - public $numSamplesTotal = 0; - - //Length of the sound buffer for one channel. - public $sampleSize = 0; - - public $dutyLookup = [0.125, 0.25, 0.5, 0.75]; - - //The audio buffer we're working on (When not overflowing). - public $audioSamples = []; - - //Audio overflow buffer. - public $audioBackup = []; - - //Pointer to the sample workbench. - public $currentBuffer = null; - - //How many channels are being fed into the left side stereo / mono. - public $channelLeftCount = 0; - - //How many channels are being fed into the right side stereo. - public $channelRightCount = 0; - - public $noiseTableLookup = null; - - public $smallNoiseTable = [0x80]; - - public $largeNoiseTable = [0x8000]; - - //As its name implies - public $soundMasterEnabled = false; - - //Track what method we're using for audio output. - public $audioType = -1; - - // - //Vin Shit: - // - - public $VinLeftChannelEnabled = false; - - public $VinRightChannelEnabled = false; - - public $VinLeftChannelMasterVolume = 0; - - public $VinRightChannelMasterVolume = 0; - - public $vinLeft = 1; - - public $vinRight = 1; - - //Channels Enabled: - - //Which channels are enabled for left side stereo / mono? - public $leftChannel = [true, true, true, false]; - - //Which channels are enabled for right side stereo? - public $rightChannel = [true, true, true, false]; - - - //Current Samples Being Computed: - public $currentSampleLeft = 0; - - public $currentSampleRight = 0; - - public $channel3Tracker = 0; - - // - //Pre-multipliers to cache some calculations: - // - public $preChewedAudioComputationMultiplier; - - public $preChewedWAVEAudioComputationMultiplier; - - public $whiteNoiseFrequencyPreMultiplier; - - //Premultiplier for audio samples per instructions. - public $samplesOut = 0; - - public $volumeEnvelopePreMultiplier; - - public $channel1TimeSweepPreMultiplier; - - public $channel1lastTotalLength; - - public $channel1lastTimeSweep; - - public $channel1frequency; - - public $channel2lastTotalLength; - - public $channel2frequency; - - public $channel3frequency; - - public $channel4lastTotalLength; - - public $audioTotalLengthMultiplier; - - // //Audio generation counters: // - public $audioOverflow = false; - //Used to sample the audio system every x CPU instructions. public $audioTicks = 0; - //Used to keep alignment on audio generation. - public $audioIndex = 0; - - //Used to keep alignment on the number of samples to output (Realign from counter alias). - public $rollover = 0; - // //Timing Variables // @@ -523,14 +403,6 @@ class Core //Array of line 0 function to handle the LCD controller when it's off (Do nothing!). }; - $this->preChewedAudioComputationMultiplier = 0x20000 / Settings::$settings[14]; - $this->preChewedWAVEAudioComputationMultiplier = 0x200000 / Settings::$settings[14]; - $this->whiteNoiseFrequencyPreMultiplier = 4194300 / Settings::$settings[14] / 8; - - $this->volumeEnvelopePreMultiplier = Settings::$settings[14] / 0x40; - $this->channel1TimeSweepPreMultiplier = Settings::$settings[14] / 0x80; - $this->audioTotalLengthMultiplier = Settings::$settings[14] / 0x100; - $this->tileCountInvalidator = $this->tileCount * 4; $this->ROMBanks[0x52] = 72; @@ -558,8 +430,6 @@ class Core $this->SecondaryTICKTable = TICKTables::$secondary; $this->LINECONTROL = array_fill(0, 154, null); - - // $this->initializeStartState(); } public function saveState() @@ -632,7 +502,7 @@ class Core $this->cHuC3, $this->cHuC1, $this->drewBlank, - $this->tileData.slice(0), + $this->tileData, $this->fromTypedArray($this->frameBuffer), $this->tileCount, $this->colorCount, @@ -644,64 +514,6 @@ class Core $this->spritePriorityEnabled, $this->fromTypedArray($this->tileReadState), $this->windowSourceLine, - $this->channel1adjustedFrequencyPrep, - $this->channel1duty, - $this->channel1lastSampleLookup, - $this->channel1adjustedDuty, - $this->channel1totalLength, - $this->channel1envelopeVolume, - $this->channel1currentVolume, - $this->channel1envelopeType, - $this->channel1envelopeSweeps, - $this->channel1consecutive, - $this->channel1frequency, - $this->channel1volumeEnvTime, - $this->channel1lastTotalLength, - $this->channel1timeSweep, - $this->channel1lastTimeSweep, - $this->channel1numSweep, - $this->channel1frequencySweepDivider, - $this->channel1decreaseSweep, - $this->channel2adjustedFrequencyPrep, - $this->channel2duty, - $this->channel2lastSampleLookup, - $this->channel2adjustedDuty, - $this->channel2totalLength, - $this->channel2envelopeVolume, - $this->channel2currentVolume, - $this->channel2envelopeType, - $this->channel2envelopeSweeps, - $this->channel2consecutive, - $this->channel2frequency, - $this->channel2volumeEnvTime, - $this->channel2lastTotalLength, - $this->channel3canPlay, - $this->channel3totalLength, - $this->channel3lastTotalLength, - $this->channel3patternType, - $this->channel3frequency, - $this->channel3consecutive, - $this->channel3PCM, - $this->channel3adjustedFrequencyPrep, - $this->channel4adjustedFrequencyPrep, - $this->channel4lastSampleLookup, - $this->channel4totalLength, - $this->channel4envelopeVolume, - $this->channel4currentVolume, - $this->channel4envelopeType, - $this->channel4envelopeSweeps, - $this->channel4consecutive, - $this->channel4volumeEnvTime, - $this->channel4lastTotalLength, - $this->soundMasterEnabled, - $this->VinLeftChannelEnabled, - $this->VinRightChannelEnabled, - $this->VinLeftChannelMasterVolume, - $this->VinRightChannelMasterVolume, - $this->vinLeft, - $this->vinRight, - $this->leftChannel, - $this->rightChannel, $this->actualScanLine, $this->RTCisLatched, $this->latchedSeconds, @@ -958,8 +770,6 @@ class Core $this->FHalfCarry = true; $this->FCarry = true; $this->registersHL = 0x014D; - $this->leftChannel = [true, true, true, false]; - $this->rightChannel = [true, true, true, false]; //Fill in the boot ROM set register values //Default values to the GB boot ROM values, then fill in the GBC boot ROM values after ROM loading @@ -1003,11 +813,6 @@ class Core $this->registerE = 0; $this->FZero = $this->FSubtract = $this->FHalfCarry = $this->FCarry = false; $this->registersHL = 0; - $this->leftChannel = $this->ArrayPad(4, false); - $this->rightChannel = $this->ArrayPad(4, false); - $this->channel2frequency = $this->channel1frequency = 0; - $this->channel2volumeEnvTime = $this->channel1volumeEnvTime = 0; - $this->channel2consecutive = $this->channel1consecutive = true; $this->memory[0xFF00] = 0xF; //Set the joypad state. } @@ -1343,81 +1148,42 @@ class Core } } } - try { - if (Settings::$settings[5]) { - //Nasty since we are throwing on purpose to force a try/catch fallback - // throw(new Error("")); - throw new \Exception(""); - } - - // @TODO - //Create a white screen - // $this->drawContext = $this->canvas.getContext("2d"); - // $this->drawContext->fillStyle = "rgb(255, 255, 255)"; - // $this->drawContext->fillRect(0, 0, $this->width, $this->height); - - $this->drawContext = new DrawContext(); - // NEW - $this->width = 160; - $this->height = 144; + // @TODO + //Create a white screen + // $this->drawContext = $this->canvas.getContext("2d"); + // $this->drawContext->fillStyle = "rgb(255, 255, 255)"; + // $this->drawContext->fillRect(0, 0, $this->width, $this->height); - //Get a CanvasPixelArray buffer: - try { - //$this->canvasBuffer = $this->drawContext->createImageData($this->width, $this->height); - $this->canvasBuffer = new \stdClass(); - $this->canvasBuffer->data = array_fill(0, 4 * $this->width * $this->height, 255); - } - catch (\Exception $error) { - echo "Falling back to the getImageData initialization" . PHP_EOL; - - $this->canvasBuffer = $this->drawContext->getImageData(0, 0, $this->width, $this->height); - } + $this->drawContext = new DrawContext(); - $index = $this->pixelCount; - $index2 = $this->rgbCount; + // NEW + $this->width = 160; + $this->height = 144; - while ($index > 0) { - $this->frameBuffer[--$index] = 0x00FFFFFF; - $this->canvasBuffer->data[$index2 -= 4] = 0xFF; - $this->canvasBuffer->data[$index2 + 1] = 0xFF; - $this->canvasBuffer->data[$index2 + 2] = 0xFF; - $this->canvasBuffer->data[$index2 + 3] = 0xFF; - } - - $this->drawContext->putImageData($this->canvasBuffer, 0, 0); //Throws any browser that won't support this later on. - // $this->canvasAlt->style->visibility = "hidden"; //Make sure, if restarted, that the fallback images aren't going cover the canvas. - // $this->canvas->style->visibility = "visible"; - $this->canvasFallbackHappened = false; - } catch (\Exception $error) { - //Falling back to an experimental data URI BMP file canvas alternative: - echo "Falling back to BMP imaging as a canvas alternative." . PHP_EOL; + //Get a CanvasPixelArray buffer: + $this->canvasBuffer = new \stdClass(); + $this->canvasBuffer->data = array_fill(0, 4 * $this->width * $this->height, 255); - $this->width = 160; - $this->height = 144; - $this->canvasFallbackHappened = true; - $this->drawContext = new BMPCanvas($this->canvasAlt, 160, 144, Settings::$settings[6][0], Settings::$settings[6][1]); - $this->canvasBuffer = new Object(); + $index = $this->pixelCount; + $index2 = $this->rgbCount; - $index = 23040; - while ($index > 0) { - $this->frameBuffer[--$index] = 0x00FFFFFF; - } - $this->canvasBuffer->data = $this->ArrayPad(92160, 0xFF); - $this->drawContext->putImageData($this->canvasBuffer, 0, 0); - //Make visible only after the images have been initialized. - $this->canvasAlt->style->visibility = "visible"; - $this->canvas->style->visibility = "hidden"; //Speedier layout in some browsers. + while ($index > 0) { + $this->frameBuffer[--$index] = 0x00FFFFFF; + $this->canvasBuffer->data[$index2 -= 4] = 0xFF; + $this->canvasBuffer->data[$index2 + 1] = 0xFF; + $this->canvasBuffer->data[$index2 + 2] = 0xFF; + $this->canvasBuffer->data[$index2 + 3] = 0xFF; } + + $this->drawContext->putImageData($this->canvasBuffer, 0, 0); + $this->canvasFallbackHappened = false; } public function JoyPadEvent($key, $down) { if ($down) { $this->JoyPad &= 0xFF ^ (1 << $key); - /*if (!$this->cGBC) { - $this->memory[0xFF0F] |= 0x10; //A real GBC doesn't set this! - }*/ } else { $this->JoyPad |= (1 << $key); } @@ -1481,7 +1247,7 @@ class Core if (($this->stopEmulator & 1) == 1) { $this->stopEmulator = 0; $this->clockUpdate(); //Frame skip and RTC code. - // $this->audioUpdate(); //Lookup the rollover buffer and output WAVE PCM samples if sound is on and have fallen back to it. + if (!$this->halt) { //If no HALT... Execute normally $this->executeIteration(); } @@ -1623,24 +1389,15 @@ class Core // LCD Timing $this->LCDTicks += $timedTicks; //LCD timing $this->LCDCONTROL[$this->actualScanLine]($this); //Scan Line and STAT Mode Control + //Audio Timing $this->audioTicks += $timedTicks; //Not the same as the LCD timing (Cannot be altered by display on/off changes!!!). + if ($this->audioTicks >= Settings::$settings[11]) { //Are we past the granularity setting? - $amount = $this->audioTicks * $this->samplesOut; - $actual = floor($amount); - $this->rollover += $amount - $actual; - if ($this->rollover >= 1) { - $this->rollover -= 1; - $actual += 1; - } - if (!$this->audioOverflow && $actual > 0) { - $this->generateAudio($actual); - } //Emulator Timing (Timed against audio for optimization): $this->emulatorTicks += $this->audioTicks; if ($this->emulatorTicks >= Settings::$settings[13]) { if (($this->stopEmulator & 1) == 0) { //Make sure we don't overdo the audio. - $this->playAudio(); //Output all the samples built up. if ($this->drewBlank == 0) { //LCD off takes at least 2 frames. $this->drawToCanvas(); //Display frame } @@ -1650,6 +1407,7 @@ class Core } $this->audioTicks = 0; } + // Internal Timer if ($this->TIMAEnabled) { $this->timerTicks += $this->CPUTicks; @@ -1864,7 +1622,7 @@ class Core public function clockUpdate() { //We're tying in the same timer for RTC and frame skipping, since we can and this reduces load. if (Settings::$settings[7] || $this->cTIMER) { - $timeElapsed = microtime(true) - $this->lastIteration; //Get the numnber of milliseconds since this last executed. + $timeElapsed = ((int) (microtime(true) * 1000)) - $this->lastIteration; //Get the numnber of milliseconds since this last executed. if ($this->cTIMER && !$this->RTCHALT) { //Update the MBC3 RTC: $this->RTCSeconds += $timeElapsed / 1000; @@ -1898,7 +1656,7 @@ class Core Settings::$settings[4]--; } } - $this->lastIteration = microtime(); + $this->lastIteration = (int) (microtime() * 1000); } } @@ -1994,7 +1752,7 @@ class Core $this->gbColorizedPalette[$startIndex + 3] = ($pal4 >= 0x80000000) ? $pal4 : 0xFFFFFFFF; } - //@TODO - Need to copy the new palette + //@PHP - Need to copy the new palette $this->checkPaletteType(); } } @@ -2866,267 +2624,87 @@ class Core $parentObj->TIMAEnabled = ($data & 0x04) == 0x04; $parentObj->TACClocker = pow(4, (($data & 0x3) != 0) ? ($data & 0x3) : 4); //TODO: Find a way to not make a conditional in here... }; + + // BEGIN - Audio Writers $this->memoryWriter[0xFF10] = function ($parentObj, $address, $data) { - $parentObj->channel1lastTimeSweep = $parentObj->channel1timeSweep = floor((($data & 0x70) >> 4) * $parentObj->channel1TimeSweepPreMultiplier); - $parentObj->channel1numSweep = $data & 0x07; - $parentObj->channel1frequencySweepDivider = 1 << $parentObj->channel1numSweep; - $parentObj->channel1decreaseSweep = (($data & 0x08) == 0x08); - $parentObj->memory[0xFF10] = $data; }; $this->memoryWriter[0xFF11] = function ($parentObj, $address, $data) { - $parentObj->channel1duty = $data >> 6; - $parentObj->channel1adjustedDuty = $parentObj->dutyLookup[$parentObj->channel1duty]; - $parentObj->channel1lastTotalLength = $parentObj->channel1totalLength = (0x40 - ($data & 0x3F)) * $parentObj->audioTotalLengthMultiplier; - $parentObj->memory[0xFF11] = $data & 0xC0; }; $this->memoryWriter[0xFF12] = function ($parentObj, $address, $data) { - $parentObj->channel1envelopeVolume = $data >> 4; - $parentObj->channel1currentVolume = $parentObj->channel1envelopeVolume / 0xF; - $parentObj->channel1envelopeType = (($data & 0x08) == 0x08); - $parentObj->channel1envelopeSweeps = $data & 0x7; - $parentObj->channel1volumeEnvTime = $parentObj->channel1envelopeSweeps * $parentObj->volumeEnvelopePreMultiplier; - $parentObj->memory[0xFF12] = $data; }; $this->memoryWriter[0xFF13] = function ($parentObj, $address, $data) { - $parentObj->channel1frequency = ($parentObj->channel1frequency & 0x700) | $data; - //Pre-calculate the frequency computation outside the waveform generator for speed: - $parentObj->channel1adjustedFrequencyPrep = $parentObj->preChewedAudioComputationMultiplier / (0x800 - $parentObj->channel1frequency); - $parentObj->memory[0xFF13] = $data; }; $this->memoryWriter[0xFF14] = function ($parentObj, $address, $data) { - if (($data & 0x80) == 0x80) { - $parentObj->channel1envelopeVolume = $parentObj->memory[0xFF12] >> 4; - $parentObj->channel1currentVolume = $parentObj->channel1envelopeVolume / 0xF; - $parentObj->channel1envelopeSweeps = $parentObj->memory[0xFF12] & 0x7; - $parentObj->channel1volumeEnvTime = $parentObj->channel1envelopeSweeps * $parentObj->volumeEnvelopePreMultiplier; - $parentObj->channel1totalLength = $parentObj->channel1lastTotalLength; - $parentObj->channel1timeSweep = $parentObj->channel1lastTimeSweep; - $parentObj->channel1numSweep = $parentObj->memory[0xFF10] & 0x07; - $parentObj->channel1frequencySweepDivider = 1 << $parentObj->channel1numSweep; - if (($data & 0x40) == 0x40) { - $parentObj->memory[0xFF26] |= 0x1; - } - } - $parentObj->channel1consecutive = (($data & 0x40) == 0x0); - $parentObj->channel1frequency = (($data & 0x7) << 8) | ($parentObj->channel1frequency & 0xFF); - //Pre-calculate the frequency computation outside the waveform generator for speed: - $parentObj->channel1adjustedFrequencyPrep = $parentObj->preChewedAudioComputationMultiplier / (0x800 - $parentObj->channel1frequency); - $parentObj->memory[0xFF14] = $data & 0x40; }; $this->memoryWriter[0xFF16] = function ($parentObj, $address, $data) { - $parentObj->channel2duty = $data >> 6; - $parentObj->channel2adjustedDuty = $parentObj->dutyLookup[$parentObj->channel2duty]; - $parentObj->channel2lastTotalLength = $parentObj->channel2totalLength = (0x40 - ($data & 0x3F)) * $parentObj->audioTotalLengthMultiplier; - $parentObj->memory[0xFF16] = $data & 0xC0; }; $this->memoryWriter[0xFF17] = function ($parentObj, $address, $data) { - $parentObj->channel2envelopeVolume = $data >> 4; - $parentObj->channel2currentVolume = $parentObj->channel2envelopeVolume / 0xF; - $parentObj->channel2envelopeType = (($data & 0x08) == 0x08); - $parentObj->channel2envelopeSweeps = $data & 0x7; - $parentObj->channel2volumeEnvTime = $parentObj->channel2envelopeSweeps * $parentObj->volumeEnvelopePreMultiplier; - $parentObj->memory[0xFF17] = $data; }; $this->memoryWriter[0xFF18] = function ($parentObj, $address, $data) { - $parentObj->channel2frequency = ($parentObj->channel2frequency & 0x700) | $data; - //Pre-calculate the frequency computation outside the waveform generator for speed: - $parentObj->channel2adjustedFrequencyPrep = $parentObj->preChewedAudioComputationMultiplier / (0x800 - $parentObj->channel2frequency); - $parentObj->memory[0xFF18] = $data; }; $this->memoryWriter[0xFF19] = function ($parentObj, $address, $data) { - if (($data & 0x80) == 0x80) { - $parentObj->channel2envelopeVolume = $parentObj->memory[0xFF17] >> 4; - $parentObj->channel2currentVolume = $parentObj->channel2envelopeVolume / 0xF; - $parentObj->channel2envelopeSweeps = $parentObj->memory[0xFF17] & 0x7; - $parentObj->channel2volumeEnvTime = $parentObj->channel2envelopeSweeps * $parentObj->volumeEnvelopePreMultiplier; - $parentObj->channel2totalLength = $parentObj->channel2lastTotalLength; - if (($data & 0x40) == 0x40) { - $parentObj->memory[0xFF26] |= 0x2; - } - } - $parentObj->channel2consecutive = (($data & 0x40) == 0x0); - $parentObj->channel2frequency = (($data & 0x7) << 8) | ($parentObj->channel2frequency & 0xFF); - //Pre-calculate the frequency computation outside the waveform generator for speed: - $parentObj->channel2adjustedFrequencyPrep = $parentObj->preChewedAudioComputationMultiplier / (0x800 - $parentObj->channel2frequency); - $parentObj->memory[0xFF19] = $data & 0x40; }; $this->memoryWriter[0xFF1A] = function ($parentObj, $address, $data) { - $parentObj->channel3canPlay = ($data >= 0x80); - if ($parentObj->channel3canPlay && ($parentObj->memory[0xFF1A] & 0x80) == 0x80) { - $parentObj->channel3totalLength = $parentObj->channel3lastTotalLength; - if (!$parentObj->channel3consecutive) { - $parentObj->memory[0xFF26] |= 0x4; - } - } - $parentObj->memory[0xFF1A] = $data & 0x80; }; $this->memoryWriter[0xFF1B] = function ($parentObj, $address, $data) { - $parentObj->channel3lastTotalLength = $parentObj->channel3totalLength = (0x100 - $data) * $parentObj->audioTotalLengthMultiplier; - $parentObj->memory[0xFF1B] = $data; }; $this->memoryWriter[0xFF1C] = function ($parentObj, $address, $data) { - $parentObj->memory[0xFF1C] = $data & 0x60; - $parentObj->channel3patternType = $parentObj->memory[0xFF1C] >> 5; }; $this->memoryWriter[0xFF1D] = function ($parentObj, $address, $data) { - $parentObj->channel3frequency = ($parentObj->channel3frequency & 0x700) | $data; - $parentObj->channel3adjustedFrequencyPrep = $parentObj->preChewedWAVEAudioComputationMultiplier / (0x800 - $parentObj->channel3frequency); - $parentObj->memory[0xFF1D] = $data; }; $this->memoryWriter[0xFF1E] = function ($parentObj, $address, $data) { - if (($data & 0x80) == 0x80) { - $parentObj->channel3totalLength = $parentObj->channel3lastTotalLength; - if (($data & 0x40) == 0x40) { - $parentObj->memory[0xFF26] |= 0x4; - } - } - $parentObj->channel3consecutive = (($data & 0x40) == 0x0); - $parentObj->channel3frequency = (($data & 0x7) << 8) | ($parentObj->channel3frequency & 0xFF); - $parentObj->channel3adjustedFrequencyPrep = $parentObj->preChewedWAVEAudioComputationMultiplier / (0x800 - $parentObj->channel3frequency); - $parentObj->memory[0xFF1E] = $data & 0x40; }; $this->memoryWriter[0xFF20] = function ($parentObj, $address, $data) { - $parentObj->channel4lastTotalLength = $parentObj->channel4totalLength = (0x40 - ($data & 0x3F)) * $parentObj->audioTotalLengthMultiplier; - $parentObj->memory[0xFF20] = $data | 0xC0; }; $this->memoryWriter[0xFF21] = function ($parentObj, $address, $data) { - $parentObj->channel4envelopeVolume = $data >> 4; - $parentObj->channel4currentVolume = $parentObj->channel4envelopeVolume / 0xF; - $parentObj->channel4envelopeType = (($data & 0x08) == 0x08); - $parentObj->channel4envelopeSweeps = $data & 0x7; - $parentObj->channel4volumeEnvTime = $parentObj->channel4envelopeSweeps * $parentObj->volumeEnvelopePreMultiplier; - $parentObj->memory[0xFF21] = $data; }; $this->memoryWriter[0xFF22] = function ($parentObj, $address, $data) { - $parentObj->channel4lastSampleLookup = 0; - $parentObj->channel4adjustedFrequencyPrep = $parentObj->whiteNoiseFrequencyPreMultiplier / max($data & 0x7, 0.5) / pow(2, ($data >> 4) + 1); - $parentObj->noiseTableLookup = (($data & 0x8) == 0x8) ? $parentObj->smallNoiseTable : $parentObj->largeNoiseTable; - $parentObj->memory[0xFF22] = $data; }; $this->memoryWriter[0xFF23] = function ($parentObj, $address, $data) { - $parentObj->memory[0xFF23] = $data; - $parentObj->channel4consecutive = (($data & 0x40) == 0x0); - if (($data & 0x80) == 0x80) { - $parentObj->channel4lastSampleLookup = 0; - $parentObj->channel4envelopeVolume = $parentObj->memory[0xFF21] >> 4; - $parentObj->channel4currentVolume = $parentObj->channel4envelopeVolume / 0xF; - $parentObj->channel4envelopeSweeps = $parentObj->memory[0xFF21] & 0x7; - $parentObj->channel4volumeEnvTime = $parentObj->channel4envelopeSweeps * $parentObj->volumeEnvelopePreMultiplier; - $parentObj->channel4totalLength = $parentObj->channel4lastTotalLength; - if (($data & 0x40) == 0x40) { - $parentObj->memory[0xFF26] |= 0x8; - } - } }; $this->memoryWriter[0xFF24] = function ($parentObj, $address, $data) { - $parentObj->memory[0xFF24] = $data; - /*$parentObj->VinLeftChannelEnabled = (($data >> 7) == 0x1); - $parentObj->VinRightChannelEnabled = ((($data >> 3) & 0x1) == 0x1); - $parentObj->VinLeftChannelMasterVolume = (($data >> 4) & 0x07); - $parentObj->VinRightChannelMasterVolume = ($data & 0x07); - $parentObj->vinLeft = ($parentObj->VinLeftChannelEnabled) ? $parentObj->VinLeftChannelMasterVolume / 7 : 1; - $parentObj->vinRight = ($parentObj->VinRightChannelEnabled) ? $parentObj->VinRightChannelMasterVolume / 7 : 1;*/ }; $this->memoryWriter[0xFF25] = function ($parentObj, $address, $data) { - $parentObj->memory[0xFF25] = $data; - $parentObj->leftChannel = [($data & 0x01) == 0x01, ($data & 0x02) == 0x02, ($data & 0x04) == 0x04, ($data & 0x08) == 0x08]; - $parentObj->rightChannel = [($data & 0x10) == 0x10, ($data & 0x20) == 0x20, ($data & 0x40) == 0x40, ($data & 0x80) == 0x80]; }; $this->memoryWriter[0xFF26] = function ($parentObj, $address, $data) { - $soundEnabled = ($data & 0x80); - $parentObj->memory[0xFF26] = $soundEnabled | ($parentObj->memory[0xFF26] & 0xF); - $parentObj->soundMasterEnabled = ($soundEnabled == 0x80); - if (!$parentObj->soundMasterEnabled) { - $parentObj->memory[0xFF26] = 0; - $parentObj->initializeStartState(); - for ($address = 0xFF30; $address < 0xFF40; $address++) { - $parentObj->memory[$address] = 0; - } - } }; $this->memoryWriter[0xFF30] = function ($parentObj, $address, $data) { - $parentObj->channel3PCM[0] = $data >> 4; - $parentObj->channel3PCM[1] = $data & 0xF; - $parentObj->memory[0xFF30] = $data; }; $this->memoryWriter[0xFF31] = function ($parentObj, $address, $data) { - $parentObj->channel3PCM[2] = $data >> 4; - $parentObj->channel3PCM[3] = $data & 0xF; - $parentObj->memory[0xFF31] = $data; }; $this->memoryWriter[0xFF32] = function ($parentObj, $address, $data) { - $parentObj->channel3PCM[4] = $data >> 4; - $parentObj->channel3PCM[5] = $data & 0xF; - $parentObj->memory[0xFF32] = $data; }; $this->memoryWriter[0xFF33] = function ($parentObj, $address, $data) { - $parentObj->channel3PCM[6] = $data >> 4; - $parentObj->channel3PCM[7] = $data & 0xF; - $parentObj->memory[0xFF33] = $data; }; $this->memoryWriter[0xFF34] = function ($parentObj, $address, $data) { - $parentObj->channel3PCM[8] = $data >> 4; - $parentObj->channel3PCM[9] = $data & 0xF; - $parentObj->memory[0xFF34] = $data; }; $this->memoryWriter[0xFF35] = function ($parentObj, $address, $data) { - $parentObj->channel3PCM[10] = $data >> 4; - $parentObj->channel3PCM[11] = $data & 0xF; - $parentObj->memory[0xFF35] = $data; }; $this->memoryWriter[0xFF36] = function ($parentObj, $address, $data) { - $parentObj->channel3PCM[12] = $data >> 4; - $parentObj->channel3PCM[13] = $data & 0xF; - $parentObj->memory[0xFF36] = $data; }; $this->memoryWriter[0xFF37] = function ($parentObj, $address, $data) { - $parentObj->channel3PCM[14] = $data >> 4; - $parentObj->channel3PCM[15] = $data & 0xF; - $parentObj->memory[0xFF37] = $data; }; $this->memoryWriter[0xFF38] = function ($parentObj, $address, $data) { - $parentObj->channel3PCM[16] = $data >> 4; - $parentObj->channel3PCM[17] = $data & 0xF; - $parentObj->memory[0xFF38] = $data; }; $this->memoryWriter[0xFF39] = function ($parentObj, $address, $data) { - $parentObj->channel3PCM[18] = $data >> 4; - $parentObj->channel3PCM[19] = $data & 0xF; - $parentObj->memory[0xFF39] = $data; }; $this->memoryWriter[0xFF3A] = function ($parentObj, $address, $data) { - $parentObj->channel3PCM[20] = $data >> 4; - $parentObj->channel3PCM[21] = $data & 0xF; - $parentObj->memory[0xFF3A] = $data; }; $this->memoryWriter[0xFF3B] = function ($parentObj, $address, $data) { - $parentObj->channel3PCM[22] = $data >> 4; - $parentObj->channel3PCM[23] = $data & 0xF; - $parentObj->memory[0xFF3B] = $data; }; $this->memoryWriter[0xFF3C] = function ($parentObj, $address, $data) { - $parentObj->channel3PCM[24] = $data >> 4; - $parentObj->channel3PCM[25] = $data & 0xF; - $parentObj->memory[0xFF3C] = $data; }; $this->memoryWriter[0xFF3D] = function ($parentObj, $address, $data) { - $parentObj->channel3PCM[26] = $data >> 4; - $parentObj->channel3PCM[27] = $data & 0xF; - $parentObj->memory[0xFF3D] = $data; }; $this->memoryWriter[0xFF3E] = function ($parentObj, $address, $data) { - $parentObj->channel3PCM[28] = $data >> 4; - $parentObj->channel3PCM[29] = $data & 0xF; - $parentObj->memory[0xFF3E] = $data; }; $this->memoryWriter[0xFF3F] = function ($parentObj, $address, $data) { - $parentObj->channel3PCM[30] = $data >> 4; - $parentObj->channel3PCM[31] = $data & 0xF; - $parentObj->memory[0xFF3F] = $data; }; $this->memoryWriter[0xFF44] = function ($parentObj, $address, $data) { //Read only }; + // END - Audio Writers + // $this->memoryWriter[0xFF45] = function ($parentObj, $address, $data) { $parentObj->memory[0xFF45] = $data; if ($parentObj->LCDisOn) { @@ -3449,61 +3027,15 @@ class Core } public function getTypedArray($length, $defaultValue, $numberType) { - try { - if (Settings::$settings[22]) { - throw(new Error("")); - } + // @PHP - We dont have typed arrays and unsigned int in PHP + // This function just creates an array and initialize with a value + $arrayHandle = array_fill(0, $length, $defaultValue); - /* - switch ($numberType) { - case "uint8": - $arrayHandle = new Uint8Array($length); - break; - case "int8": - $arrayHandle = new Int8Array($length); - break; - case "uint16": - $arrayHandle = new Uint16Array($length); - break; - case "int16": - $arrayHandle = new Int16Array($length); - break; - case "uint32": - $arrayHandle = new Uint32Array($length); - break; - case "int32": - $arrayHandle = new Int32Array($length); - break; - case "float32": - $arrayHandle = new Float32Array($length); - } - */ - - $arrayHandle = array_fill(0, $length, 0); - - if ($defaultValue > 0) { - $index = 0; - while ($index < $length) { - $arrayHandle[$index++] = $defaultValue; - } - } - } - catch (\Exception $error) { - $arrayHandle = array_fill(0, $length, 0); - $index = 0; - while ($index < $length) { - $arrayHandle[$index++] = $defaultValue; - } - } return $arrayHandle; } public function ArrayPad($length, $defaultValue) { - $arrayHandle = array_fill(0, $length, 0); - $index = 0; - while ($index < $length) { - $arrayHandle[$index++] = $defaultValue; - } + $arrayHandle = array_fill(0, $length, $defaultValue); return $arrayHandle; } }
\ No newline at end of file diff --git a/src/Gameboy/DrawContext.php b/src/Gameboy/DrawContext.php index 36a13f8..5cded7f 100644 --- a/src/Gameboy/DrawContext.php +++ b/src/Gameboy/DrawContext.php @@ -48,7 +48,7 @@ class DrawContext } echo "\e[H\e[2J"; - echo 'FPS: ' . $this->fps . PHP_EOL; + echo 'FPS: ' . $this->fps . ' - Frame Skip: ' . Settings::$settings[4] . PHP_EOL; echo $this->canvas->frame(); $this->canvas->clear(); } diff --git a/src/Gameboy/Opcode.php b/src/Gameboy/Opcode.php index cb2aae9..80c82a7 100644 --- a/src/Gameboy/Opcode.php +++ b/src/Gameboy/Opcode.php @@ -801,9 +801,8 @@ class Opcode $parentObj->updateCore(); } + //Throw an error on purpose to exit out of the loop. throw new \Exception("HALT_OVERRUN"); - - // throw(new Error("HALT_OVERRUN")); //Throw an error on purpose to exit out of the loop. } }; //LD (HL), A @@ -1701,9 +1700,8 @@ class Opcode //0xDB - Illegal //#0xDB: $this->functionsArray[] = function ($parentObj) { - // @TODO - // cout("Illegal op code 0xDB called, pausing emulation.", 2); - // pause(); + echo "Illegal op code 0xDB called, pausing emulation."; + exit(); }; //CALL FC, nn //#0xDC: @@ -1725,9 +1723,8 @@ class Opcode //0xDD - Illegal //#0xDD: $this->functionsArray[] = function ($parentObj) { - // @TODO - // cout("Illegal op code 0xDD called, pausing emulation.", 2); - // pause(); + echo "Illegal op code 0xDD called, pausing emulation."; + exit(); }; //SBC A, n //#0xDE: @@ -1770,16 +1767,14 @@ class Opcode //0xE3 - Illegal //#0xE3: $this->functionsArray[] = function ($parentObj) { - // @TODO - // cout("Illegal op code 0xE3 called, pausing emulation.", 2); - // pause(); + echo "Illegal op code 0xE3 called, pausing emulation."; + exit(); }; //0xE4 - Illegal //#0xE4: $this->functionsArray[] = function ($parentObj) { - // @TODO - // cout("Illegal op code 0xE4 called, pausing emulation.", 2); - // pause(); + echo "Illegal op code 0xE4 called, pausing emulation."; + exit(); }; //PUSH HL //#0xE5: @@ -1832,23 +1827,20 @@ class Opcode //0xEB - Illegal //#0xEB: $this->functionsArray[] = function ($parentObj) { - // @TODO - // cout("Illegal op code 0xEB called, pausing emulation.", 2); - // pause(); + echo "Illegal op code 0xEB called, pausing emulation."; + exit(); }; //0xEC - Illegal //#0xEC: $this->functionsArray[] = function ($parentObj) { - // @TODO - // cout("Illegal op code 0xEC called, pausing emulation.", 2); - // pause(); + echo "Illegal op code 0xEC called, pausing emulation."; + exit(); }; //0xED - Illegal //#0xED: $this->functionsArray[] = function ($parentObj) { - // @TODO - // cout("Illegal op code 0xED called, pausing emulation.", 2); - // pause(); + echo "Illegal op code 0xED called, pausing emulation."; + exit(); }; //XOR n //#0xEE: @@ -1956,16 +1948,14 @@ class Opcode //0xFC - Illegal //#0xFC: $this->functionsArray[] = function ($parentObj) { - // @TODO - // cout("Illegal op code 0xFC called, pausing emulation.", 2); - // pause(); + echo "Illegal op code 0xFC called, pausing emulation."; + exit(); }; //0xFD - Illegal //#0xFD: $this->functionsArray[] = function ($parentObj) { - // @TODO - // cout("Illegal op code 0xFD called, pausing emulation.", 2); - // pause(); + echo "Illegal op code 0xFD called, pausing emulation."; + exit(); }; //CP n //#0xFE: |