Well it wasn't exactly stupid..
I would like to know where you got it from to see if the UpdateSampleCounters corresponds with AFC audio. I noticed that Render_AFC looks nearly similar to the code for PCM16. I am piecing in some code from PCM16 as the current AFC code is improper and has issues, here is what I've done so far:
Code:
void UpdateSampleCounters59(ZeldaVoicePB &PB)
{
PB.RemLength = PB.Length - PB.RestartPos;
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 4);
PB.ReachedEnd = 0;
}
void CUCode_Zelda::RenderVoice_AFC(ZeldaVoicePB &PB, s16 *_Buffer, int _Size)
{
// TODO: Compare mono, stereo and surround samples
#if defined DEBUG || defined DEBUGFAST
PrintObject(PB);
#endif
int _RealSize = SizeForResampling(PB, _Size, PB.RatioInt);
u32 rem_samples = _RealSize;
if (PB.KeyOff)
goto clear_buffer;
// initialize "decoder" if the sample is played the first time
if (PB.NeedsReset)
{
// This is 0717_ReadOutPBStuff
// increment 4fb
// zelda:
// perhaps init or "has played before"
PB.CurBlock = 0x00;
PB.YN2 = 0x00; // history1
PB.YN1 = 0x00; // history2
// Length in samples.
PB.RemLength = PB.Length;
// Copy ARAM addr from r to rw area.
PB.CurAddr = PB.StartAddr;
PB.ReachedEnd = 0;
PB.CurSampleFrac = 0;
UpdateSampleCounters59(PB);
for (int i = 0; i < 4; i++)
PB.ResamplerOldData[i] = 0;
}
if (PB.ReachedEnd)
{
PB.ReachedEnd = 0;
reached_end:
if (!PB.RepeatMode) {
// One shot - play zeros the rest of the buffer.
clear_buffer:
for (int i = 0; i < _RealSize; i++)
*_Buffer++ = 0;
PB.KeyOff = 1;
return;
}
else
{
PB.RestartPos = PB.LoopStartPos;
UpdateSampleCounters59(PB);
}
}
There's more to do yet and it seems I haven't broke anything so far, but I need your help and the help of another developer to fix the AFC code completely.
What are these lines of code responsible for, this just looks funky:
Code:
// This is 0717_ReadOutPBStuff
// increment 4fb
// zelda:
// perhaps init or "has played before"
PB.CurBlock = 0x00;
PB.YN2 = 0x00; // history1
PB.YN1 = 0x00; // history2
// Length in samples.
PB.RemLength = PB.Length;
// Copy ARAM addr from r to rw area.
PB.CurAddr = PB.StartAddr;
PB.ReachedEnd = 0;
PB.CurSampleFrac = 0;
That isn't in the PCM16 code since it relates to AFC looping. Hopefully if we can get the AFC code more corect'ish it might fix the music looping issue.
This part of the code should be focused on next:
Code:
// Round upwards how many samples we need to copy, 0759
// u32 frac = NumberOfSamples & 0xF;
// NumberOfSamples = (NumberOfSamples + 0xf) >> 4; // i think the lower 4 are the fraction
const u8 *source;
u32 ram_mask = 1024 * 1024 * 16 - 1;
if (IsDMAVersion()) {
source = g_dspInitialize.pGetMemoryPointer(m_DMABaseAddr);
ram_mask = 1024 * 1024 * 64 - 1;
}
else
source = g_dspInitialize.pGetARAMPointer();
int sampleCount = 0; // must be above restart.
restart:
if (PB.ReachedEnd)
{
PB.ReachedEnd = 0;
if ((PB.RepeatMode == 0) || (!PB.StopOnSilence == 0))
{
PB.KeyOff = 1;
PB.RemLength = 0;
PB.CurAddr = PB.StartAddr + PB.RestartPos + PB.Length;
while (sampleCount < _RealSize)
_Buffer[sampleCount++] = 0;
return;
}
else
{
//AFC looping
// The loop start pos is incorrect? (Fixed?), so samples will loop a bit wrong.
// this fixes the intro music in ZTP.
PB.RestartPos = PB.LoopStartPos;
PB.RemLength = PB.Length - PB.RestartPos;
// see DSP_UC_Zelda.txt line 2817
PB.CurAddr = ((((((PB.LoopStartPos >> 4) & 0xffff0000) * PB.Format) << 16) + (((PB.LoopStartPos >> 4) & 0xffff) * PB.Format)) + PB.StartAddr) & 0xffffffff;
// Hmm, this shouldn't be reversed .. or should it? Is it different between versions of the ucode?
// -> it has to be reversed in ZTP, otherwise intro music is broken...
PB.YN1 = PB.LoopYN2;
PB.YN2 = PB.LoopYN1;
}
}
And so on until all of the AFC code is corrected and accounted for. I think the above code is the last piece of code that should be focused on to fix the issue, if not we'll need to go from there to find and fix the issue. I verified that the alterations I made did not have any unwanted side effects, although it does nothing to fix the music looping issue.
According to this it appears the dsp get's desynced, then tries to write to the left/right buffer address and that's when the AFC starts going crazy. Even if this is the issue that still doesn't mean AFC can't be cleaned and properly done as it may save headaches down the road:
http://forums.dolphin-emu.org/thread-10800-post-103192.html#pid103192
Code:
26:25:920 .\Src\UCodes\UCode_Zelda.cpp:433 D[DSPHLE]: ==============================================================================
26:25:920 .\Src\UCodes\UCode_Zelda.cpp:434 D[DSPHLE]: Zelda UCode - execute dlist (cmd: 0x0002 : sync: 0x8207)
26:25:920 .\Src\UCodes\UCode_Zelda.cpp:489 D[DSPHLE]: DsyncFrame
26:25:920 .\Src\UCodes\UCode_Zelda.cpp:492 D[DSPHLE]: Right buffer address: 0x008b6160
26:25:920 .\Src\UCodes\UCode_Zelda.cpp:493 D[DSPHLE]: Left buffer address: 0x008b65c0