public function memoryRead($address)
{
if ($address < 0x4000) {
return $this->memory[$address];
} elseif ($address < 0x8000) {
return $this->ROM[$this->currentROMBank + $address];
} elseif ($address >= 0x8000 && $address < 0xa000) {
if ($this->cGBC) {
//CPU Side Reading The VRAM (Optimized for GameBoy Color)
return $this->lcdController->modeSTAT > 2 ? 0xff : ($this->currVRAMBank == 0 ? $this->memory[$address] : $this->VRAM[$address - 0x8000]);
}
//CPU Side Reading The VRAM (Optimized for classic GameBoy)
return $this->lcdController->modeSTAT > 2 ? 0xff : $this->memory[$address];
} elseif ($address >= 0xa000 && $address < 0xc000) {
if ($this->numRAMBanks == 1 / 16 && $address < 0xa200 || $this->numRAMBanks >= 1) {
if (!$this->cMBC3) {
//memoryReadMBC
//Switchable RAM
if ($this->MBCRAMBanksEnabled || Settings::$overrideMBC) {
return $this->MBCRam[$address + $this->currMBCRAMBankPosition];
}
//cout("Reading from disabled RAM.", 1);
return 0xff;
} else {
//MBC3 RTC + RAM:
//memoryReadMBC3
//Switchable RAM
if ($this->MBCRAMBanksEnabled || Settings::$overrideMBC) {
switch ($this->currMBCRAMBank) {
case 0x0:
case 0x1:
case 0x2:
case 0x3:
return $this->MBCRam[$address + $this->currMBCRAMBankPosition];
break;
case 0x8:
return $this->latchedSeconds;
break;
case 0x9:
return $this->latchedMinutes;
break;
case 0xa:
return $this->latchedHours;
break;
case 0xb:
return $this->latchedLDays;
break;
case 0xc:
return ($this->RTCDayOverFlow ? 0x80 : 0) + ($this->RTCHALT ? 0x40 : 0) + $this->latchedHDays;
}
}
//cout("Reading from invalid or disabled RAM.", 1);
return 0xff;
}
} else {
return 0xff;
}
} elseif ($address >= 0xc000 && $address < 0xe000) {
if (!$this->cGBC || $address < 0xd000) {
return $this->memory[$address];
} else {
//memoryReadGBCMemory
return $this->GBCMemory[$address + $this->gbcRamBankPosition];
}
} elseif ($address >= 0xe000 && $address < 0xfe00) {
if (!$this->cGBC || $address < 0xf000) {
//memoryReadECHONormal
return $this->memory[$address - 0x2000];
} else {
//memoryReadECHOGBCMemory
return $this->GBCMemory[$address + $this->gbcRamBankPositionECHO];
}
} elseif ($address < 0xfea0) {
//memoryReadOAM
return $this->lcdController->modeSTAT > 1 ? 0xff : $this->memory[$address];
} elseif ($this->cGBC && $address >= 0xfea0 && $address < 0xff00) {
//memoryReadNormal
return $this->memory[$address];
} elseif ($address >= 0xff00) {
switch ($address) {
case 0xff00:
return 0xc0 | $this->memory[0xff00];
//Top nibble returns as set.
break;
case 0xff01:
return ($this->memory[0xff02] & 0x1) == 0x1 ? 0xff : $this->memory[0xff01];
break;
case 0xff02:
if ($this->cGBC) {
return 0x7c | $this->memory[0xff02];
} else {
return 0x7e | $this->memory[0xff02];
}
break;
case 0xff07:
return 0xf8 | $this->memory[0xff07];
break;
case 0xff0f:
return 0xe0 | $this->memory[0xff0f];
break;
case 0xff10:
return 0x80 | $this->memory[0xff10];
break;
case 0xff11:
return 0x3f | $this->memory[0xff11];
break;
case 0xff14:
return 0xbf | $this->memory[0xff14];
break;
case 0xff16:
return 0x3f | $this->memory[0xff16];
break;
case 0xff19:
return 0xbf | $this->memory[0xff19];
break;
case 0xff1a:
return 0x7f | $this->memory[0xff1a];
break;
case 0xff1b:
return 0xff;
break;
case 0xff1c:
return 0x9f | $this->memory[0xff1c];
break;
case 0xff1e:
return 0xbf | $this->memory[0xff1e];
break;
case 0xff20:
return 0xff;
break;
case 0xff23:
return 0xbf | $this->memory[0xff23];
break;
case 0xff26:
return 0x70 | $this->memory[0xff26];
break;
case 0xff30:
case 0xff31:
case 0xff32:
case 0xff33:
case 0xff34:
case 0xff35:
case 0xff36:
case 0xff37:
case 0xff38:
case 0xff39:
case 0xff3a:
case 0xff3b:
case 0xff3c:
case 0xff3d:
case 0xff3e:
case 0xff3f:
return ($this->memory[0xff26] & 0x4) == 0x4 ? 0xff : $this->memory[$address];
break;
case 0xff41:
return 0x80 | $this->memory[0xff41] | $this->lcdController->modeSTAT;
break;
case 0xff44:
return $this->lcdController->LCDisOn ? $this->memory[0xff44] : 0;
break;
case 0xff4f:
return $this->currVRAMBank;
break;
default:
//memoryReadNormal
return $this->memory[$address];
}
} else {
//memoryReadBAD
return 0xff;
}
}