diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt
index 636d8fa928..207743bbd0 100644
--- a/Source/Core/Core/CMakeLists.txt
+++ b/Source/Core/Core/CMakeLists.txt
@@ -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
diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj
index eaba8a5f96..335d505c62 100644
--- a/Source/Core/Core/Core.vcxproj
+++ b/Source/Core/Core/Core.vcxproj
@@ -108,9 +108,6 @@
-
-
-
diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters
index b35c0caa9c..92d88bc479 100644
--- a/Source/Core/Core/Core.vcxproj.filters
+++ b/Source/Core/Core/Core.vcxproj.filters
@@ -336,15 +336,6 @@
HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE\uCodes
-
- HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE\uCodes
-
-
- HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE\uCodes
-
-
- HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE\uCodes
-
HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE\uCodes
diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.cpp b/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.cpp
index c18b8a6ce9..72a8b0d42e 100644
--- a/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.cpp
+++ b/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.cpp
@@ -23,21 +23,10 @@ ZeldaUCode::ZeldaUCode(DSPHLE *dsphle, u32 crc)
m_current_voice(0),
m_current_buffer(0),
m_num_buffers(0),
- m_voice_pbs_addr(0),
- m_unk_table_addr(0),
- m_reverb_pbs_addr(0),
- m_right_buffers_addr(0),
- m_left_buffers_addr(0),
- m_pos(0),
- m_dma_base_addr(0),
m_num_steps(0),
m_list_in_progress(false),
m_step(0),
- m_read_offset(0),
- m_mail_state(WaitForMail),
- m_num_pbs(0),
- m_pb_address(0),
- m_pb_address2(0)
+ m_read_offset(0)
{
DEBUG_LOG(DSPHLE, "UCode_Zelda - add boot mails for handshake");
@@ -52,34 +41,11 @@ ZeldaUCode::ZeldaUCode(DSPHLE *dsphle, u32 crc)
DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP);
m_mail_handler.PushMail(0xF3551111); // handshake
}
-
- m_voice_buffer = new s32[256 * 1024];
- m_resample_buffer = new s16[256 * 1024];
- m_left_buffer = new s32[256 * 1024];
- m_right_buffer = new s32[256 * 1024];
-
- memset(m_buffer, 0, sizeof(m_buffer));
- memset(m_sync_flags, 0, sizeof(m_sync_flags));
- memset(m_afc_coef_table, 0, sizeof(m_afc_coef_table));
- memset(m_pb_mask, 0, sizeof(m_pb_mask));
}
ZeldaUCode::~ZeldaUCode()
{
m_mail_handler.Clear();
-
- delete [] m_voice_buffer;
- delete [] m_resample_buffer;
- delete [] m_left_buffer;
- delete [] m_right_buffer;
-}
-
-u8 *ZeldaUCode::GetARAMPointer(u32 address)
-{
- if (IsDMAVersion())
- return Memory::GetPointer(m_dma_base_addr) + address;
- else
- return DSP::GetARAMPtr() + address;
}
void ZeldaUCode::Update()
@@ -116,7 +82,7 @@ void ZeldaUCode::HandleMail_LightVersion(u32 mail)
{
DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP);
- MixAudio();
+ // TODO(delroth): Mix audio.
m_current_buffer++;
@@ -176,7 +142,7 @@ void ZeldaUCode::HandleMail_SMSVersion(u32 mail)
m_num_sync_mail = 0;
m_sync_in_progress = false;
- MixAudio();
+ // TODO(delroth): Mix audio.
m_current_buffer++;
@@ -281,7 +247,7 @@ void ZeldaUCode::HandleMail_NormalVersion(u32 mail)
if (m_current_voice >= m_num_voices)
{
- MixAudio();
+ // TODO(delroth): Mix audio.
m_current_buffer++;
@@ -403,63 +369,16 @@ void ZeldaUCode::ExecuteList()
// DsetupTable ... zelda ww jumps to 0x0095
case 0x01:
- {
- m_num_voices = extra_data;
- m_voice_pbs_addr = Read32() & 0x7FFFFFFF;
- m_unk_table_addr = Read32() & 0x7FFFFFFF;
- m_afc_coef_table_addr = Read32() & 0x7FFFFFFF;
- m_reverb_pbs_addr = Read32() & 0x7FFFFFFF; // WARNING: reverb PBs are very different from voice PBs!
-
- // Read the other table
- u16 *tmp_ptr = (u16*)Memory::GetPointer(m_unk_table_addr);
- for (int i = 0; i < 0x280; i++)
- m_misc_table[i] = (s16)Common::swap16(tmp_ptr[i]);
-
- // Read AFC coef table
- tmp_ptr = (u16*)Memory::GetPointer(m_afc_coef_table_addr);
- for (int i = 0; i < 32; i++)
- m_afc_coef_table[i] = (s16)Common::swap16(tmp_ptr[i]);
-
- DEBUG_LOG(DSPHLE, "DsetupTable");
- DEBUG_LOG(DSPHLE, "Num voice param blocks: %i", m_num_voices);
- DEBUG_LOG(DSPHLE, "Voice param blocks address: 0x%08x", m_voice_pbs_addr);
-
- // This points to some strange data table. Don't know yet what it's for. Reverb coefs?
- DEBUG_LOG(DSPHLE, "DSPRES_FILTER (size: 0x40): 0x%08x", m_unk_table_addr);
-
- // Zelda WW: This points to a 64-byte array of coefficients, which are EXACTLY the same
- // as the AFC ADPCM coef array in decode.c of the in_cube winamp plugin,
- // which can play Zelda audio. So, these should definitely be used when decoding AFC.
- DEBUG_LOG(DSPHLE, "DSPADPCM_FILTER (size: 0x500): 0x%08x", m_afc_coef_table_addr);
- DEBUG_LOG(DSPHLE, "Reverb param blocks address: 0x%08x", m_reverb_pbs_addr);
- }
+ Read32(); Read32(); Read32(); Read32();
break;
// SyncFrame ... zelda ww jumps to 0x0243
case 0x02:
- {
- m_sync_cmd_pending = true;
-
- m_current_buffer = 0;
- m_num_buffers = (cmd_mail >> 16) & 0xFF;
-
- // Addresses for right & left buffers in main memory
- // Each buffer is 160 bytes long. The number of (both left & right) buffers
- // is set by the first mail of the list.
- m_left_buffers_addr = Read32() & 0x7FFFFFFF;
- m_right_buffers_addr = Read32() & 0x7FFFFFFF;
-
- DEBUG_LOG(DSPHLE, "DsyncFrame");
- // These alternate between three sets of mixing buffers. They are all three fairly near,
- // but not at, the ADMA read addresses.
- DEBUG_LOG(DSPHLE, "Right buffer address: 0x%08x", m_right_buffers_addr);
- DEBUG_LOG(DSPHLE, "Left buffer address: 0x%08x", m_left_buffers_addr);
-
+ Read32(); Read32();
if (IsLightVersion())
break;
else
return;
- }
// Simply sends the sync messages
@@ -485,11 +404,7 @@ void ZeldaUCode::ExecuteList()
// This opcode, in the SMG ucode, sets the base address for audio data transfers from main memory (using DMA).
// In the Zelda ucode, it is dummy, because this ucode uses accelerator for audio data transfers.
case 0x0e:
- {
- m_dma_base_addr = Read32() & 0x7FFFFFFF;
- DEBUG_LOG(DSPHLE, "DsetDMABaseAddr");
- DEBUG_LOG(DSPHLE, "DMA base address: 0x%08x", m_dma_base_addr);
- }
+ Read32();
break;
// default ... zelda ww jumps to 0x0043
@@ -521,9 +436,6 @@ u32 ZeldaUCode::GetUpdateMs()
void ZeldaUCode::DoState(PointerWrap &p)
{
- p.Do(m_afc_coef_table);
- p.Do(m_misc_table);
-
p.Do(m_sync_in_progress);
p.Do(m_max_voice);
p.Do(m_sync_flags);
@@ -537,17 +449,6 @@ void ZeldaUCode::DoState(PointerWrap &p)
p.Do(m_current_buffer);
p.Do(m_num_buffers);
- p.Do(m_voice_pbs_addr);
- p.Do(m_unk_table_addr);
- p.Do(m_afc_coef_table_addr);
- p.Do(m_reverb_pbs_addr);
-
- p.Do(m_right_buffers_addr);
- p.Do(m_left_buffers_addr);
- p.Do(m_pos);
-
- p.Do(m_dma_base_addr);
-
p.Do(m_num_steps);
p.Do(m_list_in_progress);
p.Do(m_step);
@@ -555,12 +456,5 @@ void ZeldaUCode::DoState(PointerWrap &p)
p.Do(m_read_offset);
- p.Do(m_mail_state);
- p.Do(m_pb_mask);
-
- p.Do(m_num_pbs);
- p.Do(m_pb_address);
- p.Do(m_pb_address2);
-
DoStateShared(p);
}
diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.h b/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.h
index 6785f52b70..5f65008c35 100644
--- a/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.h
+++ b/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.h
@@ -7,113 +7,6 @@
#include "Common/CommonTypes.h"
#include "Core/HW/DSPHLE/UCodes/UCodes.h"
-// Obviously missing things that must be in here, somewhere among the "unknown":
-// * Volume
-// * L/R Pan
-// * (probably) choice of resampling algorithm (point, linear, cubic)
-
-union ZeldaVoicePB
-{
- 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)?
-
- 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? used by zelda's AFC decoder. we don't need it.
- u16 FixedSample; // 0x33 | sample value for "blank" voices
- u32 RestartPos; // 0x34 | restart pos / "loop start offset"
- u16 Unk36[2]; // 0x36 | unknown // loaded at 0adc/ZWW in 0x21 decoder
- u32 CurAddr; // 0x38 | current address
- u32 RemLength; // 0x3A | remaining length
- u16 ResamplerOldData[4]; // 0x3C | The resampler stores the last 4 decoded samples here from the previous frame, so that the filter kernel has something to read before the start of the buffer.
- 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 LoopYN1; // 0x82 | YN1 reload (when AFC loops)
- u16 LoopYN2; // 0x83 | YN2 reload (when AFC loops)
- 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 (0xa4 controls the appearance of 0xa5-0xa7 and is almost always 0x7FFF)
- u16 FilterEnable; // 0xa8 | FilterBufferInPlace enable
- u16 Padding3[0x7]; // 0xa9 | padding
- u16 Padding4[0x10]; // 0xb0 | padding
- };
- u16 raw[0xc0]; // WARNING-do not use on parts of the 32-bit values - they are swapped!
-};
-
-union ZeldaUnkPB
-{
- struct
- {
- u16 Control; // 0x00 | control
- u16 Unk01; // 0x01 | unknown
- u32 SrcAddr; // 0x02 | some address
- u16 Unk04[0xC]; // 0x04 | unknown
- };
- u16 raw[16];
-};
-
class ZeldaUCode : public UCodeInterface
{
public:
@@ -127,17 +20,8 @@ public:
void HandleMail_NormalVersion(u32 mail);
void Update() override;
- void CopyPBsFromRAM();
- void CopyPBsToRAM();
-
void DoState(PointerWrap &p) override;
- int *templbuffer;
- int *temprbuffer;
-
- // Simple dump ...
- int DumpAFC(u8* pIn, const int size, const int srate);
-
u32 Read32()
{
u32 res = *(u32*)&m_buffer[m_read_offset];
@@ -197,17 +81,6 @@ private:
}
}
- // These are the only dynamically allocated things allowed in the ucode.
- s32* m_voice_buffer;
- s16* m_resample_buffer;
- s32* m_left_buffer;
- s32* m_right_buffer;
-
- // If you add variables, remember to keep DoState() and the constructor up to date.
-
- s16 m_afc_coef_table[32];
- s16 m_misc_table[0x280];
-
bool m_sync_in_progress;
u32 m_max_voice;
u32 m_sync_flags[16];
@@ -222,21 +95,6 @@ private:
u32 m_current_buffer;
u32 m_num_buffers;
- // Those are set by command 0x1 (DsetupTable)
- u32 m_voice_pbs_addr;
- u32 m_unk_table_addr;
- u32 m_afc_coef_table_addr;
- u32 m_reverb_pbs_addr;
-
- u32 m_right_buffers_addr;
- u32 m_left_buffers_addr;
- //u32 m_unkAddr;
- u32 m_pos;
-
- // Only in SMG ucode
- // Set by command 0xE (DsetDMABaseAddr)
- u32 m_dma_base_addr;
-
// List, buffer management =====================
u32 m_num_steps;
bool m_list_in_progress;
@@ -245,50 +103,5 @@ private:
u32 m_read_offset;
- enum EMailState
- {
- WaitForMail,
- ReadingFrameSync,
- ReadingMessage,
- ReadingSystemMsg
- };
-
- EMailState m_mail_state;
- u16 m_pb_mask[0x10];
-
- u32 m_num_pbs;
- u32 m_pb_address; // The main param block array
- u32 m_pb_address2; // 4 smaller param blocks
-
void ExecuteList();
-
- u8 *GetARAMPointer(u32 address);
-
- // AFC decoder
- static void AFCdecodebuffer(const s16 *coef, const char *input, signed short *out, short *histp, short *hist2p, int type);
-
- void ReadVoicePB(u32 _Addr, ZeldaVoicePB& PB);
- void WritebackVoicePB(u32 _Addr, ZeldaVoicePB& PB);
-
- // Voice formats
- void RenderSynth_Constant(ZeldaVoicePB &PB, s32* _Buffer, int _Size);
- void RenderSynth_RectWave(ZeldaVoicePB &PB, s32* _Buffer, int _Size);
- void RenderSynth_SawWave(ZeldaVoicePB &PB, s32* _Buffer, int _Size);
- void RenderSynth_WaveTable(ZeldaVoicePB &PB, s32* _Buffer, int _Size);
-
- void RenderVoice_PCM8(ZeldaVoicePB& PB, s16* _Buffer, int _Size);
- void RenderVoice_PCM16(ZeldaVoicePB& PB, s16* _Buffer, int _Size);
-
- void RenderVoice_AFC(ZeldaVoicePB& PB, s16* _Buffer, int _Size);
- void RenderVoice_Raw(ZeldaVoicePB& PB, s16* _Buffer, int _Size);
-
- void Resample(ZeldaVoicePB &PB, int size, s16 *in, s32 *out, bool do_resample = false);
-
- int ConvertRatio(int pb_ratio);
- int SizeForResampling(ZeldaVoicePB &PB, int size);
-
- // Renders a voice and mixes it into LeftBuffer, RightBuffer
- void RenderAddVoice(ZeldaVoicePB& PB, s32* _LeftBuffer, s32* _RightBuffer, int _Size);
-
- void MixAudio();
};
diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/ZeldaADPCM.cpp b/Source/Core/Core/HW/DSPHLE/UCodes/ZeldaADPCM.cpp
deleted file mode 100644
index 52e7ae44bb..0000000000
--- a/Source/Core/Core/HW/DSPHLE/UCodes/ZeldaADPCM.cpp
+++ /dev/null
@@ -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;
-}
diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/ZeldaSynth.cpp b/Source/Core/Core/HW/DSPHLE/UCodes/ZeldaSynth.cpp
deleted file mode 100644
index 054efeaddd..0000000000
--- a/Source/Core/Core/HW/DSPHLE/UCodes/ZeldaSynth.cpp
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright 2008 Dolphin Emulator Project
-// Licensed under GPLv2+
-// Refer to the license.txt file included.
-
-#include
-
-#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;
-}
-
-
diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/ZeldaVoice.cpp b/Source/Core/Core/HW/DSPHLE/UCodes/ZeldaVoice.cpp
deleted file mode 100644
index e6db1b0d85..0000000000
--- a/Source/Core/Core/HW/DSPHLE/UCodes/ZeldaVoice.cpp
+++ /dev/null
@@ -1,790 +0,0 @@
-// Copyright 2009 Dolphin Emulator Project
-// Licensed under GPLv2+
-// Refer to the license.txt file included.
-
-#include
-
-#include "Common/CommonFuncs.h"
-#include "Common/MathUtil.h"
-
-#include "Core/HW/DSP.h"
-#include "Core/HW/Memmap.h"
-#include "Core/HW/DSPHLE/UCodes/UCodes.h"
-#include "Core/HW/DSPHLE/UCodes/Zelda.h"
-
-void ZeldaUCode::ReadVoicePB(u32 _Addr, ZeldaVoicePB& PB)
-{
- u16 *memory = (u16*)Memory::GetPointer(_Addr);
-
- // Perform byteswap
- for (int i = 0; i < (0x180 / 2); i++)
- ((u16*)&PB)[i] = Common::swap16(memory[i]);
-
- // Word swap all 32-bit variables.
- PB.RestartPos = (PB.RestartPos << 16) | (PB.RestartPos >> 16);
- PB.CurAddr = (PB.CurAddr << 16) | (PB.CurAddr >> 16);
- PB.RemLength = (PB.RemLength << 16) | (PB.RemLength >> 16);
- // Read only part
- PB.LoopStartPos = (PB.LoopStartPos << 16) | (PB.LoopStartPos >> 16);
- PB.Length = (PB.Length << 16) | (PB.Length >> 16);
- PB.StartAddr = (PB.StartAddr << 16) | (PB.StartAddr >> 16);
- PB.UnkAddr = (PB.UnkAddr << 16) | (PB.UnkAddr >> 16);
-}
-
-void ZeldaUCode::WritebackVoicePB(u32 _Addr, ZeldaVoicePB& PB)
-{
- u16 *memory = (u16*)Memory::GetPointer(_Addr);
-
- // Word swap all 32-bit variables.
- PB.RestartPos = (PB.RestartPos << 16) | (PB.RestartPos >> 16);
- PB.CurAddr = (PB.CurAddr << 16) | (PB.CurAddr >> 16);
- PB.RemLength = (PB.RemLength << 16) | (PB.RemLength >> 16);
-
- // Perform byteswap
- // Only the first 0x100 bytes are written back
- for (int i = 0; i < (0x100 / 2); i++)
- memory[i] = Common::swap16(((u16*)&PB)[i]);
-}
-
-int ZeldaUCode::ConvertRatio(int pb_ratio)
-{
- return pb_ratio * 16;
-}
-
-int ZeldaUCode::SizeForResampling(ZeldaVoicePB &PB, int size)
-{
- // This is the little calculation at the start of every sample decoder
- // in the ucode.
- return (PB.CurSampleFrac + size * ConvertRatio(PB.RatioInt)) >> 16;
-}
-
-// Simple resampler, linear interpolation.
-// Any future state should be stored in PB.raw[0x3c to 0x3f].
-// In must point 4 samples into a buffer.
-void ZeldaUCode::Resample(ZeldaVoicePB &PB, int size, s16 *in, s32 *out, bool do_resample)
-{
- if (!do_resample)
- {
- memcpy(out, in, size * sizeof(int));
- return;
- }
-
- for (int i = 0; i < 4; i++)
- {
- in[i - 4] = (s16)PB.ResamplerOldData[i];
- }
-
- int ratio = ConvertRatio(PB.RatioInt);
- int in_size = SizeForResampling(PB, size);
-
- int position = PB.CurSampleFrac;
- for (int i = 0; i < size; i++)
- {
- int int_pos = (position >> 16);
- int frac = ((position & 0xFFFF) >> 1);
- out[i] = (in[int_pos - 3] * (frac ^ 0x7FFF) + in[int_pos - 2] * frac) >> 15;
- position += ratio;
- }
-
- for (int i = 0; i < 4; i++)
- {
- PB.ResamplerOldData[i] = (u16)(s16)in[in_size - 4 + i];
- }
- PB.CurSampleFrac = position & 0xFFFF;
-}
-
-static void UpdateSampleCounters10(ZeldaVoicePB &PB)
-{
- PB.RemLength = PB.Length - PB.RestartPos;
- PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
- PB.ReachedEnd = 0;
-}
-
-void ZeldaUCode::RenderVoice_PCM16(ZeldaVoicePB &PB, s16 *_Buffer, int _Size)
-{
- int _RealSize = SizeForResampling(PB, _Size);
- u32 rem_samples = _RealSize;
- if (PB.KeyOff)
- goto clear_buffer;
- if (PB.NeedsReset)
- {
- UpdateSampleCounters10(PB);
- for (int i = 0; i < 4; i++)
- PB.ResamplerOldData[i] = 0; // Doesn't belong here, but dunno where to do it.
- }
- if (PB.ReachedEnd)
- {
- PB.ReachedEnd = 0;
-reached_end:
- if (!PB.RepeatMode)
- {
- // One shot - play zeros the rest of the buffer.
-clear_buffer:
- for (u32 i = 0; i < rem_samples; i++)
- *_Buffer++ = 0;
- PB.KeyOff = 1;
- return;
- }
- else
- {
- PB.RestartPos = PB.LoopStartPos;
- UpdateSampleCounters10(PB);
- }
- }
- // SetupAccelerator
- const s16 *read_ptr = (s16*)GetARAMPointer(PB.CurAddr);
- if (PB.RemLength < (u32)rem_samples)
- {
- // finish-up loop
- for (u32 i = 0; i < PB.RemLength; i++)
- *_Buffer++ = Common::swap16(*read_ptr++);
- rem_samples -= PB.RemLength;
- goto reached_end;
- }
- // main render loop
- for (u32 i = 0; i < rem_samples; i++)
- *_Buffer++ = Common::swap16(*read_ptr++);
-
- PB.RemLength -= rem_samples;
- if (PB.RemLength == 0)
- PB.ReachedEnd = 1;
- PB.CurAddr += rem_samples << 1;
-}
-
-static void UpdateSampleCounters8(ZeldaVoicePB &PB)
-{
- PB.RemLength = PB.Length - PB.RestartPos;
- PB.CurAddr = PB.StartAddr + PB.RestartPos;
- PB.ReachedEnd = 0;
-}
-
-void ZeldaUCode::RenderVoice_PCM8(ZeldaVoicePB &PB, s16 *_Buffer, int _Size)
-{
- int _RealSize = SizeForResampling(PB, _Size);
- u32 rem_samples = _RealSize;
- if (PB.KeyOff)
- goto clear_buffer;
- if (PB.NeedsReset)
- {
- UpdateSampleCounters8(PB);
- for (int i = 0; i < 4; i++)
- PB.ResamplerOldData[i] = 0; // Doesn't belong here, but dunno where to do it.
- }
- if (PB.ReachedEnd)
- {
-reached_end:
- PB.ReachedEnd = 0;
- if (!PB.RepeatMode)
- {
- // One shot - play zeros the rest of the buffer.
-clear_buffer:
- for (u32 i = 0; i < rem_samples; i++)
- *_Buffer++ = 0;
- PB.KeyOff = 1;
- return;
- }
- else
- {
- PB.RestartPos = PB.LoopStartPos;
- UpdateSampleCounters8(PB);
- }
- }
-
- // SetupAccelerator
- const s8 *read_ptr = (s8*)GetARAMPointer(PB.CurAddr);
- if (PB.RemLength < (u32)rem_samples)
- {
- // finish-up loop
- for (u32 i = 0; i < PB.RemLength; i++)
- *_Buffer++ = (s8)(*read_ptr++) << 8;
- rem_samples -= PB.RemLength;
- goto reached_end;
- }
- // main render loop
- for (u32 i = 0; i < rem_samples; i++)
- *_Buffer++ = (s8)(*read_ptr++) << 8;
-
- PB.RemLength -= rem_samples;
- if (PB.RemLength == 0)
- PB.ReachedEnd = 1;
- PB.CurAddr += rem_samples;
-}
-
-template
-void PrintObject(const T &Obj)
-{
- std::stringstream ss;
- u8 *o = (u8 *)&Obj;
-
- // If this miscompiles, adjust the size of
- // ZeldaVoicePB to 0x180 bytes (0xc0 shorts).
- static_assert(sizeof(ZeldaVoicePB) == 0x180, "ZeldaVoicePB incorrectly defined.");
-
- ss << std::hex;
- for (size_t i = 0; i < sizeof(T); i++)
- {
- if ((i & 1) == 0)
- ss << ' ';
- ss.width(2);
- ss.fill('0');
- ss << Common::swap16(o[i]);
- }
-
- DEBUG_LOG(DSPHLE, "AFC PB:%s", ss.str().c_str());
-}
-
-void ZeldaUCode::RenderVoice_AFC(ZeldaVoicePB &PB, s16 *_Buffer, int _Size)
-{
- // TODO: Compare mono, stereo and surround samples
-#if defined DEBUG || defined DEBUGFAST
- PrintObject(PB);
-#endif
-
- int _RealSize = SizeForResampling(PB, _Size);
-
- // initialize "decoder" if the sample is played the first time
- if (PB.NeedsReset != 0)
- {
- // This is 0717_ReadOutPBStuff
- // increment 4fb
- // zelda:
- // perhaps init or "has played before"
- PB.CurBlock = 0x00;
- PB.YN2 = 0x00; // history1
- PB.YN1 = 0x00; // history2
-
- // Length in samples.
- PB.RemLength = PB.Length;
- // Copy ARAM addr from r to rw area.
- PB.CurAddr = PB.StartAddr;
- PB.ReachedEnd = 0;
- PB.CurSampleFrac = 0;
-
- for (int i = 0; i < 4; i++)
- PB.ResamplerOldData[i] = 0;
- }
-
- if (PB.KeyOff != 0) // 0747 early out... i dunno if this can happen because we filter it above
- {
- for (int i = 0; i < _RealSize; i++)
- *_Buffer++ = 0;
- return;
- }
-
- // Round upwards how many samples we need to copy, 0759
- // u32 frac = NumberOfSamples & 0xF;
- // NumberOfSamples = (NumberOfSamples + 0xf) >> 4; // i think the lower 4 are the fraction
-
- const u8 *source;
- u32 ram_mask = 1024 * 1024 * 16 - 1;
- if (IsDMAVersion())
- {
- source = Memory::GetPointer(m_dma_base_addr);
- ram_mask = 1024 * 1024 * 64 - 1;
- }
- else
- {
- source = DSP::GetARAMPtr();
- }
-
- int sampleCount = 0; // must be above restart.
-
-restart:
- if (PB.ReachedEnd)
- {
- PB.ReachedEnd = 0;
-
- if ((PB.RepeatMode == 0) || (PB.StopOnSilence != 0))
- {
- PB.KeyOff = 1;
- PB.RemLength = 0;
- PB.CurAddr = PB.StartAddr + PB.RestartPos + PB.Length;
-
- while (sampleCount < _RealSize)
- _Buffer[sampleCount++] = 0;
- return;
- }
- else
- {
- //AFC looping
- // The loop start pos is incorrect? (Fixed?), so samples will loop a bit wrong.
- // this fixes the intro music in ZTP.
- PB.RestartPos = PB.LoopStartPos;
- PB.RemLength = PB.Length - PB.RestartPos;
- // see DSP_UC_Zelda.txt line 2817
- PB.CurAddr = ((((((PB.LoopStartPos >> 4) & 0xffff0000)*PB.Format)<<16)+
- (((PB.LoopStartPos >> 4) & 0xffff)*PB.Format))+PB.StartAddr) & 0xffffffff;
-
- // Hmm, this shouldn't be reversed .. or should it? Is it different between versions of the ucode?
- // -> it has to be reversed in ZTP, otherwise intro music is broken...
- PB.YN1 = PB.LoopYN2;
- PB.YN2 = PB.LoopYN1;
- }
- }
-
- short outbuf[16] = {0};
- u16 prev_yn1 = PB.YN1;
- u16 prev_yn2 = PB.YN2;
- u32 prev_addr = PB.CurAddr;
-
- // Prefill the decode buffer.
- AFCdecodebuffer(m_afc_coef_table, (char*)(source + (PB.CurAddr & ram_mask)), outbuf, (short*)&PB.YN2, (short*)&PB.YN1, PB.Format);
- PB.CurAddr += PB.Format; // 9 or 5
-
- u32 SamplePosition = PB.Length - PB.RemLength;
- while (sampleCount < _RealSize)
- {
- _Buffer[sampleCount] = outbuf[SamplePosition & 15];
- sampleCount++;
-
- SamplePosition++;
- PB.RemLength--;
- if (PB.RemLength == 0)
- {
- PB.ReachedEnd = 1;
- goto restart;
- }
-
- // Need new samples!
- if ((SamplePosition & 15) == 0)
- {
- prev_yn1 = PB.YN1;
- prev_yn2 = PB.YN2;
- prev_addr = PB.CurAddr;
-
- AFCdecodebuffer(m_afc_coef_table, (char*)(source + (PB.CurAddr & ram_mask)), outbuf, (short*)&PB.YN2, (short*)&PB.YN1, PB.Format);
- PB.CurAddr += PB.Format; // 9 or 5
- }
- }
-
- // Here we should back off to the previous addr/yn1/yn2, since we didn't consume the full last block.
- // We'll re-decode it the next time around.
- PB.YN2 = prev_yn2;
- PB.YN1 = prev_yn1;
- PB.CurAddr = prev_addr;
-
- PB.NeedsReset = 0;
- // PB.CurBlock = 0x10 - (PB.LoopStartPos & 0xf);
- // write back
- // NumberOfSamples = (NumberOfSamples << 4) | frac; // missing fraction
-
- // i think pTest[0x3a] and pTest[0x3b] got an update after you have decoded some samples...
- // just decrement them with the number of samples you have played
- // and increase the ARAM Offset in pTest[0x38], pTest[0x39]
-
- // end of block (Zelda 03b2)
-}
-
-void Decoder21_ReadAudio(ZeldaVoicePB &PB, int size, s16 *_Buffer);
-
-// Researching what's actually inside the mysterious 0x21 case
-// 0x21 seems to really just be reading raw 16-bit audio from RAM (not ARAM).
-// The rules seem to be quite different, though.
-// It's used for streaming, not for one-shot or looped sample playback.
-void ZeldaUCode::RenderVoice_Raw(ZeldaVoicePB &PB, s16 *_Buffer, int _Size)
-{
- // Decoder0x21 starts here.
- u32 _RealSize = SizeForResampling(PB, _Size);
-
- // Decoder0x21Core starts here.
- u32 AX0 = _RealSize;
-
- // ERROR_LOG(DSPHLE, "0x21 volume mode: %i , stop: %i ", PB.VolumeMode, PB.StopOnSilence);
-
- // The PB.StopOnSilence check is a hack, we should check the buffers and enter this
- // only when the buffer is completely 0 (i.e. when the music has finished fading out)
- if (PB.StopOnSilence || PB.RemLength < (u32)_RealSize)
- {
- WARN_LOG(DSPHLE, "Raw: END");
- // Let's ignore this entire case since it doesn't seem to happen
- // in Zelda, since Length is set to 0xF0000000
- // blah
- // blah
- // readaudio
- // blah
- PB.RemLength = 0;
- PB.KeyOff = 1;
- }
-
- PB.RemLength -= _RealSize;
-
- u64 ACC0 = (u32)(PB.raw[0x8a ^ 1] << 16); // 0x8a 0ad5, yes it loads a, not b
- u64 ACC1 = (u32)(PB.raw[0x34 ^ 1] << 16); // 0x34
-
- // ERROR_LOG(DSPHLE, "%08x %08x", (u32)ACC0, (u32)ACC1);
-
- ACC0 -= ACC1;
-
- PB.Unk36[0] = (u16)(ACC0 >> 16);
-
- ACC0 -= AX0 << 16;
-
- if ((s64)ACC0 < 0)
- {
- // ERROR_LOG(DSPHLE, "Raw loop: ReadAudio size = %04x 34:%04x %08x", PB.Unk36[0], PB.raw[0x34 ^ 1], (int)ACC0);
- Decoder21_ReadAudio(PB, PB.Unk36[0], _Buffer);
-
- ACC0 = -(s64)ACC0;
- _Buffer += PB.Unk36[0];
-
- PB.raw[0x34 ^ 1] = 0;
-
- PB.StartAddr = PB.LoopStartPos;
-
- Decoder21_ReadAudio(PB, (int)(ACC0 >> 16), _Buffer);
- return;
- }
-
- Decoder21_ReadAudio(PB, _RealSize, _Buffer);
-}
-
-void Decoder21_ReadAudio(ZeldaVoicePB &PB, int size, s16* _Buffer)
-{
- // 0af6
- if (!size)
- return;
-
-#if 0
- // 0afa
- u32 AX1 = (PB.RestartPos >> 16) & 1; // PB.raw[0x34], except that it's part of a dword
- // 0b00 - Eh, WTF.
- u32 ACC0 = PB.StartAddr + ((PB.RestartPos >> 16) << 1) - 2*AX1;
- u32 ACC1 = (size << 16) + 0x20000;
- // All this trickery, and more, seems to be to align the DMA, which
- // we really don't care about. So let's skip it. See the #else.
-
-#else
- // ERROR_LOG(DSPHLE, "ReadAudio: %08x %08x", PB.StartAddr, PB.raw[0x34 ^ 1]);
- u32 ACC0 = PB.StartAddr + (PB.raw[0x34 ^ 1] << 1);
- u32 ACC1 = (size << 16);
-#endif
- // ACC0 is the address
- // ACC1 is the read size
-
- const u16* src = (u16*)Memory::GetPointer(ACC0 & Memory::RAM_MASK);
-
- for (u32 i = 0; i < (ACC1 >> 16); i++)
- {
- _Buffer[i] = Common::swap16(src[i]);
- }
-
- PB.raw[0x34 ^ 1] += size;
-}
-
-
-void ZeldaUCode::RenderAddVoice(ZeldaVoicePB &PB, s32* _LeftBuffer, s32* _RightBuffer, int _Size)
-{
- if (PB.IsBlank)
- {
- s32 sample = (s32)(s16)PB.FixedSample;
- for (int i = 0; i < _Size; i++)
- m_voice_buffer[i] = sample;
-
- goto ContinueWithBlock; // Yes, a goto. Yes, it's evil, but it makes the flow look much more like the DSP code.
- }
-
- // XK: Use this to disable MIDI music (GREAT for testing). Also kills some sound FX.
- //if (PB.SoundType == 0x0d00)
- //{
- // PB.NeedsReset = 0;
- // return;
- //}
-
- // The Resample calls actually don't resample yet.
-
- // ResampleBuffer corresponds to 0x0580 in ZWW ucode.
- // VoiceBuffer corresponds to 0x0520.
-
- // First jump table at ZWW: 2a6
- switch (PB.Format)
- {
- case 0x0005: // AFC with extra low bitrate (32:5 compression).
- case 0x0009: // AFC with normal bitrate (32:9 compression).
- RenderVoice_AFC(PB, m_resample_buffer + 4, _Size);
- Resample(PB, _Size, m_resample_buffer + 4, m_voice_buffer, true);
- break;
-
- case 0x0008: // PCM8 - normal PCM 8-bit audio. Used in Mario Kart DD + very little in Zelda WW.
- RenderVoice_PCM8(PB, m_resample_buffer + 4, _Size);
- Resample(PB, _Size, m_resample_buffer + 4, m_voice_buffer, true);
- break;
-
- case 0x0010: // PCM16 - normal PCM 16-bit audio.
- RenderVoice_PCM16(PB, m_resample_buffer + 4, _Size);
- Resample(PB, _Size, m_resample_buffer + 4, m_voice_buffer, true);
- break;
-
- case 0x0020:
- // Normally, this shouldn't resample, it should just decode directly
- // to the output buffer. However, (if we ever see this sound type), we'll
- // have to resample anyway since we're running at a different sample rate.
-
- RenderVoice_Raw(PB, m_resample_buffer + 4, _Size);
- Resample(PB, _Size, m_resample_buffer + 4, m_voice_buffer, true);
- break;
-
- case 0x0021:
- // Raw sound from RAM. Important for Zelda WW. Cutscenes use the music
- // to let the game know they ended
- RenderVoice_Raw(PB, m_resample_buffer + 4, _Size);
- Resample(PB, _Size, m_resample_buffer + 4, m_voice_buffer, true);
- break;
-
- default:
- // Second jump table
- // TODO: Cases to find examples of:
- // -0x0002
- // -0x0003
- // -0x0006
- // -0x000a
- switch (PB.Format)
- {
- // Synthesized sounds
- case 0x0003: WARN_LOG(DSPHLE, "PB Format 0x03 used!");
- case 0x0000: // Example: Magic meter filling up in ZWW
- RenderSynth_RectWave(PB, m_voice_buffer, _Size);
- break;
-
- case 0x0001: // Example: "Denied" sound when trying to pull out a sword indoors in ZWW
- RenderSynth_SawWave(PB, m_voice_buffer, _Size);
- break;
-
- case 0x0006:
- WARN_LOG(DSPHLE, "Synthesizing 0x0006 (constant sound)");
- RenderSynth_Constant(PB, m_voice_buffer, _Size);
- break;
-
- // These are more "synth" formats - square wave, saw wave etc.
- case 0x0002:
- WARN_LOG(DSPHLE, "PB Format 0x02 used!");
- break;
-
- case 0x0004: // Example: Big Pikmin onion mothership landing/building a bridge in Pikmin
- case 0x0007: // Example: "success" SFX in Pikmin 1, Pikmin 2 in a cave, not sure what sound it is.
- case 0x000b: // Example: SFX in area selection menu in Pikmin
- case 0x000c: // Example: beam of death/yellow force-field in Temple of the Gods, ZWW
- RenderSynth_WaveTable(PB, m_voice_buffer, _Size);
- break;
-
- default:
- // TODO: Implement general decoder here
- memset(m_voice_buffer, 0, _Size * sizeof(s32));
- ERROR_LOG(DSPHLE, "Unknown MixAddVoice format in zelda %04x", PB.Format);
- break;
- }
- }
-
-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++)
- {
- // TODO?
- }
-
- // Apply volume. There are two different modes.
- 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;
- }
- }
-
- short AX0L = PB.raw[0x28] >> 8;
- short AX0H = PB.raw[0x28] & 0x7F;
- short AX1L = AX0L ^ 0x7F;
- short AX1H = AX0H ^ 0x7F;
- AX0L = m_misc_table[0x200 + AX0L];
- AX0H = m_misc_table[0x200 + AX0H];
- AX1L = m_misc_table[0x200 + AX1L];
- AX1H = m_misc_table[0x200 + AX1H];
-
- short b00[20];
- 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] = (s16)b00[i] * (s16)PB.raw[0x2a] >> 16;
- }
-
- int prod = ((s16)PB.raw[0x2a] * (s16)PB.raw[0x29] * 2) >> 16;
- for (int i = 0; i < 4; i++)
- {
- b00[i + 8] = (s16)b00[i + 4] * prod;
- }
-
- // ZWW 0d34
-
- int diff = (s16)PB.raw[0x2b] - (s16)PB.raw[0x2a];
- PB.raw[0x2a] = PB.raw[0x2b];
-
- for (int i = 0; i < 4; i++)
- {
- b00[i + 0xc] = (unsigned short)b00[i] * diff >> 16;
- }
-
- for (int i = 0; i < 4; i++)
- {
- b00[i + 0x10] = (s16)b00[i + 0xc] * PB.raw[0x29];
- }
-
- for (int count = 0; count < 8; count++)
- {
- // The 8 buffers to mix to: 0d00, 0d60, 0f40 0ca0 0e80 0ee0 0c00 0c50
- // We just mix to the first two and call it stereo :p
- int value = b00[0x4 + count];
- //int delta = b00[0xC + count] << 11; // Unused?
-
- int ramp = value << 16;
- for (int i = 0; i < _Size; i++)
- {
- int unmixed_audio = m_voice_buffer[i];
- switch (count)
- {
- case 0: _LeftBuffer[i] += (u64)unmixed_audio * ramp >> 29; break;
- case 1: _RightBuffer[i] += (u64)unmixed_audio * ramp >> 29; break;
- }
- }
- }
- }
- 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_voice_buffer[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++;
- }
- }
- // 03b2, this is the reason of using PB.NeedsReset. Seems to be necessary for SMG, and maybe other games.
- if (PB.IsBlank == 0)
- {
- PB.NeedsReset = 0;
- }
-}
-
-void ZeldaUCode::MixAudio()
-{
- const int BufferSamples = 5 * 16;
-
- // Final mix buffers
- memset(m_left_buffer, 0, BufferSamples * sizeof(s32));
- memset(m_right_buffer, 0, BufferSamples * sizeof(s32));
-
- // For each PB...
- for (u32 i = 0; i < m_num_voices; i++)
- {
- if (!IsLightVersion())
- {
- u32 flags = m_sync_flags[(i >> 4) & 0xF];
- if (!(flags & 1 << (15 - (i & 0xF))))
- continue;
- }
-
- ZeldaVoicePB pb;
- ReadVoicePB(m_voice_pbs_addr + (i * 0x180), pb);
-
- if (pb.Status == 0)
- continue;
- if (pb.KeyOff != 0)
- continue;
-
- RenderAddVoice(pb, m_left_buffer, m_right_buffer, BufferSamples);
- WritebackVoicePB(m_voice_pbs_addr + (i * 0x180), pb);
- }
-
- // Post processing, final conversion.
- s16* left_buffer = (s16*)HLEMemory_Get_Pointer(m_left_buffers_addr);
- s16* right_buffer = (s16*)HLEMemory_Get_Pointer(m_right_buffers_addr);
- left_buffer += m_current_buffer * BufferSamples;
- right_buffer += m_current_buffer * BufferSamples;
- for (int i = 0; i < BufferSamples; i++)
- {
- s32 left = m_left_buffer[i];
- s32 right = m_right_buffer[i];
-
- MathUtil::Clamp(&left, -32768, 32767);
- left_buffer[i] = Common::swap16((short)left);
-
- MathUtil::Clamp(&right, -32768, 32767);
- right_buffer[i] = Common::swap16((short)right);
- }
-}