Zelda HLE: Support both NTSC and PAL IPL.

Add a flag for UCodes that only have four non-Dolby mixing destinations
(instead of the standard six destinations).

NTSC IPL is still hopelessly broken.
This commit is contained in:
Pierre Bourdon 2014-12-22 06:20:48 +01:00
parent 4ace79024d
commit 1807c113b5
2 changed files with 22 additions and 14 deletions

View File

@ -55,7 +55,8 @@ UCodeInterface* UCodeFactory(u32 crc, DSPHLE* dsphle, bool wii)
case 0x86840740: // Zelda WW - US
case 0x6ca33a6d: // Zelda TP GC - US
case 0xd643001f: // Super Mario Galaxy - US
case 0x6ba3b3ea: // GC IPL - US
case 0x6ba3b3ea: // GC IPL - PAL
case 0x24b22038: // GC IPL - US
return new ZeldaUCode(dsphle, crc);
case 0x2ea36ce6: // Some Wii demos

View File

@ -23,6 +23,10 @@ enum ZeldaUCodeFlag
// Light version of the UCode: no Dolby mixing, different synchronization
// protocol, etc.
LIGHT_PROTOCOL = 0x00000004,
// If set, only consider 4 of the 6 non-Dolby mixing outputs. Early
// versions of the Zelda UCode only had 4.
FOUR_MIXING_DESTS = 0x00000008,
};
static const std::map<u32, u32> UCODE_FLAGS = {
@ -32,8 +36,10 @@ static const std::map<u32, u32> UCODE_FLAGS = {
{ 0x6CA33A6D, MAKE_DOLBY_LOUDER },
// Super Mario Galaxy.
{ 0xD643001F, NO_ARAM | MAKE_DOLBY_LOUDER },
// GameCube IPL/BIOS.
{ 0x6BA3B3EA, LIGHT_PROTOCOL },
// GameCube IPL/BIOS, PAL.
{ 0x6BA3B3EA, LIGHT_PROTOCOL | FOUR_MIXING_DESTS },
// GameCube IPL/BIOS, NTSC.
{ 0x24B22038, LIGHT_PROTOCOL | FOUR_MIXING_DESTS },
// TODO: Other games that use this UCode (exhaustive list):
// * Animal Crossing (type ????, CRC ????)
@ -973,44 +979,45 @@ void ZeldaAudioRenderer::AddVoice(u16 voice_id)
{
// TODO: Store input samples if requested by the VPB.
int num_channels = (m_flags & FOUR_MIXING_DESTS) ? 4 : 6;
if (vpb.end_requested)
{
bool all_mute = true;
for (auto& channel : vpb.channels)
for (int i = 0; i < num_channels; ++i)
{
channel.target_volume = channel.current_volume / 2;
all_mute &= (channel.target_volume == 0);
vpb.channels[i].target_volume = vpb.channels[i].current_volume / 2;
all_mute &= (vpb.channels[i].target_volume == 0);
}
if (all_mute)
vpb.done = true;
}
for (auto& channel : vpb.channels)
for (int i = 0; i < num_channels; ++i)
{
if (!channel.id)
if (!vpb.channels[i].id)
continue;
s16 volume_delta = channel.target_volume - channel.current_volume;
s16 volume_delta = vpb.channels[i].target_volume - vpb.channels[i].current_volume;
s32 volume_step = (volume_delta << 16) / (s32)input_samples.size(); // In 1.31 format.
// TODO: The last value of each channel structure is used to
// determine whether a channel should be skipped or not. Not
// implemented yet.
if (!channel.current_volume && !volume_step)
if (!vpb.channels[i].current_volume && !volume_step)
continue;
MixingBuffer* dst_buffer = BufferForID(channel.id);
MixingBuffer* dst_buffer = BufferForID(vpb.channels[i].id);
if (!dst_buffer)
{
PanicAlert("Mixing to an unmapped buffer: %04x", channel.id);
PanicAlert("Mixing to an unmapped buffer: %04x", vpb.channels[i].id);
continue;
}
s32 new_volume = AddBuffersWithVolumeRamp(
dst_buffer, input_samples, channel.current_volume << 16,
dst_buffer, input_samples, vpb.channels[i].current_volume << 16,
volume_step);
channel.current_volume = new_volume >> 16;
vpb.channels[i].current_volume = new_volume >> 16;
}
}