CDROM: Stub implementation

This commit is contained in:
Connor McLaughlin 2019-09-17 19:22:39 +10:00
parent a0e7dff37c
commit b951f27381
9 changed files with 321 additions and 8 deletions

View File

@ -2,6 +2,7 @@
#include "YBaseLib/ByteStream.h" #include "YBaseLib/ByteStream.h"
#include "YBaseLib/Log.h" #include "YBaseLib/Log.h"
#include "YBaseLib/String.h" #include "YBaseLib/String.h"
#include "cdrom.h"
#include "common/state_wrapper.h" #include "common/state_wrapper.h"
#include "cpu_core.h" #include "cpu_core.h"
#include "cpu_disasm.h" #include "cpu_disasm.h"
@ -23,7 +24,7 @@ Bus::Bus() = default;
Bus::~Bus() = default; Bus::~Bus() = default;
bool Bus::Initialize(CPU::Core* cpu, DMA* dma, InterruptController* interrupt_controller, GPU* gpu) bool Bus::Initialize(CPU::Core* cpu, DMA* dma, InterruptController* interrupt_controller, GPU* gpu, CDROM* cdrom)
{ {
if (!LoadBIOS()) if (!LoadBIOS())
return false; return false;
@ -32,6 +33,7 @@ bool Bus::Initialize(CPU::Core* cpu, DMA* dma, InterruptController* interrupt_co
m_dma = dma; m_dma = dma;
m_interrupt_controller = interrupt_controller; m_interrupt_controller = interrupt_controller;
m_gpu = gpu; m_gpu = gpu;
m_cdrom = cdrom;
return true; return true;
} }
@ -214,6 +216,22 @@ bool Bus::WriteExpansionRegion2(MemoryAccessSize size, u32 offset, u32 value)
return DoInvalidAccess(MemoryAccessType::Write, size, EXP2_BASE | offset, EXP2_BASE | offset, value); return DoInvalidAccess(MemoryAccessType::Write, size, EXP2_BASE | offset, EXP2_BASE | offset, value);
} }
bool Bus::DoReadCDROM(MemoryAccessSize size, u32 offset, u32& value)
{
// TODO: Splitting of half/word reads.
Assert(size == MemoryAccessSize::Byte);
value = ZeroExtend32(m_cdrom->ReadRegister(offset));
return true;
}
bool Bus::DoWriteCDROM(MemoryAccessSize size, u32 offset, u32 value)
{
// TODO: Splitting of half/word reads.
Assert(size == MemoryAccessSize::Byte);
m_cdrom->WriteRegister(offset, Truncate8(value));
return true;
}
bool Bus::DoReadGPU(MemoryAccessSize size, u32 offset, u32& value) bool Bus::DoReadGPU(MemoryAccessSize size, u32 offset, u32& value)
{ {
Assert(size == MemoryAccessSize::Word); Assert(size == MemoryAccessSize::Word);

View File

@ -12,8 +12,9 @@ class Core;
} }
class DMA; class DMA;
class GPU;
class InterruptController; class InterruptController;
class GPU;
class CDROM;
class System; class System;
class Bus class Bus
@ -22,7 +23,7 @@ public:
Bus(); Bus();
~Bus(); ~Bus();
bool Initialize(CPU::Core* cpu, DMA* dma, InterruptController* interrupt_controller, GPU* gpu); bool Initialize(CPU::Core* cpu, DMA* dma, InterruptController* interrupt_controller, GPU* gpu, CDROM* cdrom);
void Reset(); void Reset();
bool DoState(StateWrapper& sw); bool DoState(StateWrapper& sw);
@ -39,15 +40,18 @@ public:
void PatchBIOS(u32 address, u32 value, u32 mask = UINT32_C(0xFFFFFFFF)); void PatchBIOS(u32 address, u32 value, u32 mask = UINT32_C(0xFFFFFFFF));
private: private:
static constexpr u32 GPU_BASE = 0x1F801810;
static constexpr u32 GPU_SIZE = 0x10;
static constexpr u32 GPU_MASK = GPU_SIZE - 1;
static constexpr u32 INTERRUPT_CONTROLLER_BASE = 0x1F801070; static constexpr u32 INTERRUPT_CONTROLLER_BASE = 0x1F801070;
static constexpr u32 INTERRUPT_CONTROLLER_SIZE = 0x08; static constexpr u32 INTERRUPT_CONTROLLER_SIZE = 0x08;
static constexpr u32 INTERRUPT_CONTROLLER_MASK = INTERRUPT_CONTROLLER_SIZE - 1; static constexpr u32 INTERRUPT_CONTROLLER_MASK = INTERRUPT_CONTROLLER_SIZE - 1;
static constexpr u32 DMA_BASE = 0x1F801080; static constexpr u32 DMA_BASE = 0x1F801080;
static constexpr u32 DMA_SIZE = 0x80; static constexpr u32 DMA_SIZE = 0x80;
static constexpr u32 DMA_MASK = DMA_SIZE - 1; static constexpr u32 DMA_MASK = DMA_SIZE - 1;
static constexpr u32 CDROM_BASE = 0x1F801800;
static constexpr u32 CDROM_SIZE = 0x04;
static constexpr u32 CDROM_MASK = CDROM_SIZE - 1;
static constexpr u32 GPU_BASE = 0x1F801810;
static constexpr u32 GPU_SIZE = 0x10;
static constexpr u32 GPU_MASK = GPU_SIZE - 1;
static constexpr u32 SPU_BASE = 0x1F801C00; static constexpr u32 SPU_BASE = 0x1F801C00;
static constexpr u32 SPU_SIZE = 0x300; static constexpr u32 SPU_SIZE = 0x300;
static constexpr u32 SPU_MASK = 0x3FF; static constexpr u32 SPU_MASK = 0x3FF;
@ -71,6 +75,9 @@ private:
bool ReadExpansionRegion2(MemoryAccessSize size, u32 offset, u32& value); bool ReadExpansionRegion2(MemoryAccessSize size, u32 offset, u32& value);
bool WriteExpansionRegion2(MemoryAccessSize size, u32 offset, u32 value); bool WriteExpansionRegion2(MemoryAccessSize size, u32 offset, u32 value);
bool DoReadCDROM(MemoryAccessSize size, u32 offset, u32& value);
bool DoWriteCDROM(MemoryAccessSize size, u32 offset, u32 value);
bool DoReadGPU(MemoryAccessSize size, u32 offset, u32& value); bool DoReadGPU(MemoryAccessSize size, u32 offset, u32& value);
bool DoWriteGPU(MemoryAccessSize size, u32 offset, u32 value); bool DoWriteGPU(MemoryAccessSize size, u32 offset, u32 value);
@ -87,6 +94,7 @@ private:
DMA* m_dma = nullptr; DMA* m_dma = nullptr;
InterruptController* m_interrupt_controller = nullptr; InterruptController* m_interrupt_controller = nullptr;
GPU* m_gpu = nullptr; GPU* m_gpu = nullptr;
CDROM* m_cdrom = nullptr;
std::array<u8, 2097152> m_ram{}; // 2MB RAM std::array<u8, 2097152> m_ram{}; // 2MB RAM
std::array<u8, 524288> m_bios{}; // 512K BIOS ROM std::array<u8, 524288> m_bios{}; // 512K BIOS ROM

View File

@ -99,6 +99,15 @@ bool Bus::DispatchAccess(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddres
return (type == MemoryAccessType::Read) ? DoReadDMA(size, bus_address & DMA_MASK, value) : return (type == MemoryAccessType::Read) ? DoReadDMA(size, bus_address & DMA_MASK, value) :
DoWriteDMA(size, bus_address & DMA_MASK, value); DoWriteDMA(size, bus_address & DMA_MASK, value);
} }
else if (bus_address < CDROM_BASE)
{
return DoInvalidAccess(type, size, cpu_address, bus_address, value);
}
else if (bus_address < (CDROM_BASE + GPU_SIZE))
{
return (type == MemoryAccessType::Read) ? DoReadCDROM(size, bus_address & CDROM_MASK, value) :
DoWriteCDROM(size, bus_address & CDROM_MASK, value);
}
else if (bus_address < GPU_BASE) else if (bus_address < GPU_BASE)
{ {
return DoInvalidAccess(type, size, cpu_address, bus_address, value); return DoInvalidAccess(type, size, cpu_address, bus_address, value);

View File

@ -1 +1,198 @@
#include "interrupt_controller.h" #include "cdrom.h"
#include "YBaseLib/Log.h"
#include "common/state_wrapper.h"
Log_SetChannel(CDROM);
CDROM::CDROM() = default;
CDROM::~CDROM() = default;
bool CDROM::Initialize(DMA* dma, InterruptController* interrupt_controller)
{
m_dma = dma;
m_interrupt_controller = interrupt_controller;
return true;
}
void CDROM::Reset()
{
m_param_fifo.Clear();
m_response_fifo.Clear();
m_data_fifo.Clear();
}
bool CDROM::DoState(StateWrapper& sw)
{
sw.Do(&m_state);
sw.Do(&m_status.bits);
sw.Do(&m_param_fifo);
sw.Do(&m_response_fifo);
sw.Do(&m_data_fifo);
return !sw.HasError();
}
u8 CDROM::ReadRegister(u32 offset)
{
switch (offset)
{
case 0: // status register
return m_status.bits;
case 1: // always response FIFO
return m_response_fifo.Pop();
case 2: // always data FIFO
return m_data_fifo.Pop();
case 3:
{
switch (m_status.index)
{
case 0:
case 2:
return m_interrupt_enable_register | ~INTERRUPT_REGISTER_MASK;
case 1:
case 3:
return m_interrupt_flag_register;
}
}
break;
}
Log_ErrorPrintf("Unknown CDROM register read: offset=0x%02X, index=%d", offset,
ZeroExtend32(m_status.index.GetValue()));
Panic("Unknown CDROM register");
return 0;
}
void CDROM::WriteRegister(u32 offset, u8 value)
{
switch (offset)
{
case 0:
{
Log_DebugPrintf("CDROM status register <- 0x%02X", ZeroExtend32(value));
m_status.bits = (m_status.bits & static_cast<u8>(~3)) | (value & u8(3));
return;
}
break;
case 1:
{
switch (m_status.index)
{
case 0:
{
Log_DebugPrintf("CDROM command register <- 0x%02X", ZeroExtend32(value));
if (m_state != State::Idle)
Log_ErrorPrintf("Ignoring write (0x%02X) to command register in non-idle state", ZeroExtend32(value));
else
WriteCommand(value);
return;
}
case 1:
{
Log_ErrorPrintf("Sound map data out <- 0x%02X", ZeroExtend32(value));
return;
}
case 2:
{
Log_ErrorPrintf("Sound map coding info <- 0x%02X", ZeroExtend32(value));
return;
}
case 3:
{
Log_ErrorPrintf("Audio volume for right-to-left output <- 0x%02X", ZeroExtend32(value));
return;
}
}
}
break;
case 2:
{
switch (m_status.index)
{
case 0:
{
if (m_param_fifo.IsFull())
{
Log_WarningPrintf("Parameter FIFO overflow");
m_param_fifo.RemoveOne();
}
m_param_fifo.Push(value);
return;
}
case 1:
{
Log_DebugPrintf("Interrupt enable register <- 0x%02X", ZeroExtend32(value));
m_interrupt_enable_register = value & INTERRUPT_REGISTER_MASK;
return;
}
case 2:
{
Log_ErrorPrintf("Audio volume for left-to-left output <- 0x%02X", ZeroExtend32(value));
return;
}
case 3:
{
Log_ErrorPrintf("Audio volume for right-to-left output <- 0x%02X", ZeroExtend32(value));
return;
}
}
}
break;
case 3:
{
switch (m_status.index)
{
case 0:
{
Log_ErrorPrintf("Request register <- 0x%02X", value);
return;
}
case 1:
{
Log_DebugPrintf("Interrupt flag register <- 0x%02X", value);
m_interrupt_flag_register &= ~(value & INTERRUPT_REGISTER_MASK);
Execute();
return;
}
case 2:
{
Log_ErrorPrintf("Audio volume for left-to-right output <- 0x%02X", ZeroExtend32(value));
return;
}
case 3:
{
Log_ErrorPrintf("Audio volume apply changes <- 0x%02X", ZeroExtend32(value));
return;
}
}
}
break;
}
Log_ErrorPrintf("Unknown CDROM register write: offset=0x%02X, index=%d, value=0x%02X", offset,
ZeroExtend32(m_status.index.GetValue()), ZeroExtend32(value));
}
void CDROM::Execute() {}
void CDROM::WriteCommand(u8 command)
{
Log_ErrorPrintf("CDROM write command 0x%02X", ZeroExtend32(command));
}

66
src/pse/cdrom.h Normal file
View File

@ -0,0 +1,66 @@
#pragma once
#include "types.h"
#include "common/bitfield.h"
#include "common/fifo_queue.h"
class StateWrapper;
class DMA;
class InterruptController;
class CDROM
{
public:
CDROM();
~CDROM();
bool Initialize(DMA* dma, InterruptController* interrupt_controller);
void Reset();
bool DoState(StateWrapper& sw);
// I/O
u8 ReadRegister(u32 offset);
void WriteRegister(u32 offset, u8 value);
void Execute();
private:
static constexpr u32 PARAM_FIFO_SIZE = 16;
static constexpr u32 RESPONSE_FIFO_SIZE = 16;
static constexpr u32 DATA_FIFO_SIZE = 4096;
static constexpr u32 NUM_INTERRUPTS = 32;
static constexpr u8 INTERRUPT_REGISTER_MASK = 0x1F;
bool HasPendingInterrupt() const { return m_interrupt_flag_register != 0; }
void WriteCommand(u8 command);
DMA* m_dma;
InterruptController* m_interrupt_controller;
enum class State : u32
{
Idle
};
State m_state = State::Idle;
union
{
u8 bits;
BitField<u8, u8, 0, 2> index;
BitField<u8, bool, 2, 1> ADPBUSY;
BitField<u8, bool, 3, 1> PRMEMPTY;
BitField<u8, bool, 4, 1> PRMWRDY;
BitField<u8, bool, 5, 1> RSLRRDY;
BitField<u8, bool, 6, 1> DRQSTS;
BitField<u8, bool, 7, 1> BUSYSTS;
} m_status = {};
u8 m_interrupt_enable_register = INTERRUPT_REGISTER_MASK;
u8 m_interrupt_flag_register = 0;
InlineFIFOQueue<u8, PARAM_FIFO_SIZE> m_param_fifo;
InlineFIFOQueue<u8, RESPONSE_FIFO_SIZE> m_response_fifo;
HeapFIFOQueue<u8, DATA_FIFO_SIZE> m_data_fifo;
};

View File

@ -36,6 +36,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="bus.cpp" /> <ClCompile Include="bus.cpp" />
<ClCompile Include="cdrom.cpp" />
<ClCompile Include="cpu_core.cpp" /> <ClCompile Include="cpu_core.cpp" />
<ClCompile Include="cpu_disasm.cpp" /> <ClCompile Include="cpu_disasm.cpp" />
<ClCompile Include="dma.cpp" /> <ClCompile Include="dma.cpp" />
@ -48,6 +49,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="bus.h" /> <ClInclude Include="bus.h" />
<ClInclude Include="cdrom.h" />
<ClInclude Include="cpu_core.h" /> <ClInclude Include="cpu_core.h" />
<ClInclude Include="cpu_disasm.h" /> <ClInclude Include="cpu_disasm.h" />
<ClInclude Include="cpu_types.h" /> <ClInclude Include="cpu_types.h" />

View File

@ -11,6 +11,7 @@
<ClCompile Include="gpu_hw.cpp" /> <ClCompile Include="gpu_hw.cpp" />
<ClCompile Include="host_interface.cpp" /> <ClCompile Include="host_interface.cpp" />
<ClCompile Include="interrupt_controller.cpp" /> <ClCompile Include="interrupt_controller.cpp" />
<ClCompile Include="cdrom.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="types.h" /> <ClInclude Include="types.h" />
@ -26,6 +27,7 @@
<ClInclude Include="gpu_hw.h" /> <ClInclude Include="gpu_hw.h" />
<ClInclude Include="host_interface.h" /> <ClInclude Include="host_interface.h" />
<ClInclude Include="interrupt_controller.h" /> <ClInclude Include="interrupt_controller.h" />
<ClInclude Include="cdrom.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="cpu_core.inl" /> <None Include="cpu_core.inl" />

View File

@ -6,6 +6,7 @@
#include "dma.h" #include "dma.h"
#include "gpu.h" #include "gpu.h"
#include "interrupt_controller.h" #include "interrupt_controller.h"
#include "cdrom.h"
System::System(HostInterface* host_interface) : m_host_interface(host_interface) System::System(HostInterface* host_interface) : m_host_interface(host_interface)
{ {
@ -15,6 +16,7 @@ System::System(HostInterface* host_interface) : m_host_interface(host_interface)
m_interrupt_controller = std::make_unique<InterruptController>(); m_interrupt_controller = std::make_unique<InterruptController>();
// m_gpu = std::make_unique<GPU>(); // m_gpu = std::make_unique<GPU>();
m_gpu = GPU::CreateHardwareOpenGLRenderer(); m_gpu = GPU::CreateHardwareOpenGLRenderer();
m_cdrom = std::make_unique<CDROM>();
} }
System::~System() = default; System::~System() = default;
@ -24,7 +26,7 @@ bool System::Initialize()
if (!m_cpu->Initialize(m_bus.get())) if (!m_cpu->Initialize(m_bus.get()))
return false; return false;
if (!m_bus->Initialize(m_cpu.get(), m_dma.get(), m_interrupt_controller.get(), m_gpu.get())) if (!m_bus->Initialize(m_cpu.get(), m_dma.get(), m_interrupt_controller.get(), m_gpu.get(), m_cdrom.get()))
return false; return false;
if (!m_dma->Initialize(m_bus.get(), m_gpu.get())) if (!m_dma->Initialize(m_bus.get(), m_gpu.get()))
@ -36,6 +38,9 @@ bool System::Initialize()
if (!m_gpu->Initialize(this, m_bus.get(), m_dma.get())) if (!m_gpu->Initialize(this, m_bus.get(), m_dma.get()))
return false; return false;
if (!m_cdrom->Initialize(m_dma.get(), m_interrupt_controller.get()))
return false;
return true; return true;
} }
@ -56,6 +61,9 @@ bool System::DoState(StateWrapper& sw)
if (!sw.DoMarker("GPU") || !m_gpu->DoState(sw)) if (!sw.DoMarker("GPU") || !m_gpu->DoState(sw))
return false; return false;
if (!sw.DoMarker("CDROM") || !m_cdrom->DoState(sw))
return false;
return !sw.HasError(); return !sw.HasError();
} }
@ -68,6 +76,7 @@ void System::Reset()
m_dma->Reset(); m_dma->Reset();
m_interrupt_controller->Reset(); m_interrupt_controller->Reset();
m_gpu->Reset(); m_gpu->Reset();
m_cdrom->Reset();
m_frame_number = 1; m_frame_number = 1;
} }

View File

@ -15,6 +15,7 @@ class Bus;
class DMA; class DMA;
class InterruptController; class InterruptController;
class GPU; class GPU;
class CDROM;
class System class System
{ {
@ -48,5 +49,6 @@ private:
std::unique_ptr<DMA> m_dma; std::unique_ptr<DMA> m_dma;
std::unique_ptr<InterruptController> m_interrupt_controller; std::unique_ptr<InterruptController> m_interrupt_controller;
std::unique_ptr<GPU> m_gpu; std::unique_ptr<GPU> m_gpu;
std::unique_ptr<CDROM> m_cdrom;
u32 m_frame_number = 1; u32 m_frame_number = 1;
}; };