allow "swapping" of hle'd ucodes

hle the gba ucode

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6046 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Shawn Hoffman 2010-08-04 11:44:06 +00:00
parent dc0a67b53a
commit 0a3c150f69
16 changed files with 809 additions and 415 deletions

View file

@ -570,6 +570,14 @@
RelativePath=".\Src\UCodes\UCode_CARD.h"
>
</File>
<File
RelativePath=".\Src\UCodes\UCode_GBA.cpp"
>
</File>
<File
RelativePath=".\Src\UCodes\UCode_GBA.h"
>
</File>
<File
RelativePath=".\Src\UCodes\UCode_InitAudioSystem.cpp"
>

View file

@ -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;
}
}

View file

@ -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;

View file

@ -45,7 +45,7 @@ public:
else
{
// WARN_LOG(DSPHLE, "GetNextMail: No mails");
return 0; //
return 0;
}
}

View file

@ -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)

View file

@ -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);
};

View file

@ -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");
}

View file

@ -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

View file

@ -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);
}

View file

@ -38,7 +38,6 @@ private:
u32 m_DMEMLength;
u32 m_StartPC;
};
SUCode m_CurrentUCode;
int m_BootTask_numSteps;

View file

@ -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();

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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

View file

@ -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
}