From 25b77d4654ba3995a5965efc6d3b69a2a67a9b80 Mon Sep 17 00:00:00 2001 From: "XTra.KrazzY" Date: Wed, 8 Jul 2009 01:08:43 +0000 Subject: [PATCH] Zelda UCode: Synth fixes and some RE. (Why does it still sound awful?) git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3707 8ced0084-cf51-0410-be5f-012b33b47a6e --- .../Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.h | 3 +- .../Src/UCodes/UCode_Zelda_Synth.cpp | 19 +++++- .../Src/UCodes/UCode_Zelda_Voice.cpp | 8 ++- docs/DSP/DSP_UC_Zelda.txt | 68 ++++++++++++------- 4 files changed, 69 insertions(+), 29 deletions(-) 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 280d007707..34fb077bd7 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.h +++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.h @@ -221,7 +221,8 @@ private: // Voice formats void RenderSynth_Constant(ZeldaVoicePB &PB, s32* _Buffer, int _Size); - void RenderSynth_Waveform(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 RenderVoice_PCM16(ZeldaVoicePB& PB, s32* _Buffer, int _Size); void RenderVoice_AFC(ZeldaVoicePB& PB, s32* _Buffer, int _Size); void RenderVoice_Raw(ZeldaVoicePB& PB, s32* _Buffer, int _Size); diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda_Synth.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda_Synth.cpp index c2e26eeadb..adb489c29c 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda_Synth.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda_Synth.cpp @@ -22,14 +22,14 @@ #include "../main.h" #include "Mixer.h" -void CUCode_Zelda::RenderSynth_Waveform(ZeldaVoicePB &PB, s32* _Buffer, int _Size) +void CUCode_Zelda::RenderSynth_RectWave(ZeldaVoicePB &PB, s32* _Buffer, int _Size) { float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate(); u32 _ratio = (PB.RatioInt << 16); s64 ratio = (_ratio * ratioFactor) * 16; - s64 TrueSamplePosition = (s64)(PB.Length - PB.RemLength) << 16; - TrueSamplePosition += PB.CurSampleFrac; + s64 TrueSamplePosition = PB.CurSampleFrac; + // PB.Format == 0x3 -> Rectangular Wave, 0x0 -> Square Wave int mask = PB.Format ? 3 : 1, shift = PB.Format ? 2 : 1; u32 pos[2] = {0, 0}; @@ -93,6 +93,19 @@ _lRestart: PB.CurSampleFrac = TrueSamplePosition & 0xFFFF; } +void CUCode_Zelda::RenderSynth_SawWave(ZeldaVoicePB &PB, s32* _Buffer, int _Size) +{ + s32 ratio = PB.RatioInt * 2; + s64 pos = PB.CurSampleFrac; + + for(int i = 0; i < 0x50; i++) { + pos += ratio; + + _Buffer[i] = pos & 0xFFFF; + } + + PB.CurSampleFrac = pos & 0xFFFF; +} void CUCode_Zelda::RenderSynth_Constant(ZeldaVoicePB &PB, s32* _Buffer, int _Size) { 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 7db6e7d3b3..9518077d67 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 @@ -386,9 +386,13 @@ void CUCode_Zelda::RenderAddVoice(ZeldaVoicePB &PB, s32* _LeftBuffer, s32* _Righ { // Synthesized sounds case 0x0000: // Example: Magic meter filling up in ZWW + case 0x0003: + RenderSynth_RectWave(PB, m_TempBuffer, _Size); + break; + case 0x0001: // Example: "Denied" sound when trying to pull out a sword - // indoors in ZWW - RenderSynth_Waveform(PB, m_TempBuffer, _Size); + // indoors in ZWW + RenderSynth_SawWave(PB, m_TempBuffer, _Size); break; case 0x0006: diff --git a/docs/DSP/DSP_UC_Zelda.txt b/docs/DSP/DSP_UC_Zelda.txt index 1101b7bd28..74b10bb717 100644 --- a/docs/DSP/DSP_UC_Zelda.txt +++ b/docs/DSP/DSP_UC_Zelda.txt @@ -2876,27 +2876,37 @@ void 07eb_AFCDecoder(_numberOfSample(AC0.M)) //////////////////////////////////////////// DEFAULT DECODER void 087c_DefaultDecoder() { - 087c 8100 clr $ACC0 - 087c 8100 clr $ACC0 // ACC0 = 0 - 087d 1f5e mrr $AX0.H, $AC0.M - 087e 00d8 0402 lr $AX0.L, @0x0402 // AX0.L = PB.RatioInt + // 087c 8100 clr $ACC0 + // 087d 1f5e mrr $AX0.H, $AC0.M + // 087e 00d8 0402 lr $AX0.L, @0x0402 + + ACC0 = 0; + AX0.L = *0x0402; // == PB.RatioInt // Sample fraction is stored in a common way, but sample position is not, so // it's in the individual decoders. Some decoders, like square wave, only care about // fractional sample position. So here we just load up the fractional sample // position before handing control over. - 0880 00dc 0430 lr $AC0.L, @0x0430 // AC0.L = PB.CurSampleFrac - 0882 0080 0520 lri $AR0, #0x0520 // AR0 = 0x0520 - + // 0880 00dc 0430 lr $AC0.L, @0x0430 + // 0882 0080 0520 lri $AR0, #0x0520 + + AC0.L = *0x430; // == PB.CurSampleFrac + AR0 = 0x0520; + // 0884 00df 0480 lr $AC1.M, @0x0480 - // 0886 1501 lsl $ACC1, #1 // AC1.M = (PB.Format << 1) - // 0887 0340 007e andi $AC1.M, #0x007e // AC1.M &= 0x007e - // 0889 0300 0891 addi $AC1.M, #0x0891 // AC1.M += 0x0891 - // 088b 1c5f mrr $AR2, $AC1.M // AR2 = AC1.M + // 0886 1501 lsl $ACC1, #1 + // 0887 0340 007e andi $AC1.M, #0x007e + // 0889 0300 0891 addi $AC1.M, #0x0891 + // 088b 1c5f mrr $AR2, $AC1.M // 088c 175f callr $AR2 // (*$AR2)() <-- See jump table at 0x0891 + + AC1.M = ((*0x480 * 2) & 0x007e) + 0x0891; // == ((PB.Format * 2) & 0x007e) + 0x0891 + AR2 = AC1.M; + JumpTable0891(PB.Format); - 088d 00fc 0430 sr @0x0430, $AC0.L // PB.CurSampleFrac = AC0.L + //088d 00fc 0430 sr @0x0430, $AC0.L + *0x430 = AC0.L; // *0x430 == PB.CurSampleFrac // 088f 029f 02d8 jmp 0x02d8 GOTO ContinueWithBlock: // in SyncFrame @@ -2923,7 +2933,7 @@ void 087c_DefaultDecoder() 08af 029f 08b1 jmp 0x08b1 // case 0xf (unused) 08b1 02df ret -void 08b2_Decoder0x0_SquareWave() { +void 08b2_Decoder0x0_SquareWave(ACC0, AR0, AX0.L) { 08b2 1401 lsl $ACC0, #1 // t = samplePosition * 2 // Set up sound buffers @@ -2949,7 +2959,7 @@ void 08b2_Decoder0x0_SquareWave() { // 08c1 02df ret } -void 08c2_Decoder0x3_RectangleWave() { +void 08c2_Decoder0x3_RectangleWave(ACC0, AR0, AX0.L) { 08c2 1402 lsl $ACC0, #2 // t = PB.CurSampleFrac * 4 08c3 8900 clr $ACC1 // ACC1 = 0 08c4 1fb8 mrr $AC1.L, $AX0.L // AC1.L = PB.RatioInt @@ -2976,7 +2986,7 @@ void 08c2_Decoder0x3_RectangleWave() { // 08d4 02df ret } -void 08d5_Decoder0x2_SquareSaw() { +void 08d5_Decoder0x2_SquareSaw(ACC0, AR0, AX0.L) { 08d5 1401 lsl $ACC0, #1 08d6 0081 0ca0 lri $AR1, #0x0ca0 08d8 009b c000 lri $AX1.H, #0xc000 @@ -2997,12 +3007,24 @@ void 08d5_Decoder0x2_SquareSaw() { // 08ec 02df ret } -void 08ed_Decoder0x1_SawWave() { - 08ed 8900 clr $ACC1 - 08ee 1fb8 mrr $AC1.L, $AX0.L - 08ef 157f lsr $ACC1, #-1 - 08f0 1050 loopi #0x50 - 08f1 4c20 add's $ACC0, $AC1.L : @$AR0, $AC0.L +void 08ed_Decoder0x1_SawWave(ACC0, AR0, AX0.L) { + // 08ed 8900 clr $ACC1 + // 08ee 1fb8 mrr $AC1.L, $AX0.L + // 08ef 157f lsr $ACC1, #-1 + + // At this point AX0.L is PB.RatioInt and AC0.L is PB.CurSampleFrac + ACC1 = 0; + AC1.L = AX0.L * 2; + + + + // 08f0 1050 loopi #0x50 + for(int i = 0; i < 0x50; i++) { + // 08f1 4c20 add's $ACC0, $AC1.L : @$AR0, $AC0.L + ACC0 += AC1.L; + + *$AR0++ = AC0.L; + } // 08f2 02df ret } @@ -3038,7 +3060,7 @@ void 08f3_Unk() { // 0918 02df ret } -void 0919_Decoder0x6() { +void 0919_Decoder0x6(AR0, AX0.L) { // case 0x6: Fills the buffer with PB.RatioInt (zero?) 0919 1050 loopi #0x50 @@ -3046,7 +3068,7 @@ void 0919_Decoder0x6() { 091b 02df ret } -void 091c_Decoder0x7_WaveTable() { +void 091c_Decoder0x7_WaveTable(ACC0, AR0, AX0.L) { 091c 0082 0100 lri $AR2, #0x0100 091e 008a 003f lri $WR2, #0x003f 0920 0086 0000 lri $IX2, #0x0000