Take the size of the audio data into account when checking for the loop address. Fixes the static audio in the FMV of Megaman X Collection, Pac Man World 2, off pitched instruments in Skies of Arcadia and audio desync in the Taiko no Tatsujin series.

Fixes:
issue 7154
issue 7222
issue 7280
issue 7457
This commit is contained in:
skid 2014-09-01 21:43:33 +10:00
parent ea7eee1f58
commit 91a6962565
2 changed files with 17 additions and 7 deletions

View File

@ -15,7 +15,7 @@ static s16 ADPCM_Step(u32& _rSamplePos)
{ {
const s16 *pCoefTable = (const s16 *)&g_dsp.ifx_regs[DSP_COEF_A1_0]; const s16 *pCoefTable = (const s16 *)&g_dsp.ifx_regs[DSP_COEF_A1_0];
if (((_rSamplePos) & 15) == 0) if (((_rSamplePos)& 15) == 0)
{ {
g_dsp.ifx_regs[DSP_PRED_SCALE] = DSPHost::ReadHostMemory((_rSamplePos & ~15) >> 1); g_dsp.ifx_regs[DSP_PRED_SCALE] = DSPHost::ReadHostMemory((_rSamplePos & ~15) >> 1);
_rSamplePos += 2; _rSamplePos += 2;
@ -63,7 +63,7 @@ u16 dsp_read_aram_d3()
Address++; Address++;
break; break;
case 0x6: // u16 reads case 0x6: // u16 reads
val = (DSPHost::ReadHostMemory(Address*2) << 8) | DSPHost::ReadHostMemory(Address*2 + 1); val = (DSPHost::ReadHostMemory(Address * 2) << 8) | DSPHost::ReadHostMemory(Address * 2 + 1);
Address++; Address++;
break; break;
default: default:
@ -93,8 +93,8 @@ void dsp_write_aram_d3(u16 value)
switch (g_dsp.ifx_regs[DSP_FORMAT]) switch (g_dsp.ifx_regs[DSP_FORMAT])
{ {
case 0xA: // u16 writes case 0xA: // u16 writes
DSPHost::WriteHostMemory(value >> 8, Address*2); DSPHost::WriteHostMemory(value >> 8, Address * 2);
DSPHost::WriteHostMemory(value & 0xFF, Address*2 + 1); DSPHost::WriteHostMemory(value & 0xFF, Address * 2 + 1);
Address++; Address++;
break; break;
default: default:
@ -111,6 +111,7 @@ u16 dsp_read_accelerator()
const u32 EndAddress = (g_dsp.ifx_regs[DSP_ACEAH] << 16) | g_dsp.ifx_regs[DSP_ACEAL]; const u32 EndAddress = (g_dsp.ifx_regs[DSP_ACEAH] << 16) | g_dsp.ifx_regs[DSP_ACEAL];
u32 Address = (g_dsp.ifx_regs[DSP_ACCAH] << 16) | g_dsp.ifx_regs[DSP_ACCAL]; u32 Address = (g_dsp.ifx_regs[DSP_ACCAH] << 16) | g_dsp.ifx_regs[DSP_ACCAL];
u16 val; u16 val;
u8 step_size_bytes = 0;
// let's do the "hardware" decode DSP_FORMAT is interesting - the Zelda // let's do the "hardware" decode DSP_FORMAT is interesting - the Zelda
// ucode seems to indicate that the bottom two bits specify the "read size" // ucode seems to indicate that the bottom two bits specify the "read size"
@ -122,21 +123,25 @@ u16 dsp_read_accelerator()
{ {
case 0x00: // ADPCM audio case 0x00: // ADPCM audio
val = ADPCM_Step(Address); val = ADPCM_Step(Address);
step_size_bytes = 2;
break; break;
case 0x0A: // 16-bit PCM audio case 0x0A: // 16-bit PCM audio
val = (DSPHost::ReadHostMemory(Address*2) << 8) | DSPHost::ReadHostMemory(Address*2 + 1); val = (DSPHost::ReadHostMemory(Address * 2) << 8) | DSPHost::ReadHostMemory(Address * 2 + 1);
g_dsp.ifx_regs[DSP_YN2] = g_dsp.ifx_regs[DSP_YN1]; g_dsp.ifx_regs[DSP_YN2] = g_dsp.ifx_regs[DSP_YN1];
g_dsp.ifx_regs[DSP_YN1] = val; g_dsp.ifx_regs[DSP_YN1] = val;
step_size_bytes = 2;
Address++; Address++;
break; break;
case 0x19: // 8-bit PCM audio case 0x19: // 8-bit PCM audio
val = DSPHost::ReadHostMemory(Address) << 8; val = DSPHost::ReadHostMemory(Address) << 8;
g_dsp.ifx_regs[DSP_YN2] = g_dsp.ifx_regs[DSP_YN1]; g_dsp.ifx_regs[DSP_YN2] = g_dsp.ifx_regs[DSP_YN1];
g_dsp.ifx_regs[DSP_YN1] = val; g_dsp.ifx_regs[DSP_YN1] = val;
step_size_bytes = 1;
Address++; Address++;
break; break;
default: default:
ERROR_LOG(DSPLLE, "dsp_read_accelerator() - unknown format 0x%x", g_dsp.ifx_regs[DSP_FORMAT]); ERROR_LOG(DSPLLE, "dsp_read_accelerator() - unknown format 0x%x", g_dsp.ifx_regs[DSP_FORMAT]);
step_size_bytes = 1;
Address++; Address++;
val = 0; val = 0;
break; break;
@ -151,7 +156,7 @@ u16 dsp_read_accelerator()
// Somehow, YN1 and YN2 must be initialized with their "loop" values, // Somehow, YN1 and YN2 must be initialized with their "loop" values,
// so yeah, it seems likely that we should raise an exception to let // so yeah, it seems likely that we should raise an exception to let
// the DSP program do that, at least if DSP_FORMAT == 0x0A. // the DSP program do that, at least if DSP_FORMAT == 0x0A.
if ((Address & ~1) == (EndAddress & ~1)) if (Address == (EndAddress + step_size_bytes - 1))
{ {
// Set address back to start address. // Set address back to start address.
Address = (g_dsp.ifx_regs[DSP_ACSAH] << 16) | g_dsp.ifx_regs[DSP_ACSAL]; Address = (g_dsp.ifx_regs[DSP_ACSAH] << 16) | g_dsp.ifx_regs[DSP_ACSAL];

View File

@ -149,12 +149,17 @@ void AcceleratorSetup(PB_TYPE* pb, u32* cur_addr)
u16 AcceleratorGetSample() u16 AcceleratorGetSample()
{ {
u16 ret; u16 ret;
u8 step_size_bytes = 2;
// 8-bit PCM audio uses 1 byte per sample/sample block, not 2 like other formats.
if (acc_pb->audio_addr.sample_format == 0x19)
step_size_bytes = 1;
// Have we reached the end address? // Have we reached the end address?
// //
// On real hardware, this would raise an interrupt that is handled by the // On real hardware, this would raise an interrupt that is handled by the
// UCode. We simulate what this interrupt does here. // UCode. We simulate what this interrupt does here.
if ((*acc_cur_addr & ~1) == (acc_end_addr & ~1)) if (*acc_cur_addr == (acc_end_addr + step_size_bytes - 1))
{ {
// loop back to loop_addr. // loop back to loop_addr.
*acc_cur_addr = acc_loop_addr; *acc_cur_addr = acc_loop_addr;