Frame dumps: Share them as zips where folders can't be shown

Where the file can't be shown in its folder (Android, iOS), "Create frame
dump" in the dev menu now zips the dump and opens the share sheet. The
frame dump hotkey does the same when its message is clicked, so the game
isn't interrupted. Both go through OnFrameDumpCreated(), which moves the
share to the main thread, since the recorder calls back on the emulation
thread.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-11-11 12:14:46 +01:00
1 parent f2c049d178
commit 9be62bb7d5
3 files changed
+40 -13

No files matched your search

+34 -6
View File
@@ -82,6 +82,7 @@
#include "UI/ControlMappingScreen.h"
#include "UI/GameSettingsScreen.h"
#include "UI/JitCompareScreen.h"
#include "UI/ShareFiles.h"
#include "android/jni/app-android.h"
@@ -121,17 +122,44 @@ void AddOverlayList(UI::ViewGroup *items, ScreenManager *screenManager) {
}
}
// Zipped, so apps that only take known file types accept it. The zip import recognizes it too.
static void ShareFrameDump(const Path &dumpPath) {
std::string name = dumpPath.GetFilename();
if (endsWithNoCase(name, ".ppdmp")) {
name.resize(name.size() - strlen(".ppdmp"));
}
if (!ShareFilesAsZip(name, { { dumpPath, "" } })) {
auto sy = GetI18NCategory(I18NCat::SYSTEM);
g_OSD.Show(OSDType::MESSAGE_ERROR, sy->T("Failed"));
}
}
void OnFrameDumpCreated(const Path &dumpPath, bool openNow) {
NOTICE_LOG(Log::System, "Frame dump created at '%s'", dumpPath.c_str());
std::function<void()> open;
if (System_GetPropertyBool(SYSPROP_CAN_SHOW_FILE)) {
open = [dumpPath]() { System_ShowFileInFolder(dumpPath); };
} else if (CanShareFiles()) {
open = [dumpPath]() { ShareFrameDump(dumpPath); };
}
g_OSD.Show(OSDType::MESSAGE_SUCCESS, GetFriendlyPath(dumpPath), 7.0f, "framedump");
if (!open) {
return;
}
if (openNow) {
// The recorder calls back on the emulation thread.
System_RunOnMainThread(open);
} else {
g_OSD.SetClickCallback("framedump", open);
}
}
void SaveFrameDump() {
if (!gpu) {
return;
}
gpu->GetRecorder()->RecordNextFrame([](const Path &dumpPath) {
NOTICE_LOG(Log::System, "Frame dump created at '%s'", dumpPath.c_str());
if (System_GetPropertyBool(SYSPROP_CAN_SHOW_FILE)) {
System_ShowFileInFolder(dumpPath);
} else {
g_OSD.Show(OSDType::MESSAGE_SUCCESS, GetFriendlyPath(dumpPath), 7.0f);
}
OnFrameDumpCreated(dumpPath, true);
});
}
+4
View File
@@ -213,3 +213,7 @@ public:
void DrawProfile(UIContext &ui);
void AddOverlayList(UI::ViewGroup *items, ScreenManager *screenManager);
// Tells the user where the dump went. With openNow, shows it in its folder (or shares it, where
// folders can't be shown) right away, otherwise when the message is clicked. Callable from any thread.
void OnFrameDumpCreated(const Path &dumpPath, bool openNow);
+2 -7
View File
@@ -771,14 +771,9 @@ void EmuScreen::ProcessVKey(VirtKey virtKey, bool down) {
if (!gpu) {
return;
}
// Not opened right away, which would interrupt the game.
gpu->GetRecorder()->RecordNextFrame([](const Path &dumpPath) {
NOTICE_LOG(Log::System, "Frame dump created at '%s'", dumpPath.c_str());
g_OSD.Show(OSDType::MESSAGE_SUCCESS, GetFriendlyPath(dumpPath), 7.0f, "framedump");
if (System_GetPropertyBool(SYSPROP_CAN_SHOW_FILE)) {
g_OSD.SetClickCallback("framedump", [dumpPath]() {
System_ShowFileInFolder(dumpPath);
});
}
OnFrameDumpCreated(dumpPath, false);
});
}
break;