More correct and cleaner merge of Zelda (normal) and Luigi (light) uCodes.

Split HandleMail into two functions, one for each version.
Let's hope it won't break anything...

BTW: if you wonder what "DMA version" and "Light version" mean:
 - DMA version is, say, the uCode used by SMG
 - Light version is Luigi-styled uCode (named that way for obvious reasons)

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3772 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
luigi2us 2009-07-12 23:51:18 +00:00
parent 5c7844df69
commit ddd09eda84
2 changed files with 106 additions and 99 deletions

View File

@ -67,16 +67,16 @@ CUCode_Zelda::CUCode_Zelda(CMailHandler& _rMailHandler, u32 _CRC)
m_PBAddress2(0)
{
DEBUG_LOG(DSPHLE, "UCode_Zelda - add boot mails for handshake");
if (LuigiStyle())
NOTICE_LOG(DSPHLE, "Luigi Stylee!");
m_rMailHandler.PushMail(DSP_INIT);
if (LuigiStyle())
if (IsLightVersion())
{
m_rMailHandler.PushMail(0x80000000);
NOTICE_LOG(DSPHLE, "Luigi Stylee!");
// Is it correct? seen in DSP_UC_Luigi.txt reset vector
m_rMailHandler.PushMail(0x80001111);
}
else
{
m_rMailHandler.PushMail(DSP_INIT);
g_dspInitialize.pGenerateDSPInterrupt();
m_rMailHandler.PushMail(0xF3551111); // handshake
}
@ -104,49 +104,64 @@ CUCode_Zelda::~CUCode_Zelda()
u8 *CUCode_Zelda::GetARAMPointer(u32 address)
{
if (m_CRC == 0xD643001F) // SMG
if (IsDMAVersion())
return (u8 *)(g_dspInitialize.pGetMemoryPointer(m_DMABaseAddr)) + address;
else
return (u8 *)(g_dspInitialize.pGetARAMPointer()) + address;
}
bool CUCode_Zelda::LuigiStyle() const
{
switch (m_CRC)
{
case 0x42f64ac4: // Luigi
case 0x0267d05a: // http://forums.dolphin-emu.com/thread-2134.html Pikmin PAL
case 0x4be6a5cb: // AC, Pikmin
case 0x088e38a5: // IPL - JAP
case 0xd73338cf: // IPL
return true;
default:
return false;
}
}
void CUCode_Zelda::Update(int cycles)
{
// if (!m_rMailHandler.IsEmpty())
if (!LuigiStyle()) {
if (!IsLightVersion())
{
if (m_rMailHandler.GetNextMail() == DSP_FRAME_END)
g_dspInitialize.pGenerateDSPInterrupt();
}
/* if (m_bSyncCmdPending && (m_CurBuffer == m_NumBuffers) && (m_rMailHandler.IsEmpty()))
{
m_rMailHandler.PushMail(DSP_FRAME_END);
g_dspInitialize.pGenerateDSPInterrupt();
soundStream->GetMixer()->SetHLEReady(true);
DEBUG_LOG(DSPHLE, "Update the SoundThread to be in sync");
soundStream->Update(); //do it in this thread to avoid sync problems
m_bSyncCmdPending = false;
}*/
}
void CUCode_Zelda::HandleMail(u32 _uMail)
{
if (IsLightVersion())
HandleMail_LightVersion(_uMail);
else
HandleMail_NormalVersion(_uMail);
}
void CUCode_Zelda::HandleMail_LightVersion(u32 _uMail)
{
if (!m_bListInProgress)
{
switch ((_uMail >> 24) & 0x7F)
{
case 0x01: m_numSteps = 5; break; // DsetupTable
case 0x02: m_numSteps = 3; break; // DsyncFrame
default:
{
m_numSteps = 0;
PanicAlert("Zelda uCode (light version): unknown/unsupported command %02X", (_uMail >> 24) & 0x7F);
}
return;
}
m_bListInProgress = true;
m_step = 0;
}
if (m_step < 0 || m_step >= sizeof(m_Buffer) / 4)
PanicAlert("m_step out of range");
((u32*)m_Buffer)[m_step] = _uMail;
m_step++;
if (m_step >= m_numSteps)
{
ExecuteList();
m_bListInProgress = false;
}
}
void CUCode_Zelda::HandleMail_NormalVersion(u32 _uMail)
{
// WARN_LOG(DSPHLE, "Zelda uCode: Handle mail %08X", _uMail);
if (m_bSyncInProgress)
@ -211,7 +226,6 @@ void CUCode_Zelda::HandleMail(u32 _uMail)
return;
}
reread:
if (m_bListInProgress)
{
if (m_step < 0 || m_step >= sizeof(m_Buffer) / 4)
@ -231,17 +245,16 @@ reread:
// Here holds: m_bSyncInProgress == false && m_bListInProgress == false
// Zelda-only mails:
// - 0000XXXX - Begin list
// - 00000000, 000X0000 - Sync mails
// - CDD1XXXX - comes after DsyncFrame completed, seems to be debugging stuff
if (_uMail == 0)
{
if (!LuigiStyle())
m_bSyncInProgress = true;
else {
soundStream->GetMixer()->SetHLEReady(true);
soundStream->Update(); //do it in this thread to avoid sync problems
g_dspInitialize.pGenerateDSPInterrupt();
}
m_bSyncInProgress = true;
}
else if (!LuigiStyle() && (_uMail >> 16) == 0)
else if ((_uMail >> 16) == 0)
{
m_bListInProgress = true;
m_numSteps = _uMail;
@ -250,6 +263,8 @@ reread:
else if ((_uMail >> 16) == 0xCDD1) // A 0xCDD1000X mail should come right after we send a DSP_SYNCEND 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
@ -266,34 +281,6 @@ reread:
return;
}
}
else if (LuigiStyle() && (_uMail >> 28) == 0x8)
{
m_bListInProgress = true;
m_step = 0;
m_numSteps = 0;
// We have to guess the message size.
int command = (_uMail & 0xFFFF);
switch (command)
{
case 0x0000:
g_dspInitialize.pGenerateDSPInterrupt();
break;
case 0x0040:
m_numSteps = 5;
ERROR_LOG(DSPHLE, "WE GUESS STEPS: %i", m_numSteps);
break;
case 0x2000:
case 0x4000:
m_numSteps = 3;
ERROR_LOG(DSPHLE, "WE GUESS STEPS: %i", m_numSteps);
break;
default:
ERROR_LOG(DSPHLE, "LUIGI UNKNOWN: %i", command);
break;
}
// UGLY
goto reread;
}
else
{
WARN_LOG(DSPHLE, "Zelda uCode: unknown mail %08X", _uMail);
@ -311,27 +298,8 @@ void CUCode_Zelda::ExecuteList()
u32 Sync = CmdMail >> 16;
u32 ExtraData = CmdMail & 0xFFFF;
if (!LuigiStyle()) {
DEBUG_LOG(DSPHLE, "==============================================================================");
DEBUG_LOG(DSPHLE, "Zelda UCode - execute dlist (cmd: 0x%04x : sync: 0x%04x)", Command, Sync);
}
else
{
Command = CmdMail & 0xFFFF;
DEBUG_LOG(DSPHLE, "==============================================================================");
DEBUG_LOG(DSPHLE, "Zelda UCode L-mode - execute dlist (cmd: 0x%04x : sync: 0x%04x)", Command, Sync);
// Translate Luigi commands
switch (Command) {
case 0x0040: Command = 0x01; break;
case 0x2000:
case 0x4000: Command = 2; break;
default:
DEBUG_LOG(DSPHLE, "Luigi translate: FAIL %04x", Command);
break;
}
}
DEBUG_LOG(DSPHLE, "==============================================================================");
DEBUG_LOG(DSPHLE, "Zelda UCode - execute dlist (cmd: 0x%04x : sync: 0x%04x)", Command, Sync);
switch (Command)
{
@ -376,7 +344,7 @@ void CUCode_Zelda::ExecuteList()
// DEBUG_LOG(DSPHLE, "Update the SoundThread to be in sync");
//soundStream->Update(); //do it in this thread to avoid sync problems
if (!LuigiStyle())
if (!IsLightVersion())
m_bSyncCmdPending = true;
m_CurBuffer = 0;
@ -394,7 +362,7 @@ void CUCode_Zelda::ExecuteList()
DEBUG_LOG(DSPHLE, "Right buffer address: 0x%08x", m_RightBuffersAddr);
DEBUG_LOG(DSPHLE, "Left buffer address: 0x%08x", m_LeftBuffersAddr);
if (LuigiStyle())
if (IsLightVersion())
break;
else
return;
@ -438,10 +406,16 @@ void CUCode_Zelda::ExecuteList()
}
// sync, we are ready
m_rMailHandler.PushMail(DSP_SYNC);
if (!LuigiStyle())
if (IsLightVersion())
{
m_rMailHandler.PushMail(0x80000000 | Sync);
}
else
{
m_rMailHandler.PushMail(DSP_SYNC);
g_dspInitialize.pGenerateDSPInterrupt();
m_rMailHandler.PushMail(0xF3550000 | Sync);
m_rMailHandler.PushMail(0xF3550000 | Sync);
}
}

View File

@ -127,6 +127,9 @@ public:
virtual ~CUCode_Zelda();
void HandleMail(u32 _uMail);
void HandleMail_LightVersion(u32 _uMail);
void HandleMail_NormalVersion(u32 _uMail);
void Update(int cycles);
void MixAdd(short* buffer, int size);
@ -160,7 +163,37 @@ private:
};
// These map CRC to behaviour.
bool LuigiStyle() const;
// DMA version
// - sound data transferred using DMA instead of accelerator
bool IsDMAVersion() const
{
switch (m_CRC)
{
case 0xD643001F: // Super Mario Galaxy
return true;
default:
return false;
}
}
// Light version
// - slightly different communication protocol (no list begin mail)
// - exceptions and interrupts not used
bool IsLightVersion() const
{
switch (m_CRC)
{
case 0x42f64ac4: // Luigi
case 0x0267d05a: // http://forums.dolphin-emu.com/thread-2134.html Pikmin PAL
case 0x4be6a5cb: // AC, Pikmin
case 0x088e38a5: // IPL - JAP
case 0xd73338cf: // IPL
return true;
default:
return false;
}
}
u32 m_CRC;