2019-09-29 02:51:34 +00:00
|
|
|
#pragma once
|
|
|
|
#include "common/bitfield.h"
|
|
|
|
#include "common/fifo_queue.h"
|
|
|
|
#include "types.h"
|
2019-09-29 08:11:18 +00:00
|
|
|
#include <array>
|
2020-01-24 04:53:40 +00:00
|
|
|
#include <memory>
|
2019-09-29 02:51:34 +00:00
|
|
|
|
|
|
|
class StateWrapper;
|
|
|
|
|
2020-01-24 04:53:40 +00:00
|
|
|
class TimingEvent;
|
2019-09-29 02:51:34 +00:00
|
|
|
|
|
|
|
class MDEC
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
MDEC();
|
|
|
|
~MDEC();
|
|
|
|
|
2020-07-31 07:09:18 +00:00
|
|
|
void Initialize();
|
|
|
|
void Shutdown();
|
2019-09-29 02:51:34 +00:00
|
|
|
void Reset();
|
|
|
|
bool DoState(StateWrapper& sw);
|
|
|
|
|
|
|
|
// I/O
|
|
|
|
u32 ReadRegister(u32 offset);
|
|
|
|
void WriteRegister(u32 offset, u32 value);
|
|
|
|
|
2019-10-13 06:48:11 +00:00
|
|
|
void DMARead(u32* words, u32 word_count);
|
|
|
|
void DMAWrite(const u32* words, u32 word_count);
|
2019-09-29 02:51:34 +00:00
|
|
|
|
2019-10-26 03:31:21 +00:00
|
|
|
void DrawDebugStateWindow();
|
2019-10-12 12:47:00 +00:00
|
|
|
|
2019-09-29 02:51:34 +00:00
|
|
|
private:
|
2020-03-25 14:13:07 +00:00
|
|
|
static constexpr u32 DATA_IN_FIFO_SIZE = 1024;
|
|
|
|
static constexpr u32 DATA_OUT_FIFO_SIZE = 768;
|
2019-10-06 15:04:20 +00:00
|
|
|
static constexpr u32 NUM_BLOCKS = 6;
|
2019-09-29 02:51:34 +00:00
|
|
|
|
|
|
|
enum DataOutputDepth : u8
|
|
|
|
{
|
|
|
|
DataOutputDepth_4Bit = 0,
|
|
|
|
DataOutputDepth_8Bit = 1,
|
|
|
|
DataOutputDepth_24Bit = 2,
|
|
|
|
DataOutputDepth_15Bit = 3
|
|
|
|
};
|
|
|
|
|
2019-09-29 08:11:18 +00:00
|
|
|
enum class Command : u8
|
|
|
|
{
|
|
|
|
None = 0,
|
|
|
|
DecodeMacroblock = 1,
|
|
|
|
SetIqTab = 2,
|
|
|
|
SetScale = 3
|
|
|
|
};
|
|
|
|
|
2020-03-25 14:13:07 +00:00
|
|
|
enum class State : u8
|
|
|
|
{
|
|
|
|
Idle,
|
|
|
|
DecodingMacroblock,
|
|
|
|
WritingMacroblock,
|
|
|
|
SetIqTable,
|
2020-12-18 15:16:12 +00:00
|
|
|
SetScaleTable,
|
|
|
|
NoCommand
|
2020-03-25 14:13:07 +00:00
|
|
|
};
|
|
|
|
|
2019-09-29 02:51:34 +00:00
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
2019-09-29 08:11:18 +00:00
|
|
|
union CommandWord
|
|
|
|
{
|
|
|
|
u32 bits;
|
|
|
|
|
|
|
|
BitField<u32, Command, 29, 3> command;
|
|
|
|
BitField<u32, DataOutputDepth, 27, 2> data_output_depth;
|
|
|
|
BitField<u32, bool, 26, 1> data_output_signed;
|
|
|
|
BitField<u32, u8, 25, 1> data_output_bit15;
|
|
|
|
BitField<u32, u16, 0, 16> parameter_word_count;
|
|
|
|
};
|
|
|
|
|
2020-01-24 04:53:40 +00:00
|
|
|
bool HasPendingBlockCopyOut() const;
|
2019-10-17 14:40:07 +00:00
|
|
|
|
2019-09-29 02:51:34 +00:00
|
|
|
void SoftReset();
|
2020-03-25 14:13:07 +00:00
|
|
|
void ResetDecoder();
|
2019-10-17 14:40:07 +00:00
|
|
|
void UpdateStatus();
|
2019-09-29 02:51:34 +00:00
|
|
|
|
|
|
|
u32 ReadDataRegister();
|
2019-09-29 08:11:18 +00:00
|
|
|
void WriteCommandRegister(u32 value);
|
2020-03-25 14:13:07 +00:00
|
|
|
void Execute();
|
2019-09-29 08:11:18 +00:00
|
|
|
|
2019-10-06 15:04:20 +00:00
|
|
|
bool HandleDecodeMacroblockCommand();
|
2019-10-17 14:40:07 +00:00
|
|
|
void HandleSetQuantTableCommand();
|
|
|
|
void HandleSetScaleCommand();
|
2019-09-29 08:11:18 +00:00
|
|
|
|
2019-10-06 15:04:20 +00:00
|
|
|
bool DecodeMonoMacroblock();
|
2019-10-17 14:40:07 +00:00
|
|
|
bool DecodeColoredMacroblock();
|
|
|
|
void ScheduleBlockCopyOut(TickCount ticks);
|
|
|
|
void CopyOutBlock();
|
2019-09-29 08:11:18 +00:00
|
|
|
|
|
|
|
// from nocash spec
|
2019-10-06 15:04:20 +00:00
|
|
|
bool rl_decode_block(s16* blk, const u8* qt);
|
2019-09-29 08:11:18 +00:00
|
|
|
void IDCT(s16* blk);
|
|
|
|
void yuv_to_rgb(u32 xx, u32 yy, const std::array<s16, 64>& Crblk, const std::array<s16, 64>& Cbblk,
|
2019-10-17 14:40:07 +00:00
|
|
|
const std::array<s16, 64>& Yblk);
|
|
|
|
void y_to_mono(const std::array<s16, 64>& Yblk);
|
2019-09-29 02:51:34 +00:00
|
|
|
|
2019-09-29 08:11:18 +00:00
|
|
|
StatusRegister m_status = {};
|
2019-10-08 09:27:22 +00:00
|
|
|
bool m_enable_dma_in = false;
|
|
|
|
bool m_enable_dma_out = false;
|
2019-09-29 08:11:18 +00:00
|
|
|
|
2019-10-06 15:04:20 +00:00
|
|
|
// Even though the DMA is in words, we access the FIFO as halfwords.
|
2019-10-13 04:16:49 +00:00
|
|
|
InlineFIFOQueue<u16, DATA_IN_FIFO_SIZE / sizeof(u16)> m_data_in_fifo;
|
|
|
|
InlineFIFOQueue<u32, DATA_OUT_FIFO_SIZE / sizeof(u32)> m_data_out_fifo;
|
2020-03-25 14:13:07 +00:00
|
|
|
State m_state = State::Idle;
|
2019-10-17 14:40:07 +00:00
|
|
|
u32 m_remaining_halfwords = 0;
|
2019-09-29 08:11:18 +00:00
|
|
|
|
|
|
|
std::array<u8, 64> m_iq_uv{};
|
|
|
|
std::array<u8, 64> m_iq_y{};
|
|
|
|
|
|
|
|
std::array<s16, 64> m_scale_table{};
|
2019-10-06 15:04:20 +00:00
|
|
|
|
|
|
|
// blocks, for colour: 0 - Crblk, 1 - Cbblk, 2-5 - Y 1-4
|
|
|
|
std::array<std::array<s16, 64>, NUM_BLOCKS> m_blocks;
|
2019-10-17 14:40:07 +00:00
|
|
|
u32 m_current_block = 0; // block (0-5)
|
|
|
|
u32 m_current_coefficient = 64; // k (in block)
|
2019-10-06 15:04:20 +00:00
|
|
|
u16 m_current_q_scale = 0;
|
2019-10-12 12:47:00 +00:00
|
|
|
|
2019-10-17 14:40:07 +00:00
|
|
|
std::array<u32, 256> m_block_rgb{};
|
2020-01-24 04:53:40 +00:00
|
|
|
std::unique_ptr<TimingEvent> m_block_copy_out_event;
|
2019-10-17 14:40:07 +00:00
|
|
|
|
|
|
|
u32 m_total_blocks_decoded = 0;
|
|
|
|
};
|
2020-07-31 07:09:18 +00:00
|
|
|
|
|
|
|
extern MDEC g_mdec;
|