mirror of https://github.com/stenzek/duckstation
Skeleton for MDEC
parent
d47717fdd6
commit
a48b856a62
@ -0,0 +1,139 @@
|
||||
#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));
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
#pragma once
|
||||
#include "common/bitfield.h"
|
||||
#include "common/fifo_queue.h"
|
||||
#include "types.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class StateWrapper;
|
||||
|
||||
class System;
|
||||
class DMA;
|
||||
|
||||
class MDEC
|
||||
{
|
||||
public:
|
||||
MDEC();
|
||||
~MDEC();
|
||||
|
||||
bool Initialize(System* system, DMA* dma);
|
||||
void Reset();
|
||||
bool DoState(StateWrapper& sw);
|
||||
|
||||
// I/O
|
||||
u32 ReadRegister(u32 offset);
|
||||
void WriteRegister(u32 offset, u32 value);
|
||||
|
||||
u32 DMARead();
|
||||
void DMAWrite(u32 value);
|
||||
|
||||
private:
|
||||
static constexpr u32 DATA_IN_FIFO_SIZE = 256;
|
||||
static constexpr u32 DATA_OUT_FIFO_SIZE = 256;
|
||||
|
||||
enum DataOutputDepth : u8
|
||||
{
|
||||
DataOutputDepth_4Bit = 0,
|
||||
DataOutputDepth_8Bit = 1,
|
||||
DataOutputDepth_24Bit = 2,
|
||||
DataOutputDepth_15Bit = 3
|
||||
};
|
||||
|
||||
union StatusRegister
|
||||
{
|
||||
u32 bits;
|
||||
|
||||
BitField<u32, bool, 31, 1> data_out_fifo_empty;
|
||||
BitField<u32, bool, 30, 1> data_in_fifo_full;
|
||||
BitField<u32, bool, 29, 1> command_busy;
|
||||
BitField<u32, bool, 28, 1> data_in_request;
|
||||
BitField<u32, bool, 27, 1> data_out_request;
|
||||
BitField<u32, DataOutputDepth, 25, 2> data_output_depth;
|
||||
BitField<u32, bool, 24, 1> data_output_signed;
|
||||
BitField<u32, u8, 23, 1> data_output_bit15;
|
||||
BitField<u32, u8, 16, 3> current_block;
|
||||
BitField<u32, u16, 0, 16> parameter_words_remaining;
|
||||
};
|
||||
|
||||
union ControlRegister
|
||||
{
|
||||
u32 bits;
|
||||
BitField<u32, bool, 31, 1> reset;
|
||||
BitField<u32, bool, 30, 1> enable_dma_in;
|
||||
BitField<u32, bool, 29, 1> enable_dma_out;
|
||||
};
|
||||
|
||||
void SoftReset();
|
||||
void UpdateStatusRegister();
|
||||
|
||||
void WriteCommandRegister(u32 value);
|
||||
u32 ReadDataRegister();
|
||||
|
||||
void HandleCommand();
|
||||
|
||||
System* m_system = nullptr;
|
||||
DMA* m_dma = nullptr;
|
||||
|
||||
StatusRegister m_status_register = {};
|
||||
|
||||
InlineFIFOQueue<u32, DATA_IN_FIFO_SIZE> m_data_in_fifo;
|
||||
InlineFIFOQueue<u32, DATA_OUT_FIFO_SIZE> m_data_out_fifo;
|
||||
};
|
Loading…
Reference in New Issue