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
}