mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-10-23 23:55:42 +00:00
140 lines
2.5 KiB
C++
140 lines
2.5 KiB
C++
|
#include "mdec.h"
|
||
|
#include "YBaseLib/Log.h"
|
||
|
#include "common/state_wrapper.h"
|
||
|
#include "dma.h"
|
||
|
#include "interrupt_controller.h"
|
||
|
#include "system.h"
|
||
|
Log_SetChannel(MDEC);
|
||
|
|
||
|
MDEC::MDEC() = default;
|
||
|
|
||
|
MDEC::~MDEC() = default;
|
||
|
|
||
|
bool MDEC::Initialize(System* system, DMA* dma)
|
||
|
{
|
||
|
m_system = system;
|
||
|
m_dma = dma;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void MDEC::Reset()
|
||
|
{
|
||
|
SoftReset();
|
||
|
}
|
||
|
|
||
|
bool MDEC::DoState(StateWrapper& sw)
|
||
|
{
|
||
|
sw.Do(&m_status_register.bits);
|
||
|
sw.Do(&m_data_in_fifo);
|
||
|
sw.Do(&m_data_out_fifo);
|
||
|
|
||
|
return !sw.HasError();
|
||
|
}
|
||
|
|
||
|
u32 MDEC::ReadRegister(u32 offset)
|
||
|
{
|
||
|
switch (offset)
|
||
|
{
|
||
|
case 0:
|
||
|
return ReadDataRegister();
|
||
|
|
||
|
case 4:
|
||
|
{
|
||
|
Log_DebugPrintf("MDEC status register -> 0x%08X", m_status_register.bits);
|
||
|
return m_status_register.bits;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
{
|
||
|
Log_ErrorPrintf("Unknown MDEC register read: 0x%08X", offset);
|
||
|
return UINT32_C(0xFFFFFFFF);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void MDEC::WriteRegister(u32 offset, u32 value)
|
||
|
{
|
||
|
switch (offset)
|
||
|
{
|
||
|
case 0:
|
||
|
{
|
||
|
WriteCommandRegister(value);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
case 4:
|
||
|
{
|
||
|
Log_DebugPrintf("MDEC control register <- 0x%08X", value);
|
||
|
|
||
|
const ControlRegister cr{value};
|
||
|
if (cr.reset)
|
||
|
SoftReset();
|
||
|
|
||
|
m_status_register.data_in_request = cr.enable_dma_in;
|
||
|
m_status_register.data_out_request = cr.enable_dma_out;
|
||
|
m_dma->SetRequest(DMA::Channel::MDECin, cr.enable_dma_in);
|
||
|
m_dma->SetRequest(DMA::Channel::MDECout, cr.enable_dma_out);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
{
|
||
|
Log_ErrorPrintf("Unknown MDEC register write: 0x%08X <- 0x%08X", offset, value);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
u32 MDEC::DMARead()
|
||
|
{
|
||
|
return ReadDataRegister();
|
||
|
}
|
||
|
|
||
|
void MDEC::DMAWrite(u32 value)
|
||
|
{
|
||
|
WriteCommandRegister(value);
|
||
|
}
|
||
|
|
||
|
void MDEC::SoftReset()
|
||
|
{
|
||
|
m_status_register = {};
|
||
|
m_data_in_fifo.Clear();
|
||
|
m_data_out_fifo.Clear();
|
||
|
|
||
|
UpdateStatusRegister();
|
||
|
}
|
||
|
|
||
|
void MDEC::UpdateStatusRegister()
|
||
|
{
|
||
|
m_status_register.data_out_fifo_empty = m_data_out_fifo.IsEmpty();
|
||
|
m_status_register.data_in_fifo_full = m_data_in_fifo.IsFull();
|
||
|
}
|
||
|
|
||
|
void MDEC::WriteCommandRegister(u32 value)
|
||
|
{
|
||
|
Log_DebugPrintf("MDEC command/data register <- 0x%08X", value);
|
||
|
|
||
|
m_data_in_fifo.Push(value);
|
||
|
HandleCommand();
|
||
|
UpdateStatusRegister();
|
||
|
}
|
||
|
|
||
|
u32 MDEC::ReadDataRegister()
|
||
|
{
|
||
|
if (m_data_out_fifo.IsEmpty())
|
||
|
{
|
||
|
Log_WarningPrintf("MDEC data out FIFO empty on read");
|
||
|
return UINT32_C(0xFFFFFFFF);
|
||
|
}
|
||
|
|
||
|
const u32 value = m_data_out_fifo.Pop();
|
||
|
UpdateStatusRegister();
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
void MDEC::HandleCommand()
|
||
|
{
|
||
|
Log_DebugPrintf("MDEC command: 0x%08X", m_data_in_fifo.Peek(0));
|
||
|
}
|