diff --git a/Source/Plugins/Plugin_DSP_HLE/Plugin_DSP_HLE.vcproj b/Source/Plugins/Plugin_DSP_HLE/Plugin_DSP_HLE.vcproj index a4d0349ad6..3b0d96237d 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Plugin_DSP_HLE.vcproj +++ b/Source/Plugins/Plugin_DSP_HLE/Plugin_DSP_HLE.vcproj @@ -570,6 +570,14 @@ RelativePath=".\Src\UCodes\UCode_CARD.h" > + + + + diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/DSPHandler.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/DSPHandler.cpp index 71df9f6020..897c687c0a 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/DSPHandler.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/DSPHandler.cpp @@ -21,6 +21,7 @@ CDSPHandler* CDSPHandler::m_pInstance = NULL; CDSPHandler::CDSPHandler() : m_pUCode(NULL), + m_lastUCode(NULL), m_bHalt(false), m_bAssertInt(false) { @@ -86,3 +87,23 @@ void CDSPHandler::SetUCode(u32 _crc) m_MailHandler.Clear(); m_pUCode = UCodeFactory(_crc, m_MailHandler); } + +// TODO do it better? +// Assumes that every odd call to this func is by the persistent ucode. +// Even callers are deleted. +void CDSPHandler::SwapUCode(u32 _crc) +{ + m_MailHandler.Clear(); + + if (m_lastUCode == NULL) + { + m_lastUCode = m_pUCode; + m_pUCode = UCodeFactory(_crc, m_MailHandler); + } + else + { + delete m_pUCode; + m_pUCode = m_lastUCode; + m_lastUCode = NULL; + } +} diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/DSPHandler.h b/Source/Plugins/Plugin_DSP_HLE/Src/DSPHandler.h index a6d9af8665..569f20f001 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/DSPHandler.h +++ b/Source/Plugins/Plugin_DSP_HLE/Src/DSPHandler.h @@ -32,6 +32,7 @@ public: void SendMailToDSP(u32 _uMail); IUCode* GetUCode(); void SetUCode(u32 _crc); + void SwapUCode(u32 _crc); CMailHandler& AccessMailHandler() { return m_MailHandler; } @@ -63,6 +64,8 @@ private: static CDSPHandler* m_pInstance; IUCode* m_pUCode; + IUCode* m_lastUCode; + UDSPControl m_DSPControl; CMailHandler m_MailHandler; diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/MailHandler.h b/Source/Plugins/Plugin_DSP_HLE/Src/MailHandler.h index 34a28a9038..6c025fe34e 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/MailHandler.h +++ b/Source/Plugins/Plugin_DSP_HLE/Src/MailHandler.h @@ -45,7 +45,7 @@ public: else { // WARN_LOG(DSPHLE, "GetNextMail: No mails"); - return 0; // + return 0; } } diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_GBA.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_GBA.cpp new file mode 100644 index 0000000000..fd8e72c7bb --- /dev/null +++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_GBA.cpp @@ -0,0 +1,157 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "../Globals.h" +#include "../DSPHandler.h" +#include "UCodes.h" +#include "UCode_GBA.h" + +CUCode_GBA::CUCode_GBA(CMailHandler& _rMailHandler) +: IUCode(_rMailHandler) +{ + m_rMailHandler.PushMail(DSP_INIT); +} + +CUCode_GBA::~CUCode_GBA() +{ + m_rMailHandler.Clear(); +} + +void CUCode_GBA::Update(int cycles) +{ + // check if we have to send something + if (!m_rMailHandler.IsEmpty()) + { + g_dspInitialize.pGenerateDSPInterrupt(); + } +} +#pragma optimize("", off) +void CUCode_GBA::HandleMail(u32 _uMail) +{ + static bool nextmail_is_mramaddr = false; + static bool calc_done = false; + + if (m_UploadSetupInProgress) + { + PrepareBootUCode(_uMail); + } + else if ((_uMail >> 16 == 0xabba) && !nextmail_is_mramaddr) + { + nextmail_is_mramaddr = true; + } + else if (nextmail_is_mramaddr) + { + nextmail_is_mramaddr = false; + u32 mramaddr = _uMail; + + struct sec_params_t { + u16 key[2]; + u16 unk1[2]; + u16 unk2[2]; + u32 length; + u32 dest_addr; + u32 pad[3]; + } sec_params; + + // 32 bytes from mram addr to dram @ 0 + for (int i = 0; i < 8; i++, mramaddr += 4) + ((u32*)&sec_params)[i] = Memory_Read_U32(mramaddr); + + // This is the main decrypt routine + u16 x11 = 0, x12 = 0, + x20 = 0, x21 = 0, x22 = 0, x23 = 0; + + x20 = ((sec_params.key[0] >> 8) | (sec_params.key[0] << 8)) ^ 0x6f64; + x21 = ((sec_params.key[1] >> 8) | (sec_params.key[1] << 8)) ^ 0x6573; + + s16 unk2 = (s8)sec_params.unk2[0]; + if (unk2 < 0) + { + x11 = ((~unk2 + 3) << 1) | (sec_params.unk1[0] << 4); + } + else if (unk2 == 0) + { + x11 = (sec_params.unk1[0] << 1) | 0x70; + } + else // unk2 > 0 + { + x11 = ((unk2 - 1) << 1) | (sec_params.unk1[0] << 4); + } + + s32 rounded_sub = ((sec_params.length + 7) & ~7) - 0x200; + u16 size = (rounded_sub < 0) ? 0 : rounded_sub >> 3; + + u32 t = ((size << 16) & 0x4000ffff) << 2; + u32 u = (((size << 16) | 0x3f80) & 0x3f80ffff) << 1; + t += u; + s16 u_low = (s8)(u >> 8); + t += (u_low & size) << 16; + x12 = t >> 16; + x11 |= (size & 0x4000) >> 14; // this would be stored in ac0.h if we weren't constrained to 32bit :) + t = ((x11 & 0xff) << 16) + ((x12 & 0xff) << 16) + (x12 << 8); + + u16 final11 = 0, final12 = 0; + final11 = x11 | ((t >> 8) & 0xff00) | 0x8080; + final12 = x12 | 0x8080; + + if ((final12 & 0x200) != 0) + { + x22 = final11 ^ 0x6f64; + x23 = final12 ^ 0x6573; + } + else + { + x22 = final11 ^ 0x6177; + x23 = final12 ^ 0x614b; + } + + // Send the result back to mram + *(u32*)Memory_Get_Pointer(sec_params.dest_addr) = Common::swap32((x20 << 16) | x21); + *(u32*)Memory_Get_Pointer(sec_params.dest_addr+4) = Common::swap32((x22 << 16) | x23); + + // Done! + WARN_LOG(DSPHLE, "\n%08x -> key %08x len %08x dest_addr %08x unk1 %08x unk2 %08x" + " 22 %04x 23 %04x", + mramaddr, + *(u32*)sec_params.key, sec_params.length, sec_params.dest_addr, + *(u32*)sec_params.unk1, *(u32*)sec_params.unk2, + x22, x23); + + calc_done = true; + m_rMailHandler.PushMail(DSP_DONE); + } + else if ((_uMail >> 16 == 0xcdd1) && calc_done) + { + switch (_uMail & 0xffff) + { + case 1: + m_UploadSetupInProgress = true; + break; + case 2: + CDSPHandler::GetInstance().SetUCode(UCODE_ROM); + break; + default: + DEBUG_LOG(DSPHLE, "CUCode_GBA - unknown 0xcdd1 cmd: %08x", _uMail); + break; + } + } + else + { + DEBUG_LOG(DSPHLE, "CUCode_GBA - unknown cmd: %08x", _uMail); + } +} +#pragma optimize("", on) \ No newline at end of file diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_GBA.h b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_GBA.h new file mode 100644 index 0000000000..9d4c02a512 --- /dev/null +++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_GBA.h @@ -0,0 +1,29 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#pragma once + +#include "UCodes.h" + +struct CUCode_GBA : public IUCode +{ + CUCode_GBA(CMailHandler& _rMailHandler); + virtual ~CUCode_GBA(); + + void HandleMail(u32 _uMail); + void Update(int cycles); +}; diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_InitAudioSystem.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_InitAudioSystem.cpp index 36e17a0552..23af66dd8f 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_InitAudioSystem.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_InitAudioSystem.cpp @@ -22,9 +22,6 @@ CUCode_InitAudioSystem::CUCode_InitAudioSystem(CMailHandler& _rMailHandler) : IUCode(_rMailHandler) - , m_BootTask_numSteps(0) - , m_NextParameter(0) - , IsInitialized(false) { DEBUG_LOG(DSPHLE, "CUCode_InitAudioSystem - initialized"); } diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_InitAudioSystem.h b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_InitAudioSystem.h index e73f3d399b..b174e94732 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_InitAudioSystem.h +++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_InitAudioSystem.h @@ -29,25 +29,6 @@ public: void HandleMail(u32 _uMail); void Update(int cycles); void Init(); - -private: - struct SUCode - { - u32 m_RAMAddress; - u32 m_Length; - u32 m_IMEMAddress; - u32 m_DMEMLength; - u32 m_StartPC; - }; - - SUCode m_CurrentUCode; - int m_BootTask_numSteps; - - u32 m_NextParameter; - - bool IsInitialized; - - void BootUCode(); }; #endif diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_ROM.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_ROM.cpp index 100c805e4e..c9cd67a842 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_ROM.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_ROM.cpp @@ -19,9 +19,11 @@ #include "../DSPHandler.h" #include "UCodes.h" #include "UCode_ROM.h" +#include "Hash.h" CUCode_Rom::CUCode_Rom(CMailHandler& _rMailHandler) : IUCode(_rMailHandler) + , m_CurrentUCode() , m_BootTask_numSteps(0) , m_NextParameter(0) { @@ -93,25 +95,19 @@ void CUCode_Rom::HandleMail(u32 _uMail) void CUCode_Rom::BootUCode() { - // simple non-scientific crc invented by ector :P - // too annoying to change now, and probably good enough anyway - u32 crc = 0; - for (u32 i = 0; i < m_CurrentUCode.m_Length; i++) - { - crc ^= Memory_Read_U8(m_CurrentUCode.m_RAMAddress + i); - //let's rol - crc = (crc << 3) | (crc >> 29); - } + u32 ector_crc = HashEctor( + (u8*)Memory_Get_Pointer(m_CurrentUCode.m_RAMAddress), + m_CurrentUCode.m_Length); DEBUG_LOG(DSPHLE, "CurrentUCode SOURCE Addr: 0x%08x", m_CurrentUCode.m_RAMAddress); DEBUG_LOG(DSPHLE, "CurrentUCode Length: 0x%08x", m_CurrentUCode.m_Length); DEBUG_LOG(DSPHLE, "CurrentUCode DEST Addr: 0x%08x", m_CurrentUCode.m_IMEMAddress); DEBUG_LOG(DSPHLE, "CurrentUCode DMEM Length: 0x%08x", m_CurrentUCode.m_DMEMLength); DEBUG_LOG(DSPHLE, "CurrentUCode init_vector: 0x%08x", m_CurrentUCode.m_StartPC); - DEBUG_LOG(DSPHLE, "CurrentUCode CRC: 0x%08x", crc); + DEBUG_LOG(DSPHLE, "CurrentUCode CRC: 0x%08x", ector_crc); DEBUG_LOG(DSPHLE, "BootTask - done"); - CDSPHandler::GetInstance().SetUCode(crc); + CDSPHandler::GetInstance().SetUCode(ector_crc); } diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_ROM.h b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_ROM.h index aa0c592a5d..4de00d2ff2 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_ROM.h +++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_ROM.h @@ -38,7 +38,6 @@ private: u32 m_DMEMLength; u32 m_StartPC; }; - SUCode m_CurrentUCode; int m_BootTask_numSteps; diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.cpp index 9db9cec783..065ebbe23b 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.cpp @@ -28,6 +28,8 @@ #include "Mixer.h" #include "WaveFile.h" +#include "../DSPHandler.h" + CUCode_Zelda::CUCode_Zelda(CMailHandler& _rMailHandler, u32 _CRC) : @@ -118,6 +120,12 @@ void CUCode_Zelda::Update(int cycles) if (m_rMailHandler.GetNextMail() == DSP_FRAME_END) g_dspInitialize.pGenerateDSPInterrupt(); } + + if (NeedsResumeMail()) + { + m_rMailHandler.PushMail(DSP_RESUME); + g_dspInitialize.pGenerateDSPInterrupt(); + } } void CUCode_Zelda::HandleMail(u32 _uMail) @@ -284,6 +292,13 @@ void CUCode_Zelda::HandleMail_SMSVersion(u32 _uMail) void CUCode_Zelda::HandleMail_NormalVersion(u32 _uMail) { // WARN_LOG(DSPHLE, "Zelda uCode: Handle mail %08X", _uMail); + + if (m_UploadSetupInProgress) // evaluated first! + { + PrepareBootUCode(_uMail); + return; + } + if (m_bSyncInProgress) { if (m_bSyncCmdPending) @@ -381,23 +396,31 @@ void CUCode_Zelda::HandleMail_NormalVersion(u32 _uMail) m_numSteps = _uMail; m_step = 0; } - else if ((_uMail >> 16) == 0xCDD1) // A 0xCDD1000X mail should come right after we send a DSP_SYNCEND mail + else if ((_uMail >> 16) == 0xCDD1) // A 0xCDD1000X mail should come right after we send a DSP_FRAME_END mail { // The low part of the mail tells the operation to perform // Seeing as every possible operation number halts the uCode, // except 3, that thing seems to be intended for debugging switch (_uMail & 0xFFFF) { - case 0x0003: // Do nothing + case 0x0003: // Do nothing - continue normally return; - case 0x0000: // Halt - case 0x0001: // Dump memory? and halt - case 0x0002: // Do something and halt + case 0x0001: // accepts params to either dma to iram and/or dram (used for hotbooting a new ucode) + // TODO find a better way to protect from HLEMixer? + soundStream->GetMixer()->SetHLEReady(false); + m_UploadSetupInProgress = true; + return; + + case 0x0002: // Let IROM play us off + CDSPHandler::GetInstance().SetUCode(UCODE_ROM); + return; + + case 0x0000: // Halt WARN_LOG(DSPHLE, "Zelda uCode: received halting operation %04X", _uMail & 0xFFFF); return; - default: // Invalid (the real ucode would likely crash) + default: // Invalid (the real ucode would likely crash) WARN_LOG(DSPHLE, "Zelda uCode: received invalid operation %04X", _uMail & 0xFFFF); return; } @@ -594,6 +617,8 @@ void CUCode_Zelda::DoState(PointerWrap &p) p.Do(m_PBAddress); p.Do(m_PBAddress2); + p.Do(m_UploadSetupInProgress); + m_rMailHandler.DoState(p); m_csMix.Leave(); diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.cpp index 2dfa8fbbcb..b71d739ea2 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.cpp @@ -25,6 +25,9 @@ #include "UCode_ROM.h" #include "UCode_CARD.h" #include "UCode_InitAudioSystem.h" +#include "UCode_GBA.h" +#include "Hash.h" +#include "../DSPHandler.h" IUCode* UCodeFactory(u32 _CRC, CMailHandler& _rMailHandler) { @@ -42,14 +45,18 @@ IUCode* UCodeFactory(u32 _CRC, CMailHandler& _rMailHandler) INFO_LOG(DSPHLE, "Switching to CARD ucode"); return new CUCode_CARD(_rMailHandler); + case 0xdd7e72d5: + INFO_LOG(DSPHLE, "Switching to GBA ucode"); + return new CUCode_GBA(_rMailHandler); + case 0x3ad3b7ac: // Naruto3, Paper Mario - The Thousand Year Door case 0x3daf59b9: // Alien Hominid case 0x4e8a8b21: // spdemo, ctaxi, 18 wheeler, disney, monkeyball 1/2,cubivore,puzzlecollection,wario, - // capcom vs snk, naruto2, lost kingdoms, star fox, mario party 4, mortal kombat, - // smugglers run warzone, smash brothers, sonic mega collection, ZooCube - // nddemo, starfox + // capcom vs snk, naruto2, lost kingdoms, star fox, mario party 4, mortal kombat, + // smugglers run warzone, smash brothers, sonic mega collection, ZooCube + // nddemo, starfox case 0x07f88145: // bustamove, ikaruga, fzero, robotech battle cry, star soldier, soul calibur2, - // Zelda:OOT, Tony hawk, viewtiful joe + // Zelda:OOT, Tony hawk, viewtiful joe case 0xe2136399: // billy hatcher, dragonballz, mario party 5, TMNT, ava1080 INFO_LOG(DSPHLE, "CRC %08x: AX ucode chosen", _CRC); return new CUCode_AX(_rMailHandler); @@ -103,4 +110,65 @@ IUCode* UCodeFactory(u32 _CRC, CMailHandler& _rMailHandler) return NULL; } +bool IUCode::NeedsResumeMail() +{ + if (m_NeedsResumeMail) + { + m_NeedsResumeMail = false; + return true; + } + return false; +} +void IUCode::PrepareBootUCode(u32 mail) +{ + switch (m_NextUCode_steps) + { + case 0: m_NextUCode.mram_dest_addr = mail; break; + case 1: m_NextUCode.mram_size = mail & 0xffff; break; + case 2: m_NextUCode.mram_dram_addr = mail & 0xffff; break; + case 3: m_NextUCode.iram_mram_addr = mail; break; + case 4: m_NextUCode.iram_size = mail & 0xffff; break; + case 5: m_NextUCode.iram_dest = mail & 0xffff; break; + case 6: m_NextUCode.iram_startpc = mail & 0xffff; break; + case 7: m_NextUCode.dram_mram_addr = mail; break; + case 8: m_NextUCode.dram_size = mail & 0xffff; break; + case 9: m_NextUCode.dram_dest = mail & 0xffff; break; + } + m_NextUCode_steps++; + + if (m_NextUCode_steps == 10) + { + m_NextUCode_steps = 0; + m_NeedsResumeMail = true; + m_UploadSetupInProgress = false; + + u32 ector_crc = HashEctor( + (u8*)Memory_Get_Pointer(m_NextUCode.iram_mram_addr), + m_NextUCode.iram_size); + + DEBUG_LOG(DSPHLE, "PrepareBootUCode 0x%08x", ector_crc); + DEBUG_LOG(DSPHLE, "DRAM -> MRAM: src %04x dst %08x size %04x", + m_NextUCode.mram_dram_addr, m_NextUCode.mram_dest_addr, + m_NextUCode.mram_size); + DEBUG_LOG(DSPHLE, "MRAM -> IRAM: src %08x dst %04x size %04x startpc %04x", + m_NextUCode.iram_mram_addr, m_NextUCode.iram_dest, + m_NextUCode.iram_size, m_NextUCode.iram_startpc); + DEBUG_LOG(DSPHLE, "MRAM -> DRAM: src %08x dst %04x size %04x", + m_NextUCode.dram_mram_addr, m_NextUCode.dram_dest, + m_NextUCode.dram_size); + + if (m_NextUCode.mram_size) + { + WARN_LOG(DSPHLE, + "Trying to boot new ucode with dram download - not implemented"); + } + if (m_NextUCode.dram_size) + { + WARN_LOG(DSPHLE, + "Trying to boot new ucode with dram upload - not implemented"); + } + + CDSPHandler::GetInstance().SwapUCode(ector_crc); + } +} \ No newline at end of file diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.h b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.h index 1a3293d5bb..3e0af4c688 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.h +++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.h @@ -32,6 +32,10 @@ class IUCode public: IUCode(CMailHandler& _rMailHandler) : m_rMailHandler(_rMailHandler) + , m_NextUCode_steps(0) + , m_NextUCode() + , m_NeedsResumeMail(false) + , m_UploadSetupInProgress(false) {} virtual ~IUCode() @@ -46,6 +50,13 @@ public: virtual void DoState(PointerWrap &p) {} protected: + void PrepareBootUCode(u32 mail); + + // Some ucodes (notably zelda) require a resume mail to be + // sent if they are be started via PrepareBootUCode. + // The HLE can use this to + bool NeedsResumeMail(); + CMailHandler& m_rMailHandler; Common::CriticalSection m_csMix; @@ -58,6 +69,29 @@ protected: DSP_SYNC = 0xDCD10004, DSP_FRAME_END = 0xDCD10005, }; + + // UCode is forwarding mails to PrepareBootUCode + // UCode only needs to set this to true, IUCode will set to false when done! + bool m_UploadSetupInProgress; + +private: + struct SUCode + { + u32 mram_dest_addr; + u16 mram_size; + u16 mram_dram_addr; + u32 iram_mram_addr; + u16 iram_size; + u16 iram_dest; + u16 iram_startpc; + u32 dram_mram_addr; + u16 dram_size; + u16 dram_dest; + }; + SUCode m_NextUCode; + int m_NextUCode_steps; + + bool m_NeedsResumeMail; }; extern IUCode* UCodeFactory(u32 _CRC, CMailHandler& _rMailHandler); diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/DSPHost.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/DSPHost.cpp index 3f9b387baa..0363b533b7 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/DSPHost.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/DSPHost.cpp @@ -92,6 +92,7 @@ u32 DSPHost_CodeLoaded(const u8 *ptr, int size) case 0x3daf59b9: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_D9D066EA.txt"); break; case 0x4e8a8b21: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_6A696CE7.txt"); break; case 0xe2136399: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_EB79C705.txt"); break; + case 0xdd7e72d5: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_3B3B30CA.txt"); break; default: success = false; break; } diff --git a/docs/DSP/DSP_UC_3B3B30CA.txt b/docs/DSP/DSP_UC_3B3B30CA.txt index f5d899f435..0daa70dd11 100644 --- a/docs/DSP/DSP_UC_3B3B30CA.txt +++ b/docs/DSP/DSP_UC_3B3B30CA.txt @@ -1,56 +1,74 @@ -/* +/////////////////////////////////////////////////////////////////////////////// ROM functions used: -0x8000 dsp reset -0x8078 wait for CMBH & 0x8000 -0x807e wait for DMBH & 0x8000 -0x808b dump DRAM/IRAM to mainmem -0x80b5 boot new ucode -0x80bc boot new ucode without ACC clearing by ROM +0x8000 dsp reset +0x8078 wait for CMBH & 0x8000 +0x807e wait for DMBH & 0x8000 +0x808b dump DRAM/IRAM to mainmem +0x80b5 boot new ucode +0x80bc boot new ucode without ACC clearing by ROM For the rest, this ucode is just calling the last few instructions -from huge functions in ROM - some kind of obfuscation? +from huge functions in irom - some kind of obfuscation +Perhaps someone thought the irom would never be dumped? ;p -0x81f4 - 81f4 b51e mulxac'mv $AX0.H, $AX1.L, $ACC1 : $AX1.H, $AC0.M - 81f5 9909 asr16'ir $ACC1 : $AR1 - 81f6 1b7f srri @$AR3, $AC1.M - 81f7 812b clr's $ACC0 : @$AR3, $AC1.L -0x8458 - 8458 b51e mulxac'mv $AX0.H, $AX1.L, $ACC1 : $AX1.H, $AC0.M - 8459 9900 asr16 $ACC1 - 845a 1b7f srri @$AR3, $AC1.M - 845b 812b clr's $ACC0 : @$AR3, $AC1.L -0x8723 - 8723 3300 xorr $AC1.M, $AX1.H - 8724 1adf srrd @$AR2, $AC1.M -0x8809 - 8809 392e orr'sn $AC1.M, $AX0.H : @$AR2, $AC1.L - 880a 1b5f srri @$AR2, $AC1.M -0x88e5 - 88e5 387a orr'l $AC0.M, $AX0.H : $AC1.M, @$AR2 - 88e6 18dd lrrd $AC1.L, @$AR2 - 88e7 4c05 add'dr $ACC0, $ACC1 : $AR1 - 88e8 1b5e srri @$AR2, $AC0.M - 88e9 1a5c srr @$AR2, $AC0.L -*/ +Similarly, drom is used pretty extensively as a source of what is intended to +be "mystery" numbers. Usually a word will be fetched, and masked to create a +simple value. No problem! :) -0000 0000 nop -0001 0000 nop -0002 0000 nop -0003 0000 nop -0004 0000 nop -0005 0000 nop -0006 0000 nop -0007 0000 nop -0008 0000 nop -0009 0000 nop -000a 0000 nop -000b 0000 nop -000c 0000 nop -000d 0021 halt -000e 02ff rti -000f 0021 halt +0x81f4 + mulxac'mv $AX0.H, $AX1.L, $ACC1 : $AX1.H, $AC0.M + asr16'ir $ACC1 : $AR1 + srri @$AR3, $AC1.M + clr's $ACC0 : @$AR3, $AC1.L +0x8458 + mulxac'mv $AX0.H, $AX1.L, $ACC1 : $AX1.H, $AC0.M + asr16 $ACC1 + srri @$AR3, $AC1.M + clr's $ACC0 : @$AR3, $AC1.L +0x8723 + xorr $AC1.M, $AX1.H + srrd @$AR2, $AC1.M +0x8809 + orr'sn $AC1.M, $AX0.H : @$AR2, $AC1.L + srri @$AR2, $AC1.M +0x88e5 + orr'l $AC0.M, $AX0.H : $AC1.M, @$AR2 + lrrd $AC1.L, @$AR2 + add'dr $ACC0, $ACC1 : $AR1 + srri @$AR2, $AC0.M + srr @$AR2, $AC0.L +struct sec_params_t +{ + u32 key; // from gba + u32 unk1; // normally 2 + u32 unk2; // normally 2 + u32 length; // size of data transferred to gba + u32 dest_addr; // addr to store result in mram + u32 pad[3]; +} + +// exception vector +0000 0000 nop +0001 0000 nop +0002 0000 nop +0003 0000 nop +0004 0000 nop +0005 0000 nop +0006 0000 nop +0007 0000 nop +0008 0000 nop +0009 0000 nop +000a 0000 nop +000b 0000 nop +000c 0000 nop +000d 0021 halt +000e 02ff rti +000f 0021 halt + +// entry point +void 0010_main() +{ 0010 1306 sbset #0x06 0011 1203 sbclr #0x03 0012 1204 sbclr #0x04 @@ -60,42 +78,42 @@ from huge functions in ROM - some kind of obfuscation? 0018 0089 ffff lri $WR1, #0xffff 001a 008a ffff lri $WR2, #0xffff 001c 008b ffff lri $WR3, #0xffff -001e 8f00 set40 -001f 8b00 m0 -0020 8c00 clr15 -0021 02bf 807e call 0x807e // loop until dsp->cpu mailbox is empty +001e 8f00 set40 +001f 8b00 m0 +0020 8c00 clr15 +0021 02bf 807e call 0x807e // loop until dsp->cpu mailbox is empty 0023 16fc dcd1 si @DMBH, #0xdcd1 -0025 16fd 0000 si @DMBL, #0x0000 // sendmail 0xdcd10000 +0025 16fd 0000 si @DMBL, #0x0000 // sendmail 0xdcd10000 0027 16fb 0001 si @DIRQ, #0x0001 // wait for cpu mail == 0xabbaxxxx -0029 02bf 8078 call 0x8078 // wait for cpu mail +0029 02bf 8078 call 0x8078 // wait for cpu mail 002b 24ff lrs $AC0.L, @CMBL 002c 0280 abba cmpi $AC0.M, #0xabba 002e 0294 0029 jnz 0x0029 // wait for cpu mail -0030 8e00 set16 +0030 8e00 set16 0031 02bf 8078 call 0x8078 0033 20ff lrs $AX0.L, @CMBL 0034 0240 0fff andi $AC0.M, #0x0fff -0036 1f5e mrr $AX0.H, $AC0.M -0037 009b 0000 lri $AX1.H, #0x0000 // DSP-dram addr -0039 0099 0020 lri $AX1.L, #0x0020 // length (20 bytes = 10 words, word 9 and 10 are addr where result should DMA'd to in main mem) -003b 0087 0000 lri $IX3, #0x0000 // there will be no ucode/iram upload -003d 0080 0041 lri $AR0, #0x0041 // return addr after dram upload -003f 029f 80bc jmp 0x80bc // DRAM upload !! +0036 1f5e mrr $AX0.H, $AC0.M +0037 009b 0000 lri $AX1.H, #0x0000 // DSP-dram addr +0039 0099 0020 lri $AX1.L, #0x0020 // length (20 bytes = 10 words, word 9 and 10 are addr where result should DMA'd to in main mem) +003b 0087 0000 lri $IX3, #0x0000 // there will be no ucode/iram upload +003d 0080 0041 lri $AR0, #0x0041 // return addr after dram upload +003f 029f 80bc jmp 0x80bc // DRAM upload !! // $AX0.H-$AX0.L - CPU(PPC) addr = mail & 0x0fffffff // upload data from mainmem do dsp dram and jump to 0x41 after that -0041 02bf 008c call 008c_BigCrazyFunction() // <<------------- main crap is here!!!!!!!!! -0043 02bf 807e call 0x807e // loop until dsp->cpu mailbox is empty +0041 02bf 008c call 008c_BigCrazyFunction() +0043 02bf 807e call 0x807e // loop until dsp->cpu mailbox is empty 0045 16fc dcd1 si @DMBH, #0xdcd1 -0047 16fd 0003 si @DMBL, #0x0003 // sendmail 0xdcd10003 (aka... calc is over, result is in main mem now) +0047 16fd 0003 si @DMBL, #0x0003 // sendmail 0xdcd10003 (aka... calc is over, result is in main mem now) 0049 16fb 0001 si @DIRQ, #0x0001 -004b 8f00 set40 +004b 8f00 set40 004c 02bf 8078 call 0x8078 004e 0280 cdd1 cmpi $AC0.M, #0xcdd1 @@ -103,334 +121,378 @@ from huge functions in ROM - some kind of obfuscation? 0052 26ff lrs $AC0.M, @CMBL 0053 0280 0001 cmpi $AC0.M, #0x0001 -0055 0295 005e jz 0x005e // if cpu->dsp mail was 0xcdd10001 -> 005e_PrepareBootUcode() +0055 0295 005e jz 0x005e // if cpu->dsp mail was 0xcdd10001 -> 005e_PrepareBootUcode() 0057 0280 0002 cmpi $AC0.M, #0x0002 -0059 0295 8000 jz 0x8000 // if cpu->dsp mail was 0xcdd10002 -> dsp reset ( jmp to irom(0x8000)) +0059 0295 8000 jz 0x8000 // if cpu->dsp mail was 0xcdd10002 -> dsp reset ( jmp to irom(0x8000)) -005b 029f 004c jmp 0x004c // wait for next mail from cpu -005d 0021 halt +005b 029f 004c jmp 0x004c // wait for next mail from cpu +005d 0021 halt +} -void 005e_PrepareBootUcode() -{ -005e 8e00 set16 -005f 02bf 8078 call 0x8078 // wait for cpu mail -0061 24ff lrs $AC0.L, @CMBL -0062 02bf 8078 call 0x8078 // wait for cpu mail -0064 24ff lrs $AC0.L, @CMBL -0065 02bf 8078 call 0x8078 // wait for cpu mail -0067 24ff lrs $AC0.L, @CMBL -0068 02bf 8078 call 0x8078 // wait for cpu mail +void 005e_PrepareBootUcode() +{ +005e 8e00 set16 +005f 02bf 8078 call 0x8078 +0061 24ff lrs $AC0.L, @CMBL // ??? +0062 02bf 8078 call 0x8078 +0064 24ff lrs $AC0.L, @CMBL // ??? +0065 02bf 8078 call 0x8078 +0067 24ff lrs $AC0.L, @CMBL // ??? +0068 02bf 8078 call 0x8078 006a 00c5 ffff lr $IX1, @CMBL 006c 0240 0fff andi $AC0.M, #0x0fff -006e 1c9e mrr $IX0, $AC0.M -006f 02bf 8078 call 0x8078 // wait for cpu mail -0071 00c7 ffff lr $IX3, @CMBL -0073 02bf 8078 call 0x8078 // wait for cpu mail -0075 00c6 ffff lr $IX2, @CMBL -0077 02bf 8078 call 0x8078 // wait for cpu mail -0079 00c0 ffff lr $AR0, @CMBL -007b 02bf 8078 call 0x8078 // wait for cpu mail +006e 1c9e mrr $IX0, $AC0.M // mram addr for iram +006f 02bf 8078 call 0x8078 +0071 00c7 ffff lr $IX3, @CMBL // iram upload length. upload skipped if 0 +0073 02bf 8078 call 0x8078 +0075 00c6 ffff lr $IX2, @CMBL // iram dest +0077 02bf 8078 call 0x8078 +0079 00c0 ffff lr $AR0, @CMBL // startpc / return addr +007b 02bf 8078 call 0x8078 007d 20ff lrs $AX0.L, @CMBL 007e 0240 0fff andi $AC0.M, #0x0fff -0080 1f5e mrr $AX0.H, $AC0.M -0081 02bf 8078 call 0x8078 // wait for cpu mail -0083 21ff lrs $AX1.L, @CMBL -0084 02bf 8078 call 0x8078 // wait for cpu mail -0086 23ff lrs $AX1.H, @CMBL +0080 1f5e mrr $AX0.H, $AC0.M // mram addr for dram +0081 02bf 8078 call 0x8078 +0083 21ff lrs $AX1.L, @CMBL // dram upload length. upload skipped if 0 +0084 02bf 8078 call 0x8078 +0086 23ff lrs $AX1.H, @CMBL // dram dest 0087 1205 sbclr #0x05 0088 1206 sbclr #0x06 0089 029f 80b5 jmp 80b5_BootUcode() -008b 0021 halt +008b 0021 halt } // does some crazy stuff with data at dram @0x3/0x5/0x6/0x7 with help of some values from drom :) // result is @0x22,@0x23 and written back to main memory to dmem-0x08:dmem-0x09 -void 008c_BigCrazyFunction() +void 008c_BigCrazyFunction() { -008c 8100 clr $ACC0 -008d 0081 0010 lri $AR1, #0x0010 -008f 1020 loopi #0x20 - 0090 1b3e srri @$AR1, $AC0.M -0091 00df 1456 lr $AC1.M, @0x1456 -0093 0340 ffd0 andi $AC1.M, #0xffd0 -0095 8417 clrp'mv : $AX1.L, $AC1.M -0096 0080 0000 lri $AR0, #0x0000 -0098 0086 0000 lri $IX2, #0x0000 -009a 0082 001f lri $AR2, #0x001f -009c 00de 15f6 lr $AC0.M, @0x15f6 -009e 1408 lsl $ACC0, #8 -009f 00df 1766 lr $AC1.M, @0x1766 -00a1 0340 00ff andi $AC1.M, #0x00ff -00a3 1f5f mrr $AX0.H, $AC1.M -00a4 02bf 88e5 call 0x88e5 - 88e5 387a orr'l $AC0.M, $AX0.H : $AC1.M, @$AR2 - 88e6 18dd lrrd $AC1.L, @$AR2 - 88e7 4c05 add'dr $ACC0, $ACC1 : $AR1 - 88e8 1b5e srri @$AR2, $AC0.M - 88e9 1a5c srr @$AR2, $AC0.L -00a6 1f1c mrr $AX0.L, $AC0.L -00a7 811e clr'mv $ACC0 : $AX1.H, $AC0.M -00a8 191e lrri $AC0.M, @$AR0 -00a9 1478 lsr $ACC0, #-8 -00aa 1ffc mrr $AC1.M, $AC0.L -00ab 1f5e mrr $AX0.H, $AC0.M -00ac 02bf 8809 call 0x8809 - 8809 392e orr'sn $AC1.M, $AX0.H : @$AR2, $AC1.L - 880a 1b5f srri @$AR2, $AC1.M -00ae 02bf 8723 call 0x8723 - 8723 3300 xorr $AC1.M, $AX1.H - 8724 1adf srrd @$AR2, $AC1.M -00b0 0006 dar $AR2 -00b1 8106 clr'dr $ACC0 : $AR2 -00b2 00de 166c lr $AC0.M, @0x166c -00b4 1404 lsl $ACC0, #4 -00b5 0240 ff00 andi $AC0.M, #0xff00 -00b7 00df 1231 lr $AC1.M, @0x1231 -00b9 1578 lsr $ACC1, #-8 -00ba 0340 00ff andi $AC1.M, #0x00ff -00bc 1f5f mrr $AX0.H, $AC1.M -00bd 02bf 88e5 call 0x88e5 - 88e5 387a orr'l $AC0.M, $AX0.H : $AC1.M, @$AR2 - 88e6 18dd lrrd $AC1.L, @$AR2 - 88e7 4c05 add'dr $ACC0, $ACC1 : $AR1 - 88e8 1b5e srri @$AR2, $AC0.M - 88e9 1a5c srr @$AR2, $AC0.L -00bf 1f1c mrr $AX0.L, $AC0.L -00c0 811e clr'mv $ACC0 : $AX1.H, $AC0.M -00c1 191e lrri $AC0.M, @$AR0 -00c2 1478 lsr $ACC0, #-8 -00c3 1ffc mrr $AC1.M, $AC0.L -00c4 1f5e mrr $AX0.H, $AC0.M -00c5 02bf 8809 call 0x8809 - 8809 392e orr'sn $AC1.M, $AX0.H : @$AR2, $AC1.L - 880a 1b5f srri @$AR2, $AC1.M -00c7 02bf 8723 call 0x8723 - 8723 3300 xorr $AC1.M, $AX1.H - 8724 1adf srrd @$AR2, $AC1.M -00c9 8100 clr $ACC0 -00ca 8900 clr $ACC1 -00cb 00d1 0005 lr $AC1.H, @0x0005 -00cd 9900 asr16 $ACC1 -00ce 8200 cmp -00cf 0295 00e5 jz 0x00e5 +// 008c 8100 clr $ACC0 +// 008d 0081 0010 lri $AR1, #0x0010 +// 008f 1020 loopi #0x20 +// 0090 1b3e srri @$AR1, $AC0.M + memset(0x10, 0, 0x20 * sizeof(dsp_word)); -00d1 0291 00f3 jl 0x00f3 +// 0091 00df 1456 lr $AC1.M, @0x1456 // drom 102f +// 0093 0340 ffd0 andi $AC1.M, #0xffd0 // -> 0x1000 +// 0095 8417 clrp'mv : $AX1.L, $AC1.M // clrp, ax1.l = 0x1000 + IMPORTANT: "confusing" section relies on prod being cleared, and ax1.l == 0x1000 -00d3 0082 0010 lri $AR2, #0x0010 -00d5 0086 0001 lri $IX2, #0x0001 -00d7 00d0 171b lr $AC0.H, @0x171b -00d9 9100 asr16 $ACC0 -00da 7d00 neg $ACC1 -00db 4d00 add $ACC1, $ACC0 -00dc 1501 lsl $ACC1, #1 -00dd 1f5f mrr $AX0.H, $AC1.M -00de 00df 0003 lr $AC1.M, @0x0003 -00e0 1504 lsl $ACC1, #4 -00e1 02bf 8809 call 0x8809 - 8809 392e orr'sn $AC1.M, $AX0.H : @$AR2, $AC1.L - 880a 1b5f srri @$AR2, $AC1.M -00e3 029f 0102 jmp 0x0102 +// 0096 0080 0000 lri $AR0, #0x0000 +// 0098 0086 0000 lri $IX2, #0x0000 +// 009a 0082 001f lri $AR2, #0x001f +// 009c 00de 15f6 lr $AC0.M, @0x15f6 // drom 7f65 +// 009e 1408 lsl $ACC0, #8 // -> 0x7f_6500 +// 009f 00df 1766 lr $AC1.M, @0x1766 // drom 0273 +// 00a1 0340 00ff andi $AC1.M, #0x00ff // -> 0x73 +// 00a3 1f5f mrr $AX0.H, $AC1.M // ax0.h = 0x73 +// 00a4 02bf 88e5 call 0x88e5 // ar2 = 0x1f, ar1 = 0x30 +// orr'l $AC0.M, $AX0.H : $AC1.M, @$AR2 // acc0 = 0x7f_6573, ac1.m = 0, ar2 = 0x20 +// lrrd $AC1.L, @$AR2 // ac1.l = 0, ar2 = 0x1f +// add'dr $ACC0, $ACC1 : $AR1 +// srri @$AR2, $AC0.M // *0x1f = 0x6573, ar2 = 0x20 +// srr @$AR2, $AC0.L // *0x20 = 0 +// 00a6 1f1c mrr $AX0.L, $AC0.L // ax0.l = 0 +// 00a7 811e clr'mv $ACC0 : $AX1.H, $AC0.M // acc0 = 0, ax1.h = 0x6573 +// 00a8 191e lrri $AC0.M, @$AR0 // ac0.m = sec_params.key[0], ar1 = 1 +// 00a9 1478 lsr $ACC0, #-8 // acc0 0x00_00.._..00 +// 00aa 1ffc mrr $AC1.M, $AC0.L // ac1.m = sec_params.key[0] & 0x00ff +// 00ab 1f5e mrr $AX0.H, $AC0.M // ax0.h = sec_params.key[0] >> 8 +// 00ac 02bf 8809 call 0x8809 +// orr'sn $AC1.M, $AX0.H : @$AR2, $AC1.L // ac1.m |= ax0.h ..tricky tricky :D +// srri @$AR2, $AC1.M // *0x20 = bswap(sec_params.key[0]), ar2 = 0x21 +// 00ae 02bf 8723 call 0x8723 +// xorr $AC1.M, $AX1.H // ac1.m = sec_params.key[0] ^ 0x6573 +// srrd @$AR2, $AC1.M // *0x21 = bswap(sec_params.key[0]) ^ 0x6573, ar2 = 0x20 + // Initialize 0x21 + *0x1f = 0x6573 + *0x20 = bswap(sec_params.key[0]) + *0x21 = bswap(sec_params.key[0]) ^ 0x6573 -: -00e5 0082 0011 lri $AR2, #0x0011 -00e7 00df 0003 lr $AC1.M, @0x0003 -00e9 1501 lsl $ACC1, #1 -00ea 1f5f mrr $AX0.H, $AC1.M -00eb 00de 1043 lr $AC0.M, @0x1043 -00ed 0240 fff0 andi $AC0.M, #0xfff0 -00ef 02bf 88e5 call 0x88e5 - 88e5 387a orr'l $AC0.M, $AX0.H : $AC1.M, @$AR2 - 88e6 18dd lrrd $AC1.L, @$AR2 - 88e7 4c05 add'dr $ACC0, $ACC1 : $AR1 - 88e8 1b5e srri @$AR2, $AC0.M - 88e9 1a5c srr @$AR2, $AC0.L -00f1 029f 0102 jmp 0x0102 +// 00b0 0006 dar $AR2 // ar2 = 0x1f +// 00b1 8106 clr'dr $ACC0 : $AR2 // acc0 = 0, ar2 = 0x1e +// 00b2 00de 166c lr $AC0.M, @0x166c // drom 06f2 +// 00b4 1404 lsl $ACC0, #4 +// 00b5 0240 ff00 andi $AC0.M, #0xff00 // -> 0x6f00 +// 00b7 00df 1231 lr $AC1.M, @0x1231 // drom 64fc +// 00b9 1578 lsr $ACC1, #-8 +// 00ba 0340 00ff andi $AC1.M, #0x00ff // -> 0x64 +// 00bc 1f5f mrr $AX0.H, $AC1.M // ax0.h = 0x64 +// 00bd 02bf 88e5 call 0x88e5 +// orr'l $AC0.M, $AX0.H : $AC1.M, @$AR2 // ac0.m = 0x6f64, ac1.m = 0, ar2 = 0x1f +// lrrd $AC1.L, @$AR2 // ac1.l = 0x6573, ar2 = 0x1e +// add'dr $ACC0, $ACC1 : $AR1 // acc0 = 0x00_6f64_6573 +// srri @$AR2, $AC0.M // *0x1e = 0x6f64, ar2 = 0x1f +// srr @$AR2, $AC0.L // *0x1f = 0x6573 +// 00bf 1f1c mrr $AX0.L, $AC0.L +// 00c0 811e clr'mv $ACC0 : $AX1.H, $AC0.M // acc0 = 0, ax1.h = 0x6f64 +// 00c1 191e lrri $AC0.M, @$AR0 // ac0.m = sec_params.key[1] +// 00c2 1478 lsr $ACC0, #-8 // acc0 = 0x00_00.._..00 +// 00c3 1ffc mrr $AC1.M, $AC0.L // ac1.m = sec_params.key[1] & 0xff +// 00c4 1f5e mrr $AX0.H, $AC0.M // ax0.h = sec_params.key[1] >> 8 +// 00c5 02bf 8809 call 0x8809 +// orr'sn $AC1.M, $AX0.H : @$AR2, $AC1.L // ac1.m |= ax0.h +// srri @$AR2, $AC1.M // *0x1f = bswap(sec_params.key[1]), ar2 = 0x20 +// 00c7 02bf 8723 call 0x8723 +// xorr $AC1.M, $AX1.H +// srrd @$AR2, $AC1.M // *0x20 = bswap(sec_params.key[1]) ^ 0x6f64 + // Initialize 0x20 + *0x1e = 0x6f64 + *0x1f = bswap(sec_params.key[1]) + *0x20 = bswap(sec_params.key[1]) ^ 0x6f64 -: -00f3 0082 0010 lri $AR2, #0x0010 -00f5 0086 0001 lri $IX2, #0x0001 -00f7 00d0 1285 lr $AC0.H, @0x1285 -00f9 9100 asr16 $ACC0 -00fa 4d00 add $ACC1, $ACC0 -00fb 1501 lsl $ACC1, #1 -00fc 00de 0003 lr $AC0.M, @0x0003 -00fe 1404 lsl $ACC0, #4 -00ff 1f5e mrr $AX0.H, $AC0.M -0100 02bf 8809 call 0x8809 - 8809 392e orr'sn $AC1.M, $AX0.H : @$AR2, $AC1.L - 880a 1b5f srri @$AR2, $AC1.M + // Initialize 0x11 +// 00c9 8100 clr $ACC0 +// 00ca 8900 clr $ACC1 +// 00cb 00d1 0005 lr $AC1.H, @0x0005 +// 00cd 9900 asr16 $ACC1 // s16 unk2 = (s8)(sec_params.unk2[1]) +// 00ce 8200 cmp +// 00cf 0295 00e5 jz 0x00e5 +// 00d1 0291 00f3 jl 0x00f3 +if (unk2 < 0) { + // 00d3 0082 0010 lri $AR2, #0x0010 + // 00d5 0086 0001 lri $IX2, #0x0001 // 'sn will inc ar2 by 1 + // 00d7 00d0 171b lr $AC0.H, @0x171b // drom ff03 + // 00d9 9100 asr16 $ACC0 // -> 0x00_0003_0000 + // 00da 7d00 neg $ACC1 + // 00db 4d00 add $ACC1, $ACC0 + // 00dc 1501 lsl $ACC1, #1 + // 00dd 1f5f mrr $AX0.H, $AC1.M // ax0.h = ((~unk2 + 3) << 1) & 0xffff + // 00de 00df 0003 lr $AC1.M, @0x0003 // sec_params.unk1[1] + // 00e0 1504 lsl $ACC1, #4 + // 00e1 02bf 8809 call 0x8809 + // orr'sn $AC1.M, $AX0.H : @$AR2, $AC1.L // ac1.m = (((~unk2 + 3) << 1) & 0xffff) | (sec_params.unk1[1] << 4), ar2 = 0x11 + // srri @$AR2, $AC1.M + // 00e3 029f 0102 jmp 0x0102 + *0x11 = (((~unk2 + 3) << 1) | (sec_params.unk1[1] << 4)) & 0xffff -: -0102 0083 0013 lri $AR3, #0x0013 -0104 1b7e srri @$AR3, $AC0.M -0105 8923 clr's $ACC1 : @$AR3, $AC0.L -0106 0083 0013 lri $AR3, #0x0013 -0108 00df 0007 lr $AC1.M, @0x0007 -010a 00de 11b8 lr $AC0.M, @0x11b8 -010c 0240 fff0 andi $AC0.M, #0xfff0 -010e 1f5e mrr $AX0.H, $AC0.M -010f 02bf 81f4 call 0x81f4 - 81f4 b51e mulxac'mv $AX0.H, $AX1.L, $ACC1 : $AX1.H, $AC0.M - 81f5 9909 asr16'ir $ACC1 : $AR1 - 81f6 1b7f srri @$AR3, $AC1.M - 81f7 812b clr's $ACC0 : @$AR3, $AC1.L -0111 f100 lsl16 $ACC1 -0112 02bf 8458 call 0x8458 - 8458 b51e mulxac'mv $AX0.H, $AX1.L, $ACC1 : $AX1.H, $AC0.M - 8459 9900 asr16 $ACC1 - 845a 1b7f srri @$AR3, $AC1.M - 845b 812b clr's $ACC0 : @$AR3, $AC1.L -0114 8f00 set40 -0115 0082 0015 lri $AR2, #0x0015 -0117 00de 0006 lr $AC0.M, @0x0006 -0119 00da 165b lr $AX0.H, @0x165b -011b 02bf 88e5 call 0x88e5 - 88e5 387a orr'l $AC0.M, $AX0.H : $AC1.M, @$AR2 - 88e6 18dd lrrd $AC1.L, @$AR2 - 88e7 4c05 add'dr $ACC0, $ACC1 : $AR1 - 88e8 1b5e srri @$AR2, $AC0.M - 88e9 1a5c srr @$AR2, $AC0.L -011d 14fd asr $ACC0, #-3 -011e 1403 lsl $ACC0, #3 -011f 1b5e srri @$AR2, $AC0.M -0120 1b5c srri @$AR2, $AC0.L -0121 0082 0016 lri $AR2, #0x0016 -0123 00de 1723 lr $AC0.M, @0x1723 -0125 14f4 asr $ACC0, #-12 -0126 00da 166b lr $AX0.H, @0x166b -0128 02bf 88e5 call 0x88e5 - 88e5 387a orr'l $AC0.M, $AX0.H : $AC1.M, @$AR2 - 88e6 18dd lrrd $AC1.L, @$AR2 - 88e7 4c05 add'dr $ACC0, $ACC1 : $AR1 - 88e8 1b5e srri @$AR2, $AC0.M - 88e9 1a5c srr @$AR2, $AC0.L -012a b100 tst $ACC0 -012b 0290 012e jge 0x012e +} else if (unk2 == 0) { + // unk2 is unused + // 00e5 0082 0011 lri $AR2, #0x0011 + // 00e7 00df 0003 lr $AC1.M, @0x0003 // sec_params.unk1[1] + // 00e9 1501 lsl $ACC1, #1 + // 00ea 1f5f mrr $AX0.H, $AC1.M // ax0.h = sec_params.unk1[1] << 1 + // 00eb 00de 1043 lr $AC0.M, @0x1043 // drom 0076 + // 00ed 0240 fff0 andi $AC0.M, #0xfff0 // -> 0x70 + // 00ef 02bf 88e5 call 0x88e5 + // orr'l $AC0.M, $AX0.H : $AC1.M, @$AR2 // ac0.m = (sec_params.unk1[1] << 1) | 0x70, ac1.m = 0, ar2 = 0x12 + // lrrd $AC1.L, @$AR2 // ar2 = 0x11 + // add'dr $ACC0, $ACC1 : $AR1 // acc1 must be 0 + // srri @$AR2, $AC0.M // *0x11 = (sec_params.unk1[1] << 1) | 0x70, ar2 = 0x12 + // srr @$AR2, $AC0.L // *0x12 = 0 // just a side effect, it's already 0 anyways + // 00f1 029f 0102 jmp 0x0102 + *0x11 = ((sec_params.unk1[1] << 1) | 0x70) & 0xffff -012d 8100 clr $ACC0 +} else if (unk2 > 0) { + // 00f3 0082 0010 lri $AR2, #0x0010 + // 00f5 0086 0001 lri $IX2, #0x0001 // 'sn will inc ar2 by 1 + // 00f7 00d0 1285 lr $AC0.H, @0x1285 // drom 5aff (0xffff because of .h) + // 00f9 9100 asr16 $ACC0 // -> 0xff_ffff_0000 = -1 + // 00fa 4d00 add $ACC1, $ACC0 // ac1.m = unk2 - 1 + // 00fb 1501 lsl $ACC1, #1 // ac1.m <<= 1 ..in the normal case, this makes it 2 again... + // 00fc 00de 0003 lr $AC0.M, @0x0003 // sec_params.unk1[1] + // 00fe 1404 lsl $ACC0, #4 + // 00ff 1f5e mrr $AX0.H, $AC0.M // ax0.h = sec_params.unk1[1] << 4 + // 0100 02bf 8809 call 0x8809 + // orr'sn $AC1.M, $AX0.H : @$AR2, $AC1.L // ac1.m = ((unk2 - 1) << 1) | (sec_params.unk1[1] << 4), ar2 = 0x11 + // srri @$AR2, $AC1.M + *0x11 = (((unk2 - 1) << 1) | (sec_params.unk1[1] << 4)) & 0xffff +} -: -012e 14fd asr $ACC0, #-3 -012f 8e00 set16 -0130 00df 1491 lr $AC1.M, @0x1491 -0132 0340 d0f0 andi $AC1.M, #0xd0f0 -0134 1cbf mrr $IX1, $AC1.M -0135 00df 1468 lr $AC1.M, @0x1468 -0137 00d1 11fc lr $AC1.H, @0x11fc -0139 157c lsr $ACC1, #-4 -013a 1cdf mrr $IX2, $AC1.M -013b 00d1 11b8 lr $AC1.H, @0x11b8 -013d 9900 asr16 $ACC1 +// This just clears acc1 +// 0102 0083 0013 lri $AR3, #0x0013 +// 0104 1b7e srri @$AR3, $AC0.M // *0x13 = intermediate from above -> unused +// 0105 8923 clr's $ACC1 : @$AR3, $AC0.L // acc1 = 0, *0x14 = intermediate from above -> unused + +// The "confusion" +// 0106 0083 0013 lri $AR3, #0x0013 +// 0108 00df 0007 lr $AC1.M, @0x0007 // ac1.m = sec_params.length[1] +// 010a 00de 11b8 lr $AC0.M, @0x11b8 // drom 007f +// 010c 0240 fff0 andi $AC0.M, #0xfff0 // -> 0x70 +// 010e 1f5e mrr $AX0.H, $AC0.M // ax0.h = 0x70 +// 010f 02bf 81f4 call 0x81f4 +// mulxac'mv $AX0.H, $AX1.L, $ACC1 : $AX1.H, $AC0.M// prod = 0x70 * 0x1000 : .m1 = 7 +// asr16'ir $ACC1 : $AR1 // ac1.l = sec_params.length[1], the rest of acc1 must be 0 +// srri @$AR3, $AC1.M // *0x13 = 0, ar3 = 0x14 +// clr's $ACC0 : @$AR3, $AC1.L // acc0 = 0, *0x14 = sec_params.length[1], ar3 = 0x15 +// +// 0111 f100 lsl16 $ACC1 // ac1.m = sec_params.length[1] +// 0112 02bf 8458 call 0x8458 // this is the same routine, just adds 7 and stores to different location +// mulxac'mv $AX0.H, $AX1.L, $ACC1 : $AX1.H, $AC0.M// acc1 += 7 // last prod has 7 in the mid +// asr16 $ACC1 // ac1.l = sec_params.length[1] + 7 +// srri @$AR3, $AC1.M // *0x15 = 0, ar3 = 0x16 +// clr's $ACC0 : @$AR3, $AC1.L // *0x16 = sec_params.length[1] + 7 + *0x13 = 0 + *0x14 = sec_params.length[1] + *0x15 = 0 + *0x16 = sec_params.length[1] + 7 + +// 0114 8f00 set40 // SIGN EXTENSION IN EFFECT!! +// 0115 0082 0015 lri $AR2, #0x0015 +// 0117 00de 0006 lr $AC0.M, @0x0006 // ac0.m = sec_params.length[0] ..always 0? // sign extended +// 0119 00da 165b lr $AX0.H, @0x165b // drom 0000 +// 011b 02bf 88e5 call 0x88e5 +// orr'l $AC0.M, $AX0.H : $AC1.M, @$AR2 // ac0.m = sec_params.length[0], effectively clears acc1 (*0x15 == 0), ar2 = 0x16 +// lrrd $AC1.L, @$AR2 // ac1.l = sec_params.length[1] + 7, ar2 = 0x15 +// add'dr $ACC0, $ACC1 : $AR1 // ac0.m = sec_params.length[0], ac0.l = sec_params.length[1] + 7 +// srri @$AR2, $AC0.M // *0x15 = sec_params.length[0], ar2 = 0x16 +// srr @$AR2, $AC0.L // *0x16 = sec_params.length[1] + 7 +// 011d 14fd asr $ACC0, #-3 +// 011e 1403 lsl $ACC0, #3 // ((acc0 + 7) & ~7) (round up) // consider .length rounded from here on out +// 011f 1b5e srri @$AR2, $AC0.M // *0x16 = sec_params.length[0], ar2 = 0x17 +// 0120 1b5c srri @$AR2, $AC0.L // *0x17 = sec_params.length[1], ar2 = 0x18 +// 0121 0082 0016 lri $AR2, #0x0016 +// 0123 00de 1723 lr $AC0.M, @0x1723 // drom ffe0 // obviously sign extended +// 0125 14f4 asr $ACC0, #-12 // -> 0xff_ffff_fe00 = -1, -0x200 +// 0126 00da 166b lr $AX0.H, @0x166b // drom 0000 +// 0128 02bf 88e5 call 0x88e5 +// orr'l $AC0.M, $AX0.H : $AC1.M, @$AR2 // ac1.m = sec_params.length[0] // sign extended +// lrrd $AC1.L, @$AR2 // ac1.l = sec_params.length[1] +// add'dr $ACC0, $ACC1 : $AR1 // acc0 = sec_params.length - 0x200 // this is a proper signed operation :) +// srri @$AR2, $AC0.M // *0x16 = sec_params.length - 0x200 HIGH +// srr @$AR2, $AC0.L // *0x17 = sec_params.length - 0x200 LOW + // The above block just does 40bit subtraction...so annoying :p + *0x15 = sec_params.length[0] + *0x16 = sec_params.length - 0x200 HIGH + *0x17 = sec_params.length - 0x200 LOW + +// 012a b100 tst $ACC0 +// 012b 0290 012e jge 0x012e +// 012d 8100 clr $ACC0 +if (acc0 < 0) acc0 = 0 + +// At this point, ACC0 = max40bit(0, sec_params.length - 0x200) + +// 012e 14fd asr $ACC0, #-3 // taken into account at 013f +// 012f 8e00 set16 // back to sanity + +// voodoo +0130 00df 1491 lr $AC1.M, @0x1491 // drom 6a0f +0132 0340 d0f0 andi $AC1.M, #0xd0f0 // -> 0x4000 +0134 1cbf mrr $IX1, $AC1.M // ix1 = 0x4000 +0135 00df 1468 lr $AC1.M, @0x1468 // drom f808 +0137 00d1 11fc lr $AC1.H, @0x11fc // drom 0003 +0139 157c lsr $ACC1, #-4 // -> 0x00_3f80_8000 +013a 1cdf mrr $IX2, $AC1.M // ix2 = 0x3f80 +013b 00d1 11b8 lr $AC1.H, @0x11b8 // drom 007f +013d 9900 asr16 $ACC1 // -> 0x00_007f_3f80 013e 1418 lsl $ACC0, #24 -013f 1478 lsr $ACC0, #-8 -0140 1f5e mrr $AX0.H, $AC0.M -0141 1ffe mrr $AC1.M, $AC0.M -0142 1f65 mrr $AX1.H, $IX1 -0143 3600 andr $AC0.M, $AX1.H -0144 1402 lsl $ACC0, #2 -0145 1f66 mrr $AX1.H, $IX2 -0146 3700 andr $AC1.M, $AX1.H -0147 1501 lsl $ACC1, #1 -0148 4c00 add $ACC0, $ACC1 +013f 1478 lsr $ACC0, #-8 // (((ACC0 >> 3) << 24) >> 8) +same as ((ACC0 >> 3) << 16) & 0x00_ffff_0000 -> ac0.m = (u16)((sec_params.length - 0x200) >> 3) +u16 size = (u16)((sec_params.length - 0x200) >> 3) +0140 1f5e mrr $AX0.H, $AC0.M // ax0.h = size +0141 1ffe mrr $AC1.M, $AC0.M // ac1.m = size +0142 1f65 mrr $AX1.H, $IX1 // ax1.h = 0x4000 +0143 3600 andr $AC0.M, $AX1.H // ac0.m = size & 0x4000 +0144 1402 lsl $ACC0, #2 // acc0 <<= 2 // t = (0x00_size_0000 & 0x00_4000_ffff) << 2 +0145 1f66 mrr $AX1.H, $IX2 // ax1.h = 0x3f80 +0146 3700 andr $AC1.M, $AX1.H // ac1.m = size & 0x3f80 +0147 1501 lsl $ACC1, #1 // acc1 <<= 1 // u = (0x00_size_3f80 & 0x00_3f80_ffff) << 1 +0148 4c00 add $ACC0, $ACC1 // acc0 += acc1 // t += u 0149 1518 lsl $ACC1, #24 -014a 9900 asr16 $ACC1 -014b 3500 andr $AC1.M, $AX0.H -014c 4c00 add $ACC0, $ACC1 +014a 9900 asr16 $ACC1 // signed cast (s16)ac1.l (ends up in ac1.m) +014b 3500 andr $AC1.M, $AX0.H // ac1.m = (s16)u & size +014c 4c00 add $ACC0, $ACC1 // acc0 += acc1 // t += (s16)u & size 014d 00df 0012 lr $AC1.M, @0x0012 -014f 3f00 orc $AC1.M, $AC0.M -0150 00ff 0012 sr @0x0012, $AC1.M -0152 1470 lsr $ACC0, #-16 +014f 3f00 orc $AC1.M, $AC0.M // ac1.m = acc0 | 0x00_ffff_0000 +0150 00ff 0012 sr @0x0012, $AC1.M // *0x12 = ac1.m +0152 1470 lsr $ACC0, #-16 // // t >>= 16 unsigned 0153 00df 0011 lr $AC1.M, @0x0011 0155 3f00 orc $AC1.M, $AC0.M -0156 00ff 0011 sr @0x0011, $AC1.M -0158 1fa5 mrr $AC1.L, $IX1 -0159 1501 lsl $ACC1, #1 -015a 1fe6 mrr $AC1.M, $IX2 -015b f100 lsl16 $ACC1 +0156 00ff 0011 sr @0x0011, $AC1.M // *0x11 |= previous ac0.h, now at ac0.m <- so ac0.m = unsigned ac0.h +0158 1fa5 mrr $AC1.L, $IX1 // ac1.l = 0x4000 +0159 1501 lsl $ACC1, #1 // ac1.l = 0x8000 +015a 1fe6 mrr $AC1.M, $IX2 // ac1.m = 0x3f80 0x00_3f80_8000 +015b f100 lsl16 $ACC1 // ((acc1 << 16) >> 8) << 16 015c 15f8 asr $ACC1, #-8 -015d f500 lsr16 $ACC1 -015e 1f5f mrr $AX0.H, $AC1.M -015f 1f7d mrr $AX1.H, $AC1.L +015d f500 lsr16 $ACC1 // acc1 = 0x00_00ff_8080 +015e 1f5f mrr $AX0.H, $AC1.M // ax0.h = 0xff +015f 1f7d mrr $AX1.H, $AC1.L // ax1.h = 0x8080 0160 8100 clr $ACC0 0161 00de 0011 lr $AC0.M, @0x0011 -0163 3400 andr $AC0.M, $AX0.H -0164 8900 clr $ACC1 +0163 3400 andr $AC0.M, $AX0.H // ac0.m = *0x11 & 0xff +0164 8900 clr $ACC1 // so it was all to setup ax0.h and ax1.h... 0165 00df 0012 lr $AC1.M, @0x0012 -0167 3500 andr $AC1.M, $AX0.H +0167 3500 andr $AC1.M, $AX0.H // ac1.m = *0x12 & 0xff 0168 4c00 add $ACC0, $ACC1 0169 00df 0012 lr $AC1.M, @0x0012 016b 1578 lsr $ACC1, #-8 -016c 4c00 add $ACC0, $ACC1 +016c 4c00 add $ACC0, $ACC1 // acc0 = ((*0x11 & 0xff) << 16) + ((*0x12 & 0xff) << 16) + (*0x12 << 8) 016d 8900 clr $ACC1 016e 1ffe mrr $AC1.M, $AC0.M 016f 1508 lsl $ACC1, #8 -0170 3b00 orr $AC1.M, $AX1.H +0170 3b00 orr $AC1.M, $AX1.H // ac1.m = (ac0.m << 8) | 0x8080 0171 00de 0011 lr $AC0.M, @0x0011 -0173 3e00 orc $AC0.M, $AC1.M +0173 3e00 orc $AC0.M, $AC1.M // final11 = *0x11 | (ac0.m << 8) | 0x8080 0174 00df 0012 lr $AC1.M, @0x0012 0176 3b00 orr $AC1.M, $AX1.H -0177 1cbf mrr $IX1, $AC1.M -0178 00da 15f1 lr $AX0.H, @0x15f1 -017a 3500 andr $AC1.M, $AX0.H -017b 0295 0192 jz 0x0192 -if () { +0177 1cbf mrr $IX1, $AC1.M // final12 = *0x12 | 0x8080 + +// write the final values @22 and @23 +// 0178 00da 15f1 lr $AX0.H, @0x15f1 // drom 0200 +// 017a 3500 andr $AC1.M, $AX0.H +// 017b 0295 0192 jz 0x0192 +if (final12 & 0x200 != 0) { + + // 017d 00df 10e2 lr $AC1.M, @0x10e2 // drom 376f + // 017f 1508 lsl $ACC1, #8 // -> 0x37_6f00 + // 0180 1f5f mrr $AX0.H, $AC1.M + // 0181 00df 103b lr $AC1.M, @0x103b // drom 0065 + // 0183 7900 decm $AC1.M // -> 0x64 + // 0184 3900 orr $AC1.M, $AX0.H + // 0185 3080 xorc $AC0.M, $AC1.M + // 0186 00fe 0022 sr @0x0022, $AC0.M // *0x22 = final11 ^ 0x6f64 + // 0188 00dc 1229 lr $AC0.L, @0x1229 // drom 657c + // 018a 00dd 11f8 lr $AC1.L, @0x11f8 // drom 0009 + // 018c 5c00 sub $ACC0, $ACC1 + // 018d f000 lsl16 $ACC0 + // 018e 1fe5 mrr $AC1.M, $IX1 + // 018f 3080 xorc $AC0.M, $AC1.M // *0x23 = final12 ^ 0x6573 + // 0190 029f 01a5 jmp 0x01a5 + *0x22 = final11 ^ 0x6f64 + *0x23 = final12 ^ 0x6573 - 017d 00df 10e2 lr $AC1.M, @0x10e2 - 017f 1508 lsl $ACC1, #8 - 0180 1f5f mrr $AX0.H, $AC1.M - 0181 00df 103b lr $AC1.M, @0x103b - 0183 7900 decm $AC1.M - 0184 3900 orr $AC1.M, $AX0.H - 0185 3080 xorc $AC0.M, $AC1.M - 0186 00fe 0022 sr @0x0022, $AC0.M - 0188 00dc 1229 lr $AC0.L, @0x1229 - 018a 00dd 11f8 lr $AC1.L, @0x11f8 - 018c 5c00 sub $ACC0, $ACC1 - 018d f000 lsl16 $ACC0 - 018e 1fe5 mrr $AC1.M, $IX1 - 018f 3080 xorc $AC0.M, $AC1.M - 0190 029f 01a5 jmp 0x01a5 - } else { - - 0192 00df 10ca lr $AC1.M, @0x10ca - 0194 1508 lsl $ACC1, #8 - 0195 1f5f mrr $AX0.H, $AC1.M - 0196 00df 1043 lr $AC1.M, @0x1043 - 0198 7500 incm $AC1.M - 0199 3900 orr $AC1.M, $AX0.H - 019a 3080 xorc $AC0.M, $AC1.M - 019b 00fe 0022 sr @0x0022, $AC0.M - 019d 00dc 1259 lr $AC0.L, @0x1259 - 019f 00dd 16fe lr $AC1.L, @0x16fe - 01a1 4c00 add $ACC0, $ACC1 - 01a2 f000 lsl16 $ACC0 - 01a3 1fe5 mrr $AC1.M, $IX1 - 01a4 3080 xorc $AC0.M, $AC1.M + // 0192 00df 10ca lr $AC1.M, @0x10ca // drom 3461 + // 0194 1508 lsl $ACC1, #8 // -> 0x34_6100 + // 0195 1f5f mrr $AX0.H, $AC1.M + // 0196 00df 1043 lr $AC1.M, @0x1043 // drom 0076 + // 0198 7500 incm $AC1.M // -> 0x77 + // 0199 3900 orr $AC1.M, $AX0.H + // 019a 3080 xorc $AC0.M, $AC1.M + // 019b 00fe 0022 sr @0x0022, $AC0.M // *0x22 = final11 ^ 0x6177 + // 019d 00dc 1259 lr $AC0.L, @0x1259 // drom 6143 + // 019f 00dd 16fe lr $AC1.L, @0x16fe // drom 0008 + // 01a1 4c00 add $ACC0, $ACC1 + // 01a2 f000 lsl16 $ACC0 + // 01a3 1fe5 mrr $AC1.M, $IX1 + // 01a4 3080 xorc $AC0.M, $AC1.M // *0x23 = final12 ^ 0x614b + *0x22 = final11 ^ 0x6177 + *0x23 = final12 ^ 0x614b } +// 01a5 00fe 0023 sr @0x0023, $AC0.M // taken care of above -01a5 00fe 0023 sr @0x0023, $AC0.M // this is where result is written to main memory -// dsp mem 0x20-0x23 (8 bytes) are written back, because only values @22 and @23 were modified result is 32bit -01a7 00da 0008 lr $AX0.H, @0x0008 // cpu addr high -01a9 00d8 0009 lr $AX0.L, @0x0009 // cpu addr low -01ab 009b 0020 lri $AX1.H, #0x0020 // dsp addr -01ad 0099 0008 lri $AX1.L, #0x0008 // length -01af 0087 0000 lri $IX3, #0x0000 // there will be no iram dma -01b1 02bf 808b call 0x808b // dram->cpu <<<--- important!! -01b3 02df ret +// dsp mem 0x20-0x23 (8 bytes) are written back - only values @22 and @23 were modified, so result is 32bit +01a7 00da 0008 lr $AX0.H, @0x0008 // sec_params.dest_addr[0] +01a9 00d8 0009 lr $AX0.L, @0x0009 // sec_params.dest_addr[1] +01ab 009b 0020 lri $AX1.H, #0x0020 // dsp addr +01ad 0099 0008 lri $AX1.L, #0x0008 // length +01af 0087 0000 lri $IX3, #0x0000 // there will be no iram dma +01b1 02bf 808b call 0x808b // do it! + +01b3 02df ret } -01b4 0000 nop -01b5 0000 nop -01b6 0000 nop -01b7 0000 nop -01b8 0000 nop -01b9 0000 nop -01ba 0000 nop -01bb 0000 nop -01bc 0000 nop -01bd 0000 nop -01be 0000 nop -01bf 0000 nop +01b4 0000 nop +01b5 0000 nop +01b6 0000 nop +01b7 0000 nop +01b8 0000 nop +01b9 0000 nop +01ba 0000 nop +01bb 0000 nop +01bc 0000 nop +01bd 0000 nop +01be 0000 nop +01bf 0000 nop diff --git a/docs/DSP/DSP_UC_Zelda.txt b/docs/DSP/DSP_UC_Zelda.txt index cc812f3922..770ca65f26 100644 --- a/docs/DSP/DSP_UC_Zelda.txt +++ b/docs/DSP/DSP_UC_Zelda.txt @@ -1555,7 +1555,7 @@ void 0243_COMMAND_02() // sync frame // 0419 0080 002d lri $AR0, #0x002d // 041b 029f 0603 jmp 0x0603 - 0603_Unk(0x02d) + 0603_FinalizeFrame(0x02d) } // Command 07 - not seen used. @@ -2111,7 +2111,8 @@ void 05f0_HaltUCode() 0601 0658 cmpis $ACC0, #0x58 0602 065b cmpis $ACC0, #0x5b -void 0603_Unk(_returnAddr($AR0)) + // at the end of a frame, we get a mail telling ucode what to do next +void 0603_FinalizeFrame(_returnAddr($AR0)) { // 0603 00e0 03f9 sr @0x03f9, $AR0 0x03f9 = _returnAddr @@ -2143,28 +2144,32 @@ void 0603_Unk(_returnAddr($AR0)) switch(AR3 - 0x05FF) { case 0x00: HALT(); break; - case 0x00: HALT(); break; - case 0x01: 0658_SoftReset(); break; - case 0x02: 065b_ContinueWithUCode(); break; + case 0x01: 0618_PrepareBootUcode(); break; + case 0x02: 0658_SoftReset(); break; + case 0x03: 065b_ContinueWithUCode(); break; + default: HALT(); + // 0616 0021 halt } - } - - -0616 0021 halt + 0617 0021 halt -void 0618_Unk() { + // Sets up info needed to dma in a chunk to iram or dram, + // and calls irom to do actual dma. irom returns to address given in AR0 +void 0618_PrepareBootUcode() { + // Dunno what that's about... 0618 009a 0002 lri $AX0.H, #0x0002 061a 00fa 03a3 sr @0x03a3, $AX0.H + 061c 8100 clr $ACC0 061d 8900 clr $ACC1 + //061e 02bf 065e call 0x065e 065e_WaitForCPUMailBox_AC0() 0620 24ff lrs $AC0.L, @CMBL - //0621 02bf 0664 call 0x0664 + //0621 02bf 0664 call 0x0664 0664_WaitForCPUMailBox_AC1() 0623 25ff lrs $AC1.L, @CMBL @@ -2174,10 +2179,11 @@ void 0618_Unk() { 0626 27ff lrs $AC1.M, @CMBL 0627 2ece srs @DSMAH, $AC0.M - 0628 2ccf srs @DSMAL, $AC0.L + 0628 2ccf srs @DSMAL, $AC0.L // 0 0629 16c9 0001 si @DSCR, #0x0001 - 062b 2fcd srs @DSPA, $AC1.M - 062c 2dcb srs @DSBL, $AC1.L + 062b 2fcd srs @DSPA, $AC1.M // 2 + 062c 2dcb srs @DSBL, $AC1.L // 1 + 062d 8100 clr $ACC0 062e 8900 clr $ACC1 @@ -2220,15 +2226,22 @@ void 0618_Unk() { 065e_WaitForCPUMailBox_AC0() 064b 23ff lrs $AX1.H, @CMBL - 064c 26c9 lrs $AC0.M, @DSCR - 064d 02a0 0004 andf $AC0.M, #0x0004 - 064f 029c 064c jlnz 0x064c - 0651 1206 sbclr #0x06 - 0652 1203 sbclr #0x03 - 0653 1204 sbclr #0x04 - 0654 1205 sbclr #0x05 - 0655 029f 80b5 jmp 0x80b5 - **** GOTO ROM!! + + // Make sure dma is ready + // 064c 26c9 lrs $AC0.M, @DSCR + // 064d 02a0 0004 andf $AC0.M, #0x0004 + // 064f 029c 064c jlnz 0x064c + + // Reset some of the state + // 0651 1206 sbclr #0x06 + // 0652 1203 sbclr #0x03 + // 0653 1204 sbclr #0x04 + // 0654 1205 sbclr #0x05 + + // 0655 029f 80b5 jmp 0x80b5 + 80b5_BootUcode(); + + // Should not reach here 0657 0021 halt }