From bfff0a72dfada81a0f0844c42b93c8f29f59eafa Mon Sep 17 00:00:00 2001 From: Pierre Bourdon Date: Sun, 21 Dec 2014 17:08:57 +0100 Subject: [PATCH] Zelda HLE: Implement sample sources 4, 7, 11 and 12. Just 4 different versions of the same sample source, using a different constant pattern uploaded to the DSP during command 01. --- Source/Core/Core/HW/DSPHLE/UCodes/Zelda.cpp | 44 ++++++++++++++++++++- Source/Core/Core/HW/DSPHLE/UCodes/Zelda.h | 4 ++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.cpp b/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.cpp index 61c92aaa8a..afb3bd3419 100644 --- a/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.cpp +++ b/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.cpp @@ -226,7 +226,10 @@ void ZeldaUCode::RunPendingCommands() resampling_coeffs[i] = Common::swap16(data_ptr[i]); m_renderer.SetResamplingCoeffs(std::move(resampling_coeffs)); - // TODO: 0x100 more words here to figure out. + std::array const_patterns; + for (size_t i = 0; i < 0x100; ++i) + const_patterns[i] = Common::swap16(data_ptr[0x100 + i]); + m_renderer.SetConstPatterns(std::move(const_patterns)); std::array sine_table; for (size_t i = 0; i < 0x80; ++i) @@ -491,6 +494,15 @@ struct ZeldaAudioRenderer::VPB // Simple saw wave at 100% amplitude and frequency controlled via the // resampling ratio. SRC_SAW_WAVE = 1, + + // Breaking the numerical ordering for these, but they are all related. + // Simple pattern stored in the data downloaded by command 01. Playback + // frequency is controlled by the resampling ratio. + SRC_CONST_PATTERN_0 = 7, + SRC_CONST_PATTERN_1 = 4, + SRC_CONST_PATTERN_2 = 11, + SRC_CONST_PATTERN_3 = 12, + // Samples stored in ARAM in PCM8 format, at an arbitrary sampling rate // (resampling is applied). SRC_PCM8_FROM_ARAM = 8, @@ -948,6 +960,36 @@ void ZeldaAudioRenderer::LoadInputSamples(MixingBuffer* buffer, VPB* vpb) break; } + case VPB::SRC_CONST_PATTERN_0: + case VPB::SRC_CONST_PATTERN_1: + case VPB::SRC_CONST_PATTERN_2: + case VPB::SRC_CONST_PATTERN_3: + { + const u16 PATTERN_SIZE = 0x40; + + std::map samples_source_to_pattern = { + { VPB::SRC_CONST_PATTERN_0, 0 }, + { VPB::SRC_CONST_PATTERN_1, 1 }, + { VPB::SRC_CONST_PATTERN_2, 2 }, + { VPB::SRC_CONST_PATTERN_3, 3 }, + }; + u16 pattern_idx = samples_source_to_pattern[vpb->samples_source_type]; + u16 pattern_offset = pattern_idx * PATTERN_SIZE; + s16* pattern = m_const_patterns.data() + pattern_offset; + + u32 pos = vpb->current_pos_frac << 6; // log2(PATTERN_SIZE) + u32 step = vpb->resampling_ratio << 5; + + for (size_t i = 0; i < buffer->size(); ++i) + { + (*buffer)[i] = pattern[pos >> 16]; + pos = (pos + step) % (PATTERN_SIZE << 16); + } + + vpb->current_pos_frac = pos >> 6; + break; + } + case VPB::SRC_PCM8_FROM_ARAM: DownloadPCM8SamplesFromARAM(raw_input_samples.data() + 4, vpb, NeededRawSamplesCount(*vpb)); diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.h b/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.h index d90ce1794e..736051fca0 100644 --- a/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.h +++ b/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.h @@ -16,6 +16,7 @@ public: void FinalizeFrame(); void SetSineTable(std::array&& sine_table) { m_sine_table = sine_table; } + void SetConstPatterns(std::array&& patterns) { m_const_patterns = patterns; } void SetResamplingCoeffs(std::array&& coeffs) { m_resampling_coeffs = coeffs; } void SetAfcCoeffs(std::array&& coeffs) { m_afc_coeffs = coeffs; } void SetVPBBaseAddress(u32 addr) { m_vpb_base_addr = addr; } @@ -125,6 +126,9 @@ private: // [0.0;pi/4] (sin(x) in [1.0;0.0]), in 1.15 fixed format. std::array m_sine_table{}; + // Const patterns used for some voice samples source. 4 x 0x40 samples. + std::array m_const_patterns{}; + // Fills up a buffer with the input samples for a voice, represented by its // VPB. void LoadInputSamples(MixingBuffer* buffer, VPB* vpb);