mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
Merge pull request #2846 from delroth/new-zelda-hle
Reimplement Zelda HLE
This commit is contained in:
@@ -74,9 +74,6 @@ set(SRCS ActionReplay.cpp
|
||||
HW/DSPHLE/UCodes/ROM.cpp
|
||||
HW/DSPHLE/UCodes/UCodes.cpp
|
||||
HW/DSPHLE/UCodes/Zelda.cpp
|
||||
HW/DSPHLE/UCodes/ZeldaADPCM.cpp
|
||||
HW/DSPHLE/UCodes/ZeldaSynth.cpp
|
||||
HW/DSPHLE/UCodes/ZeldaVoice.cpp
|
||||
HW/DSPHLE/MailHandler.cpp
|
||||
HW/DSPHLE/DSPHLE.cpp
|
||||
HW/DSPLLE/DSPDebugInterface.cpp
|
||||
|
||||
@@ -284,6 +284,7 @@ void SConfig::SaveDSPSettings(IniFile& ini)
|
||||
|
||||
dsp->Set("EnableJIT", m_DSPEnableJIT);
|
||||
dsp->Set("DumpAudio", m_DumpAudio);
|
||||
dsp->Set("DumpUCode", m_DumpUCode);
|
||||
dsp->Set("Backend", sBackend);
|
||||
dsp->Set("Volume", m_Volume);
|
||||
dsp->Set("CaptureLog", m_DSPCaptureLog);
|
||||
@@ -543,6 +544,7 @@ void SConfig::LoadDSPSettings(IniFile& ini)
|
||||
|
||||
dsp->Get("EnableJIT", &m_DSPEnableJIT, true);
|
||||
dsp->Get("DumpAudio", &m_DumpAudio, false);
|
||||
dsp->Get("DumpUCode", &m_DumpUCode, false);
|
||||
#if defined __linux__ && HAVE_ALSA
|
||||
dsp->Get("Backend", &sBackend, BACKEND_ALSA);
|
||||
#elif defined __APPLE__
|
||||
|
||||
@@ -255,6 +255,7 @@ struct SConfig : NonCopyable
|
||||
bool m_DSPCaptureLog;
|
||||
bool m_DumpAudio;
|
||||
bool m_IsMuted;
|
||||
bool m_DumpUCode;
|
||||
int m_Volume;
|
||||
std::string sBackend;
|
||||
|
||||
|
||||
@@ -108,9 +108,6 @@
|
||||
<ClCompile Include="HW\DSPHLE\UCodes\INIT.cpp" />
|
||||
<ClCompile Include="HW\DSPHLE\UCodes\ROM.cpp" />
|
||||
<ClCompile Include="HW\DSPHLE\UCodes\Zelda.cpp" />
|
||||
<ClCompile Include="HW\DSPHLE\UCodes\ZeldaADPCM.cpp" />
|
||||
<ClCompile Include="HW\DSPHLE\UCodes\ZeldaSynth.cpp" />
|
||||
<ClCompile Include="HW\DSPHLE\UCodes\ZeldaVoice.cpp" />
|
||||
<ClCompile Include="HW\DSPLLE\DSPDebugInterface.cpp" />
|
||||
<ClCompile Include="HW\DSPLLE\DSPHost.cpp" />
|
||||
<ClCompile Include="HW\DSPLLE\DSPLLE.cpp" />
|
||||
|
||||
@@ -336,15 +336,6 @@
|
||||
<ClCompile Include="HW\DSPHLE\UCodes\Zelda.cpp">
|
||||
<Filter>HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE\uCodes</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HW\DSPHLE\UCodes\ZeldaADPCM.cpp">
|
||||
<Filter>HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE\uCodes</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HW\DSPHLE\UCodes\ZeldaSynth.cpp">
|
||||
<Filter>HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE\uCodes</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HW\DSPHLE\UCodes\ZeldaVoice.cpp">
|
||||
<Filter>HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE\uCodes</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HW\DSPHLE\UCodes\UCodes.cpp">
|
||||
<Filter>HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE\uCodes</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "Common/ChunkFile.h"
|
||||
#include "Core/HW/DSP.h"
|
||||
#include "Core/HW/DSPHLE/MailHandler.h"
|
||||
|
||||
CMailHandler::CMailHandler()
|
||||
@@ -14,9 +15,20 @@ CMailHandler::~CMailHandler()
|
||||
Clear();
|
||||
}
|
||||
|
||||
void CMailHandler::PushMail(u32 _Mail)
|
||||
void CMailHandler::PushMail(u32 _Mail, bool interrupt)
|
||||
{
|
||||
m_Mails.push(_Mail);
|
||||
if (interrupt)
|
||||
{
|
||||
if (m_Mails.empty())
|
||||
{
|
||||
DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Mails.front().second = true;
|
||||
}
|
||||
}
|
||||
m_Mails.emplace(_Mail, false);
|
||||
DEBUG_LOG(DSP_MAIL, "DSP writes 0x%08x", _Mail);
|
||||
}
|
||||
|
||||
@@ -25,7 +37,7 @@ u16 CMailHandler::ReadDSPMailboxHigh()
|
||||
// check if we have a mail for the core
|
||||
if (!m_Mails.empty())
|
||||
{
|
||||
u16 result = (m_Mails.front() >> 16) & 0xFFFF;
|
||||
u16 result = (m_Mails.front().first >> 16) & 0xFFFF;
|
||||
return result;
|
||||
}
|
||||
return 0x00;
|
||||
@@ -36,8 +48,15 @@ u16 CMailHandler::ReadDSPMailboxLow()
|
||||
// check if we have a mail for the core
|
||||
if (!m_Mails.empty())
|
||||
{
|
||||
u16 result = m_Mails.front() & 0xFFFF;
|
||||
u16 result = m_Mails.front().first & 0xFFFF;
|
||||
bool generate_interrupt = m_Mails.front().second;
|
||||
m_Mails.pop();
|
||||
|
||||
if (generate_interrupt)
|
||||
{
|
||||
DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
return 0x00;
|
||||
@@ -59,7 +78,7 @@ void CMailHandler::Halt(bool _Halt)
|
||||
if (_Halt)
|
||||
{
|
||||
Clear();
|
||||
m_Mails.push(0x80544348);
|
||||
PushMail(0x80544348);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,21 +92,25 @@ void CMailHandler::DoState(PointerWrap &p)
|
||||
for (int i = 0; i < sz; i++)
|
||||
{
|
||||
u32 mail = 0;
|
||||
bool interrupt = false;
|
||||
p.Do(mail);
|
||||
m_Mails.push(mail);
|
||||
p.Do(interrupt);
|
||||
m_Mails.emplace(mail, interrupt);
|
||||
}
|
||||
}
|
||||
else // WRITE and MEASURE
|
||||
{
|
||||
std::queue<u32> temp;
|
||||
std::queue<std::pair<u32, bool>> temp;
|
||||
int sz = (int)m_Mails.size();
|
||||
p.Do(sz);
|
||||
for (int i = 0; i < sz; i++)
|
||||
{
|
||||
u32 value = m_Mails.front();
|
||||
u32 value = m_Mails.front().first;
|
||||
bool interrupt = m_Mails.front().second;
|
||||
m_Mails.pop();
|
||||
p.Do(value);
|
||||
temp.push(value);
|
||||
p.Do(interrupt);
|
||||
temp.emplace(value, interrupt);
|
||||
}
|
||||
if (!m_Mails.empty())
|
||||
PanicAlert("CMailHandler::DoState - WTF?");
|
||||
@@ -95,9 +118,10 @@ void CMailHandler::DoState(PointerWrap &p)
|
||||
// Restore queue.
|
||||
for (int i = 0; i < sz; i++)
|
||||
{
|
||||
u32 value = temp.front();
|
||||
u32 value = temp.front().first;
|
||||
bool interrupt = temp.front().second;
|
||||
temp.pop();
|
||||
m_Mails.push(value);
|
||||
m_Mails.emplace(value, interrupt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <queue>
|
||||
#include <utility>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
class PointerWrap;
|
||||
@@ -15,7 +17,7 @@ public:
|
||||
CMailHandler();
|
||||
~CMailHandler();
|
||||
|
||||
void PushMail(u32 _Mail);
|
||||
void PushMail(u32 _Mail, bool interrupt = false);
|
||||
void Clear();
|
||||
void Halt(bool _Halt);
|
||||
void DoState(PointerWrap &p);
|
||||
@@ -24,20 +26,7 @@ public:
|
||||
u16 ReadDSPMailboxHigh();
|
||||
u16 ReadDSPMailboxLow();
|
||||
|
||||
u32 GetNextMail() const
|
||||
{
|
||||
if (!m_Mails.empty())
|
||||
{
|
||||
return m_Mails.front();
|
||||
}
|
||||
else
|
||||
{
|
||||
// WARN_LOG(DSPHLE, "GetNextMail: No mails");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// mail handler
|
||||
std::queue<u32> m_Mails;
|
||||
std::queue<std::pair<u32, bool>> m_Mails;
|
||||
};
|
||||
|
||||
@@ -7,6 +7,81 @@
|
||||
#include "Core/HW/DSPHLE/UCodes/GBA.h"
|
||||
#include "Core/HW/DSPHLE/UCodes/UCodes.h"
|
||||
|
||||
void ProcessGBACrypto(u32 address)
|
||||
{
|
||||
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++, address += 4)
|
||||
((u32*)&sec_params)[i] = HLEMemory_Read_U32(address);
|
||||
|
||||
// This is the main decrypt routine
|
||||
u16 x11 = 0, x12 = 0,
|
||||
x20 = 0, x21 = 0, x22 = 0, x23 = 0;
|
||||
|
||||
x20 = Common::swap16(sec_params.key[0]) ^ 0x6f64;
|
||||
x21 = Common::swap16(sec_params.key[1]) ^ 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) | 0x3f80) & 0x3f80ffff) << 1;
|
||||
s16 t_low = (s8)(t >> 8);
|
||||
t += (t_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*)HLEMemory_Get_Pointer(sec_params.dest_addr) = Common::swap32((x20 << 16) | x21);
|
||||
*(u32*)HLEMemory_Get_Pointer(sec_params.dest_addr+4) = Common::swap32((x22 << 16) | x23);
|
||||
|
||||
// Done!
|
||||
DEBUG_LOG(DSPHLE, "\n%08x -> key: %08x, len: %08x, dest_addr: %08x, unk1: %08x, unk2: %08x"
|
||||
" 22: %04x, 23: %04x",
|
||||
address,
|
||||
*(u32*)sec_params.key, sec_params.length, sec_params.dest_addr,
|
||||
*(u32*)sec_params.unk1, *(u32*)sec_params.unk2,
|
||||
x22, x23);
|
||||
}
|
||||
|
||||
GBAUCode::GBAUCode(DSPHLE *dsphle, u32 crc)
|
||||
: UCodeInterface(dsphle, crc)
|
||||
{
|
||||
@@ -48,79 +123,8 @@ void GBAUCode::HandleMail(u32 mail)
|
||||
else if (nextmail_is_mramaddr)
|
||||
{
|
||||
nextmail_is_mramaddr = false;
|
||||
u32 mramaddr = mail;
|
||||
|
||||
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] = HLEMemory_Read_U32(mramaddr);
|
||||
|
||||
// This is the main decrypt routine
|
||||
u16 x11 = 0, x12 = 0,
|
||||
x20 = 0, x21 = 0, x22 = 0, x23 = 0;
|
||||
|
||||
x20 = Common::swap16(sec_params.key[0]) ^ 0x6f64;
|
||||
x21 = Common::swap16(sec_params.key[1]) ^ 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) | 0x3f80) & 0x3f80ffff) << 1;
|
||||
s16 t_low = (s8)(t >> 8);
|
||||
t += (t_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*)HLEMemory_Get_Pointer(sec_params.dest_addr) = Common::swap32((x20 << 16) | x21);
|
||||
*(u32*)HLEMemory_Get_Pointer(sec_params.dest_addr+4) = Common::swap32((x22 << 16) | x23);
|
||||
|
||||
// Done!
|
||||
DEBUG_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);
|
||||
ProcessGBACrypto(mail);
|
||||
|
||||
calc_done = true;
|
||||
m_mail_handler.PushMail(DSP_DONE);
|
||||
|
||||
@@ -6,6 +6,11 @@
|
||||
|
||||
#include "Core/HW/DSPHLE/UCodes/UCodes.h"
|
||||
|
||||
// Computes two 32 bit integers to be returned to the game, based on the
|
||||
// provided crypto parameters at the provided MRAM address. The integers are
|
||||
// written back to RAM at the dest address provided in the crypto parameters.
|
||||
void ProcessGBACrypto(u32 address);
|
||||
|
||||
struct GBAUCode : public UCodeInterface
|
||||
{
|
||||
GBAUCode(DSPHLE *dsphle, u32 crc);
|
||||
|
||||
@@ -10,6 +10,7 @@ INITUCode::INITUCode(DSPHLE *dsphle, u32 crc)
|
||||
: UCodeInterface(dsphle, crc)
|
||||
{
|
||||
DEBUG_LOG(DSPHLE, "INITUCode - initialized");
|
||||
m_mail_handler.PushMail(0x80544348);
|
||||
}
|
||||
|
||||
INITUCode::~INITUCode()
|
||||
@@ -22,11 +23,6 @@ void INITUCode::Init()
|
||||
|
||||
void INITUCode::Update()
|
||||
{
|
||||
if (m_mail_handler.IsEmpty())
|
||||
{
|
||||
m_mail_handler.PushMail(0x80544348);
|
||||
// HALT
|
||||
}
|
||||
}
|
||||
|
||||
u32 INITUCode::GetUpdateMs()
|
||||
|
||||
@@ -92,17 +92,18 @@ void ROMUCode::BootUCode()
|
||||
(u8*)HLEMemory_Get_Pointer(m_current_ucode.m_ram_address),
|
||||
m_current_ucode.m_length);
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
std::string ucode_dump_path = StringFromFormat(
|
||||
"%sDSP_UC_%08X.bin", File::GetUserPath(D_DUMPDSP_IDX).c_str(), ector_crc);
|
||||
|
||||
File::IOFile fp(ucode_dump_path, "wb");
|
||||
if (fp)
|
||||
if (SConfig::GetInstance().m_DumpUCode)
|
||||
{
|
||||
fp.WriteArray((u8*)HLEMemory_Get_Pointer(m_current_ucode.m_ram_address),
|
||||
m_current_ucode.m_length);
|
||||
std::string ucode_dump_path = StringFromFormat(
|
||||
"%sDSP_UC_%08X.bin", File::GetUserPath(D_DUMPDSP_IDX).c_str(), ector_crc);
|
||||
|
||||
File::IOFile fp(ucode_dump_path, "wb");
|
||||
if (fp)
|
||||
{
|
||||
fp.WriteArray((u8*)HLEMemory_Get_Pointer(m_current_ucode.m_ram_address),
|
||||
m_current_ucode.m_length);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
DEBUG_LOG(DSPHLE, "CurrentUCode SOURCE Addr: 0x%08x", m_current_ucode.m_ram_address);
|
||||
DEBUG_LOG(DSPHLE, "CurrentUCode Length: 0x%08x", m_current_ucode.m_length);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "Common/Hash.h"
|
||||
#include "Common/StringUtil.h"
|
||||
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/HW/DSPHLE/UCodes/AX.h"
|
||||
#include "Core/HW/DSPHLE/UCodes/AXWii.h"
|
||||
#include "Core/HW/DSPHLE/UCodes/CARD.h"
|
||||
@@ -51,27 +52,18 @@ UCodeInterface* UCodeFactory(u32 crc, DSPHLE* dsphle, bool wii)
|
||||
INFO_LOG(DSPHLE, "CRC %08x: AX ucode chosen", crc);
|
||||
return new AXUCode(dsphle, crc);
|
||||
|
||||
case 0x6ba3b3ea: // IPL - PAL
|
||||
case 0x24b22038: // IPL - NTSC/NTSC-JAP
|
||||
case 0x42f64ac4: // Luigi's Mansion
|
||||
case 0x4be6a5cb: // AC, Pikmin
|
||||
INFO_LOG(DSPHLE, "CRC %08x: JAC (early Zelda) ucode chosen", crc);
|
||||
return new ZeldaUCode(dsphle, crc);
|
||||
|
||||
case 0x6CA33A6D: // DK Jungle Beat
|
||||
case 0x86840740: // Zelda WW - US
|
||||
case 0x56d36052: // Mario Sunshine
|
||||
case 0x2fcdf1ec: // Mario Kart, Zelda 4 Swords
|
||||
case 0x267fd05a: // Pikmin PAL
|
||||
INFO_LOG(DSPHLE, "CRC %08x: Zelda ucode chosen", crc);
|
||||
return new ZeldaUCode(dsphle, crc);
|
||||
|
||||
// Wii CRCs
|
||||
case 0xb7eb9a9c: // Wii Pikmin - PAL
|
||||
case 0xeaeb38cc: // Wii Pikmin 2 - PAL
|
||||
case 0x6c3f6f94: // Zelda TP - PAL
|
||||
case 0xd643001f: // Mario Galaxy - PAL / Wii DK Jungle Beat - PAL
|
||||
INFO_LOG(DSPHLE, "CRC %08x: Zelda Wii ucode chosen\n", crc);
|
||||
case 0x6ca33a6d: // Zelda TP GC - US
|
||||
case 0xd643001f: // Super Mario Galaxy - US
|
||||
case 0x6ba3b3ea: // GC IPL - PAL
|
||||
case 0x24b22038: // GC IPL - US
|
||||
case 0x2fcdf1ec: // Zelda FSA - US
|
||||
case 0x4be6a5cb: // Pikmin 1 GC - US
|
||||
case 0x267fd05a: // Pikmin 1 GC - PAL
|
||||
case 0x42f64ac4: // Luigi's Mansion - US
|
||||
case 0x56d36052: // Super Mario Sunshine - US
|
||||
case 0x6c3f6f94: // Zelda TP Wii - US
|
||||
case 0xeaeb38cc: // Pikmin 1/2 New Play Control Wii - US
|
||||
return new ZeldaUCode(dsphle, crc);
|
||||
|
||||
case 0x2ea36ce6: // Some Wii demos
|
||||
@@ -142,17 +134,18 @@ void UCodeInterface::PrepareBootUCode(u32 mail)
|
||||
(u8*)HLEMemory_Get_Pointer(m_next_ucode.iram_mram_addr),
|
||||
m_next_ucode.iram_size);
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
std::string ucode_dump_path = StringFromFormat(
|
||||
"%sDSP_UC_%08X.bin", File::GetUserPath(D_DUMPDSP_IDX).c_str(), ector_crc);
|
||||
|
||||
File::IOFile fp(ucode_dump_path, "wb");
|
||||
if (fp)
|
||||
if (SConfig::GetInstance().m_DumpUCode)
|
||||
{
|
||||
fp.WriteArray((u8*)Memory::GetPointer(m_next_ucode.iram_mram_addr),
|
||||
m_next_ucode.iram_size);
|
||||
std::string ucode_dump_path = StringFromFormat(
|
||||
"%sDSP_UC_%08X.bin", File::GetUserPath(D_DUMPDSP_IDX).c_str(), ector_crc);
|
||||
|
||||
File::IOFile fp(ucode_dump_path, "wb");
|
||||
if (fp)
|
||||
{
|
||||
fp.WriteArray((u8*)Memory::GetPointer(m_next_ucode.iram_mram_addr),
|
||||
m_next_ucode.iram_size);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
DEBUG_LOG(DSPHLE, "PrepareBootUCode 0x%08x", ector_crc);
|
||||
DEBUG_LOG(DSPHLE, "DRAM -> MRAM: src %04x dst %08x size %04x",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,68 +0,0 @@
|
||||
// Copyright 2009 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/MathUtil.h"
|
||||
#include "Core/HW/DSPHLE/UCodes/Zelda.h"
|
||||
|
||||
void ZeldaUCode::AFCdecodebuffer(const s16 *coef, const char *src, signed short *out, short *histp, short *hist2p, int type)
|
||||
{
|
||||
// First 2 nibbles are ADPCM scale etc.
|
||||
short delta = 1 << (((*src) >> 4) & 0xf);
|
||||
short idx = (*src) & 0xf;
|
||||
src++;
|
||||
|
||||
short nibbles[16];
|
||||
if (type == 9)
|
||||
{
|
||||
for (int i = 0; i < 16; i += 2)
|
||||
{
|
||||
nibbles[i + 0] = *src >> 4;
|
||||
nibbles[i + 1] = *src & 15;
|
||||
src++;
|
||||
}
|
||||
|
||||
for (auto& nibble : nibbles)
|
||||
{
|
||||
if (nibble >= 8)
|
||||
nibble = nibble - 16;
|
||||
nibble <<= 11;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// In Pikmin, Dolphin's engine sound is using AFC type 5, even though such a sound is hard
|
||||
// to compare, it seems like to sound exactly like a real GC
|
||||
// In Super Mario Sunshine, you can get such a sound by talking to/jumping on anyone
|
||||
for (int i = 0; i < 16; i += 4)
|
||||
{
|
||||
nibbles[i + 0] = (*src >> 6) & 0x03;
|
||||
nibbles[i + 1] = (*src >> 4) & 0x03;
|
||||
nibbles[i + 2] = (*src >> 2) & 0x03;
|
||||
nibbles[i + 3] = (*src >> 0) & 0x03;
|
||||
src++;
|
||||
}
|
||||
|
||||
for (auto& nibble : nibbles)
|
||||
{
|
||||
if (nibble >= 2)
|
||||
nibble = nibble - 4;
|
||||
nibble <<= 13;
|
||||
}
|
||||
}
|
||||
|
||||
short hist = *histp;
|
||||
short hist2 = *hist2p;
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
int sample = delta * nibbles[i] + ((int)hist * coef[idx * 2]) + ((int)hist2 * coef[idx * 2 + 1]);
|
||||
sample >>= 11;
|
||||
MathUtil::Clamp(&sample, -32768, 32767);
|
||||
out[i] = sample;
|
||||
hist2 = hist;
|
||||
hist = (short)sample;
|
||||
}
|
||||
*histp = hist;
|
||||
*hist2p = hist2;
|
||||
}
|
||||
@@ -1,173 +0,0 @@
|
||||
// Copyright 2008 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "Core/HW/DSPHLE/UCodes/UCodes.h"
|
||||
#include "Core/HW/DSPHLE/UCodes/Zelda.h"
|
||||
|
||||
void ZeldaUCode::RenderSynth_RectWave(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
|
||||
{
|
||||
s64 ratio = ((s64)PB.RatioInt << 16) * 16;
|
||||
s64 TrueSamplePosition = PB.CurSampleFrac;
|
||||
|
||||
// PB.Format == 0x3 -> Rectangular Wave, 0x0 -> Square Wave
|
||||
unsigned int mask = PB.Format ? 3 : 1;
|
||||
// int shift = PB.Format ? 2 : 1; // Unused?
|
||||
|
||||
u32 pos[2] = {0, 0};
|
||||
int i = 0;
|
||||
|
||||
if (PB.KeyOff != 0)
|
||||
return;
|
||||
|
||||
if (PB.NeedsReset)
|
||||
{
|
||||
PB.RemLength = PB.Length - PB.RestartPos;
|
||||
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
|
||||
PB.ReachedEnd = 0;
|
||||
}
|
||||
|
||||
_lRestart:
|
||||
if (PB.ReachedEnd)
|
||||
{
|
||||
PB.ReachedEnd = 0;
|
||||
|
||||
if (PB.RepeatMode == 0)
|
||||
{
|
||||
PB.KeyOff = 1;
|
||||
PB.RemLength = 0;
|
||||
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1) + PB.Length;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
PB.RestartPos = PB.LoopStartPos;
|
||||
PB.RemLength = PB.Length - PB.RestartPos;
|
||||
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
|
||||
pos[1] = 0; pos[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
while (i < _Size)
|
||||
{
|
||||
s16 sample = ((pos[1] & mask) == mask) ? 0xc000 : 0x4000;
|
||||
|
||||
TrueSamplePosition += (ratio >> 16);
|
||||
|
||||
_Buffer[i++] = (s32)sample;
|
||||
|
||||
(*(u64*)&pos) += ratio;
|
||||
if ((pos[1] + ((PB.CurAddr - PB.StartAddr) >> 1)) >= PB.Length)
|
||||
{
|
||||
PB.ReachedEnd = 1;
|
||||
goto _lRestart;
|
||||
}
|
||||
}
|
||||
|
||||
if (PB.RemLength < pos[1])
|
||||
{
|
||||
PB.RemLength = 0;
|
||||
PB.ReachedEnd = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
PB.RemLength -= pos[1];
|
||||
}
|
||||
|
||||
PB.CurSampleFrac = TrueSamplePosition & 0xFFFF;
|
||||
}
|
||||
|
||||
void ZeldaUCode::RenderSynth_SawWave(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
|
||||
{
|
||||
s32 ratio = (s32)ceil((float)PB.RatioInt / 3);
|
||||
s64 pos = PB.CurSampleFrac;
|
||||
|
||||
for (int i = 0; i < _Size; i++)
|
||||
{
|
||||
pos += ratio;
|
||||
_Buffer[i] = pos & 0xFFFF;
|
||||
}
|
||||
|
||||
PB.CurSampleFrac = pos & 0xFFFF;
|
||||
}
|
||||
|
||||
void ZeldaUCode::RenderSynth_Constant(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
|
||||
{
|
||||
// TODO: Header, footer
|
||||
for (int i = 0; i < _Size; i++)
|
||||
_Buffer[i] = (s32)PB.RatioInt;
|
||||
}
|
||||
|
||||
// A piece of code from LLE so we can see how the wrap register affects the sound
|
||||
|
||||
inline u16 AddValueToReg(u32 ar, s32 ix)
|
||||
{
|
||||
u32 wr = 0x3f;
|
||||
u32 mx = (wr | 1) << 1;
|
||||
u32 nar = ar + ix;
|
||||
u32 dar = (nar ^ ar ^ ix) & mx;
|
||||
|
||||
if (ix >= 0)
|
||||
{
|
||||
if (dar > wr) //overflow
|
||||
nar -= wr + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((((nar + wr + 1) ^ nar) & dar) <= wr) //underflow or below min for mask
|
||||
nar += wr + 1;
|
||||
}
|
||||
return nar;
|
||||
}
|
||||
|
||||
void ZeldaUCode::RenderSynth_WaveTable(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
|
||||
{
|
||||
u16 address;
|
||||
|
||||
switch (PB.Format)
|
||||
{
|
||||
default:
|
||||
case 0x0004:
|
||||
address = 0x140;
|
||||
break;
|
||||
|
||||
case 0x0007:
|
||||
address = 0x100;
|
||||
break;
|
||||
|
||||
case 0x000b:
|
||||
address = 0x180;
|
||||
break;
|
||||
|
||||
case 0x000c:
|
||||
address = 0x1c0;
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: Resample this!
|
||||
INFO_LOG(DSPHLE, "Synthesizing the incomplete format 0x%04x", PB.Format);
|
||||
|
||||
u64 ACC0 = PB.CurSampleFrac << 6;
|
||||
|
||||
ACC0 &= 0xffff003fffffULL;
|
||||
|
||||
address = AddValueToReg(address, ((ACC0 >> 16) & 0xffff));
|
||||
ACC0 &= 0xffff0000ffffULL;
|
||||
|
||||
for (int i = 0; i < 0x50; i++)
|
||||
{
|
||||
_Buffer[i] = m_misc_table[address];
|
||||
|
||||
ACC0 += PB.RatioInt << 5;
|
||||
address = AddValueToReg(address, ((ACC0 >> 16) & 0xffff));
|
||||
|
||||
ACC0 &= 0xffff0000ffffULL;
|
||||
}
|
||||
|
||||
ACC0 += address << 16;
|
||||
PB.CurSampleFrac = (ACC0 >> 6) & 0xffff;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -66,7 +66,7 @@ static Common::Event g_compressAndDumpStateSyncEvent;
|
||||
static std::thread g_save_thread;
|
||||
|
||||
// Don't forget to increase this after doing changes on the savestate system
|
||||
static const u32 STATE_VERSION = 44; // Last changed in PR 2464
|
||||
static const u32 STATE_VERSION = 45; // Last changed in PR 2846
|
||||
|
||||
// Maps savestate versions to Dolphin versions.
|
||||
// Versions after 42 don't need to be added to this list,
|
||||
|
||||
Reference in New Issue
Block a user