DSP: Fix ACCOV not suspending accelerator reads
When an ACCOV is triggered, the accelerator stops reading back anything and updating the current address until the YN2 register is set. This is kept track of internally by the DSP; this state is not exposed via any register. However, we need to emulate this behaviour correctly because some ucodes rely on it (notably AX GC); failure to emulate it will result in reading past the end and start address for non-looped voices.
This commit is contained in:
parent
8310a672b0
commit
bd03f2e46e
|
@ -60,6 +60,9 @@ void Accelerator::WriteD3(u16 value)
|
|||
|
||||
u16 Accelerator::Read(s16* coefs)
|
||||
{
|
||||
if (m_reads_stopped)
|
||||
return 0x0000;
|
||||
|
||||
u16 val;
|
||||
u8 step_size_bytes = 0;
|
||||
|
||||
|
@ -148,6 +151,7 @@ u16 Accelerator::Read(s16* coefs)
|
|||
{
|
||||
// Set address back to start address.
|
||||
m_current_address = m_start_address;
|
||||
m_reads_stopped = true;
|
||||
OnEndException();
|
||||
}
|
||||
|
||||
|
@ -164,6 +168,7 @@ void Accelerator::DoState(PointerWrap& p)
|
|||
p.Do(m_yn1);
|
||||
p.Do(m_yn2);
|
||||
p.Do(m_pred_scale);
|
||||
p.Do(m_reads_stopped);
|
||||
}
|
||||
|
||||
constexpr u32 START_END_ADDRESS_MASK = 0x3fffffff;
|
||||
|
@ -197,6 +202,7 @@ void Accelerator::SetYn1(s16 yn1)
|
|||
void Accelerator::SetYn2(s16 yn2)
|
||||
{
|
||||
m_yn2 = yn2;
|
||||
m_reads_stopped = false;
|
||||
}
|
||||
|
||||
void Accelerator::SetPredScale(u16 pred_scale)
|
||||
|
|
|
@ -50,5 +50,10 @@ protected:
|
|||
s16 m_yn1 = 0;
|
||||
s16 m_yn2 = 0;
|
||||
u16 m_pred_scale = 0;
|
||||
|
||||
// When an ACCOV is triggered, the accelerator stops reading back anything
|
||||
// and updating the current address register, unless the YN2 register is written to.
|
||||
// This is kept track of internally; this state is not exposed via any register.
|
||||
bool m_reads_stopped = false;
|
||||
};
|
||||
} // namespace DSP
|
||||
|
|
|
@ -199,10 +199,10 @@ protected:
|
|||
|
||||
#ifdef AX_WII
|
||||
// One of the few meaningful differences between AXGC and AXWii:
|
||||
// while AXGC handles non looping voices ending by having 0000
|
||||
// samples at the loop address, AXWii has the 0000 samples
|
||||
// internally in DRAM and use an internal pointer to it (loop addr
|
||||
// does not contain 0000 samples on AXWii!).
|
||||
// while AXGC handles non looping voices ending by relying on the
|
||||
// accelerator to stop reads once the loop address is reached,
|
||||
// AXWii has the 0000 samples internally in DRAM and use an internal
|
||||
// pointer to it (loop addr does not contain 0000 samples on AXWii!).
|
||||
acc_end_reached = true;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ static Common::Event g_compressAndDumpStateSyncEvent;
|
|||
static std::thread g_save_thread;
|
||||
|
||||
// Don't forget to increase this after doing changes on the savestate system
|
||||
static const u32 STATE_VERSION = 89; // Last changed in PR 5890
|
||||
static const u32 STATE_VERSION = 90; // Last changed in PR 6077
|
||||
|
||||
// Maps savestate versions to Dolphin versions.
|
||||
// Versions after 42 don't need to be added to this list,
|
||||
|
|
Loading…
Reference in New Issue