diff --git a/Source/Plugins/Plugin_DSP_HLE/Plugin_DSP_HLE.vcproj b/Source/Plugins/Plugin_DSP_HLE/Plugin_DSP_HLE.vcproj
index 1c16f33808..d285a1a1ab 100644
--- a/Source/Plugins/Plugin_DSP_HLE/Plugin_DSP_HLE.vcproj
+++ b/Source/Plugins/Plugin_DSP_HLE/Plugin_DSP_HLE.vcproj
@@ -1,7 +1,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
@@ -616,7 +608,7 @@
/>
+
+
@@ -817,22 +813,6 @@
UsePrecompiledHeader="1"
/>
-
-
-
-
-
-
@@ -841,6 +821,14 @@
UsePrecompiledHeader="1"
/>
+
+
+
@@ -849,6 +837,14 @@
UsePrecompiledHeader="1"
/>
+
+
+
diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/SConscript b/Source/Plugins/Plugin_DSP_HLE/Src/SConscript
index 3e6f5a9683..d31141e0d2 100644
--- a/Source/Plugins/Plugin_DSP_HLE/Src/SConscript
+++ b/Source/Plugins/Plugin_DSP_HLE/Src/SConscript
@@ -8,7 +8,7 @@ name = "Plugin_DSP_HLE"
files = [
'DSPHandler.cpp',
'MailHandler.cpp',
- 'HLEMixer.cpp',
+ 'HLEMixer.cpp',
'main.cpp',
'Config.cpp',
'Globals.cpp',
@@ -17,7 +17,6 @@ files = [
'UCodes/UCode_AXWii.cpp',
'UCodes/UCode_CARD.cpp',
'UCodes/UCode_InitAudioSystem.cpp',
- 'UCodes/UCode_Jac.cpp',
'UCodes/UCode_ROM.cpp',
'UCodes/UCodes.cpp',
'UCodes/UCode_Zelda.cpp',
diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Jac.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Jac.cpp
deleted file mode 100644
index 7d471565b3..0000000000
--- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Jac.cpp
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright (C) 2003-2008 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 "UCodes.h"
-#include "UCode_Jac.h"
-#include "../MailHandler.h"
-
-CUCode_Jac::CUCode_Jac(CMailHandler& _rMailHandler)
- : IUCode(_rMailHandler)
- , m_bListInProgress(false)
-{
- DEBUG_LOG(DSPHLE, "CUCode_Jac: init");
- m_rMailHandler.PushMail(0xDCD10000);
- m_rMailHandler.PushMail(0x80000000);
-}
-
-
-CUCode_Jac::~CUCode_Jac()
-{
- m_rMailHandler.Clear();
-}
-
-
-void CUCode_Jac::HandleMail(u32 _uMail)
-{
- // this is prolly totally bullshit and should work like the zelda one...
- // but i am to lazy to change it atm
-
- if (m_bListInProgress == false)
- {
- // get the command to find out how much steps it has
- switch (_uMail & 0xFFFF)
- {
- // release halt
- case 0x00:
- // m_Mails.push(0x80000000);
- g_dspInitialize.pGenerateDSPInterrupt();
- break;
-
- case 0x40:
- m_step = 0;
- ((u32*)m_Buffer)[m_step++] = _uMail;
- m_bListInProgress = true;
- m_numSteps = 5;
- break;
-
- case 0x2000:
- case 0x4000:
- m_step = 0;
- ((u32*)m_Buffer)[m_step++] = _uMail;
- m_bListInProgress = true;
- m_numSteps = 3;
- break;
-
- default:
- PanicAlert("UCode Jac");
- DEBUG_LOG(DSPHLE, "UCode Jac - unknown cmd: %x", _uMail & 0xFFFF);
- break;
- }
- }
- else
- {
- ((u32*)m_Buffer)[m_step] = _uMail;
- m_step++;
-
- if (m_step == m_numSteps)
- {
- ExecuteList();
- m_bListInProgress = false;
- }
- }
-}
-
-
-void CUCode_Jac::Update(int cycles)
-{
- // check if we have to sent something
-/* if (!g_MailHandler.empty())
- {
- g_dspInitialize.pGenerateDSPInterrupt();
- }*/
-}
-
-
-void CUCode_Jac::ExecuteList()
-{
- // begin with the list
- m_readOffset = 0;
-
- u16 cmd = Read16();
- u16 sync = Read16();
-
- DEBUG_LOG(DSPHLE, "==============================================================================");
- DEBUG_LOG(DSPHLE, "UCode Jac - execute dlist (cmd: 0x%04x : sync: 0x%04x)", cmd, sync);
-
- switch (cmd)
- {
- // ==============================================================================
- // DsetupTable
- // ==============================================================================
- case 0x40:
- {
- u32 tmp[4];
- tmp[0] = Read32();
- tmp[1] = Read32();
- tmp[2] = Read32();
- tmp[3] = Read32();
-
- DEBUG_LOG(DSPHLE, "DsetupTable");
- DEBUG_LOG(DSPHLE, "???: 0x%08x", tmp[0]);
- DEBUG_LOG(DSPHLE, "DSPRES_FILTER (size: 0x40): 0x%08x", tmp[1]);
- DEBUG_LOG(DSPHLE, "DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp[2]);
- DEBUG_LOG(DSPHLE, "???: 0x%08x", tmp[3]);
- }
- break;
-
- // ==============================================================================
- // UpdateDSPChannel
- // ==============================================================================
- case 0x2000:
- case 0x4000: // animal crossing
- {
- u32 tmp[3];
- tmp[0] = Read32();
- tmp[1] = Read32();
- tmp[2] = Read32();
-
- DEBUG_LOG(DSPHLE, "UpdateDSPChannel");
- DEBUG_LOG(DSPHLE, "audiomemory: 0x%08x", tmp[0]);
- DEBUG_LOG(DSPHLE, "audiomemory: 0x%08x", tmp[1]);
- DEBUG_LOG(DSPHLE, "DSPADPCM_FILTER (size: 0x40): 0x%08x", tmp[2]);
- }
- break;
-
- default:
- PanicAlert("UCode Jac unknown cmd: %s (size %i)", cmd, m_numSteps);
- DEBUG_LOG(DSPHLE, "Jac UCode - unknown cmd: %x (size %i)", cmd, m_numSteps);
- break;
- }
-
- // sync, we are ready.
- m_rMailHandler.PushMail(DSP_SYNC);
- m_rMailHandler.PushMail(0xF3550000 | sync);
-}
-
-
diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Jac.h b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Jac.h
deleted file mode 100644
index a65b96287a..0000000000
--- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Jac.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (C) 2003-2008 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/
-
-#ifndef _UCODE_JAC
-#define _UCODE_JAC
-
-#include "UCodes.h"
-
-// This uCode should be deleted and replaced with a small modification of the Zelda uCode.
-// The big difference is that games using this one won't send "message counts"
-// before sending the command data.
-
-class CUCode_Jac : public IUCode
-{
-private:
-
- enum EDSP_Codes
- {
- DSP_INIT = 0xDCD10000,
- DSP_RESUME = 0xDCD10001,
- DSP_YIELD = 0xDCD10002,
- DSP_DONE = 0xDCD10003,
- DSP_SYNC = 0xDCD10004,
- DSP_UNKN = 0xDCD10005,
- };
-
- bool m_bListInProgress;
- int m_numSteps;
- int m_step;
- u8 m_Buffer[1024];
- void ExecuteList();
-
- u32 m_readOffset;
-
- u8 Read8()
- {
- return(m_Buffer[m_readOffset++]);
- }
-
- // Hmm, don't these need bswaps?
- u16 Read16()
- {
- u16 res = *(u16*)&m_Buffer[m_readOffset];
- m_readOffset += 2;
- return(res);
- }
-
- u32 Read32()
- {
- u32 res = *(u32*)&m_Buffer[m_readOffset];
- m_readOffset += 4;
- return(res);
- }
-
-public:
- CUCode_Jac(CMailHandler& _rMailHandler);
- virtual ~CUCode_Jac();
-
- void HandleMail(u32 _uMail);
- void Update(int cycles);
-};
-
-#endif
-
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 6ad0b50ac1..46150d52d3 100644
--- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.cpp
+++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.cpp
@@ -34,12 +34,12 @@ CUCode_Zelda::CUCode_Zelda(CMailHandler& _rMailHandler, u32 _CRC)
IUCode(_rMailHandler),
m_CRC(_CRC),
- m_bSyncInProgress(0),
+ m_bSyncInProgress(false),
m_MaxVoice(0),
m_NumVoices(0),
- m_bSyncCmdPending(0),
+ m_bSyncCmdPending(false),
m_CurVoice(0),
m_CurBuffer(0),
m_NumBuffers(0),
@@ -55,7 +55,7 @@ CUCode_Zelda::CUCode_Zelda(CMailHandler& _rMailHandler, u32 _CRC)
m_DMABaseAddr(0),
m_numSteps(0),
- m_bListInProgress(0),
+ m_bListInProgress(false),
m_step(0),
m_readOffset(0),
@@ -67,9 +67,19 @@ 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);
- g_dspInitialize.pGenerateDSPInterrupt();
- m_rMailHandler.PushMail(0xF3551111); // handshake
+ if (LuigiStyle())
+ {
+ m_rMailHandler.PushMail(0x80000000);
+ }
+ else
+ {
+ g_dspInitialize.pGenerateDSPInterrupt();
+ m_rMailHandler.PushMail(0xF3551111); // handshake
+ }
m_TempBuffer = new s32[256 * 1024];
m_LeftBuffer = new s32[256 * 1024];
@@ -90,10 +100,29 @@ CUCode_Zelda::~CUCode_Zelda()
delete [] m_RightBuffer;
}
+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())
- g_dspInitialize.pGenerateDSPInterrupt();
+ // if (!m_rMailHandler.IsEmpty())
+
+ if (!LuigiStyle()) {
+ 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);
@@ -110,7 +139,6 @@ void CUCode_Zelda::Update(int cycles)
void CUCode_Zelda::HandleMail(u32 _uMail)
{
// WARN_LOG(DSPHLE, "Zelda uCode: Handle mail %08X", _uMail);
-
if (m_bSyncInProgress)
{
if (m_bSyncCmdPending)
@@ -171,12 +199,12 @@ void CUCode_Zelda::HandleMail(u32 _uMail)
}
return;
-
}
+reread:
if (m_bListInProgress)
{
- if (m_step < 0 || m_step >= sizeof(m_Buffer)/4)
+ if (m_step < 0 || m_step >= sizeof(m_Buffer) / 4)
PanicAlert("m_step out of range");
((u32*)m_Buffer)[m_step] = _uMail;
@@ -191,11 +219,19 @@ void CUCode_Zelda::HandleMail(u32 _uMail)
return;
}
+ // Here holds: m_bSyncInProgress == false && m_bListInProgress == false
+
if (_uMail == 0)
{
- m_bSyncInProgress = true;
+ if (!LuigiStyle())
+ m_bSyncInProgress = true;
+ else {
+ soundStream->GetMixer()->SetHLEReady(true);
+ soundStream->Update(); //do it in this thread to avoid sync problems
+ g_dspInitialize.pGenerateDSPInterrupt();
+ }
}
- else if ((_uMail >> 16) == 0)
+ else if (!LuigiStyle() && (_uMail >> 16) == 0)
{
m_bListInProgress = true;
m_numSteps = _uMail;
@@ -220,7 +256,35 @@ void CUCode_Zelda::HandleMail(u32 _uMail)
return;
}
}
- else
+ 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);
}
@@ -237,8 +301,27 @@ void CUCode_Zelda::ExecuteList()
u32 Sync = CmdMail >> 16;
u32 ExtraData = CmdMail & 0xFFFF;
- DEBUG_LOG(DSPHLE, "==============================================================================");
- DEBUG_LOG(DSPHLE, "Zelda UCode - execute dlist (cmd: 0x%04x : sync: 0x%04x)", Command, Sync);
+ 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;
+ }
+ }
+
switch (Command)
{
@@ -251,8 +334,13 @@ void CUCode_Zelda::ExecuteList()
m_AFCCoefTableAddr = Read32() & 0x7FFFFFFF;
m_ReverbPBsAddr = Read32() & 0x7FFFFFFF; // WARNING: reverb PBs are very different from voice PBs!
+ // Read the other table
+ u16 *TempPtr = (u16*) g_dspInitialize.pGetMemoryPointer(m_UnkTableAddr);
+ for (int i = 0; i < 0x280; i++)
+ m_MiscTable[i] = (s16)Common::swap16(TempPtr[i]);
+
// Read AFC coef table
- u16 *TempPtr = (u16*) g_dspInitialize.pGetMemoryPointer(m_AFCCoefTableAddr);
+ TempPtr = (u16*) g_dspInitialize.pGetMemoryPointer(m_AFCCoefTableAddr);
for (int i = 0; i < 32; i++)
m_AFCCoefTable[i] = (s16)Common::swap16(TempPtr[i]);
@@ -274,11 +362,13 @@ void CUCode_Zelda::ExecuteList()
// SyncFrame ... zelda ww jumps to 0x0243
case 0x02:
{
- //soundStream->GetMixer()->SetHLEReady(true);
+ //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 = true;
+ if (!LuigiStyle())
+ m_bSyncCmdPending = true;
+
m_CurBuffer = 0;
m_NumBuffers = (CmdMail >> 16) & 0xFF;
@@ -294,8 +384,11 @@ void CUCode_Zelda::ExecuteList()
DEBUG_LOG(DSPHLE, "Right buffer address: 0x%08x", m_RightBuffersAddr);
DEBUG_LOG(DSPHLE, "Left buffer address: 0x%08x", m_LeftBuffersAddr);
- }
- return;
+ if (LuigiStyle())
+ break;
+ else
+ return;
+ }
// Simply sends the sync messages
@@ -309,7 +402,7 @@ void CUCode_Zelda::ExecuteList()
case 0x09: break; // dunno ... zelda ww jmps to 0x044d
*/
- // DsetDolbyDelay ... zelda ww jumps to 0x00b2
+ // DsetDolbyDelay ... zelda ww jumps to 0x00b2
case 0x0d:
{
u32 tmp = Read32();
@@ -336,56 +429,11 @@ void CUCode_Zelda::ExecuteList()
// sync, we are ready
m_rMailHandler.PushMail(DSP_SYNC);
- g_dspInitialize.pGenerateDSPInterrupt();
+ if (!LuigiStyle())
+ g_dspInitialize.pGenerateDSPInterrupt();
m_rMailHandler.PushMail(0xF3550000 | Sync);
}
-// size is in stereo samples.
-void CUCode_Zelda::MixAdd(short* _Buffer, int _Size)
-{
- if (_Size > 256 * 1024)
- _Size = 256 * 1024;
-
- memset(m_LeftBuffer, 0, _Size * sizeof(s32));
- memset(m_RightBuffer, 0, _Size * sizeof(s32));
-
- for (u32 i = 0; i < m_NumVoices; i++)
- {
- u32 flags = m_SyncFlags[(i >> 4) & 0xF];
- if (!(flags & 1 << (15 - (i & 0xF))))
- continue;
-
- ZeldaVoicePB pb;
- ReadVoicePB(m_VoicePBsAddr + (i * 0x180), pb);
-
- if (pb.Status == 0)
- continue;
- if (pb.KeyOff != 0)
- continue;
-
- RenderAddVoice(pb, m_LeftBuffer, m_RightBuffer, _Size);
- WritebackVoicePB(m_VoicePBsAddr + (i * 0x180), pb);
- }
-
- if (_Buffer)
- {
- for (u32 i = 0; i < _Size; i++)
- {
- s32 left = (s32)_Buffer[0] + m_LeftBuffer[i];
- s32 right = (s32)_Buffer[1] + m_RightBuffer[i];
-
- if (left < -32768) left = -32768;
- if (left > 32767) left = 32767;
- _Buffer[0] = (short)left;
-
- if (right < -32768) right = -32768;
- if (right > 32767) right = 32767;
- _Buffer[1] = (short)right;
-
- _Buffer += 2;
- }
- }
-}
void CUCode_Zelda::DoState(PointerWrap &p) {
p.Do(m_CRC);
diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.h b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.h
index 34fb077bd7..96339072a4 100644
--- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.h
+++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.h
@@ -26,84 +26,96 @@
// * L/R Pan
// * (probably) choice of resampling algorithm (point, linear, cubic)
-struct ZeldaVoicePB
+union ZeldaVoicePB
{
- // Read-Write part
- u16 Status; // 0x00 | 1 = play, 0 = stop
- u16 KeyOff; // 0x01 | writing 1 stops voice?
- u16 RatioInt; // 0x02 | Position delta (playback speed)
- u16 Unk03; // 0x03 | unknown
- u16 NeedsReset; // 0x04 | indicates if some values in PB need to be reset
- u16 ReachedEnd; // 0x05 | set to 1 when end reached
- u16 IsBlank; // 0x06 | 0 = normal sound, 1 = samples are always the same
- u16 Unk07; // 0x07 | unknown, in zelda always 0x0010
- u16 SoundType; // 0x08 | Sound type: so far in zww: 0x0d00 for music, 0x4861 for sfx
- u16 volumeLeft1; // 0x09 | Left Volume 1 // There's probably two of each because they should be ramped within each frame.
- u16 volumeLeft2; // 0x0A | Left Volume 2
- u16 Unk0B[2]; // 0x0B | unknown
- u16 volumeRight1; // 0x0D | Right Volume 1
- u16 volumeRight2; // 0x0E | Right Volume 2
- u16 Unk0F[2]; // 0x0F | unknown // Buffer / something, see 036e/ZWW. there's a pattern here
- u16 volumeUnknown1_1; // 0x11 | Unknown Volume 1
- u16 volumeUnknown1_2; // 0x12 | Unknown Volume 1
- u16 Unk13[2]; // 0x13 | unknown
- u16 volumeUnknown2_1; // 0x15 | Unknown Volume 2
- u16 volumeUnknown2_2; // 0x16 | Unknown Volume 2
- u16 Unk17; // 0x17 | unknown
- u16 Unk18[0x10]; // 0x18 | unknown
- u16 Unk28; // 0x28 | unknown
- u16 Unk29; // 0x29 | unknown // multiplied by 0x2a @ 0d21/ZWW
- u16 Unk2a; // 0x2A | unknown // loaded at 0d2e/ZWW
- u16 Unk2b; // 0x2B | unknown
- u16 Unk2C; // 0x2C | unknown // See 0337/ZWW
- u16 Unk2D; // 0x2D | unknown
- u16 Unk2E; // 0x2E | unknown
- u16 Unk2F; // 0x2F | unknown
- u16 CurSampleFrac; // 0x30 | Fractional part of the current sample position
- u16 Unk31; // 0x31 | unknown / unused
- u16 CurBlock; // 0x32 | current block?
- u16 FixedSample; // 0x33 | sample value for "blank" voices
- u32 RestartPos; // 0x34 | restart pos
- u16 Unk36[2]; // 0x36 | unknown // loaded at 0adc/ZWW in 0x21 decoder
- u32 CurAddr; // 0x38 | current address
- u32 RemLength; // 0x3A | remaining length
- u16 Unk3C; // 0x3C | something to do with the resampler - a DRAM address?
- u16 Unk3D; // 0x3D | unknown
- u16 Unk3E; // 0x3E | unknown
- u16 Unk3F; // 0x3F | unknown
- u16 Unk40[0x10]; // 0x40 | Used as some sort of buffer by IIR
- u16 Unk50[0x8]; // 0x50 | Used as some sort of buffer by 06ff/ZWW
- u16 Unk58[0x8]; // 0x58 |
- u16 Unk60[0x6]; // 0x60 |
- u16 YN2; // 0x66 | YN2
- u16 YN1; // 0x67 | YN1
- u16 Unk68[0x8]; // 0x68 | unknown
- u16 Unk70[0x8]; // 0x70 | unknown // 034b/ZWW - weird
- u16 Unk78; // 0x78 | unknown // ZWW: ModifySample loads and stores. Ramped volume?
- u16 Unk79; // 0x79 | unknown // ZWW: ModifySample loads and stores. Ramped volume?
- u16 Unk7A; // 0x7A | unknown
- u16 Unk7B; // 0x7B | unknown
- u16 Unk7C; // 0x7C | unknown
- u16 Unk7D; // 0x7D | unknown
- u16 Unk7E; // 0x7E | unknown
- u16 Unk7F; // 0x7F | unknown
+ struct {
+ // Read-Write part
+ u16 Status; // 0x00 | 1 = play, 0 = stop
+ u16 KeyOff; // 0x01 | writing 1 stops voice?
+ u16 RatioInt; // 0x02 | Position delta (playback speed)
+ u16 Unk03; // 0x03 | unknown
+ u16 NeedsReset; // 0x04 | indicates if some values in PB need to be reset
+ u16 ReachedEnd; // 0x05 | set to 1 when end reached
+ u16 IsBlank; // 0x06 | 0 = normal sound, 1 = samples are always the same
+ u16 Unk07; // 0x07 | unknown, in zelda always 0x0010. Something to do with number of saved samples (0x68)?
- // Read-only part
- u16 Format; // 0x80 | audio format
- u16 RepeatMode; // 0x81 | 0 = one-shot, non zero = loop
- u16 Unk82; // 0x82 | unknown
- u16 Unk83; // 0x83 | unknown
- u16 Unk84; // 0x84 | IIR Filter # coefs?
- u16 Unk85; // 0x85 | Decides the weird stuff at 035a/ZWW, alco 0cd3
- u16 Unk86; // 0x86 | unknown
- u16 Unk87; // 0x87 | unknown
- u32 LoopStartPos; // 0x88 | loopstart pos
- u32 Length; // 0x8A | sound length
- u32 StartAddr; // 0x8C | sound start address
- u32 UnkAddr; // 0x8E | ???
- u16 Padding[0x10]; // 0x90 | padding
- u16 Padding2[0x10]; // 0xa0 | FIR filter coefs of some sort
- u16 Padding3[0x10]; // 0xb0 | padding
+ u16 SoundType; // 0x08 | "Sound type": so far in zww: 0x0d00 for music (volume mode 0), 0x4861 for sfx (volume mode 1)
+ u16 volumeLeft1; // 0x09 | Left Volume 1 // There's probably two of each because they should be ramped within each frame.
+ u16 volumeLeft2; // 0x0A | Left Volume 2
+ u16 Unk0B; // 0x0B | unknown
+
+ u16 SoundType2; // 0x0C | "Sound type" 2 (not really sound type)
+ u16 volumeRight1; // 0x0D | Right Volume 1
+ u16 volumeRight2; // 0x0E | Right Volume 2
+ u16 Unk0F; // 0x0F | unknown
+
+ u16 SoundType3; // 0x10 | "Sound type" 3 (not really sound type)
+ u16 volumeUnknown1_1; // 0x11 | Unknown Volume 1
+ u16 volumeUnknown1_2; // 0x12 | Unknown Volume 1
+ u16 Unk13; // 0x13 | unknown
+
+ u16 SoundType4; // 0x14 | "Sound type" 4 (not really sound type)
+ u16 volumeUnknown2_1; // 0x15 | Unknown Volume 2
+ u16 volumeUnknown2_2; // 0x16 | Unknown Volume 2
+ u16 Unk17; // 0x17 | unknown
+
+ u16 Unk18[0x10]; // 0x18 | unknown
+ u16 Unk28; // 0x28 | unknown
+ u16 Unk29; // 0x29 | unknown // multiplied by 0x2a @ 0d21/ZWW
+ u16 Unk2a; // 0x2A | unknown // loaded at 0d2e/ZWW
+ u16 Unk2b; // 0x2B | unknown
+ u16 VolumeMode; // 0x2C | unknown // See 0337/ZWW
+ u16 Unk2D; // 0x2D | unknown
+ u16 Unk2E; // 0x2E | unknown
+ u16 Unk2F; // 0x2F | unknown
+ u16 CurSampleFrac; // 0x30 | Fractional part of the current sample position
+ u16 Unk31; // 0x31 | unknown / unused
+ u16 CurBlock; // 0x32 | current block?
+ u16 FixedSample; // 0x33 | sample value for "blank" voices
+ u32 RestartPos; // 0x34 | restart pos
+ u16 Unk36[2]; // 0x36 | unknown // loaded at 0adc/ZWW in 0x21 decoder
+ u32 CurAddr; // 0x38 | current address
+ u32 RemLength; // 0x3A | remaining length
+ u16 Unk3C; // 0x3C | something to do with the resampler - a DRAM address?
+ u16 Unk3D; // 0x3D | unknown
+ u16 Unk3E; // 0x3E | unknown
+ u16 Unk3F; // 0x3F | unknown
+ u16 Unk40[0x10]; // 0x40 | Used as some sort of buffer by IIR
+ u16 Unk50[0x8]; // 0x50 | Used as some sort of buffer by 06ff/ZWW
+ u16 Unk58[0x8]; // 0x58 |
+ u16 Unk60[0x6]; // 0x60 |
+ u16 YN2; // 0x66 | YN2
+ u16 YN1; // 0x67 | YN1
+ u16 Unk68[0x10]; // 0x68 | Saved samples from last decode?
+ u16 FilterState1; // 0x78 | unknown // ZWW: 0c84_FilterBufferInPlace loads and stores. Simply, the filter state.
+ u16 FilterState2; // 0x79 | unknown // ZWW: same as above. these two are active if 0x04a8 != 0.
+ u16 Unk7A; // 0x7A | unknown
+ u16 Unk7B; // 0x7B | unknown
+ u16 Unk7C; // 0x7C | unknown
+ u16 Unk7D; // 0x7D | unknown
+ u16 Unk7E; // 0x7E | unknown
+ u16 Unk7F; // 0x7F | unknown
+
+ // Read-only part
+ u16 Format; // 0x80 | audio format
+ u16 RepeatMode; // 0x81 | 0 = one-shot, non zero = loop
+ u16 Unk82; // 0x82 | unknown
+ u16 Unk83; // 0x83 | unknown
+ u16 Unk84; // 0x84 | IIR Filter # coefs?
+ u16 StopOnSilence; // 0x85 | Stop on silence? (Flag for something volume related. Decides the weird stuff at 035a/ZWW, alco 0cd3)
+ u16 Unk86; // 0x86 | unknown
+ u16 Unk87; // 0x87 | unknown
+ u32 LoopStartPos; // 0x88 | loopstart pos
+ u32 Length; // 0x8A | sound length
+ u32 StartAddr; // 0x8C | sound start address
+ u32 UnkAddr; // 0x8E | ???
+ u16 Padding[0x10]; // 0x90 | padding
+ u16 Padding2[0x8]; // 0xa0 | FIR filter coefs of some sort
+ u16 FilterEnable; // 0xa8 | FilterBufferInPlace enable.
+ u16 Padding3[0x7]; // 0xa9 | padding
+ u16 Padding4[0x10]; // 0xb0 | padding
+ };
+ u16 raw[0xc0];
};
namespace {
@@ -129,7 +141,7 @@ public:
int *templbuffer;
int *temprbuffer;
- // simple dump ...
+ // Simple dump ...
int DumpAFC(u8* pIn, const int size, const int srate);
u32 Read32()
@@ -150,6 +162,9 @@ private:
DSP_FRAME_END = 0xDCD10005,
};
+ // These map CRC to behaviour.
+ bool LuigiStyle() const;
+
u32 m_CRC;
// These are the only dynamically allocated things allowed in the ucode.
@@ -161,6 +176,7 @@ private:
// If you add variables, remember to keep DoState() and the constructor up to date.
s16 m_AFCCoefTable[32];
+ s16 m_MiscTable[0x280];
bool m_bSyncInProgress;
u32 m_MaxVoice;
diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda_Voice.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda_Voice.cpp
index 9518077d67..28791e732e 100644
--- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda_Voice.cpp
+++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda_Voice.cpp
@@ -444,27 +444,182 @@ void CUCode_Zelda::RenderAddVoice(ZeldaVoicePB &PB, s32* _LeftBuffer, s32* _Righ
PB.NeedsReset = 0;
}
+// ContinueWithBlock:
+
+ if (PB.FilterEnable)
+ { // 0x04a8
+ for (int i = 0; i < _Size; i++)
+ {
+ // TODO: Apply filter from ZWW: 0c84_FilterBufferInPlace
+ }
+ }
+
for (int i = 0; i < _Size; i++)
{
- /*if(PB.volumeLeft2)
- lastLeft = PB.volumeLeft2;
- if(PB.volumeRight2)
- lastRight = PB.volumeRight2;*/
+
+ }
+
+ if (PB.VolumeMode != 0)
+ {
+ // Complex volume mode. Let's see what we can do.
+ if (PB.StopOnSilence) {
+ PB.raw[0x2b] = PB.raw[0x2a] >> 1;
+ if (PB.raw[0x2b] == 0)
+ {
+ PB.KeyOff = 1;
+ }
+ }
- // TODO: Some noises in Zelda WW (birds, etc) have a volume of 0
- // Really not sure about the masking here, but it seems to kill off some overly loud
- // sounds in Zelda TP. Needs investigation.
- s32 left = _LeftBuffer[i] + (m_TempBuffer[i] * (float)(
- (PB.volumeLeft1 & 0x1FFF) + (PB.volumeLeft2 & 0x1FFF)) * 0.00005);
- s32 right = _RightBuffer[i] + (m_TempBuffer[i] * (float)(
- (PB.volumeRight1 & 0x1FFF) + (PB.volumeRight2 & 0x1FFF)) * 0.00005);
+ short AX0L = PB.raw[0x28] >> 8;
+ short AX0H = PB.raw[0x28] & 0x7F;
+ short AX1L = AX0L ^ 0x7F;
+ short AX1H = AX1L ^ 0x7F;
+ AX0L = m_MiscTable[0x200 + AX0L];
+ AX0H = m_MiscTable[0x200 + AX0H];
+ AX1L = m_MiscTable[0x200 + AX1L];
+ AX1H = m_MiscTable[0x200 + AX1H];
- if (left < -32768) left = -32768;
- if (left > 32767) left = 32767;
- _LeftBuffer[i] = left; //(s32)(((float)left * (float)PB.volumeLeft) / 1000.f);
+ short b00[16];
+ b00[0] = AX1L * AX1H >> 16;
+ b00[1] = AX0L * AX1H >> 16;
+ b00[2] = AX0H * AX1L >> 16;
+ b00[3] = AX0L * AX0H >> 16;
+ for (int i = 0; i < 4; i++) {
+ b00[i + 4] = b00[i] * PB.raw[0x2a] >> 16;
+ }
- if (right < -32768) right = -32768;
- if (right > 32767) right = 32767;
- _RightBuffer[i] = right; //(s32)(((float)right * (float)PB.volumeRight) / 1000.0f);
+ // ... not done yet...
+
+ for (int count = 0; count < 8; count++)
+ {
+ // The 8 buffers to mix to: 0d00, 0d60, 0f40 0ca0 0e80 0ee0 0c00 0c50
+
+ }
+
+ // this should be scrapped
+ for (int i = 0; i < _Size; i++)
+ {
+ // arbitrary
+ s32 left = m_TempBuffer[i] >> 3;
+ s32 right = m_TempBuffer[i] >> 3;
+
+ _LeftBuffer[i] += left; //(s32)(((float)left * (float)PB.volumeLeft) / 1000.f);
+ _RightBuffer[i] += right; //(s32)(((float)right * (float)PB.volumeRight) / 1000.0f);
+ }
+ }
+ else
+ {
+ // ZWW 0355
+ if (PB.StopOnSilence)
+ {
+ int sum = 0;
+ int addr = 0x0a;
+ for (int i = 0; i < 6; i++)
+ {
+ u16 value = PB.raw[addr];
+ addr--;
+ value >>= 1;
+ PB.raw[addr] = value;
+ sum += value;
+ addr += 5;
+ }
+ if (sum == 0) {
+ PB.KeyOff = 1;
+ }
+ }
+
+ // Seems there are 6 temporary output buffers.
+ for (int count = 0; count < 6; count++)
+ {
+ int addr = 0x08;
+
+ // we'll have to keep a map of buffers I guess...
+ u16 dest_buffer_address = PB.raw[addr++];
+
+ bool mix = dest_buffer_address ? true : false;
+
+ u16 vol2 = PB.raw[addr++];
+ u16 vol1 = PB.raw[addr++];
+
+ int delta = (vol2 - vol1) << 11;
+
+ addr--;
+
+ u32 ramp = vol1 << 16;
+ if (mix) {
+ // 0ca9_RampedMultiplyAddBuffer
+ for (int i = 0; i < _Size; i++)
+ {
+ int value = m_TempBuffer[i];
+
+ // TODO - add to buffer specified by dest_buffer_address
+ switch (count)
+ {
+ // These really should be 32.
+ case 0: _LeftBuffer[i] += (u64)value * ramp >> 29; break;
+ case 1: _RightBuffer[i] += (u64)value * ramp >> 29; break;
+ }
+ if ((i & 1) == 0 && i < 64) {
+ ramp += delta;
+ }
+ }
+ if (_Size < 32)
+ {
+ ramp += delta * (_Size - 32);
+ }
+ }
+ // Update the PB with the volume actually reached.
+ PB.raw[addr++] = ramp >> 16;
+
+ addr++;
+ }
}
}
+
+
+// size is in stereo samples.
+void CUCode_Zelda::MixAdd(short* _Buffer, int _Size)
+{
+ if (_Size > 256 * 1024)
+ _Size = 256 * 1024;
+
+ memset(m_LeftBuffer, 0, _Size * sizeof(s32));
+ memset(m_RightBuffer, 0, _Size * sizeof(s32));
+
+ for (u32 i = 0; i < m_NumVoices; i++)
+ {
+ u32 flags = m_SyncFlags[(i >> 4) & 0xF];
+ if (!(flags & 1 << (15 - (i & 0xF))))
+ continue;
+
+ ZeldaVoicePB pb;
+ ReadVoicePB(m_VoicePBsAddr + (i * 0x180), pb);
+
+ if (pb.Status == 0)
+ continue;
+ if (pb.KeyOff != 0)
+ continue;
+
+ RenderAddVoice(pb, m_LeftBuffer, m_RightBuffer, _Size);
+ WritebackVoicePB(m_VoicePBsAddr + (i * 0x180), pb);
+ }
+
+ if (_Buffer)
+ {
+ for (u32 i = 0; i < _Size; i++)
+ {
+ s32 left = (s32)_Buffer[0] + m_LeftBuffer[i];
+ s32 right = (s32)_Buffer[1] + m_RightBuffer[i];
+
+ if (left < -32768) left = -32768;
+ if (left > 32767) left = 32767;
+ _Buffer[0] = (short)left;
+
+ if (right < -32768) right = -32768;
+ if (right > 32767) right = 32767;
+ _Buffer[1] = (short)right;
+
+ _Buffer += 2;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.cpp
index e1e0be5765..2bfded6422 100644
--- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.cpp
+++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.cpp
@@ -22,7 +22,6 @@
#include "UCode_AX.h"
#include "UCode_AXWii.h"
#include "UCode_Zelda.h"
-#include "UCode_Jac.h"
#include "UCode_ROM.h"
#include "UCode_CARD.h"
#include "UCode_InitAudioSystem.h"
@@ -61,8 +60,7 @@ IUCode* UCodeFactory(u32 _CRC, CMailHandler& _rMailHandler)
case 0x0267d05a: // http://forums.dolphin-emu.com/thread-2134.html Pikmin PAL
case 0x4be6a5cb: // AC, Pikmin
INFO_LOG(DSPHLE, "CRC %08x: JAC (early Zelda) ucode chosen", _CRC);
- return new CUCode_Jac(_rMailHandler);
-// return new CUCode_Zelda(_rMailHandler, _CRC);
+ return new CUCode_Zelda(_rMailHandler, _CRC);
case 0x6CA33A6D: // DK Jungle Beat
case 0x86840740: // Zelda WW - US