Skip to content
This repository has been archived by the owner on Dec 18, 2024. It is now read-only.

Commit

Permalink
GBC: Improved IO port behavior
Browse files Browse the repository at this point in the history
Fixes unused_hwio-C test, and allows aevilia to run
  • Loading branch information
SourMesen committed Jul 3, 2020
1 parent a15b22a commit a223021
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 19 deletions.
6 changes: 6 additions & 0 deletions Core/Gameboy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,13 @@ Gameboy* Gameboy::Create(Console* console, VirtualFile &romFile, bool sgbEnabled
MessageManager::Log("File: " + romFile.GetFileName());
MessageManager::Log("Game: " + header.GetCartName());
MessageManager::Log("Cart Type: " + std::to_string(header.CartType));
switch(header.CgbFlag & 0xC0) {
case 0x00: MessageManager::Log("Supports: Game Boy"); break;
case 0x80: MessageManager::Log("Supports: Game Boy Color (compatible with GB)"); break;
case 0xC0: MessageManager::Log("Supports: Game Boy Color only"); break;
}
MessageManager::Log("File size: " + std::to_string(romData.size() / 1024) + " KB");

if(header.GetCartRamSize() > 0) {
string sizeString = header.GetCartRamSize() > 1024 ? std::to_string(header.GetCartRamSize() / 1024) + " KB" : std::to_string(header.GetCartRamSize()) + " bytes";
MessageManager::Log("Cart RAM size: " + sizeString + (header.HasBattery() ? " (with battery)" : ""));
Expand Down
11 changes: 11 additions & 0 deletions Core/GbApu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,17 @@ void GbApu::Write(uint16_t addr, uint8_t value)
}
}

uint8_t GbApu::ReadCgbRegister(uint16_t addr)
{
switch(addr) {
case 0xFF76: return _square1->GetOutput() | (_square2->GetOutput() << 4);
case 0xFF77: return _noise->GetOutput() | (_wave->GetOutput() << 4);
}

//Should not be called
return 0;
}

template<typename T>
void GbApu::ProcessLengthEnableFlag(uint8_t value, T &length, bool &lengthEnabled, bool &enabled)
{
Expand Down
2 changes: 2 additions & 0 deletions Core/GbApu.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ class GbApu : public ISerializable
uint8_t Read(uint16_t addr);
void Write(uint16_t addr, uint8_t value);

uint8_t ReadCgbRegister(uint16_t addr);

template<typename T> void ProcessLengthEnableFlag(uint8_t value, T& length, bool& lengthEnabled, bool& enabled);

void Serialize(Serializer& s) override;
Expand Down
4 changes: 0 additions & 4 deletions Core/GbDmaController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,6 @@ void GbDmaController::Write(uint8_t value)
uint8_t GbDmaController::ReadCgb(uint16_t addr)
{
switch(addr) {
case 0xFF51: return _state.CgbDmaSource >> 8;
case 0xFF52: return _state.CgbDmaSource & 0xFF;
case 0xFF53: return _state.CgbDmaDest >> 8;
case 0xFF54: return _state.CgbDmaDest & 0xFF;
case 0xFF55: return _state.CgbDmaLength | (_state.CgbHdmaDone ? 0x80 : 0);
}

Expand Down
56 changes: 44 additions & 12 deletions Core/GbMemoryManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,18 +248,28 @@ uint8_t GbMemoryManager::ReadRegister(uint16_t addr)
} else if(addr >= 0xFF4C) {
if(_gameboy->IsCgb()) {
switch(addr) {
//FF4D - KEY1 - CGB Mode Only - Prepare Speed Switch
case 0xFF4D: return _state.CgbHighSpeed ? 0x80 : 0;

case 0xFF51: case 0xFF52: case 0xFF53: case 0xFF54: case 0xFF55: //CGB - DMA
return _dmaController->ReadCgb(addr);
case 0xFF55: //CGB - DMA
return _ppu->IsCgbEnabled() ? _dmaController->ReadCgb(addr) : 0xFF;

case 0xFF4F: //CGB - VRAM bank
case 0xFF68: case 0xFF69: case 0xFF6A: case 0xFF6B: //CGB - Palette
return _ppu->ReadCgbRegister(addr);

//FF70 - SVBK - CGB Mode Only - WRAM Bank
case 0xFF70: return _state.CgbWorkRamBank;
case 0xFF70: return _ppu->IsCgbEnabled() ? (_state.CgbWorkRamBank | 0xF8) : 0xFF;
case 0xFF72: return _state.CgbRegFF72;
case 0xFF73: return _state.CgbRegFF73;

case 0xFF74:
if(_ppu->IsCgbEnabled()) {
return _state.CgbRegFF74;
}
return 0xFF;

case 0xFF75: return _state.CgbRegFF75 | 0x8F;

case 0xFF76: case 0xFF77:
return _apu->ReadCgbRegister(addr);
}
}
LogDebug("[Debug] GB - Missing read handler: $" + HexUtilities::ToHex(addr));
Expand All @@ -274,7 +284,7 @@ uint8_t GbMemoryManager::ReadRegister(uint16_t addr)
case 0xFF00: return ReadInputPort(); break;

case 0xFF01: return _state.SerialData; //SB - Serial transfer data (R/W)
case 0xFF02: return _state.SerialControl | ~(_gameboy->IsCgb() ? 0x83 : 0x81); //SC - Serial Transfer Control (R/W)
case 0xFF02: return _state.SerialControl | 0x7E; //SC - Serial Transfer Control (R/W)

case 0xFF04: case 0xFF05: case 0xFF06: case 0xFF07:
return _timer->Read(addr);
Expand Down Expand Up @@ -313,11 +323,15 @@ void GbMemoryManager::WriteRegister(uint16_t addr, uint8_t value)
switch(addr) {
case 0xFF4D:
//FF4D - KEY1 - CGB Mode Only - Prepare Speed Switch
_state.CgbSwitchSpeedRequest = (value & 0x01) != 0;
if(_ppu->IsCgbEnabled()) {
_state.CgbSwitchSpeedRequest = (value & 0x01) != 0;
}
break;

case 0xFF51: case 0xFF52: case 0xFF53: case 0xFF54: case 0xFF55: //CGB - DMA
_dmaController->WriteCgb(addr, value);
if(_ppu->IsCgbEnabled()) {
_dmaController->WriteCgb(addr, value);
}
break;

case 0xFF4C: //CGB - "LCDMODE", set by boot rom to turn off CGB features for the LCD for DMG games
Expand All @@ -333,10 +347,22 @@ void GbMemoryManager::WriteRegister(uint16_t addr, uint8_t value)

case 0xFF70:
//FF70 - SVBK - CGB Mode Only - WRAM Bank
_state.CgbWorkRamBank = std::max(1, value & 0x07);
RefreshMappings();
if(_ppu->IsCgbEnabled()) {
_state.CgbWorkRamBank = std::max(1, value & 0x07);
RefreshMappings();
}
break;

case 0xFF72: _state.CgbRegFF72 = value; break;
case 0xFF73: _state.CgbRegFF73 = value; break;
case 0xFF74:
if(_ppu->IsCgbEnabled()) {
_state.CgbRegFF74 = value;
}
break;

case 0xFF75: _state.CgbRegFF75 = value; break;

default:
LogDebug("[Debug] GBC - Missing write handler: $" + HexUtilities::ToHex(addr));
break;
Expand Down Expand Up @@ -417,6 +443,11 @@ bool GbMemoryManager::IsHighSpeed()
return _state.CgbHighSpeed;
}

bool GbMemoryManager::IsBootRomDisabled()
{
return _state.DisableBootRom;
}

uint64_t GbMemoryManager::GetCycleCount()
{
return _state.CycleCount;
Expand Down Expand Up @@ -485,7 +516,8 @@ void GbMemoryManager::Serialize(Serializer& s)
s.Stream(
_state.DisableBootRom, _state.IrqEnabled, _state.IrqRequests, _state.InputSelect,
_state.ApuCycleCount, _state.CgbHighSpeed, _state.CgbSwitchSpeedRequest, _state.CgbWorkRamBank,
_state.SerialData, _state.SerialControl, _state.SerialBitCount, _state.CycleCount
_state.SerialData, _state.SerialControl, _state.SerialBitCount, _state.CycleCount,
_state.CgbRegFF72, _state.CgbRegFF73, _state.CgbRegFF74, _state.CgbRegFF75
);
s.StreamArray(_state.MemoryType, 0x100);
s.StreamArray(_state.MemoryOffset, 0x100);
Expand Down
2 changes: 2 additions & 0 deletions Core/GbMemoryManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ class GbMemoryManager : public ISerializable

void ToggleSpeed();
bool IsHighSpeed();
bool IsBootRomDisabled();

uint64_t GetCycleCount();
uint64_t GetApuCycleCount();

Expand Down
19 changes: 16 additions & 3 deletions Core/GbPpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,11 @@ bool GbPpu::IsLcdEnabled()
return _state.LcdEnabled;
}

bool GbPpu::IsCgbEnabled()
{
return _state.CgbEnabled;
}

PpuMode GbPpu::GetMode()
{
return _state.Mode;
Expand Down Expand Up @@ -892,11 +897,15 @@ void GbPpu::WriteOam(uint8_t addr, uint8_t value, bool forDma)

uint8_t GbPpu::ReadCgbRegister(uint16_t addr)
{
if(!_state.CgbEnabled) {
return 0xFF;
}

switch(addr) {
case 0xFF4F: return _state.CgbVramBank;
case 0xFF68: return _state.CgbBgPalPosition | (_state.CgbBgPalAutoInc ? 0x80 : 0);
case 0xFF4F: return _state.CgbVramBank | 0xFE;
case 0xFF68: return _state.CgbBgPalPosition | (_state.CgbBgPalAutoInc ? 0x80 : 0) | 0x40;
case 0xFF69: return (_state.CgbBgPalettes[_state.CgbBgPalPosition >> 1] >> ((_state.CgbBgPalPosition & 0x01) ? 8 : 0) & 0xFF);
case 0xFF6A: return _state.CgbObjPalPosition | (_state.CgbObjPalAutoInc ? 0x80 : 0);
case 0xFF6A: return _state.CgbObjPalPosition | (_state.CgbObjPalAutoInc ? 0x80 : 0) | 0x40;
case 0xFF6B: return (_state.CgbObjPalettes[_state.CgbObjPalPosition >> 1] >> ((_state.CgbObjPalPosition & 0x01) ? 8 : 0) & 0xFF);
}
LogDebug("[Debug] GBC - Missing read handler: $" + HexUtilities::ToHex(addr));
Expand All @@ -905,6 +914,10 @@ uint8_t GbPpu::ReadCgbRegister(uint16_t addr)

void GbPpu::WriteCgbRegister(uint16_t addr, uint8_t value)
{
if(!_state.CgbEnabled && _memoryManager->IsBootRomDisabled()) {
return;
}

switch(addr) {
case 0xFF4C: _state.CgbEnabled = (value & 0x0C) == 0; break;
case 0xFF4F: _state.CgbVramBank = value & 0x01; break;
Expand Down
1 change: 1 addition & 0 deletions Core/GbPpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ class GbPpu : public ISerializable
uint8_t GetScanline();
uint16_t GetCycle();
bool IsLcdEnabled();
bool IsCgbEnabled();
PpuMode GetMode();

void Exec();
Expand Down
5 changes: 5 additions & 0 deletions Core/GbTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,11 @@ struct GbMemoryManagerState
bool CgbSwitchSpeedRequest;
bool CgbHighSpeed;

uint8_t CgbRegFF72;
uint8_t CgbRegFF73;
uint8_t CgbRegFF74;
uint8_t CgbRegFF75;

bool DisableBootRom;
uint8_t IrqRequests;
uint8_t IrqEnabled;
Expand Down
5 changes: 5 additions & 0 deletions UI/Interop/DebugState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,11 @@ public struct GbMemoryManagerState
[MarshalAs(UnmanagedType.I1)] public bool CgbSwitchSpeedRequest;
[MarshalAs(UnmanagedType.I1)] public bool CgbHighSpeed;

public byte CgbRegFF72;
public byte CgbRegFF73;
public byte CgbRegFF74;
public byte CgbRegFF75;

[MarshalAs(UnmanagedType.I1)] public bool DisableBootRom;
public byte IrqRequests;
public byte IrqEnabled;
Expand Down

0 comments on commit a223021

Please sign in to comment.