diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/UCodes.cpp b/Source/Core/Core/HW/DSPHLE/UCodes/UCodes.cpp index c58d4a3571..c3f9a34d09 100644 --- a/Source/Core/Core/HW/DSPHLE/UCodes/UCodes.cpp +++ b/Source/Core/Core/HW/DSPHLE/UCodes/UCodes.cpp @@ -53,7 +53,8 @@ UCodeInterface* UCodeFactory(u32 crc, DSPHLE* dsphle, bool wii) return new AXUCode(dsphle, crc); case 0x86840740: // Zelda WW - US - case 0x6CA33A6D: // Zelda TP GC - US + case 0x6ca33a6d: // Zelda TP GC - US + case 0xd643001f: // Super Mario Galaxy - US return new ZeldaUCode(dsphle, crc); case 0x2ea36ce6: // Some Wii demos diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.cpp b/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.cpp index c519b8f908..9379243c9d 100644 --- a/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.cpp +++ b/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.cpp @@ -10,7 +10,7 @@ // * Mario Kart: Double Dash!! (type ????, CRC ????) // * Pikmin (type ????, CRC ????) // * Pikmin 2 (type ????, CRC ????) -// * Super Mario Galaxy (type ????, CRC ????) +// * Super Mario Galaxy (type Wii-DAC, CRC D643001F) // * Super Mario Galaxy 2 (type ????, CRC ????) // * Super Mario Sunshine (type ????, CRC ????) // * The Legend of Zelda: Four Swords Adventures (type ????, CRC ????) @@ -191,7 +191,6 @@ void ZeldaUCode::RunPendingCommands() case 0x0A: case 0x0B: case 0x0C: - case 0x0E: case 0x0F: // NOP commands. Log anyway in case we encounter a new version // where these are not NOPs anymore. @@ -268,6 +267,16 @@ void ZeldaUCode::RunPendingCommands() SendCommandAck(CommandAck::STANDARD, sync); break; + // Command 0E: Sets the base address of the ARAM for Wii UCodes. Used + // because the Wii does not have an ARAM, so it simulates it with MRAM + // and DMAs. + case 0x0E: + if (!IsWiiDAC()) + PanicAlert("Setting base ARAM addr on non Wii DAC."); + m_renderer.SetARAMBaseAddr(Read32()); + SendCommandAck(CommandAck::STANDARD, sync); + break; + default: NOTICE_LOG(DSPHLE, "Received a non-existing command (%d), halting.", command); SetMailState(MailState::HALTED); @@ -1066,6 +1075,14 @@ void ZeldaAudioRenderer::Resample(VPB* vpb, const s16* src, MixingBuffer* dst) vpb->current_pos_frac = pos & 0xFFF; } +void* ZeldaAudioRenderer::GetARAMPtr() const +{ + if (m_aram_base_addr) + return HLEMemory_Get_Pointer(m_aram_base_addr); + else + return DSP::GetARAMPtr(); +} + void ZeldaAudioRenderer::DownloadPCM8SamplesFromARAM( s16* dst, VPB* vpb, u16 requested_samples_count) { @@ -1100,7 +1117,7 @@ void ZeldaAudioRenderer::DownloadPCM8SamplesFromARAM( vpb->SetCurrentARAMAddr( vpb->GetBaseAddress() + vpb->GetCurrentPosition()); - s8* src_ptr = (s8*)DSP::GetARAMPtr() + vpb->GetCurrentARAMAddr(); + s8* src_ptr = (s8*)GetARAMPtr() + vpb->GetCurrentARAMAddr(); u16 samples_to_download = std::min(vpb->GetRemainingLength(), (u32)requested_samples_count); @@ -1230,7 +1247,7 @@ void ZeldaAudioRenderer::DownloadAFCSamplesFromARAM( void ZeldaAudioRenderer::DecodeAFC(VPB* vpb, s16* dst, size_t block_count) { u32 addr = vpb->GetCurrentARAMAddr(); - u8* src = (u8*)DSP::GetARAMPtr() + addr; + u8* src = (u8*)GetARAMPtr() + addr; vpb->SetCurrentARAMAddr(addr + (u32)block_count * vpb->samples_source_type); for (size_t b = 0; b < block_count; ++b) diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.h b/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.h index 736051fca0..ff40aa68af 100644 --- a/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.h +++ b/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.h @@ -24,6 +24,7 @@ public: void SetOutputVolume(u16 volume) { m_output_volume = volume; } void SetOutputLeftBufferAddr(u32 addr) { m_output_lbuf_addr = addr; } void SetOutputRightBufferAddr(u32 addr) { m_output_rbuf_addr = addr; } + void SetARAMBaseAddr(u32 addr) { m_aram_base_addr = addr; } void DoState(PointerWrap& p); @@ -144,6 +145,12 @@ private: // Coefficients used for resampling. std::array m_resampling_coeffs{}; + // If non zero, base MRAM address for sound data transfers from ARAM. On + // the Wii, this points to some MRAM location since there is no ARAM to be + // used. If zero, use the top of ARAM. + u32 m_aram_base_addr = 0; + void* GetARAMPtr() const; + // Downloads PCM8 encoded samples from ARAM. Handles looping and other // parameters appropriately. void DownloadPCM8SamplesFromARAM(s16* dst, VPB* vpb, u16 requested_samples_count); @@ -182,6 +189,11 @@ public: void DoState(PointerWrap &p) override; + bool IsWiiDAC() const + { + return m_crc == 0xd643001f; + } + private: // UCode state machine. The control flow in the Zelda UCode family is quite // complex, using interrupt handlers heavily to handle incoming messages