From 7535c6d9038684c2a27f7307dd4f2439829b5a2f Mon Sep 17 00:00:00 2001 From: Pierre Bourdon Date: Wed, 14 Nov 2012 06:15:55 +0100 Subject: [PATCH] Parse the AX command list in the AX thread --- .../Core/Src/HW/DSPHLE/UCodes/UCode_NewAX.cpp | 97 +++++++++++++++++-- .../Core/Src/HW/DSPHLE/UCodes/UCode_NewAX.h | 35 ++++++- 2 files changed, 119 insertions(+), 13 deletions(-) diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_NewAX.cpp b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_NewAX.cpp index 117dac63cb..31799f2675 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_NewAX.cpp +++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_NewAX.cpp @@ -20,7 +20,7 @@ CUCode_NewAX::CUCode_NewAX(DSPHLE* dsp_hle, u32 crc) : IUCode(dsp_hle, crc) - , m_cmdlist_addr(0) + , m_cmdlist_size(0) , m_axthread(&CUCode_NewAX::AXThread, this) { m_rMailHandler.PushMail(DSP_INIT); @@ -29,7 +29,7 @@ CUCode_NewAX::CUCode_NewAX(DSPHLE* dsp_hle, u32 crc) CUCode_NewAX::~CUCode_NewAX() { - m_cmdlist_addr = (u32)-1; // Special value to signal end + m_cmdlist_size = (u16)-1; // Special value to signal end NotifyAXThread(); m_axthread.join(); @@ -42,16 +42,16 @@ void CUCode_NewAX::AXThread() { { std::unique_lock lk(m_cmdlist_mutex); - while (m_cmdlist_addr == 0) + while (m_cmdlist_size == 0) m_cmdlist_cv.wait(lk); } - if (m_cmdlist_addr == (u32)-1) // End of thread signal + if (m_cmdlist_size == (u16)-1) // End of thread signal break; m_processing.lock(); - HandleCommandList(m_cmdlist_addr); - m_cmdlist_addr = 0; + HandleCommandList(); + m_cmdlist_size = 0; // Signal end of processing m_rMailHandler.PushMail(DSP_YIELD); @@ -66,15 +66,78 @@ void CUCode_NewAX::NotifyAXThread() m_cmdlist_cv.notify_one(); } -void CUCode_NewAX::HandleCommandList(u32 addr) +void CUCode_NewAX::HandleCommandList() { - WARN_LOG(DSPHLE, "TODO: HandleCommandList(%08x)", addr); + u16 pb_addr_hi, pb_addr_lo; + u32 pb_addr = 0; + + u32 curr_idx = 0; + bool end = false; + while (!end) + { + u16 cmd = m_cmdlist[curr_idx++]; + + switch (cmd) + { + + // A lot of these commands are unknown, or unused in this AX HLE. + // We still need to skip their arguments using "curr_idx += N". + + case CMD_STUDIO_ADDR: curr_idx += 2; break; + case CMD_UNK_01: curr_idx += 5; break; + + case CMD_PB_ADDR: + pb_addr_hi = m_cmdlist[curr_idx++]; + pb_addr_lo = m_cmdlist[curr_idx++]; + pb_addr = (pb_addr_hi << 16) | pb_addr_lo; + + WARN_LOG(DSPHLE, "PB addr: %08x", pb_addr); + break; + + case CMD_PROCESS: + ProcessPB(pb_addr); + break; + + case CMD_UNK_04: curr_idx += 4; break; + case CMD_UNK_05: curr_idx += 4; break; + case CMD_UNK_06: curr_idx += 2; break; + case CMD_SBUFFER_ADDR: curr_idx += 2; break; + case CMD_UNK_08: curr_idx += 10; break; // TODO: check + case CMD_UNK_09: curr_idx += 2; break; + case CMD_COMPRESSOR_TABLE_ADDR: curr_idx += 2; break; + case CMD_UNK_0B: break; // TODO: check other versions + case CMD_UNK_0C: break; // TODO: check other versions + case CMD_UNK_0D: curr_idx += 2; break; + case CMD_UNK_0E: curr_idx += 4; break; + + case CMD_END: + end = true; + break; + + case CMD_UNK_10: curr_idx += 4; break; + case CMD_UNK_11: curr_idx += 2; break; + case CMD_UNK_12: curr_idx += 1; break; + case CMD_UNK_13: curr_idx += 12; break; + + default: + ERROR_LOG(DSPHLE, "Unknown command in AX cmdlist: %04x", cmd); + end = true; + break; + } + } +} + +void CUCode_NewAX::ProcessPB(u32 pb_addr) +{ + NOTICE_LOG(DSPHLE, "TODO: process pb %08x", pb_addr); } void CUCode_NewAX::HandleMail(u32 mail) { // Indicates if the next message is a command list address. static bool next_is_cmdlist = false; + static u16 cmdlist_size = 0; + bool set_next_is_cmdlist = false; // Wait for DSP processing to be done before answering any mail. This is @@ -84,7 +147,7 @@ void CUCode_NewAX::HandleMail(u32 mail) if (next_is_cmdlist) { - m_cmdlist_addr = mail; + CopyCmdList(mail, cmdlist_size); NotifyAXThread(); } else if (m_UploadSetupInProgress) @@ -97,7 +160,7 @@ void CUCode_NewAX::HandleMail(u32 mail) m_rMailHandler.PushMail(DSP_RESUME); DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP); } - else if (mail == MAIL_NEWUCODE) + else if (mail == MAIL_NEW_UCODE) { soundStream->GetMixer()->SetHLEReady(false); m_UploadSetupInProgress = true; @@ -115,6 +178,7 @@ void CUCode_NewAX::HandleMail(u32 mail) { // A command list address is going to be sent next. set_next_is_cmdlist = true; + cmdlist_size = (u16)(mail & ~MAIL_CMDLIST_MASK); } else { @@ -125,6 +189,19 @@ void CUCode_NewAX::HandleMail(u32 mail) next_is_cmdlist = set_next_is_cmdlist; } +void CUCode_NewAX::CopyCmdList(u32 addr, u16 size) +{ + if (size >= (sizeof (m_cmdlist) / sizeof (u16))) + { + ERROR_LOG(DSPHLE, "Command list at %08x is too large: size=%d", addr, size); + return; + } + + for (u32 i = 0; i < size; ++i, addr += 2) + m_cmdlist[i] = HLEMemory_Read_U16(addr); + m_cmdlist_size = size; +} + void CUCode_NewAX::MixAdd(short* out_buffer, int nsamples) { // nsamples * 2 for left and right audio channel diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_NewAX.h b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_NewAX.h index a1f881bd38..92184fe38f 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_NewAX.h +++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_NewAX.h @@ -36,7 +36,7 @@ private: enum MailType { MAIL_RESUME = 0xCDD10000, - MAIL_NEWUCODE = 0xCDD10001, + MAIL_NEW_UCODE = 0xCDD10001, MAIL_RESET = 0xCDD10002, MAIL_CONTINUE = 0xCDD10003, @@ -45,9 +45,34 @@ private: MAIL_CMDLIST_MASK = 0xFFFF0000 }; + enum CmdType + { + CMD_STUDIO_ADDR = 0x00, + CMD_UNK_01 = 0x01, + CMD_PB_ADDR = 0x02, + CMD_PROCESS = 0x03, + CMD_UNK_04 = 0x04, + CMD_UNK_05 = 0x05, + CMD_UNK_06 = 0x06, + CMD_SBUFFER_ADDR = 0x07, + CMD_UNK_08 = 0x08, + CMD_UNK_09 = 0x09, + CMD_COMPRESSOR_TABLE_ADDR = 0x0A, + CMD_UNK_0B = 0x0B, + CMD_UNK_0C = 0x0C, + CMD_UNK_0D = 0x0D, + CMD_UNK_0E = 0x0E, + CMD_END = 0x0F, + CMD_UNK_10 = 0x10, + CMD_UNK_11 = 0x11, + CMD_UNK_12 = 0x12, + CMD_UNK_13 = 0x13, + }; + // Volatile because it's set by HandleMail and accessed in // HandleCommandList, which are running in two different threads. - volatile u32 m_cmdlist_addr; + volatile u16 m_cmdlist[512]; + volatile u32 m_cmdlist_size; std::thread m_axthread; @@ -56,12 +81,16 @@ private: std::condition_variable m_cmdlist_cv; std::mutex m_cmdlist_mutex; + // Copy a command list from memory to our temp buffer + void CopyCmdList(u32 addr, u16 size); + // Send a notification to the AX thread to tell him a new cmdlist addr is // available for processing. void NotifyAXThread(); void AXThread(); - void HandleCommandList(u32 addr); + void HandleCommandList(); + void ProcessPB(u32 pb_addr); }; #endif // !_UCODE_NEWAX_H