From a6a4229865e498dd62b74d3d7b508546a69025cf Mon Sep 17 00:00:00 2001 From: booto Date: Thu, 24 Jul 2014 02:37:00 +0800 Subject: [PATCH] DTK: Adjustments attempting to increase accuracy --- Source/Core/Core/HW/AudioInterface.cpp | 29 +++++-- Source/Core/Core/HW/AudioInterface.h | 1 + Source/Core/Core/HW/DVDInterface.cpp | 113 ++++++++++++++----------- Source/Core/Core/State.cpp | 2 +- 4 files changed, 89 insertions(+), 56 deletions(-) diff --git a/Source/Core/Core/HW/AudioInterface.cpp b/Source/Core/Core/HW/AudioInterface.cpp index 0b8b5ea792..e3daf1a7c8 100644 --- a/Source/Core/Core/HW/AudioInterface.cpp +++ b/Source/Core/Core/HW/AudioInterface.cpp @@ -58,7 +58,6 @@ This file mainly deals with the [Drive I/F], however [AIDFR] controls #include "Core/CoreTiming.h" #include "Core/HW/AudioInterface.h" #include "Core/HW/CPU.h" -#include "Core/HW/DVDInterface.h" #include "Core/HW/MMIO.h" #include "Core/HW/ProcessorInterface.h" #include "Core/HW/SystemTimers.h" @@ -177,8 +176,18 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) MMIO::ComplexWrite([](u32, u32 val) { AICR tmpAICtrl(val); - m_Control.AIINTMSK = tmpAICtrl.AIINTMSK; - m_Control.AIINTVLD = tmpAICtrl.AIINTVLD; + + if (m_Control.AIINTMSK != tmpAICtrl.AIINTMSK) + { + DEBUG_LOG(AUDIO_INTERFACE, "Change AIINTMSK to %d", tmpAICtrl.AIINTMSK); + m_Control.AIINTMSK = tmpAICtrl.AIINTMSK; + } + + if (m_Control.AIINTVLD != tmpAICtrl.AIINTVLD) + { + DEBUG_LOG(AUDIO_INTERFACE, "Change AIINTVLD to %d", tmpAICtrl.AIINTVLD); + m_Control.AIINTVLD = tmpAICtrl.AIINTVLD; + } // Set frequency of streaming audio if (tmpAICtrl.AISFR != m_Control.AISFR) @@ -205,9 +214,6 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) m_Control.PSTAT = tmpAICtrl.PSTAT; g_LastCPUTime = CoreTiming::GetTicks(); - // Tell Drive Interface to start/stop streaming - DVDInterface::g_bStream = tmpAICtrl.PSTAT; - CoreTiming::RemoveEvent(et_AI); CoreTiming::ScheduleEvent(((int)GetAIPeriod() / 2), et_AI); } @@ -251,6 +257,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) mmio->Register(base | AI_INTERRUPT_TIMING, MMIO::DirectRead(&m_InterruptTiming), MMIO::ComplexWrite([](u32, u32 val) { + DEBUG_LOG(AUDIO_INTERFACE, "AI_INTERRUPT_TIMING=%08x@%08x", val, PowerPC::ppcState.pc); m_InterruptTiming = val; CoreTiming::RemoveEvent(et_AI); CoreTiming::ScheduleEvent(((int)GetAIPeriod() / 2), et_AI); @@ -279,14 +286,22 @@ static void IncreaseSampleCount(const u32 _iAmount) { if (m_Control.PSTAT) { + u32 old_SampleCounter = m_SampleCounter + 1; m_SampleCounter += _iAmount; - if (m_Control.AIINTVLD && (m_SampleCounter >= m_InterruptTiming)) + + if ((m_InterruptTiming - old_SampleCounter) <= (m_SampleCounter - old_SampleCounter)) { + DEBUG_LOG(AUDIO_INTERFACE, "GenerateAudioInterrupt %08x:%08x @ %08x m_Control.AIINTVLD=%d", m_SampleCounter, m_InterruptTiming, PowerPC::ppcState.pc, m_Control.AIINTVLD); GenerateAudioInterrupt(); } } } +bool IsPlaying() +{ + return (m_Control.PSTAT == 1); +} + unsigned int GetAIDSampleRate() { return g_AIDSampleRate; diff --git a/Source/Core/Core/HW/AudioInterface.h b/Source/Core/Core/HW/AudioInterface.h index 0b36692083..cf79701068 100644 --- a/Source/Core/Core/HW/AudioInterface.h +++ b/Source/Core/Core/HW/AudioInterface.h @@ -17,6 +17,7 @@ namespace AudioInterface void Init(); void Shutdown(); void DoState(PointerWrap &p); +bool IsPlaying(); void RegisterMMIO(MMIO::Mapping* mmio, u32 base); diff --git a/Source/Core/Core/HW/DVDInterface.cpp b/Source/Core/Core/HW/DVDInterface.cpp index 7e4ebf5919..8c01ba64df 100644 --- a/Source/Core/Core/HW/DVDInterface.cpp +++ b/Source/Core/Core/HW/DVDInterface.cpp @@ -200,15 +200,17 @@ static UDICR m_DICR; static UDIIMMBUF m_DIIMMBUF; static UDICFG m_DICFG; -static u32 LoopStart; static u32 AudioPos; static u32 CurrentStart; -static u32 LoopLength; static u32 CurrentLength; +static u32 NextStart; +static u32 NextLength; + static u32 g_ErrorCode = 0; static bool g_bDiscInside = false; bool g_bStream = false; +static bool g_bStopAtTrackEnd = false; static int tc = 0; static int dtk = 0; @@ -240,9 +242,9 @@ void DoState(PointerWrap &p) p.Do(m_DIIMMBUF); p.DoPOD(m_DICFG); - p.Do(LoopStart); + p.Do(NextStart); p.Do(AudioPos); - p.Do(LoopLength); + p.Do(NextLength); p.Do(g_ErrorCode); p.Do(g_bDiscInside); @@ -253,6 +255,8 @@ void DoState(PointerWrap &p) p.Do(g_last_read_offset); p.Do(g_last_read_time); + + p.Do(g_bStopAtTrackEnd); } static void TransferComplete(u64 userdata, int cyclesLate) @@ -268,18 +272,22 @@ static u32 ProcessDTKSamples(short *tempPCM, u32 num_samples) { if (AudioPos >= CurrentStart + CurrentLength) { - AudioPos = LoopStart; - CurrentStart = LoopStart; - CurrentLength = LoopLength; - NGCADPCM::InitFilter(); - AudioInterface::GenerateAISInterrupt(); + DEBUG_LOG(DVDINTERFACE, + "ProcessDTKSamples: NextStart=%08x,NextLength=%08x,CurrentStart=%08x,CurrentLength=%08x,AudioPos=%08x", + NextStart, NextLength, CurrentStart, CurrentLength, AudioPos); - // If there isn't any audio to stream, stop streaming. - if (AudioPos >= CurrentStart + CurrentLength) + AudioPos = NextStart; + CurrentStart = NextStart; + CurrentLength = NextLength; + + if (g_bStopAtTrackEnd) { + g_bStopAtTrackEnd = false; g_bStream = false; + break; } - break; + + NGCADPCM::InitFilter(); } u8 tempADPCM[NGCADPCM::ONE_BLOCK_SIZE]; @@ -303,7 +311,7 @@ static void DTKStreamingCallback(u64 userdata, int cyclesLate) static const int NUM_SAMPLES = 48000 / 2000 * 7; // 3.5ms of 48kHz samples short tempPCM[NUM_SAMPLES * 2]; unsigned samples_processed; - if (g_bStream) + if (g_bStream && AudioInterface::IsPlaying()) { samples_processed = ProcessDTKSamples(tempPCM, NUM_SAMPLES); } @@ -333,12 +341,13 @@ void Init() m_DICFG.CONFIG = 1; // Disable bootrom descrambler AudioPos = 0; - LoopStart = 0; - LoopLength = 0; + NextStart = 0; + NextLength = 0; CurrentStart = 0; CurrentLength = 0; g_bStream = false; + g_bStopAtTrackEnd = false; ejectDisc = CoreTiming::RegisterEvent("EjectDisc", EjectDiscCallback); insertDisc = CoreTiming::RegisterEvent("InsertDisc", InsertDiscCallback); @@ -928,31 +937,41 @@ void ExecuteCommand() // m_DICMDBUF[2].Hex = Length of the stream case 0xE1: { - u32 pos = m_DICMDBUF[1].Hex << 2; - u32 length = m_DICMDBUF[2].Hex; - - // Start playing - if (!g_bStream && m_DICMDBUF[0].CMDBYTE1 == 0 && pos != 0 && length != 0) - { - AudioPos = pos; - CurrentStart = pos; - CurrentLength = length; - NGCADPCM::InitFilter(); - } - - LoopStart = pos; - LoopLength = length; - g_bStream = (m_DICMDBUF[0].CMDBYTE1 == 0); // This command can start/stop the stream - - // Stop stream - if (m_DICMDBUF[0].CMDBYTE1 == 1) + u8 cancel_stream = m_DICMDBUF[0].CMDBYTE1; + if (cancel_stream) { + g_bStopAtTrackEnd = false; + g_bStream = false; AudioPos = 0; - LoopStart = 0; - LoopLength = 0; + NextStart = 0; + NextLength = 0; CurrentStart = 0; CurrentLength = 0; } + else + { + u32 pos = m_DICMDBUF[1].Hex << 2; + u32 length = m_DICMDBUF[2].Hex; + + if ((pos == 0) && (length == 0)) + { + g_bStopAtTrackEnd = true; + } + else if (!g_bStopAtTrackEnd) + { + NextStart = pos; + NextLength = length; + if (!g_bStream) + { + CurrentStart = NextStart; + CurrentLength = NextLength; + AudioPos = CurrentStart; + NGCADPCM::InitFilter(); + g_bStream = true; + } + } + } + WARN_LOG(DVDINTERFACE, "(Audio) Stream subcmd = %08x offset = %08x length=%08x", m_DICMDBUF[0].Hex, m_DICMDBUF[1].Hex << 2, m_DICMDBUF[2].Hex); @@ -965,25 +984,23 @@ void ExecuteCommand() switch (m_DICMDBUF[0].CMDBYTE1) { case 0x00: // Returns streaming status - m_DIIMMBUF.Hex = (AudioPos == 0) ? 0 : 1; + DEBUG_LOG(DVDINTERFACE, "(Audio): Stream Status: Request Audio status AudioPos:%08x/%08x CurrentStart:%08x CurrentLength:%08x", AudioPos, CurrentStart + CurrentLength, CurrentStart, CurrentLength); + m_DIIMMBUF.REGVAL0 = 0; + m_DIIMMBUF.REGVAL1 = 0; + m_DIIMMBUF.REGVAL2 = 0; + m_DIIMMBUF.REGVAL3 = (g_bStream) ? 1 : 0; break; case 0x01: // Returns the current offset - if (g_bStream) - m_DIIMMBUF.Hex = (AudioPos - CurrentStart) >> 2; - else - m_DIIMMBUF.Hex = 0; + DEBUG_LOG(DVDINTERFACE, "(Audio): Stream Status: Request Audio status AudioPos:%08x", AudioPos); + m_DIIMMBUF.Hex = AudioPos >> 2; break; case 0x02: // Returns the start offset - if (g_bStream) - m_DIIMMBUF.Hex = CurrentStart >> 2; - else - m_DIIMMBUF.Hex = 0; + DEBUG_LOG(DVDINTERFACE, "(Audio): Stream Status: Request Audio status CurrentStart:%08x", CurrentStart); + m_DIIMMBUF.Hex = CurrentStart >> 2; break; case 0x03: // Returns the total length - if (g_bStream) - m_DIIMMBUF.Hex = CurrentLength; - else - m_DIIMMBUF.Hex = 0; + DEBUG_LOG(DVDINTERFACE, "(Audio): Stream Status: Request Audio status CurrentLength:%08x", CurrentLength); + m_DIIMMBUF.Hex = CurrentLength; break; default: WARN_LOG(DVDINTERFACE, "(Audio): Subcommand: %02x Request Audio status %s", m_DICMDBUF[0].CMDBYTE1, g_bStream? "on":"off"); diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp index 08fad24001..a26b4e576a 100644 --- a/Source/Core/Core/State.cpp +++ b/Source/Core/Core/State.cpp @@ -63,7 +63,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 = 28; +static const u32 STATE_VERSION = 29; enum {