From 7d7e2ec8a86d562ac0e1de0fa6bcb3661323b9c1 Mon Sep 17 00:00:00 2001 From: "XTra.KrazzY" Date: Wed, 1 Jul 2009 18:05:54 +0000 Subject: [PATCH] Added the Zelda UCode preliminary synthesizer. It's far from perfect, but it sounds like the exact pitch it should synth. I'd be glad if someone finished it. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3630 8ced0084-cf51-0410-be5f-012b33b47a6e --- .../Plugin_DSP_HLE/Plugin_DSP_HLE.vcproj | 406 +++++++++--------- Source/Plugins/Plugin_DSP_HLE/Src/SConscript | 1 + .../Src/UCodes/UCode_Zelda_Synth.cpp | 72 +++- .../Src/UCodes/UCode_Zelda_Voice.cpp | 20 +- docs/DSP/DSP_UC_Zelda.txt | 62 +-- 5 files changed, 319 insertions(+), 242 deletions(-) diff --git a/Source/Plugins/Plugin_DSP_HLE/Plugin_DSP_HLE.vcproj b/Source/Plugins/Plugin_DSP_HLE/Plugin_DSP_HLE.vcproj index dc1a5a7261..45eca9c5c3 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 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -809,22 +813,6 @@ UsePrecompiledHeader="1" /> - - - - - - @@ -833,6 +821,14 @@ UsePrecompiledHeader="1" /> + + + @@ -841,6 +837,14 @@ UsePrecompiledHeader="1" /> + + + diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/SConscript b/Source/Plugins/Plugin_DSP_HLE/Src/SConscript index 3d75c9e224..3e6f5a9683 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/SConscript +++ b/Source/Plugins/Plugin_DSP_HLE/Src/SConscript @@ -23,6 +23,7 @@ files = [ 'UCodes/UCode_Zelda.cpp', 'UCodes/UCode_Zelda_ADPCM.cpp', 'UCodes/UCode_Zelda_Voice.cpp', + 'UCodes/UCode_Zelda_Synth.cpp', ] dspenv = env.Clone() 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 2989b4ae2c..0749c4d69c 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 @@ -25,19 +25,75 @@ void CUCode_Zelda::MixAddSynth_Waveform(ZeldaVoicePB &PB, s32* _Buffer, int _Size) { - int mask = PB.Format ? 3 : 1; - - for (int i = 0; i < _Size; i++) - { - s16 sample = (i & mask) ? 0xc000 : 0x4000; - - _Buffer[i++] = (s32)sample; - } + float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate(); + u32 _ratio = (((PB.RatioInt * 80) + PB.RatioFrac) << 4) & 0xFFFF0000; + u64 ratio = (u64)(((_ratio / 80) << 16) * ratioFactor); + int mask = PB.Format ? 3 : 1, shift = PB.Format ? 2 : 1; + + 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; + } + } + + for (; i < _Size;) + { + s16 sample = ((pos[1] & mask) == mask) ? 0xc000 : 0x4000; + + _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.CurAddr += pos[1] << 1; + // There should be a position fraction as well. } void CUCode_Zelda::MixAddSynth_Constant(ZeldaVoicePB &PB, s32* _Buffer, int _Size) { + // TODO: Header, footer and cases this synth actually happens for (int i = 0; i < _Size; i++) _Buffer[i++] = (s32)PB.RatioInt; } 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 dd874708ee..bce5f0e3f2 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 @@ -281,20 +281,22 @@ void CUCode_Zelda::MixAddVoice(ZeldaVoicePB &PB, s32* _LeftBuffer, s32* _RightBu { switch (PB.Format) { - // Synthesized sounds - case 0x0000: - case 0x0001: // Used for "Denied" sound in Zelda - //MixAddSynth_Waveform(PB, m_TempBuffer, _Size); - break; + case 0x0000: // Example: Magic meter filling up in ZWW + case 0x0001: // Example: "Denied" sound when trying to pull out a sword + // indoors in ZWW + MixAddSynth_Waveform(PB, m_TempBuffer, _Size); + break; case 0x0006: - //MixAddSynth_Waveform(PB, m_TempBuffer, _Size); - break; + WARN_LOG(DSPHLE, "Synthesizing 0x0006 (constant sound)"); + MixAddSynth_Constant(PB, m_TempBuffer, _Size); + break; - // These are more "synth" formats - square wave, saw wave etc. + // These are more "synth" formats - square wave, saw wave etc. case 0x0002: - return; + WARN_LOG(DSPHLE, "Synthesizing 0x0002"); + break; // AFC formats diff --git a/docs/DSP/DSP_UC_Zelda.txt b/docs/DSP/DSP_UC_Zelda.txt index 1a62b2a1c4..066b6e46d2 100644 --- a/docs/DSP/DSP_UC_Zelda.txt +++ b/docs/DSP/DSP_UC_Zelda.txt @@ -2915,37 +2915,51 @@ void 08b2_Unk() { 08b2 1401 lsl $ACC0, #1 // t = PB.RatioFrac * 2 // Set up sound buffers - 08b3 009b c000 lri $AX1.H, #0xc000 // a = 0xc000 - 08b5 0099 4000 lri $AX1.L, #0x4000 // b = 0x4000 + //08b3 009b c000 lri $AX1.H, #0xc000 + //08b5 0099 4000 lri $AX1.L, #0x4000 - 08b7 1150 08bf bloopi #0x50, 0x08bf - // for(int i = 0; i < 80; i++) { - 08b9 02c0 0001 andcf $AC0.M, #0x0001 - 08bb 027c iflnz - 08bc 1b1b srri @$AR0, $AX1.H - 08bd 027d iflz - 08be 1b19 srri @$AR0, $AX1.L - 08bf 4800 addax $ACC0, $AX0.L - // } - 08c0 147f lsr $ACC0, #-1 + //08b7 1150 08bf bloopi #0x50, 0x08bf + for(int i = 0; i < 80; i++) { + //08b9 02c0 0001 andcf $AC0.M, #0x0001 + //08bb 027c iflnz + // 08bc 1b1b srri @$AR0, $AX1.H + //08bd 027d iflz + // 08be 1b19 srri @$AR0, $AX1.L + if(($AC0.M & 1) == 1) + *$AR0++ = 0x4000; + else + *$AR0++ = 0xc000; + + 08bf 4800 addax $ACC0, $AX0.L // t += PB.RatioInt + } + 08c0 147f lsr $ACC0, #-1 // t /= 2 08c1 02df ret } void 08c2_Unk() { - 08c2 1402 lsl $ACC0, #2 - 08c3 8900 clr $ACC1 - 08c4 1fb8 mrr $AC1.L, $AX0.L - 08c5 1501 lsl $ACC1, #1 + 08c2 1402 lsl $ACC0, #2 // t = PB.RatioFrac * 4 + 08c3 8900 clr $ACC1 // ACC1 = 0 + 08c4 1fb8 mrr $AC1.L, $AX0.L // AC1.L = PB.RatioInt + 08c5 1501 lsl $ACC1, #1 // ACC1 *= 2 08c6 009b c000 lri $AX1.H, #0xc000 08c8 0099 4000 lri $AX1.L, #0x4000 - 08ca 1150 08d2 bloopi #0x50, 0x08d2 - 08cc 02c0 0003 andcf $AC0.M, #0x0003 - 08ce 027c iflnz - 08cf 1b1b srri @$AR0, $AX1.H - 08d0 027d iflz - 08d1 1b19 srri @$AR0, $AX1.L - 08d2 4c00 add $ACC0, $AC1.L - 08d3 147e lsr $ACC0, #-2 + //08ca 1150 08d2 bloopi #0x50, 0x08d2 + for(int i = 0; i < 80; i++) { + //08cc 02c0 0003 andcf $AC0.M, #0x0003 + //08ce 027c iflnz + // 08cf 1b1b srri @$AR0, $AX1.H + //08d0 027d iflz + // 08d1 1b19 srri @$AR0, $AX1.L + //08d2 4c00 add $ACC0, $AC1.L + + if(($AC0.M & 3) == 3) + *$AR0++ = 0x4000; + else + *$AR0++ = 0xc000; + + t += (PB.RatioInt * 2); + } + 08d3 147e lsr $ACC0, #-2 // t /= 4 08d4 02df ret }