public function ROMLoad()
{
//Load the first two ROM banks (0x0000 - 0x7FFF) into regular gameboy memory:
$this->ROM = $this->getTypedArray(strlen($this->ROMImage), 0, 'uint8');
for ($romIndex = 0; $romIndex < strlen($this->ROMImage); ++$romIndex) {
$this->ROM[$romIndex] = ord($this->ROMImage[$romIndex]) & 0xff;
if ($romIndex < 0x8000) {
$this->memory[$romIndex] = $this->ROM[$romIndex];
//Load in the game ROM.
}
}
// ROM name
for ($address = 0x134; $address < 0x13f; ++$address) {
if (ord($this->ROMImage[$address]) > 0) {
$this->name .= $this->ROMImage[$address];
}
}
// ROM game code (for newer games)
for ($address = 0x13f; $address < 0x143; ++$address) {
if (ord($this->ROMImage[$address]) > 0) {
$this->gameCode .= $this->ROMImage[$address];
}
}
echo 'Game Title: ' . $this->name . '[' . $this->gameCode . '][' . $this->ROMImage[0x143] . ']' . PHP_EOL;
echo 'Game Code: ' . $this->gameCode . PHP_EOL;
// Cartridge type
$this->cartridgeType = $this->ROM[0x147];
echo 'Cartridge type #' . $this->cartridgeType . PHP_EOL;
//Map out ROM cartridge sub-types.
$MBCType = '';
switch ($this->cartridgeType) {
case 0x0:
//ROM w/o bank switching
if (!Settings::$overrideMBC1) {
$MBCType = 'ROM';
break;
}
// no break
// no break
case 0x1:
$this->cMBC1 = true;
$MBCType = 'MBC1';
break;
case 0x2:
$this->cMBC1 = true;
$this->cSRAM = true;
$MBCType = 'MBC1 + SRAM';
break;
case 0x3:
$this->cMBC1 = true;
$this->cSRAM = true;
$this->cBATT = true;
$MBCType = 'MBC1 + SRAM + BATT';
break;
case 0x5:
$this->cMBC2 = true;
$MBCType = 'MBC2';
break;
case 0x6:
$this->cMBC2 = true;
$this->cBATT = true;
$MBCType = 'MBC2 + BATT';
break;
case 0x8:
$this->cSRAM = true;
$MBCType = 'ROM + SRAM';
break;
case 0x9:
$this->cSRAM = true;
$this->cBATT = true;
$MBCType = 'ROM + SRAM + BATT';
break;
case 0xb:
$this->cMMMO1 = true;
$MBCType = 'MMMO1';
break;
case 0xc:
$this->cMMMO1 = true;
$this->cSRAM = true;
$MBCType = 'MMMO1 + SRAM';
break;
case 0xd:
$this->cMMMO1 = true;
$this->cSRAM = true;
$this->cBATT = true;
$MBCType = 'MMMO1 + SRAM + BATT';
break;
case 0xf:
$this->cMBC3 = true;
$this->cTIMER = true;
$this->cBATT = true;
$MBCType = 'MBC3 + TIMER + BATT';
break;
case 0x10:
$this->cMBC3 = true;
$this->cTIMER = true;
$this->cBATT = true;
$this->cSRAM = true;
$MBCType = 'MBC3 + TIMER + BATT + SRAM';
break;
case 0x11:
$this->cMBC3 = true;
$MBCType = 'MBC3';
break;
case 0x12:
$this->cMBC3 = true;
$this->cSRAM = true;
$MBCType = 'MBC3 + SRAM';
break;
case 0x13:
$this->cMBC3 = true;
$this->cSRAM = true;
$this->cBATT = true;
$MBCType = 'MBC3 + SRAM + BATT';
break;
case 0x19:
$this->cMBC5 = true;
$MBCType = 'MBC5';
break;
case 0x1a:
$this->cMBC5 = true;
$this->cSRAM = true;
$MBCType = 'MBC5 + SRAM';
break;
case 0x1b:
$this->cMBC5 = true;
$this->cSRAM = true;
$this->cBATT = true;
$MBCType = 'MBC5 + SRAM + BATT';
break;
case 0x1c:
$this->cRUMBLE = true;
$MBCType = 'RUMBLE';
break;
case 0x1d:
$this->cRUMBLE = true;
$this->cSRAM = true;
$MBCType = 'RUMBLE + SRAM';
break;
case 0x1e:
$this->cRUMBLE = true;
$this->cSRAM = true;
$this->cBATT = true;
$MBCType = 'RUMBLE + SRAM + BATT';
break;
case 0x1f:
$this->cCamera = true;
$MBCType = 'GameBoy Camera';
break;
case 0xfd:
$this->cTAMA5 = true;
$MBCType = 'TAMA5';
break;
case 0xfe:
$this->cHuC3 = true;
$MBCType = 'HuC3';
break;
case 0xff:
$this->cHuC1 = true;
$MBCType = 'HuC1';
break;
default:
$MBCType = 'Unknown';
throw new RuntimeException('Cartridge type is unknown.');
}
echo 'Cartridge Type: ' . $MBCType . PHP_EOL;
// ROM and RAM banks
$this->numROMBanks = $this->ROMBanks[$this->ROM[0x148]];
echo $this->numROMBanks . ' ROM banks.' . PHP_EOL;
switch ($this->RAMBanks[$this->ROM[0x149]]) {
case 0:
echo 'No RAM banking requested for allocation or MBC is of type 2.' . PHP_EOL;
break;
case 2:
echo '1 RAM bank requested for allocation.' . PHP_EOL;
break;
case 3:
echo '4 RAM banks requested for allocation.' . PHP_EOL;
break;
case 4:
echo '16 RAM banks requested for allocation.' . PHP_EOL;
break;
default:
echo 'RAM bank amount requested is unknown, will use maximum allowed by specified MBC type.' . PHP_EOL;
}
//Check the GB/GBC mode byte:
switch ($this->ROM[0x143]) {
case 0x0:
//Only GB mode
$this->cGBC = false;
echo 'Only GB mode detected.' . PHP_EOL;
break;
case 0x80:
//Both GB + GBC modes
$this->cGBC = !Settings::$priorizeGameBoyMode;
echo 'GB and GBC mode detected.' . PHP_EOL;
break;
case 0xc0:
//Only GBC mode
$this->cGBC = true;
echo 'Only GBC mode detected.' . PHP_EOL;
break;
default:
$this->cGBC = false;
echo 'Unknown GameBoy game type code #' . $this->ROM[0x143] . ", defaulting to GB mode (Old games don't have a type code)." . PHP_EOL;
}
$this->inBootstrap = false;
$this->setupRAM();
//CPU/(V)RAM initialization.
$this->initSkipBootstrap();
$this->checkPaletteType();
//License Code Lookup:
$cOldLicense = $this->ROM[0x14b];
$cNewLicense = $this->ROM[0x144] & 0xff00 | $this->ROM[0x145] & 0xff;
if ($cOldLicense != 0x33) {
//Old Style License Header
echo 'Old style license code: ' . $cOldLicense . PHP_EOL;
} else {
//New Style License Header
echo 'New style license code: ' . $cNewLicense . PHP_EOL;
}
}