DSP: Fix missing masking for accelerator registers

Based on hardware tests, masking occurs for the accelerator registers.

This fixes Red Steel and Far Cry Vengeance, which rely on this behavior
when reading back the current playback position from the DSP.
This commit is contained in:
Léo Lam 2017-09-04 00:14:22 +02:00
parent 9e0df284aa
commit 3475ba8918
3 changed files with 22 additions and 6 deletions

View File

@ -9,6 +9,7 @@
#include "Common/MathUtil.h"
#include "Core/DSP/DSPCore.h"
#include "Core/DSP/DSPHWInterface.h"
#include "Core/DSP/DSPHost.h"
namespace DSP
@ -177,8 +178,8 @@ u16 dsp_read_accelerator()
DSPCore_SetException(EXP_ACCOV);
}
g_dsp.ifx_regs[DSP_ACCAH] = Address >> 16;
g_dsp.ifx_regs[DSP_ACCAL] = Address & 0xffff;
gdsp_ifx_write(DSP_ACCAH, Address >> 16);
gdsp_ifx_write(DSP_ACCAL, Address & 0xffff);
return val;
}
} // namespace DSP

View File

@ -156,6 +156,18 @@ void gdsp_ifx_write(u32 addr, u32 val)
dsp_step_accelerator();
break;
*/
// Masking occurs for the start and end addresses as soon as the registers are written to.
case DSP_ACSAH:
case DSP_ACEAH:
g_dsp.ifx_regs[addr & 0xff] = val & 0x3fff;
break;
// This also happens for the current address, but with a different mask.
case DSP_ACCAH:
g_dsp.ifx_regs[addr & 0xff] = val & 0xbfff;
break;
default:
if ((addr & 0xff) >= 0xa0)
{

View File

@ -171,9 +171,12 @@ static bool acc_end_reached;
void AcceleratorSetup(PB_TYPE* pb, u32* cur_addr)
{
acc_pb = pb;
acc_loop_addr = HILO_TO_32(pb->audio_addr.loop_addr);
acc_end_addr = HILO_TO_32(pb->audio_addr.end_addr);
// Masking occurs for the start and end addresses as soon as the registers are written to.
acc_loop_addr = HILO_TO_32(pb->audio_addr.loop_addr) & 0x3fffffff;
acc_end_addr = HILO_TO_32(pb->audio_addr.end_addr) & 0x3fffffff;
acc_cur_addr = cur_addr;
// It also happens for the current address, but with a different mask.
*acc_cur_addr &= 0xbfffffff;
acc_end_reached = false;
}
@ -456,8 +459,8 @@ void GetInputSamples(PB_TYPE& pb, s16* samples, u16 count, const s16* coeffs)
pb.src.cur_addr_frac = (curr_pos & 0xFFFF);
// Update current position in the PB.
pb.audio_addr.cur_addr_hi = (u16)(cur_addr >> 16);
pb.audio_addr.cur_addr_lo = (u16)(cur_addr & 0xFFFF);
pb.audio_addr.cur_addr_hi = static_cast<u16>(cur_addr >> 16) & 0xbfff;
pb.audio_addr.cur_addr_lo = static_cast<u16>(cur_addr);
}
// Add samples to an output buffer, with optional volume ramping.