diff --git a/Source/Core/Core/Src/ConfigManager.cpp b/Source/Core/Core/Src/ConfigManager.cpp index 03a0d19d9a..8929ca2f29 100644 --- a/Source/Core/Core/Src/ConfigManager.cpp +++ b/Source/Core/Core/Src/ConfigManager.cpp @@ -63,7 +63,7 @@ void SConfig::SaveSettings() ini.Set("General", tmp, m_ISOFolder[i]); } - ini.Set("General", "RecersiveGCMPaths", m_RecersiveISOFolder); + ini.Set("General", "RecersiveGCMPaths", m_RecursiveISOFolder); } @@ -87,6 +87,7 @@ void SConfig::SaveSettings() ini.Set("Core", "HLEBios", m_LocalCoreStartupParameter.bHLEBios); ini.Set("Core", "UseDynarec", m_LocalCoreStartupParameter.bUseJIT); ini.Set("Core", "UseDualCore", m_LocalCoreStartupParameter.bUseDualCore); + ini.Set("Core", "DSPThread", m_LocalCoreStartupParameter.bDSPThread); ini.Set("Core", "SkipIdle", m_LocalCoreStartupParameter.bSkipIdle); ini.Set("Core", "LockThreads", m_LocalCoreStartupParameter.bLockThreads); ini.Set("Core", "DefaultGCM", m_LocalCoreStartupParameter.m_strDefaultGCM); @@ -168,7 +169,7 @@ void SConfig::LoadSettings() } } - ini.Get("General", "RecersiveGCMPaths", &m_RecersiveISOFolder, false); + ini.Get("General", "RecersiveGCMPaths", &m_RecursiveISOFolder, false); } { @@ -188,11 +189,12 @@ void SConfig::LoadSettings() ini.Get("Interface", "ShowConsole", &m_InterfaceConsole, false); // Core - ini.Get("Core", "HLEBios", &m_LocalCoreStartupParameter.bHLEBios, true); - ini.Get("Core", "UseDynarec", &m_LocalCoreStartupParameter.bUseJIT, true); - ini.Get("Core", "UseDualCore", &m_LocalCoreStartupParameter.bUseDualCore, false); - ini.Get("Core", "SkipIdle", &m_LocalCoreStartupParameter.bSkipIdle, true); - ini.Get("Core", "LockThreads", &m_LocalCoreStartupParameter.bLockThreads, true); + ini.Get("Core", "HLEBios", &m_LocalCoreStartupParameter.bHLEBios, true); + ini.Get("Core", "UseDynarec", &m_LocalCoreStartupParameter.bUseJIT, true); + ini.Get("Core", "DSPThread", &m_LocalCoreStartupParameter.bDSPThread, true); + ini.Get("Core", "UseDualCore", &m_LocalCoreStartupParameter.bUseDualCore, false); + ini.Get("Core", "SkipIdle", &m_LocalCoreStartupParameter.bSkipIdle, true); + ini.Get("Core", "LockThreads", &m_LocalCoreStartupParameter.bLockThreads, true); ini.Get("Core", "DefaultGCM", &m_LocalCoreStartupParameter.m_strDefaultGCM); ini.Get("Core", "DVDRoot", &m_LocalCoreStartupParameter.m_strDVDRoot); ini.Get("Core", "OptimizeQuantizers", &m_LocalCoreStartupParameter.bOptimizeQuantizers, true); diff --git a/Source/Core/Core/Src/ConfigManager.h b/Source/Core/Core/Src/ConfigManager.h index f13f8cc119..fcf3ed0aca 100644 --- a/Source/Core/Core/Src/ConfigManager.h +++ b/Source/Core/Core/Src/ConfigManager.h @@ -50,8 +50,8 @@ struct SConfig std::string m_LastFilename; // gcm folder - std::vectorm_ISOFolder; - bool m_RecersiveISOFolder; + std::vector m_ISOFolder; + bool m_RecursiveISOFolder; SCoreStartupParameter m_LocalCoreStartupParameter; diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp index 6bc6733931..626be6d753 100644 --- a/Source/Core/Core/Src/Core.cpp +++ b/Source/Core/Core/Src/Core.cpp @@ -414,6 +414,7 @@ THREAD_RETURN EmuThread(void *pArg) dspInit.pGetAudioStreaming = AudioInterface::Callback_GetStreaming; dspInit.pEmulatorState = (int *)PowerPC::GetStatePtr(); dspInit.bWii = _CoreParameter.bWii; + dspInit.bOnThread = _CoreParameter.bDSPThread; // May be needed for Stop and Start #ifdef SETUP_FREE_DSP_PLUGIN_ON_BOOT Plugins.FreeDSP(); diff --git a/Source/Core/Core/Src/CoreParameter.cpp b/Source/Core/Core/Src/CoreParameter.cpp index 59e84cef2f..d17b991743 100644 --- a/Source/Core/Core/Src/CoreParameter.cpp +++ b/Source/Core/Core/Src/CoreParameter.cpp @@ -41,6 +41,7 @@ void SCoreStartupParameter::LoadDefaults() bUseDualCore = false; bSkipIdle = false; bRunCompareServer = false; + bDSPThread = true; bLockThreads = true; bWii = false; SelectedLanguage = 0; diff --git a/Source/Core/Core/Src/CoreParameter.h b/Source/Core/Core/Src/CoreParameter.h index b37ddc68b3..1011ed359c 100644 --- a/Source/Core/Core/Src/CoreParameter.h +++ b/Source/Core/Core/Src/CoreParameter.h @@ -57,6 +57,7 @@ struct SCoreStartupParameter bool bJITBranchOff; bool bUseDualCore; + bool bDSPThread; bool bSkipIdle; bool bNTSC; bool bHLEBios; diff --git a/Source/Core/Core/Src/HW/SystemTimers.cpp b/Source/Core/Core/Src/HW/SystemTimers.cpp index c725de1e8e..4c83e0de40 100644 --- a/Source/Core/Core/Src/HW/SystemTimers.cpp +++ b/Source/Core/Core/Src/HW/SystemTimers.cpp @@ -210,7 +210,7 @@ void DecrementerCallback(u64 userdata, int cyclesLate) void DecrementerSet() { u32 decValue = PowerPC::ppcState.spr[SPR_DEC]; - fakeDec = decValue*TIMER_RATIO; + fakeDec = decValue * TIMER_RATIO; CoreTiming::RemoveEvent(et_Dec); CoreTiming::ScheduleEvent(decValue * TIMER_RATIO, et_Dec); } @@ -221,8 +221,8 @@ void AdvanceCallback(int cyclesExecuted) return; fakeDec -= cyclesExecuted; - u64 timebase_ticks = CoreTiming::GetTicks() / TIMER_RATIO; //works since we are little endian and TL comes first :) - *(u64*)&TL = timebase_ticks + startTimeBaseTicks; + u64 timebase_ticks = CoreTiming::GetTicks() / TIMER_RATIO; + *(u64*)&TL = timebase_ticks + startTimeBaseTicks; //works since we are little endian and TL comes first :) if (fakeDec >= 0) PowerPC::ppcState.spr[SPR_DEC] = (u32)fakeDec / TIMER_RATIO; } @@ -243,10 +243,15 @@ void Init() CPU_CORE_CLOCK = 729000000u; VI_PERIOD = GetTicksPerSecond() / (60*120); SI_PERIOD = GetTicksPerSecond() / 60; // once a frame is good for controllers - - // These are the big question marks IMHO :) + + if (!Core::GetStartupParameter().bDSPThread) { + DSP_PERIOD = 12000; // TO BE TWEAKED + } else { + DSP_PERIOD = (int)(GetTicksPerSecond() * 0.003f); + } + + // This is the biggest question mark. AI_PERIOD = GetTicksPerSecond() / 80; - DSP_PERIOD = (int)(GetTicksPerSecond() * 0.003f); IPC_HLE_PERIOD = (int)(GetTicksPerSecond() * 0.003f); } @@ -255,10 +260,15 @@ void Init() CPU_CORE_CLOCK = 486000000; VI_PERIOD = GetTicksPerSecond() / (60*120); SI_PERIOD = GetTicksPerSecond() / 60; // once a frame is good for controllers - - // These are the big question marks IMHO :) + + if (!Core::GetStartupParameter().bDSPThread) { + DSP_PERIOD = 12000; // TO BE TWEAKED + } else { + DSP_PERIOD = (int)(GetTicksPerSecond() * 0.005f); + } + + // This is the biggest question mark. AI_PERIOD = GetTicksPerSecond() / 80; - DSP_PERIOD = (int)(GetTicksPerSecond() * 0.005f); } Common::Timer::IncreaseResolution(); // store and convert localtime at boot to timebase ticks diff --git a/Source/Core/DolphinWX/Src/ConfigMain.cpp b/Source/Core/DolphinWX/Src/ConfigMain.cpp index e1cd81bb38..084617feae 100644 --- a/Source/Core/DolphinWX/Src/ConfigMain.cpp +++ b/Source/Core/DolphinWX/Src/ConfigMain.cpp @@ -49,6 +49,7 @@ EVT_CHOICE(ID_INTERFACE_LANG, CConfigMain::CoreSettingsChanged) EVT_CHECKBOX(ID_ALLWAYS_HLEBIOS, CConfigMain::CoreSettingsChanged) EVT_CHECKBOX(ID_USEDYNAREC, CConfigMain::CoreSettingsChanged) EVT_CHECKBOX(ID_USEDUALCORE, CConfigMain::CoreSettingsChanged) +EVT_CHECKBOX(ID_DSPTHREAD, CConfigMain::CoreSettingsChanged) EVT_CHECKBOX(ID_LOCKTHREADS, CConfigMain::CoreSettingsChanged) EVT_CHECKBOX(ID_OPTIMIZEQUANTIZERS, CConfigMain::CoreSettingsChanged) EVT_CHECKBOX(ID_IDLESKIP, CConfigMain::CoreSettingsChanged) @@ -131,7 +132,7 @@ void CConfigMain::UpdateGUI() if(Core::GetState() != Core::CORE_UNINITIALIZED) { // Disable the Core stuff on GeneralPage - AllwaysHLEBIOS->Disable(); + AlwaysUseHLEBIOS->Disable(); UseDynaRec->Disable(); UseDualCore->Disable(); LockThreads->Disable(); @@ -182,13 +183,15 @@ void CConfigMain::CreateGUIControls() // Core Settings - Basic UseDualCore = new wxCheckBox(GeneralPage, ID_USEDUALCORE, wxT("Enable Dual Core"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); UseDualCore->SetValue(SConfig::GetInstance().m_LocalCoreStartupParameter.bUseDualCore); + DSPThread = new wxCheckBox(GeneralPage, ID_DSPTHREAD, wxT("LLE DSP on thread"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + DSPThread->SetValue(SConfig::GetInstance().m_LocalCoreStartupParameter.bDSPThread); SkipIdle = new wxCheckBox(GeneralPage, ID_IDLESKIP, wxT("Enable Idle Skipping"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); SkipIdle->SetValue(SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle); EnableCheats = new wxCheckBox(GeneralPage, ID_ENABLECHEATS, wxT("Enable Cheats"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); EnableCheats->SetValue(SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats); // Core Settings - Advanced - AllwaysHLEBIOS = new wxCheckBox(GeneralPage, ID_ALLWAYS_HLEBIOS, wxT("HLE the BIOS all the time"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - AllwaysHLEBIOS->SetValue(SConfig::GetInstance().m_LocalCoreStartupParameter.bHLEBios); + AlwaysUseHLEBIOS = new wxCheckBox(GeneralPage, ID_ALLWAYS_HLEBIOS, wxT("HLE the BIOS all the time"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + AlwaysUseHLEBIOS->SetValue(SConfig::GetInstance().m_LocalCoreStartupParameter.bHLEBios); UseDynaRec = new wxCheckBox(GeneralPage, ID_USEDYNAREC, wxT("Enable the JIT dynarec"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); UseDynaRec->SetValue(SConfig::GetInstance().m_LocalCoreStartupParameter.bUseJIT); LockThreads = new wxCheckBox(GeneralPage, ID_LOCKTHREADS, wxT("Lock threads to cores"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); @@ -260,10 +263,11 @@ void CConfigMain::CreateGUIControls() sCore = new wxBoxSizer(wxHORIZONTAL); sbBasic = new wxStaticBoxSizer(wxVERTICAL, GeneralPage, wxT("Basic Settings")); sbBasic->Add(UseDualCore, 0, wxALL, 5); + sbBasic->Add(DSPThread, 0, wxALL, 5); sbBasic->Add(SkipIdle, 0, wxALL, 5); sbBasic->Add(EnableCheats, 0, wxALL, 5); sbAdvanced = new wxStaticBoxSizer(wxVERTICAL, GeneralPage, wxT("Advanced Settings")); - sbAdvanced->Add(AllwaysHLEBIOS, 0, wxALL, 5); + sbAdvanced->Add(AlwaysUseHLEBIOS, 0, wxALL, 5); sbAdvanced->Add(UseDynaRec, 0, wxALL, 5); sbAdvanced->Add(LockThreads, 0, wxALL, 5); sbAdvanced->Add(OptimizeQuantizers, 0, wxALL, 5); @@ -443,7 +447,7 @@ void CConfigMain::CreateGUIControls() RemoveISOPath = new wxButton(PathsPage, ID_REMOVEISOPATH, wxT("Remove"), wxDefaultPosition, wxDefaultSize, 0); RemoveISOPath->Enable(false); RecersiveISOPath = new wxCheckBox(PathsPage, ID_RECERSIVEISOPATH, wxT("Search Subfolders"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - RecersiveISOPath->SetValue(SConfig::GetInstance().m_RecersiveISOFolder); + RecersiveISOPath->SetValue(SConfig::GetInstance().m_RecursiveISOFolder); DefaultISOText = new wxStaticText(PathsPage, ID_DEFAULTISO_TEXT, wxT("Default ISO:"), wxDefaultPosition, wxDefaultSize); DefaultISO = new wxFilePickerCtrl(PathsPage, ID_DEFAULTISO, wxEmptyString, wxT("Choose a default ISO:"), wxString::Format(wxT("All GC/Wii images (gcm, iso, gcz)|*.gcm;*.iso;*.gcz|All files (%s)|%s"), wxFileSelectorDefaultWildcardStr, wxFileSelectorDefaultWildcardStr), @@ -611,7 +615,7 @@ void CConfigMain::CoreSettingsChanged(wxCommandEvent& event) break; case ID_ALLWAYS_HLEBIOS: // Core - SConfig::GetInstance().m_LocalCoreStartupParameter.bHLEBios = AllwaysHLEBIOS->IsChecked(); + SConfig::GetInstance().m_LocalCoreStartupParameter.bHLEBios = AlwaysUseHLEBIOS->IsChecked(); break; case ID_USEDYNAREC: SConfig::GetInstance().m_LocalCoreStartupParameter.bUseJIT = UseDynaRec->IsChecked(); @@ -619,6 +623,9 @@ void CConfigMain::CoreSettingsChanged(wxCommandEvent& event) case ID_USEDUALCORE: SConfig::GetInstance().m_LocalCoreStartupParameter.bUseDualCore = UseDualCore->IsChecked(); break; + case ID_DSPTHREAD: + SConfig::GetInstance().m_LocalCoreStartupParameter.bDSPThread = DSPThread->IsChecked(); + break; case ID_LOCKTHREADS: SConfig::GetInstance().m_LocalCoreStartupParameter.bLockThreads = LockThreads->IsChecked(); break; @@ -843,7 +850,7 @@ void CConfigMain::AddRemoveISOPaths(wxCommandEvent& event) void CConfigMain::RecursiveDirectoryChanged(wxCommandEvent& WXUNUSED (event)) { - SConfig::GetInstance().m_RecersiveISOFolder = RecersiveISOPath->IsChecked(); + SConfig::GetInstance().m_RecursiveISOFolder = RecersiveISOPath->IsChecked(); bRefreshList = true; } diff --git a/Source/Core/DolphinWX/Src/ConfigMain.h b/Source/Core/DolphinWX/Src/ConfigMain.h index 71698c02c1..e9de7cd613 100644 --- a/Source/Core/DolphinWX/Src/ConfigMain.h +++ b/Source/Core/DolphinWX/Src/ConfigMain.h @@ -60,9 +60,10 @@ class CConfigMain wxBoxSizer* sCore; wxStaticBoxSizer* sbBasic, *sbAdvanced, *sbInterface; - wxCheckBox* AllwaysHLEBIOS; + wxCheckBox* AlwaysUseHLEBIOS; wxCheckBox* UseDynaRec; wxCheckBox* UseDualCore; + wxCheckBox* DSPThread; wxCheckBox* LockThreads; wxCheckBox* OptimizeQuantizers; wxCheckBox* SkipIdle; @@ -213,6 +214,7 @@ class CConfigMain ID_ALLWAYS_HLEBIOS, ID_USEDYNAREC, ID_USEDUALCORE, + ID_DSPTHREAD, ID_LOCKTHREADS, ID_OPTIMIZEQUANTIZERS, ID_IDLESKIP, diff --git a/Source/Core/DolphinWX/Src/GameListCtrl.cpp b/Source/Core/DolphinWX/Src/GameListCtrl.cpp index f0e3d7cfcf..60fbdc6bf5 100644 --- a/Source/Core/DolphinWX/Src/GameListCtrl.cpp +++ b/Source/Core/DolphinWX/Src/GameListCtrl.cpp @@ -375,7 +375,7 @@ void CGameListCtrl::ScanForISOs() m_ISOFiles.clear(); CFileSearch::XStringVector Directories(SConfig::GetInstance().m_ISOFolder); - if (SConfig::GetInstance().m_RecersiveISOFolder) + if (SConfig::GetInstance().m_RecursiveISOFolder) { for (u32 i = 0; i < Directories.size(); i++) { diff --git a/Source/PluginSpecs/pluginspecs_dsp.h b/Source/PluginSpecs/pluginspecs_dsp.h index 60ea1a17a4..f9fa4ba27c 100644 --- a/Source/PluginSpecs/pluginspecs_dsp.h +++ b/Source/PluginSpecs/pluginspecs_dsp.h @@ -30,6 +30,7 @@ typedef struct TAudioGetStreaming pGetAudioStreaming; int *pEmulatorState; bool bWii; + bool bOnThread; } DSPInitialize; diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/DSPAnalyzer.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/DSPAnalyzer.cpp index 3f4bd470e7..8376d30ba4 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/DSPAnalyzer.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/DSPAnalyzer.cpp @@ -23,7 +23,7 @@ namespace DSPAnalyzer { // Holds data about all instructions in RAM. -u8 inst_flags[ISPACE]; +u8 code_flags[ISPACE]; // Good candidates for idle skipping is mail wait loops. If we're time slicing // between the main CPU and the DSP, if the DSP runs into one of these, it might @@ -39,24 +39,24 @@ const u16 idle_skip_sigs[NUM_IDLE_SIGS][MAX_IDLE_SIG_SIZE + 1] = { 0x26fc, // LRS $30, @DMBH 0x02c0, 0x8000, // ANDCF $30, #0x8000 0x029d, 0xFFFF, // JLZ 0x027a - 0x02df, 0 }, // RET + 0, 0 }, // RET { 0x27fc, // LRS $31, @DMBH 0x03c0, 0x8000, // ANDCF $31, #0x8000 0x029d, 0xFFFF, // JLZ 0x027a - 0x02df, 0 }, // RET + 0, 0 }, // RET { 0x26fe, // LRS $30, @CMBH 0x02c0, 0x8000, // ANDCF $30, #0x8000 0x029c, 0xFFFF, // JLNZ 0x0280 - 0x02df, 0 }, // RET + 0, 0 }, // RET { 0x27fe, // LRS $31, @CMBH 0x03c0, 0x8000, // ANDCF $31, #0x8000 0x029c, 0xFFFF, // JLNZ 0x0280 - 0x02df, 0 }, // RET + 0, 0 }, // RET }; void Reset() { - memset(inst_flags, 0, sizeof(inst_flags)); + memset(code_flags, 0, sizeof(code_flags)); } void AnalyzeRange(int start_addr, int end_addr) @@ -76,7 +76,7 @@ void AnalyzeRange(int start_addr, int end_addr) addr++; continue; } - inst_flags[addr] |= CODE_START_OF_INST; + code_flags[addr] |= CODE_START_OF_INST; addr += opcode->size; } @@ -98,7 +98,7 @@ void AnalyzeRange(int start_addr, int end_addr) if (found) { NOTICE_LOG(DSPLLE, "Idle skip location found at %02x", addr); - inst_flags[addr] |= CODE_IDLE_SKIP; + code_flags[addr] |= CODE_IDLE_SKIP; // TODO: actually use this flag somewhere. } } diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/DSPTables.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/DSPTables.cpp index e095b246a6..971121e6cd 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/DSPTables.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/DSPTables.cpp @@ -395,14 +395,3 @@ void InitInstructionTable() } } } - -void ComputeInstruction(const UDSPInstruction& inst) -{ - if (prologueTable[inst.hex]) - prologueTable[inst.hex](inst); - - opTable[inst.hex](inst); - - if (epilogueTable[inst.hex]) - epilogueTable[inst.hex](inst); -} diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/DSPTables.h b/Source/Plugins/Plugin_DSP_LLE/Src/DSPTables.h index 4805f1cbd4..fa32afa43a 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/DSPTables.h +++ b/Source/Plugins/Plugin_DSP_LLE/Src/DSPTables.h @@ -113,10 +113,21 @@ extern const u32 opcodes_ext_size; extern u8 opSize[OPTABLE_SIZE]; extern dspInstFunc opTable[]; +extern dspInstFunc prologueTable[OPTABLE_SIZE]; +extern dspInstFunc epilogueTable[OPTABLE_SIZE]; void InitInstructionTable(); -void ComputeInstruction(const UDSPInstruction& inst); +inline void ExecuteInstruction(const UDSPInstruction& inst) +{ + // TODO: Move the prologuetable calls into the relevant instructions themselves. + // Better not do things like this until things work correctly though. + if (prologueTable[inst.hex]) + prologueTable[inst.hex](inst); + opTable[inst.hex](inst); + if (epilogueTable[inst.hex]) + epilogueTable[inst.hex](inst); +} // This one's pretty slow, try to use it only at init or seldomly. // returns NULL if no matching instruction. diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interpreter.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interpreter.cpp index 5bcc6cb937..e6135b43a7 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interpreter.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interpreter.cpp @@ -38,8 +38,7 @@ SDSP g_dsp; -bool gdsp_running; -extern volatile u32 dsp_running; +volatile u32 gdsp_running; static bool cr_halt = true; static bool cr_external_int = false; @@ -231,14 +230,14 @@ void gdsp_step() #endif u16 opc = dsp_fetch_code(); - ComputeInstruction(UDSPInstruction(opc)); - - u16& rLoopCounter = g_dsp.r[DSP_REG_ST0 + 3]; + ExecuteInstruction(UDSPInstruction(opc)); + // Handle looping hardware. + u16& rLoopCounter = g_dsp.r[DSP_REG_ST3]; if (rLoopCounter > 0) { - const u16& rCallAddress = g_dsp.r[DSP_REG_ST0 + 0]; - const u16& rLoopAddress = g_dsp.r[DSP_REG_ST0 + 2]; + const u16 rCallAddress = g_dsp.r[DSP_REG_ST0]; + const u16 rLoopAddress = g_dsp.r[DSP_REG_ST2]; if (g_dsp.pc == (rLoopAddress + 1)) { @@ -292,15 +291,14 @@ void gdsp_step() } } - -bool gdsp_run() +// Used by thread mode. +void gdsp_run() { gdsp_running = true; - while (!cr_halt) { // Are we running? - if(*g_dspInitialize.pEmulatorState) + if (*g_dspInitialize.pEmulatorState) break; gdsp_step(); @@ -308,9 +306,41 @@ bool gdsp_run() if (!gdsp_running) break; } - gdsp_running = false; - return true; +} + +// Used by non-thread mode. +void gdsp_run_cycles(int cycles) +{ + // First, let's run a few cycles with no idle skipping so that things can progress a bit. + for (int i = 0; i < 8; i++) + { + if (cr_halt) + return; + gdsp_step(); + cycles--; + } + // Next, let's run a few cycles with idle skipping, so that we can skip loops. + for (int i = 0; i < 8; i++) + { + if (cr_halt) + return; + if (DSPAnalyzer::code_flags[g_dsp.pc] & DSPAnalyzer::CODE_IDLE_SKIP) + return; + gdsp_step(); + cycles--; + } + // Now, run the rest of the block without idle skipping. It might trip into a + // idle loop and if so we waste some time here. Might be beneficial to slice even further. + while (cycles > 0) + { + if (cr_halt) + return; + gdsp_step(); + cycles--; + // We don't bother directly supporting pause - if the main emu pauses, + // it just won't call this function anymore. + } } void gdsp_stop() diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interpreter.h b/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interpreter.h index 4c614397e8..1dd1c34d19 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interpreter.h +++ b/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interpreter.h @@ -103,11 +103,11 @@ bool gdsp_load_coef(const char *fname); // steps through DSP code, returns false if error occured -void gdsp_step(void); +void gdsp_step(); void gdsp_loop_step(); -bool gdsp_run(void); -bool gdsp_runx(u16 cnt); -void gdsp_stop(void); +void gdsp_run(); +void gdsp_run_cycles(int cycles); +void gdsp_stop(); void gdsp_write_cr(u16 val); u16 gdsp_read_cr(void); diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp index 6dc61bb020..e05201f5b4 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp @@ -116,12 +116,12 @@ void GetDllInfo(PLUGIN_INFO* _PluginInfo) _PluginInfo->Type = PLUGIN_TYPE_DSP; #ifdef DEBUGFAST - sprintf(_PluginInfo->Name, "Dolphin DSP-LLE-Testing Plugin (DebugFast)"); + sprintf(_PluginInfo->Name, "Dolphin DSP-LLE Plugin (DebugFast)"); #else #ifndef _DEBUG - sprintf(_PluginInfo->Name, "Dolphin DSP-LLE-Testing Plugin"); + sprintf(_PluginInfo->Name, "Dolphin DSP-LLE Plugin"); #else - sprintf(_PluginInfo->Name, "Dolphin DSP-LLE-Testing Plugin (Debug)"); + sprintf(_PluginInfo->Name, "Dolphin DSP-LLE Plugin (Debug)"); #endif #endif } @@ -176,11 +176,7 @@ THREAD_RETURN dsp_thread(void* lpParameter) { while (bIsRunning) { - if (!gdsp_run()) - { - ERROR_LOG(AUDIO, "DSP Halt"); - return 0; - } + gdsp_run(); } return 0; } @@ -225,7 +221,8 @@ void Initialize(void *init) PanicAlert("Failed loading DSP COEF from " DSP_COEF_FILE); } - if (!bCanWork) { + if (!bCanWork) + { gdsp_shutdown(); return; } @@ -234,7 +231,10 @@ void Initialize(void *init) InitInstructionTable(); - g_hDSPThread = new Common::Thread(dsp_thread, NULL); + if (g_dspInitialize.bOnThread) + { + g_hDSPThread = new Common::Thread(dsp_thread, NULL); + } soundStream = AudioCommon::InitSoundStream(); } @@ -242,8 +242,11 @@ void DSP_StopSoundStream() { gdsp_stop(); bIsRunning = false; - delete g_hDSPThread; - g_hDSPThread = NULL; + if (g_dspInitialize.bOnThread) + { + delete g_hDSPThread; + g_hDSPThread = NULL; + } } void Shutdown() @@ -330,13 +333,22 @@ void DSP_WriteMailboxLow(bool _CPUMailbox, u16 _uLowMail) void DSP_Update(int cycles) { - soundStream->Update(); + // This gets called VERY OFTEN. The soundstream update might be expensive so only do it 200 times per second or something. + const int cycles_between_ss_update = 80000000 / 200; + static int cycle_count = 0; + cycle_count += cycles; + if (cycle_count > cycles_between_ss_update) + { + while (cycle_count > cycles_between_ss_update) + cycle_count -= cycles_between_ss_update; + soundStream->Update(); + } -#if defined(HAVE_WX) && HAVE_WX - // TODO fix? dunno how we should handle debug thread or whatever -// if (m_DebuggerFrame->CanDoStep()) -// gdsp_runx(100); // cycles -#endif + // If we're not on a thread, run cycles here. + if (!g_dspInitialize.bOnThread) + { + gdsp_run_cycles(cycles); + } } void DSP_SendAIBuffer(unsigned int address, int sample_rate)