diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 4f54d38f8..69abea7af 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -53,6 +53,8 @@ add_library(core save_state_version.h settings.cpp settings.h + sio.cpp + sio.h spu.cpp spu.h system.cpp diff --git a/src/core/bus.cpp b/src/core/bus.cpp index 63deef8a9..e78aeef71 100644 --- a/src/core/bus.cpp +++ b/src/core/bus.cpp @@ -13,6 +13,7 @@ #include "interrupt_controller.h" #include "mdec.h" #include "pad.h" +#include "sio.h" #include "spu.h" #include "timers.h" #include @@ -35,7 +36,7 @@ Bus::~Bus() = default; void Bus::Initialize(CPU::Core* cpu, CPU::CodeCache* cpu_code_cache, DMA* dma, InterruptController* interrupt_controller, GPU* gpu, CDROM* cdrom, Pad* pad, Timers* timers, - SPU* spu, MDEC* mdec) + SPU* spu, MDEC* mdec, SIO* sio) { m_cpu = cpu; m_cpu_code_cache = cpu_code_cache; @@ -47,6 +48,7 @@ void Bus::Initialize(CPU::Core* cpu, CPU::CodeCache* cpu_code_cache, DMA* dma, m_timers = timers; m_spu = spu; m_mdec = mdec; + m_sio = sio; } void Bus::Reset() @@ -423,16 +425,12 @@ void Bus::DoWritePad(MemoryAccessSize size, u32 offset, u32 value) u32 Bus::DoReadSIO(MemoryAccessSize size, u32 offset) { - Log_ErrorPrintf("SIO Read 0x%08X", offset); - if (offset == 0x04) - return 0x5; - else - return 0; + return m_sio->ReadRegister(offset); } void Bus::DoWriteSIO(MemoryAccessSize size, u32 offset, u32 value) { - Log_ErrorPrintf("SIO Write 0x%08X <- 0x%08X", offset, value); + m_sio->WriteRegister(offset, value); } u32 Bus::DoReadCDROM(MemoryAccessSize size, u32 offset) diff --git a/src/core/bus.h b/src/core/bus.h index d86542fa5..e06acdec3 100644 --- a/src/core/bus.h +++ b/src/core/bus.h @@ -22,6 +22,7 @@ class Pad; class Timers; class SPU; class MDEC; +class SIO; class System; class Bus @@ -31,7 +32,7 @@ public: ~Bus(); void Initialize(CPU::Core* cpu, CPU::CodeCache* cpu_code_cache, DMA* dma, InterruptController* interrupt_controller, - GPU* gpu, CDROM* cdrom, Pad* pad, Timers* timers, SPU* spu, MDEC* mdec); + GPU* gpu, CDROM* cdrom, Pad* pad, Timers* timers, SPU* spu, MDEC* mdec, SIO* sio); void Reset(); bool DoState(StateWrapper& sw); @@ -253,6 +254,7 @@ private: Timers* m_timers = nullptr; SPU* m_spu = nullptr; MDEC* m_mdec = nullptr; + SIO* m_sio = nullptr; std::array m_exp1_access_time = {}; std::array m_exp2_access_time = {}; diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj index 51f663d90..6ec7923e0 100644 --- a/src/core/core.vcxproj +++ b/src/core/core.vcxproj @@ -76,6 +76,7 @@ + @@ -113,6 +114,7 @@ + diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters index 23a97837f..1a64b2e40 100644 --- a/src/core/core.vcxproj.filters +++ b/src/core/core.vcxproj.filters @@ -36,6 +36,7 @@ + @@ -74,6 +75,7 @@ + diff --git a/src/core/sio.cpp b/src/core/sio.cpp new file mode 100644 index 000000000..f64e57455 --- /dev/null +++ b/src/core/sio.cpp @@ -0,0 +1,119 @@ +#include "sio.h" +#include "YBaseLib/Log.h" +#include "common/state_wrapper.h" +#include "host_interface.h" +#include "interrupt_controller.h" +#include "memory_card.h" +#include "pad_device.h" +#include "system.h" +Log_SetChannel(SIO); + +SIO::SIO() = default; + +SIO::~SIO() = default; + +void SIO::Initialize(System* system, InterruptController* interrupt_controller) +{ + m_system = system; + m_interrupt_controller = interrupt_controller; +} + +void SIO::Reset() +{ + SoftReset(); +} + +bool SIO::DoState(StateWrapper& sw) +{ + sw.Do(&m_SIO_CTRL.bits); + sw.Do(&m_SIO_STAT.bits); + sw.Do(&m_SIO_MODE.bits); + sw.Do(&m_SIO_BAUD); + + return !sw.HasError(); +} + +u32 SIO::ReadRegister(u32 offset) +{ + switch (offset) + { + case 0x00: // SIO_DATA + { + Log_ErrorPrintf("Read SIO_DATA"); + + const u8 value = 0xFF; + return (ZeroExtend32(value) | (ZeroExtend32(value) << 8) | (ZeroExtend32(value) << 16) | + (ZeroExtend32(value) << 24)); + } + + case 0x04: // SIO_STAT + { + const u32 bits = m_SIO_STAT.bits; + return bits; + } + + case 0x08: // SIO_MODE + return ZeroExtend32(m_SIO_MODE.bits); + + case 0x0A: // SIO_CTRL + return ZeroExtend32(m_SIO_CTRL.bits); + + case 0x0E: // SIO_BAUD + return ZeroExtend32(m_SIO_BAUD); + + default: + Log_ErrorPrintf("Unknown register read: 0x%X", offset); + return UINT32_C(0xFFFFFFFF); + } +} + +void SIO::WriteRegister(u32 offset, u32 value) +{ + switch (offset) + { + case 0x00: // SIO_DATA + { + Log_WarningPrintf("SIO_DATA (W) <- 0x%02X", value); + return; + } + + case 0x0A: // SIO_CTRL + { + Log_DebugPrintf("SIO_CTRL <- 0x%04X", value); + + m_SIO_CTRL.bits = Truncate16(value); + if (m_SIO_CTRL.RESET) + SoftReset(); + + return; + } + + case 0x08: // SIO_MODE + { + Log_DebugPrintf("SIO_MODE <- 0x%08X", value); + m_SIO_MODE.bits = Truncate16(value); + return; + } + + case 0x0E: + { + Log_DebugPrintf("SIO_BAUD <- 0x%08X", value); + m_SIO_BAUD = Truncate16(value); + return; + } + + default: + Log_ErrorPrintf("Unknown register write: 0x%X <- 0x%08X", offset, value); + return; + } +} + +void SIO::SoftReset() +{ + m_SIO_CTRL.bits = 0; + m_SIO_STAT.bits = 0; + m_SIO_STAT.TXDONE = true; + m_SIO_STAT.TXRDY = true; + m_SIO_MODE.bits = 0; + m_SIO_BAUD = 0xDC; +} diff --git a/src/core/sio.h b/src/core/sio.h new file mode 100644 index 000000000..4a1e31f42 --- /dev/null +++ b/src/core/sio.h @@ -0,0 +1,83 @@ +#pragma once +#include "common/bitfield.h" +#include "common/fifo_queue.h" +#include "types.h" +#include +#include + +class StateWrapper; + +class System; +class InterruptController; +class PadDevice; +class MemoryCard; + +class SIO +{ +public: + SIO(); + ~SIO(); + + void Initialize(System* system, InterruptController* interrupt_controller); + void Reset(); + bool DoState(StateWrapper& sw); + + u32 ReadRegister(u32 offset); + void WriteRegister(u32 offset, u32 value); + +private: + union SIO_CTRL + { + u16 bits; + + BitField TXEN; + BitField DTROUTPUT; + BitField RXEN; + BitField TXOUTPUT; + BitField ACK; + BitField RTSOUTPUT; + BitField RESET; + BitField RXIMODE; + BitField TXINTEN; + BitField RXINTEN; + BitField ACKINTEN; + }; + + union SIO_STAT + { + u32 bits; + + BitField TXRDY; + BitField RXFIFONEMPTY; + BitField TXDONE; + BitField RXPARITY; + BitField RXFIFOOVERRUN; + BitField RXBADSTOPBIT; + BitField RXINPUTLEVEL; + BitField DSRINPUTLEVEL; + BitField CTSINPUTLEVEL; + BitField INTR; + BitField TMR; + }; + + union SIO_MODE + { + u16 bits; + + BitField reload_factor; + BitField character_length; + BitField parity_enable; + BitField parity_type; + BitField stop_bit_length; + }; + + void SoftReset(); + + System* m_system = nullptr; + InterruptController* m_interrupt_controller = nullptr; + + SIO_CTRL m_SIO_CTRL = {}; + SIO_STAT m_SIO_STAT = {}; + SIO_MODE m_SIO_MODE = {}; + u16 m_SIO_BAUD = 0; +}; diff --git a/src/core/system.cpp b/src/core/system.cpp index 2412acbde..d92645458 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -17,6 +17,7 @@ #include "memory_card.h" #include "pad.h" #include "pad_device.h" +#include "sio.h" #include "spu.h" #include "timers.h" #include @@ -35,6 +36,7 @@ System::System(HostInterface* host_interface) : m_host_interface(host_interface) m_timers = std::make_unique(); m_spu = std::make_unique(); m_mdec = std::make_unique(); + m_sio = std::make_unique(); m_region = host_interface->GetSettings().region; m_cpu_execution_mode = host_interface->GetSettings().cpu_execution_mode; } @@ -176,7 +178,7 @@ void System::InitializeComponents() m_cpu->Initialize(m_bus.get()); m_cpu_code_cache->Initialize(this, m_cpu.get(), m_bus.get(), m_cpu_execution_mode == CPUExecutionMode::Recompiler); m_bus->Initialize(m_cpu.get(), m_cpu_code_cache.get(), m_dma.get(), m_interrupt_controller.get(), m_gpu.get(), - m_cdrom.get(), m_pad.get(), m_timers.get(), m_spu.get(), m_mdec.get()); + m_cdrom.get(), m_pad.get(), m_timers.get(), m_spu.get(), m_mdec.get(), m_sio.get()); m_dma->Initialize(this, m_bus.get(), m_interrupt_controller.get(), m_gpu.get(), m_cdrom.get(), m_spu.get(), m_mdec.get()); @@ -292,6 +294,7 @@ void System::Reset() m_timers->Reset(); m_spu->Reset(); m_mdec->Reset(); + m_sio->Reset(); m_frame_number = 1; m_internal_frame_number = 0; m_global_tick_counter = 0; diff --git a/src/core/system.h b/src/core/system.h index f46dbd6cf..9957a582d 100644 --- a/src/core/system.h +++ b/src/core/system.h @@ -23,6 +23,7 @@ class PadDevice; class Timers; class SPU; class MDEC; +class SIO; class System { @@ -106,6 +107,7 @@ private: std::unique_ptr m_timers; std::unique_ptr m_spu; std::unique_ptr m_mdec; + std::unique_ptr m_sio; ConsoleRegion m_region = ConsoleRegion::NTSC_U; CPUExecutionMode m_cpu_execution_mode = CPUExecutionMode::Interpreter; u32 m_frame_number = 1;