diff --git a/Core/GbCpu.cpp b/Core/GbCpu.cpp index 32f76b1..90b3158 100644 --- a/Core/GbCpu.cpp +++ b/Core/GbCpu.cpp @@ -16,17 +16,19 @@ GbCpu::GbCpu(Console* console, Gameboy* gameboy, GbMemoryManager* memoryManager) if(_gameboy->UseBootRom()) { _state.PC = 0; _state.SP = 0xFFFF; + _state.CycleCount = 8; //Makes boot_sclk_align serial test pass } else { _state.PC = 0x100; _state.SP = 0xFFFE; _state.A = _gameboy->IsCgb() ? 0x11 : 0x01; _state.B = 0x00; - _state.C = 0x13; + _state.C = _gameboy->IsCgb() ? 0x00 : 0x13; _state.D = 0x00; - _state.E = 0xD8; - _state.H = 0x01; - _state.L = 0x4D; - _state.Flags = 0xB0; + _state.E = _gameboy->IsCgb() ? 0x08 : 0xD8; + _state.H = _gameboy->IsCgb() ? 0x00 : 0x01; + _state.L = _gameboy->IsCgb() ? 0x7C : 0x4D; + _state.Flags = _gameboy->IsCgb() ? 0x80 : 0xB0; + _state.CycleCount = _gameboy->IsCgb() ? 13051516 : 23440332; } } diff --git a/Core/GbMemoryManager.cpp b/Core/GbMemoryManager.cpp index 5fcd4a4..0b77604 100644 --- a/Core/GbMemoryManager.cpp +++ b/Core/GbMemoryManager.cpp @@ -73,6 +73,13 @@ void GbMemoryManager::Exec() _timer->Exec(); _ppu->Exec(); _dmaController->Exec(); + + if(_state.SerialBitCount && (_gameboy->GetCycleCount() & 0x1FF) == 0) { + _state.SerialData = (_state.SerialData << 1) | 0x01; + if(--_state.SerialBitCount == 0) { + RequestIrq(GbIrqSource::Serial); + } + } } void GbMemoryManager::MapRegisters(uint16_t start, uint16_t end, RegisterAccess access) @@ -238,8 +245,8 @@ uint8_t GbMemoryManager::ReadRegister(uint16_t addr) switch(addr) { case 0xFF00: return ReadInputPort(); break; - case 0xFF01: return 0; //SB - Serial transfer data (R/W) - case 0xFF02: return 0x7E; //SC - Serial Transfer Control (R/W) + 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 0xFF04: case 0xFF05: case 0xFF06: case 0xFF07: return _timer->Read(addr); @@ -315,7 +322,16 @@ void GbMemoryManager::WriteRegister(uint16_t addr, uint8_t value) //00-0F switch(addr) { case 0xFF00: _state.InputSelect = value; break; - case 0xFF01: break; //Serial + case 0xFF01: _state.SerialData = value; break; //FF01 - SB - Serial transfer data (R/W) + case 0xFF02: + //FF02 - SC - Serial Transfer Control (R/W) + _state.SerialControl = value & (_gameboy->IsCgb() ? 0x83 : 0x81); + if((_state.SerialControl & 0x80) && (_state.SerialControl & 0x01)) { + _state.SerialBitCount = 8; + } else { + _state.SerialBitCount = 0; + } + break; case 0xFF04: case 0xFF05: case 0xFF06: case 0xFF07: _timer->Write(addr, value); @@ -412,7 +428,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.ApuCycleCount, _state.CgbHighSpeed, _state.CgbSwitchSpeedRequest, _state.CgbWorkRamBank, + _state.SerialData, _state.SerialControl, _state.SerialBitCount ); s.StreamArray(_state.MemoryType, 0x100); s.StreamArray(_state.MemoryOffset, 0x100); diff --git a/Core/GbTypes.h b/Core/GbTypes.h index da4e481..e9ac97a 100644 --- a/Core/GbTypes.h +++ b/Core/GbTypes.h @@ -349,6 +349,10 @@ struct GbMemoryManagerState uint8_t IrqEnabled; uint8_t InputSelect; + uint8_t SerialData; + uint8_t SerialControl; + uint8_t SerialBitCount; + bool IsReadRegister[0x100]; bool IsWriteRegister[0x100]; diff --git a/UI/Interop/DebugState.cs b/UI/Interop/DebugState.cs index 284a46d..c394bec 100644 --- a/UI/Interop/DebugState.cs +++ b/UI/Interop/DebugState.cs @@ -635,6 +635,10 @@ namespace Mesen.GUI public byte IrqEnabled; public byte InputSelect; + public byte SerialData; + public byte SerialControl; + public byte SerialBitCount; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x100)] public byte[] IsReadRegister;