diff --git a/Common/Data/Text/Parsers.h b/Common/Data/Text/Parsers.h index f111a29964..7ddfa3eabe 100644 --- a/Common/Data/Text/Parsers.h +++ b/Common/Data/Text/Parsers.h @@ -91,6 +91,10 @@ public: } StringWriter(const StringWriter &) = delete; + size_t size() const { + return p_ - start_; + } + // Assumes the input is zero-terminated. // C: Copies a string literal (which always are zero-terminated, the count includes the zero) directly to the stream. template diff --git a/Common/GPU/D3D11/thin3d_d3d11.cpp b/Common/GPU/D3D11/thin3d_d3d11.cpp index 6505c56e6d..ef4d87d9b0 100644 --- a/Common/GPU/D3D11/thin3d_d3d11.cpp +++ b/Common/GPU/D3D11/thin3d_d3d11.cpp @@ -1414,7 +1414,7 @@ void D3D11DrawContext::DrawIndexedClippedBatchUP(const void *vdata, int vertexCo if (draws[i].bindTexture) { ComPtr view = ((D3D11Texture *)draws[i].bindTexture)->View(); context_->PSSetShaderResources(0, 1, view.GetAddressOf()); - } else { + } else if (draws[i].bindFramebufferAsTex) { ComPtr view = ((D3D11Framebuffer *)draws[i].bindFramebufferAsTex)->colorSRView; switch (draws[i].aspect) { case Aspect::DEPTH_BIT: diff --git a/Common/Log.cpp b/Common/Log.cpp index 9652b8df27..f2bba89c76 100644 --- a/Common/Log.cpp +++ b/Common/Log.cpp @@ -41,8 +41,8 @@ static std::mutex g_extraAssertInfoMutex; static std::string g_extraAssertInfo = "menu"; static double g_assertInfoTime = 0.0; static bool g_exitOnAssert; -static AssertNoCallbackFunc g_assertNoCallback = 0; -static void *g_assertNoCallbackUserData = 0; +static AssertNoCallbackFunc g_assertCancelCallback = 0; +static void *g_assertCancelCallbackUserData = 0; void SetExtraAssertInfo(const char *info) { std::lock_guard guard(g_extraAssertInfoMutex); @@ -50,9 +50,9 @@ void SetExtraAssertInfo(const char *info) { g_assertInfoTime = time_now_d(); } -void SetAssertNoCallback(AssertNoCallbackFunc callback, void *userdata) { - g_assertNoCallback = callback; - g_assertNoCallbackUserData = userdata; +void SetAssertCancelCallback(AssertNoCallbackFunc callback, void *userdata) { + g_assertCancelCallback = callback; + g_assertCancelCallbackUserData = userdata; } void SetCleanExitOnAssert() { @@ -60,8 +60,8 @@ void SetCleanExitOnAssert() { } void BreakIntoPSPDebugger(const char *reason) { - if (g_assertNoCallback) { - g_assertNoCallback(reason, g_assertNoCallbackUserData); + if (g_assertCancelCallback) { + g_assertCancelCallback(reason, g_assertCancelCallbackUserData); } } @@ -92,16 +92,15 @@ bool HandleAssert(const char *function, const char *file, int line, const char * #if defined(USING_WIN_UI) // Avoid hanging on CI. if (!getenv("CI")) { - int msgBoxStyle = MB_ICONINFORMATION | MB_YESNOCANCEL; + const int msgBoxStyle = MB_ICONINFORMATION | MB_YESNOCANCEL; std::string text = formatted; text += "\n\nTry to continue?"; - text += "\n\nNo: skip and break into PPSSPP debugger"; if (IsDebuggerPresent()) { - msgBoxStyle ; - text += "\n\nCancel: break directly into the native debugger"; + text += "\n\nNo: break directly into the native debugger"; + text += "\n\nCancel: skip and break into PPSSPP debugger"; } else { - msgBoxStyle |= MB_YESNO; - text += "\n\nCancel: Exit"; + text += "\n\nNo: exit"; + text += "\n\nCancel: skip and break into PPSSPP debugger"; } const char *threadName = GetCurrentThreadName(); OutputDebugStringA(formatted); @@ -111,14 +110,14 @@ bool HandleAssert(const char *function, const char *file, int line, const char * case IDYES: return true; case IDNO: - g_assertNoCallback(formatted, g_assertNoCallbackUserData); - return true; // don't crash! - case IDCANCEL: if (g_exitOnAssert || !IsDebuggerPresent()) { // Hard exit. ExitProcess(1); } return false; // Break into the native debugger. + case IDCANCEL: + g_assertCancelCallback(formatted, g_assertCancelCallbackUserData); + return true; // don't crash! } } return false; diff --git a/Common/Log.h b/Common/Log.h index b72e307eed..529e763bf1 100644 --- a/Common/Log.h +++ b/Common/Log.h @@ -114,7 +114,7 @@ bool HitAnyAsserts(); void ResetHitAnyAsserts(); void SetExtraAssertInfo(const char *info); typedef void (*AssertNoCallbackFunc)(const char *message, void *userdata); -void SetAssertNoCallback(AssertNoCallbackFunc callback, void *userdata); +void SetAssertCancelCallback(AssertNoCallbackFunc callback, void *userdata); void SetCleanExitOnAssert(); void BreakIntoPSPDebugger(const char *reason = "(userbreak)"); diff --git a/Core/HLE/AtracCtx2.cpp b/Core/HLE/AtracCtx2.cpp index 837a38d086..a3aeec8d36 100644 --- a/Core/HLE/AtracCtx2.cpp +++ b/Core/HLE/AtracCtx2.cpp @@ -697,6 +697,9 @@ u32 Atrac2::DecodeInternal(u32 outbufAddr, int *SamplesNum, int *finish) { _dbg_assert_(samplesToDecode <= info.SamplesPerFrame()); if (samplesToDecode != info.SamplesPerFrame()) { + if (!decodeTemp_) { + decodeTemp_ = new int16_t[info.SamplesPerFrame() * outputChannels_]; + } outPtr = decodeTemp_; } else { outPtr = outbufAddr ? (int16_t *)Memory::GetPointer(outbufAddr) : 0; // outbufAddr can be 0 during skip! @@ -705,9 +708,14 @@ u32 Atrac2::DecodeInternal(u32 outbufAddr, int *SamplesNum, int *finish) { context_->codec.inBuf = inAddr; context_->codec.outBuf = outbufAddr; + if (!Memory::IsValidAddress(inAddr)) { + ERROR_LOG(Log::ME, "DecodeInternal: Bad inAddr %08x", inAddr); + return SCE_ERROR_ATRAC_API_FAIL; + } + int bytesConsumed = 0; int outSamples = 0; - if (!decoder_->Decode(Memory::GetPointer(inAddr), info.sampleSize, &bytesConsumed, outputChannels_, outPtr, &outSamples)) { + if (!decoder_->Decode(Memory::GetPointerUnchecked(inAddr), info.sampleSize, &bytesConsumed, outputChannels_, outPtr, &outSamples)) { // Decode failed. *finish = 0; // TODO: The error code here varies based on what the problem is, but not sure of the right values. @@ -841,12 +849,6 @@ int Atrac2::SetData(const Track &track, u32 bufferAddr, u32 readSize, u32 buffer info.loopEnd = 0; } - if (!decodeTemp_) { - _dbg_assert_(track.channels <= 2); - decodeTemp_ = new int16_t[track.SamplesPerFrame() * outputChannels + 1]; - decodeTemp_[track.SamplesPerFrame() * outputChannels] = 1337; // Sentinel - } - context_->codec.inBuf = bufferAddr; if (readSize > track.fileSize) { diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp index af03fe484d..99237bb70e 100644 --- a/Core/HW/SasAudio.cpp +++ b/Core/HW/SasAudio.cpp @@ -526,10 +526,12 @@ void SasInstance::MixVoice(SasVoice &voice) { if (voice.type == VOICETYPE_VAG && !voice.vagAddr) break; // else fallthrough! Don't change the check above. + [[fallthrough]]; case VOICETYPE_PCM: if (voice.type == VOICETYPE_PCM && !voice.pcmAddr) break; // else fallthrough! Don't change the check above. + [[fallthrough]]; default: // This feels a bit hacky. The first 32 samples after a keyon are 0s. int delay = 0; diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 40cb22fc79..5fe70d987c 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -117,7 +117,7 @@ static bool startDumping; extern bool g_TakeScreenshot; -static void AssertNoCallback(const char *message, void *userdata) { +static void AssertCancelCallback(const char *message, void *userdata) { NOTICE_LOG(Log::CPU, "Broke after assert: %s", message); Core_Break(BreakReason::AssertChoice); g_Config.bShowImDebugger = true; @@ -304,7 +304,7 @@ void EmuScreen::bootGame(const Path &filename) { extraAssertInfoStr_ = info->id + " " + info->GetTitle(); SetExtraAssertInfo(extraAssertInfoStr_.c_str()); - SetAssertNoCallback(&AssertNoCallback, this); + SetAssertCancelCallback(&AssertCancelCallback, this); if (!info->id.empty()) { g_Config.loadGameConfig(info->id, info->GetTitle()); @@ -472,7 +472,7 @@ EmuScreen::~EmuScreen() { g_OSD.ClearAchievementStuff(); SetExtraAssertInfo(nullptr); - SetAssertNoCallback(nullptr, nullptr); + SetAssertCancelCallback(nullptr, nullptr); #ifndef MOBILE_DEVICE if (g_Config.bDumpFrames && startDumping) @@ -1832,7 +1832,7 @@ void EmuScreen::runImDebugger() { void EmuScreen::renderImDebugger() { if (g_Config.bShowImDebugger) { Draw::DrawContext *draw = screenManager()->getDrawContext(); - if (PSP_IsInited()) { + if (PSP_IsInited() && imDebugger_) { ImGui_ImplThin3d_RenderDrawData(ImGui::GetDrawData(), draw); } } diff --git a/UI/ImDebugger/ImDebugger.cpp b/UI/ImDebugger/ImDebugger.cpp index b7a31b2c58..e70dbd88ea 100644 --- a/UI/ImDebugger/ImDebugger.cpp +++ b/UI/ImDebugger/ImDebugger.cpp @@ -1544,6 +1544,30 @@ void DrawHLEModules(ImConfig &config) { } ImGui::TreePop(); } + if (ImGui::BeginPopupContextItem(label.c_str())) { + if (ImGui::MenuItem("Copy as JpscpTrace")) { + char *buffer = new char[1000000]; + StringWriter w(buffer, 1000000); + + for (int j = 0; j < mod->numFunctions; j++) { + auto &func = mod->funcTable[j]; + // Translate the argmask to fit jpscptrace + std::string amask = func.argmask; + for (int i = 0; i < amask.size(); i++) { + switch (amask[i]) { + case 'i': + case 'I': amask[i] = 'd'; break; + case 'f': + case 'F': amask[i] = 'x'; break; + } + } + w.F("%s 0x%08x %d %s", func.name, func.ID, strlen(func.argmask), amask.c_str()).endl(); + } + System_CopyStringToClipboard(std::string_view(buffer, w.size())); + delete[] buffer; + } + ImGui::EndPopup(); + } } ImGui::End(); @@ -1684,6 +1708,7 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUDebugInterface *gpuDebu ImGui::EndMenu(); } if (ImGui::BeginMenu("OS HLE")) { + ImGui::MenuItem("HLE module browser", nullptr, &cfg_.hleModulesOpen); ImGui::MenuItem("File System Browser", nullptr, &cfg_.filesystemBrowserOpen); ImGui::MenuItem("Kernel Objects", nullptr, &cfg_.kernelObjectsOpen); ImGui::MenuItem("Threads", nullptr, &cfg_.threadsOpen); diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 523c5f4d3b..aea0227eb7 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -1349,13 +1349,13 @@ namespace Libretro { case EmuThreadState::START_REQUESTED: emuThreadState = EmuThreadState::RUNNING; - /* fallthrough */ + [[fallthrough]]; case EmuThreadState::RUNNING: EmuFrame(); break; case EmuThreadState::PAUSE_REQUESTED: emuThreadState = EmuThreadState::PAUSED; - /* fallthrough */ + [[fallthrough]]; case EmuThreadState::PAUSED: sleep_ms(1, "libretro-paused"); break;