Skip to content

Commit

Permalink
ImDebugger: Add basic filesystem browser. Add partial support for "sa…
Browse files Browse the repository at this point in the history
…ve file dialogs" to System.
  • Loading branch information
hrydgard committed Nov 25, 2024
1 parent 20c4649 commit 47d8e29
Show file tree
Hide file tree
Showing 13 changed files with 165 additions and 43 deletions.
6 changes: 6 additions & 0 deletions Common/System/Request.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ typedef std::function<void(const char *responseString, int responseValue)> Reque
typedef std::function<void()> RequestFailedCallback;

typedef int RequesterToken;

#define NO_REQUESTER_TOKEN -1
#define NON_EPHEMERAL_TOKEN -2

Expand Down Expand Up @@ -101,13 +102,18 @@ enum class BrowseFileType {
DB,
SOUND_EFFECT,
ZIP,
SYMBOL_MAP,
ANY,
};

inline void System_BrowseForFile(RequesterToken token, std::string_view title, BrowseFileType type, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) {
g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_FILE, token, callback, failedCallback, title, "", (int)type);
}

inline void System_BrowseForFileSave(RequesterToken token, std::string_view title, std::string_view defaultFilename, BrowseFileType type, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) {
g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_FILE_SAVE, token, callback, failedCallback, title, defaultFilename, (int)type);
}

void System_BrowseForFolder(RequesterToken token, std::string_view title, const Path &initialPath, RequestCallback callback, RequestFailedCallback failedCallback = nullptr);

// The returned string is username + '\n' + password.
Expand Down
2 changes: 2 additions & 0 deletions Common/System/System.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ enum class SystemRequestType {
BROWSE_FOR_FILE,
BROWSE_FOR_FOLDER,

BROWSE_FOR_FILE_SAVE,

EXIT_APP,
RESTART_APP, // For graphics backend changes
RECREATE_ACTIVITY, // Android
Expand Down
2 changes: 1 addition & 1 deletion Core/FileSystems/DirectoryFileSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -964,7 +964,7 @@ VFSFileSystem::~VFSFileSystem() {
entries.clear();
}

std::string VFSFileSystem::GetLocalPath(const std::string &localPath) {
std::string VFSFileSystem::GetLocalPath(const std::string &localPath) const {
return basePath + localPath;
}

Expand Down
2 changes: 1 addition & 1 deletion Core/FileSystems/DirectoryFileSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,5 +145,5 @@ class VFSFileSystem : public IFileSystem {
std::string basePath;
IHandleAllocator *hAlloc;

std::string GetLocalPath(const std::string &localpath);
std::string GetLocalPath(const std::string &localpath) const;
};
5 changes: 5 additions & 0 deletions Core/FileSystems/MetaFileSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ class MetaFileSystem : public IHandleAllocator, public IFileSystem {
void UnmountAll();
void Unmount(const std::string &prefix);

// Would like to make this const, but...
std::vector<MountPoint> &GetMounts() {
return fileSystems;
}

// The pointer returned from these are for temporary usage only. Do not store.
IFileSystem *GetSystem(const std::string &prefix);
IFileSystem *GetSystemFromFilename(const std::string &filename);
Expand Down
14 changes: 5 additions & 9 deletions Core/FileSystems/VirtualDiscFileSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ void VirtualDiscFileSystem::DoState(PointerWrap &p)
// We don't savestate handlers (loaded on fs load), but if they change, it may not load properly.
}

Path VirtualDiscFileSystem::GetLocalPath(std::string localpath) {
Path VirtualDiscFileSystem::GetLocalPath(std::string localpath) const {
if (localpath.empty())
return basePath;

Expand Down Expand Up @@ -303,18 +303,14 @@ int VirtualDiscFileSystem::getFileListIndex(std::string &fileName)
return (int)fileList.size()-1;
}

int VirtualDiscFileSystem::getFileListIndex(u32 accessBlock, u32 accessSize, bool blockMode)
{
for (size_t i = 0; i < fileList.size(); i++)
{
if (fileList[i].firstBlock <= accessBlock)
{
int VirtualDiscFileSystem::getFileListIndex(u32 accessBlock, u32 accessSize, bool blockMode) const {
for (size_t i = 0; i < fileList.size(); i++) {
if (fileList[i].firstBlock <= accessBlock) {
u32 sectorOffset = (accessBlock-fileList[i].firstBlock)*2048;
u32 totalFileSize = blockMode ? (fileList[i].totalSize+2047) & ~2047 : fileList[i].totalSize;

u32 endOffset = sectorOffset+accessSize;
if (endOffset <= totalFileSize)
{
if (endOffset <= totalFileSize) {
return (int)i;
}
}
Expand Down
4 changes: 2 additions & 2 deletions Core/FileSystems/VirtualDiscFileSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ class VirtualDiscFileSystem: public IFileSystem {
void LoadFileListIndex();
// Warning: modifies input string.
int getFileListIndex(std::string &fileName);
int getFileListIndex(u32 accessBlock, u32 accessSize, bool blockMode = false);
Path GetLocalPath(std::string localpath);
int getFileListIndex(u32 accessBlock, u32 accessSize, bool blockMode = false) const;
Path GetLocalPath(std::string localpath) const;

typedef void *HandlerLibrary;
typedef int HandlerHandle;
Expand Down
100 changes: 99 additions & 1 deletion UI/ImDebugger/ImDebugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@

#include "Common/StringUtils.h"
#include "Core/Config.h"
#include "Core/System.h"
#include "Core/RetroAchievements.h"
#include "Core/Core.h"
#include "Core/Debugger/DebugInterface.h"
#include "Core/Debugger/DisassemblyManager.h"
#include "Core/Debugger/Breakpoints.h"
#include "Core/MIPS/MIPSDebugInterface.h"
#include "Core/MIPS/MIPSTables.h"
#include "Core/FileSystems/MetaFileSystem.h"
#include "Core/Debugger/SymbolMap.h"
#include "Core/MemMap.h"
#include "Core/HLE/HLE.h"
Expand All @@ -32,6 +34,8 @@
#include "UI/ImDebugger/ImDebugger.h"
#include "UI/ImDebugger/ImGe.h"

extern bool g_TakeScreenshot;

void DrawRegisterView(MIPSDebugInterface *mipsDebug, bool *open) {
if (!ImGui::Begin("Registers", open)) {
ImGui::End();
Expand Down Expand Up @@ -170,6 +174,40 @@ void DrawThreadView(ImConfig &cfg) {
ImGui::End();
}

// TODO: Add popup menu, export file, export dir, etc...
static void RecurseFileSystem(IFileSystem *fs, std::string path) {
std::vector<PSPFileInfo> fileInfo = fs->GetDirListing(path);
for (auto &file : fileInfo) {
if (file.type == FileType::FILETYPE_DIRECTORY) {
if (file.name != "." && file.name != ".." && ImGui::TreeNode(file.name.c_str())) {
std::string fpath = path + "/" + file.name;
RecurseFileSystem(fs, fpath);
ImGui::TreePop();
}
} else {
ImGui::TextUnformatted(file.name.c_str());
}
}
}

static void DrawFilesystemBrowser(ImConfig &cfg) {
if (!ImGui::Begin("File System", &cfg.filesystemBrowserOpen)) {
ImGui::End();
return;
}

for (auto &fs : pspFileSystem.GetMounts()) {
std::string path;
if (ImGui::TreeNode(fs.prefix.c_str())) {
auto system = fs.system;
RecurseFileSystem(system.get(), path);
ImGui::TreePop();
}
}

ImGui::End();
}

static const char *MemCheckConditionToString(MemCheckCondition cond) {
switch (cond) {
case MEMCHECK_READ: return "Read";
Expand Down Expand Up @@ -496,6 +534,10 @@ void DrawHLEModules(ImConfig &config) {
ImGui::End();
}

ImDebugger::ImDebugger() {
reqToken_ = g_requestManager.GenerateRequesterToken();
}

void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUDebugInterface *gpuDebug) {
// Snapshot the coreState to avoid inconsistency.
const CoreState coreState = ::coreState;
Expand All @@ -520,6 +562,47 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUDebugInterface *gpuDebu
Core_Break("Menu:Break");
}
}
ImGui::Separator();
ImGui::MenuItem("Ignore bad memory accesses", nullptr, &g_Config.bIgnoreBadMemAccess);
ImGui::Separator();
/*
// Symbol stuff. Move to separate menu?
// Doesn't quite seem to work yet.
if (ImGui::MenuItem("Load symbol map...")) {
System_BrowseForFile(reqToken_, "Load symbol map", BrowseFileType::SYMBOL_MAP, [&](const char *responseString, int) {
Path path(responseString);
if (!g_symbolMap->LoadSymbolMap(path)) {
ERROR_LOG(Log::Common, "Failed to load symbol map");
}
disasm_.DirtySymbolMap();
});
}
if (ImGui::MenuItem("Save symbol map...")) {
System_BrowseForFileSave(reqToken_, "Save symbol map", "symbols.map", BrowseFileType::SYMBOL_MAP, [](const char *responseString, int) {
Path path(responseString);
if (!g_symbolMap->SaveSymbolMap(path)) {
ERROR_LOG(Log::Common, "Failed to save symbol map");
}
});
}
*/
if (ImGui::MenuItem("Reset symbol map")) {
g_symbolMap->Clear();
disasm_.DirtySymbolMap();
// NotifyDebuggerMapLoaded();
}
ImGui::Separator();
if (ImGui::MenuItem("Take screenshot")) {
g_TakeScreenshot = true;
}
if (ImGui::MenuItem("Restart graphics")) {
System_PostUIMessage(UIMessage::RESTART_GRAPHICS);
}
if (System_GetPropertyBool(SYSPROP_HAS_TEXT_CLIPBOARD)) {
if (ImGui::MenuItem("Copy memory base to clipboard")) {
System_CopyStringToClipboard(StringFromFormat("%016llx", (uint64_t)(uintptr_t)Memory::base));
}
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("CPU")) {
Expand All @@ -530,6 +613,7 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUDebugInterface *gpuDebu
ImGui::EndMenu();
}
if (ImGui::BeginMenu("OS HLE")) {
ImGui::MenuItem("File System Browser", nullptr, &cfg_.filesystemBrowserOpen);
ImGui::MenuItem("HLE Threads", nullptr, &cfg_.threadsOpen);
ImGui::MenuItem("HLE Modules",nullptr, &cfg_.modulesOpen);
ImGui::MenuItem("sceAtrac", nullptr, &cfg_.atracOpen);
Expand Down Expand Up @@ -575,6 +659,10 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUDebugInterface *gpuDebu
DrawBreakpointsView(mipsDebug, cfg_);
}

if (cfg_.filesystemBrowserOpen) {
DrawFilesystemBrowser(cfg_);
}

if (cfg_.threadsOpen) {
DrawThreadView(cfg_);
}
Expand Down Expand Up @@ -664,6 +752,9 @@ void ImDisasmWindow::Draw(MIPSDebugInterface *mipsDebug, bool *open, CoreState c
}

if (ImGui::BeginPopup("disSearch")) {
if (ImGui::IsWindowAppearing()) {
ImGui::SetKeyboardFocusHere();
}
if (ImGui::InputText("Search", searchTerm_, sizeof(searchTerm_), ImGuiInputTextFlags_EnterReturnsTrue)) {
disasmView_.Search(searchTerm_);
ImGui::CloseCurrentPopup();
Expand All @@ -684,7 +775,14 @@ void ImDisasmWindow::Draw(MIPSDebugInterface *mipsDebug, bool *open, CoreState c
}

ImGui::SameLine();
ImGui::Checkbox("Follow PC", &disasmView_.followPC_);
if (ImGui::SmallButton("Settings")) {
ImGui::OpenPopup("disSettings");
}

if (ImGui::BeginPopup("disSettings")) {
ImGui::Checkbox("Follow PC", &disasmView_.followPC_);
ImGui::EndPopup();
}

ImGui::SetNextItemWidth(100);
if (ImGui::InputScalar("Go to addr: ", ImGuiDataType_U32, &gotoAddr_, NULL, NULL, "%08X", ImGuiInputTextFlags_EnterReturnsTrue)) {
Expand Down
9 changes: 9 additions & 0 deletions UI/ImDebugger/ImDebugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

#include "Common/CommonTypes.h"
#include "Common/Log.h"
#include "Common/System/Request.h"

#include "Core/Core.h"

#include "Core/Debugger/DisassemblyManager.h"
Expand All @@ -32,6 +34,9 @@ class ImDisasmWindow {
ImDisasmView &View() {
return disasmView_;
}
void DirtySymbolMap() {
symsDirty_ = true;
}
private:
// We just keep the state directly in the window. Can refactor later.

Expand Down Expand Up @@ -69,6 +74,7 @@ struct ImConfig {
bool structViewerOpen = false;
bool framebuffersOpen = false;
bool styleEditorOpen = false;
bool filesystemBrowserOpen = false;

// HLE explorer settings
// bool filterByUsed = true;
Expand All @@ -90,8 +96,11 @@ struct ImUiCommand {
};

struct ImDebugger {
ImDebugger();
void Frame(MIPSDebugInterface *mipsDebug, GPUDebugInterface *gpuDebug);

RequesterToken reqToken_;

ImDisasmWindow disasm_;
ImLuaConsole luaConsole_;
ImStructViewer structViewer_;
Expand Down
1 change: 0 additions & 1 deletion UI/ImDebugger/ImDisasmView.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ class ImDisasmView {
// Public variables bounds to imgui checkboxes
bool followPC_ = true;


void Draw(ImDrawList *drawList);

void PopupMenu();
Expand Down
3 changes: 3 additions & 0 deletions UWP/PPSSPP_UWPMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,9 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string
case BrowseFileType::ZIP:
supportedExtensions = { ".zip" };
break;
case BrowseFileType::SYMBOL_MAP:
supportedExtensions = { ".map" };
break;
case BrowseFileType::DB:
supportedExtensions = { ".db" };
break;
Expand Down
3 changes: 1 addition & 2 deletions Windows/MainWindowMenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -813,7 +813,7 @@ namespace MainWindow {

case ID_DEBUG_MEMORYBASE:
{
W32Util::CopyTextToClipboard(hWnd, ConvertUTF8ToWString(StringFromFormat("%016llx", (uint64_t)(uintptr_t)Memory::base)));
System_CopyStringToClipboard(StringFromFormat("%016llx", (uint64_t)(uintptr_t)Memory::base));
break;
}

Expand All @@ -823,7 +823,6 @@ namespace MainWindow {
if (!InputBox_GetString(hInst, hWnd, L"Disc filename", filename, filename)) {
break;
}

const char *lastSlash = strrchr(filename.c_str(), '/');
if (lastSlash) {
fn = lastSlash + 1;
Expand Down
Loading

0 comments on commit 47d8e29

Please sign in to comment.