diff --git a/Core/Debugger/SymbolMap.cpp b/Core/Debugger/SymbolMap.cpp index 82204d205b..84576a5575 100644 --- a/Core/Debugger/SymbolMap.cpp +++ b/Core/Debugger/SymbolMap.cpp @@ -15,6 +15,12 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +// These functions tends to be slow in debug mode. +// Comment this out if debugging the symbol map itself. +#if defined(_MSC_VER) && defined(_DEBUG) +#pragma optimize("gty", on) +#endif + #ifdef _WIN32 #include "Common/CommonWindows.h" #include @@ -488,13 +494,15 @@ void SymbolMap::AddFunction(const char* name, u32 address, u32 size, int moduleI if (moduleIndex == -1) { moduleIndex = GetModuleIndex(address); + } else if (moduleIndex == 0) { + sawUnknownModule = true; } // Is there an existing one? u32 relAddress = GetModuleRelativeAddr(address, moduleIndex); auto symbolKey = std::make_pair(moduleIndex, relAddress); auto existing = functions.find(symbolKey); - if (existing == functions.end()) { + if (sawUnknownModule && existing == functions.end()) { // Fall back: maybe it's got moduleIndex = 0. existing = functions.find(std::make_pair(0, address)); } @@ -558,6 +566,15 @@ u32 SymbolMap::GetFunctionStart(u32 address) const { return INVALID_ADDRESS; } +u32 SymbolMap::FindPossibleFunctionAtAfter(u32 address) const { + lock_guard guard(lock_); + auto it = activeFunctions.lower_bound(address); + if (it == activeFunctions.end()) { + return (u32)-1; + } + return it->first; +} + u32 SymbolMap::GetFunctionSize(u32 startAddress) const { lock_guard guard(lock_); auto it = activeFunctions.find(startAddress); @@ -686,13 +703,15 @@ void SymbolMap::AddLabel(const char* name, u32 address, int moduleIndex) { if (moduleIndex == -1) { moduleIndex = GetModuleIndex(address); + } else if (moduleIndex == 0) { + sawUnknownModule = true; } // Is there an existing one? u32 relAddress = GetModuleRelativeAddr(address, moduleIndex); auto symbolKey = std::make_pair(moduleIndex, relAddress); auto existing = labels.find(symbolKey); - if (existing == labels.end()) { + if (sawUnknownModule && existing == labels.end()) { // Fall back: maybe it's got moduleIndex = 0. existing = labels.find(std::make_pair(0, address)); } @@ -728,7 +747,7 @@ void SymbolMap::AddLabel(const char* name, u32 address, int moduleIndex) { } } -void SymbolMap::SetLabelName(const char* name, u32 address, bool updateImmediately) { +void SymbolMap::SetLabelName(const char* name, u32 address) { lock_guard guard(lock_); auto labelInfo = activeLabels.find(address); if (labelInfo == activeLabels.end()) { @@ -740,10 +759,11 @@ void SymbolMap::SetLabelName(const char* name, u32 address, bool updateImmediate strcpy(label->second.name,name); label->second.name[127] = 0; - // Allow the caller to skip this as it causes extreme startup slowdown - // when this gets called for every function identified by the function replacement code. - if (updateImmediately) { - UpdateActiveSymbols(); + // Refresh the active item if it exists. + auto active = activeLabels.find(address); + if (active != activeLabels.end() && active->second.module == label->second.module) { + activeLabels.erase(active); + activeLabels.insert(std::make_pair(address, label->second)); } } } @@ -792,13 +812,15 @@ void SymbolMap::AddData(u32 address, u32 size, DataType type, int moduleIndex) { if (moduleIndex == -1) { moduleIndex = GetModuleIndex(address); + } else if (moduleIndex == 0) { + sawUnknownModule = true; } // Is there an existing one? u32 relAddress = GetModuleRelativeAddr(address, moduleIndex); auto symbolKey = std::make_pair(moduleIndex, relAddress); auto existing = data.find(symbolKey); - if (existing == data.end()) { + if (sawUnknownModule && existing == data.end()) { // Fall back: maybe it's got moduleIndex = 0. existing = data.find(std::make_pair(0, address)); } diff --git a/Core/Debugger/SymbolMap.h b/Core/Debugger/SymbolMap.h index 53e6082f7f..c8badb8fce 100644 --- a/Core/Debugger/SymbolMap.h +++ b/Core/Debugger/SymbolMap.h @@ -63,7 +63,7 @@ typedef struct HWND__ *HWND; class SymbolMap { public: - SymbolMap() {} + SymbolMap() : sawUnknownModule(false) {} void Clear(); void SortSymbols(); @@ -95,10 +95,13 @@ public: u32 GetFunctionSize(u32 startAddress) const; bool SetFunctionSize(u32 startAddress, u32 newSize); bool RemoveFunction(u32 startAddress, bool removeName); + // Search for the first address their may be a function after address. + // Only valid for currently loaded modules. Not guaranteed there will be a function. + u32 FindPossibleFunctionAtAfter(u32 address) const; void AddLabel(const char* name, u32 address, int moduleIndex = -1); std::string GetLabelString(u32 address) const; - void SetLabelName(const char* name, u32 address, bool updateImmediately = true); + void SetLabelName(const char* name, u32 address); bool GetLabelValue(const char* name, u32& dest); void AddData(u32 address, u32 size, DataType type, int moduleIndex = -1); @@ -160,6 +163,7 @@ private: std::vector modules; mutable recursive_mutex lock_; + bool sawUnknownModule; }; extern SymbolMap symbolMap; diff --git a/Core/MIPS/MIPSAnalyst.cpp b/Core/MIPS/MIPSAnalyst.cpp index f9a5877eae..28bc9135c4 100644 --- a/Core/MIPS/MIPSAnalyst.cpp +++ b/Core/MIPS/MIPSAnalyst.cpp @@ -385,16 +385,22 @@ skip: bool isStraightLeaf = true; u32 addr; + u32 addrNextSym = 0; for (addr = startAddr; addr <= endAddr; addr += 4) { // Use pre-existing symbol map info if available. May be more reliable. SymbolInfo syminfo; - if (symbolMap.GetSymbolInfo(&syminfo, addr, ST_FUNCTION)) { + if (addrNextSym <= addr) { + addrNextSym = symbolMap.FindPossibleFunctionAtAfter(addr); + } + if (addrNextSym <= addr && symbolMap.GetSymbolInfo(&syminfo, addr, ST_FUNCTION)) { addr = syminfo.address + syminfo.size - 4; // We still need to insert the func for hashing purposes. currentFunction.start = syminfo.address; currentFunction.end = syminfo.address + syminfo.size - 4; + currentFunction.foundInSymbolMap = true; functions.push_back(currentFunction); + currentFunction.foundInSymbolMap = false; currentFunction.start = addr + 4; furthestBranch = 0; looking = false; @@ -485,7 +491,7 @@ skip: for (auto iter = functions.begin(); iter != functions.end(); iter++) { iter->size = iter->end - iter->start + 4; - if (insertSymbols) { + if (insertSymbols && !iter->foundInSymbolMap) { char temp[256]; symbolMap.AddFunction(DefaultFunctionName(temp, iter->start), iter->start, iter->end - iter->start + 4); } @@ -640,14 +646,12 @@ skip: std::string existingLabel = symbolMap.GetLabelString(f.start); char defaultLabel[256]; // If it was renamed, keep it. Only change the name if it's still the default. - if (existingLabel.empty() || !strcmp(existingLabel.c_str(), DefaultFunctionName(defaultLabel, f.start))) { - symbolMap.SetLabelName(mf->name, f.start, false); + if (existingLabel.empty() || existingLabel == DefaultFunctionName(defaultLabel, f.start)) { + symbolMap.SetLabelName(mf->name, f.start); } } } } - // Used to be called in SetLabelName, let's call it only once instead. - symbolMap.UpdateActiveSymbols(); } void LoadHashMap(std::string filename) { diff --git a/Core/MIPS/MIPSAnalyst.h b/Core/MIPS/MIPSAnalyst.h index 8f11c681f8..9de80cdb51 100644 --- a/Core/MIPS/MIPSAnalyst.h +++ b/Core/MIPS/MIPSAnalyst.h @@ -87,6 +87,7 @@ namespace MIPSAnalyst bool isStraightLeaf; bool hasHash; bool usesVFPU; + bool foundInSymbolMap; char name[64]; }; diff --git a/Core/System.cpp b/Core/System.cpp index 9c5d4701d5..0b4357ebe5 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -375,6 +375,11 @@ bool PSP_IsInited() { } void PSP_Shutdown() { + // Do nothing if we never inited. + if (!pspIsInited && !pspIsIniting) { + return; + } + #ifndef MOBILE_DEVICE if (g_Config.bFuncHashMap) { MIPSAnalyst::StoreHashMap(); diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 0772358df4..95643f06cd 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -590,9 +590,7 @@ void EmuScreen::render() { // set back to running for the next frame coreState = CORE_RUNNING; } else if (coreState == CORE_POWERDOWN) { - if (PSP_IsInited()) { - PSP_Shutdown(); - } + PSP_Shutdown(); ILOG("SELF-POWERDOWN!"); screenManager()->switchScreen(new MainScreen()); invalid_ = true; diff --git a/Windows/Debugger/CtrlMemView.cpp b/Windows/Debugger/CtrlMemView.cpp index 2245bba009..8de363dc6d 100644 --- a/Windows/Debugger/CtrlMemView.cpp +++ b/Windows/Debugger/CtrlMemView.cpp @@ -60,7 +60,8 @@ CtrlMemView::CtrlMemView(HWND _wnd) CtrlMemView::~CtrlMemView() { - DeleteObject(font); + DeleteObject(font); + DeleteObject(underlineFont); } void CtrlMemView::init() diff --git a/Windows/Debugger/Debugger_Disasm.cpp b/Windows/Debugger/Debugger_Disasm.cpp index 20fa90c0ab..99b9115689 100644 --- a/Windows/Debugger/Debugger_Disasm.cpp +++ b/Windows/Debugger/Debugger_Disasm.cpp @@ -171,7 +171,7 @@ CDisasm::CDisasm(HINSTANCE _hInstance, HWND _hParent, DebugInterface *_cpu) : Di bottomTabs->ShowTab(memHandle); // init status bar - statusBarWnd = CreateStatusWindow(WS_CHILD | WS_VISIBLE, L"", m_hDlg, IDC_DISASMSTATUSBAR); + statusBarWnd = CreateWindowEx(0, STATUSCLASSNAME, L"", WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, m_hDlg, (HMENU)IDC_DISASMSTATUSBAR, _hInstance, NULL); if (g_Config.bDisplayStatusBar == false) { ShowWindow(statusBarWnd,SW_HIDE); @@ -187,6 +187,14 @@ CDisasm::CDisasm(HINSTANCE _hInstance, HWND _hParent, DebugInterface *_cpu) : Di CDisasm::~CDisasm() { + DestroyWindow(statusBarWnd); + + delete leftTabs; + delete bottomTabs; + delete breakpointList; + delete threadList; + delete stackTraceView; + delete moduleList; } void CDisasm::stepInto() diff --git a/Windows/GEDebugger/CtrlDisplayListView.cpp b/Windows/GEDebugger/CtrlDisplayListView.cpp index f6ffd2cc2d..e1db230231 100644 --- a/Windows/GEDebugger/CtrlDisplayListView.cpp +++ b/Windows/GEDebugger/CtrlDisplayListView.cpp @@ -78,6 +78,9 @@ LRESULT CALLBACK CtrlDisplayListView::wndProc(HWND hwnd, UINT msg, WPARAM wParam // Continue with window creation. return win != NULL; + case WM_NCDESTROY: + delete win; + break; case WM_SIZE: win->redraw(); break; diff --git a/Windows/GEDebugger/CtrlDisplayListView.h b/Windows/GEDebugger/CtrlDisplayListView.h index 84364f867f..d8e79498a1 100644 --- a/Windows/GEDebugger/CtrlDisplayListView.h +++ b/Windows/GEDebugger/CtrlDisplayListView.h @@ -39,6 +39,10 @@ public: static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); static CtrlDisplayListView * getFrom(HWND wnd); + HWND GetHWND() { + return wnd; + } + void onPaint(WPARAM wParam, LPARAM lParam); void onKeyDown(WPARAM wParam, LPARAM lParam); void onMouseDown(WPARAM wParam, LPARAM lParam, int button); diff --git a/Windows/GEDebugger/GEDebugger.cpp b/Windows/GEDebugger/GEDebugger.cpp index 6ca5777939..0c6d31b882 100644 --- a/Windows/GEDebugger/GEDebugger.cpp +++ b/Windows/GEDebugger/GEDebugger.cpp @@ -123,6 +123,7 @@ CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent) } CGEDebugger::~CGEDebugger() { + DestroyWindow(displayList->GetHWND()); CleanupPrimPreview(); delete flags; delete lighting; diff --git a/Windows/W32Util/DialogManager.cpp b/Windows/W32Util/DialogManager.cpp index e3ee7b773f..b40563bc00 100644 --- a/Windows/W32Util/DialogManager.cpp +++ b/Windows/W32Util/DialogManager.cpp @@ -1,5 +1,6 @@ #include "Common/CommonWindows.h" #include +#include #include "Windows/W32Util/DialogManager.h" @@ -68,6 +69,11 @@ void DialogManager::AddDlg(Dialog *dialog) dialogs.push_back(dialog); } +void DialogManager::RemoveDlg(Dialog *dialog) +{ + dialogs.erase(std::remove(dialogs.begin(), dialogs.end(), dialog), dialogs.end()); +} + bool DialogManager::IsDialogMessage(LPMSG message) { diff --git a/Windows/W32Util/DialogManager.h b/Windows/W32Util/DialogManager.h index 15a657c4ae..7203b04603 100644 --- a/Windows/W32Util/DialogManager.h +++ b/Windows/W32Util/DialogManager.h @@ -37,6 +37,7 @@ class DialogManager { public: static void AddDlg(Dialog *dialog); + static void RemoveDlg(Dialog *dialog); static bool IsDialogMessage(LPMSG message); static void EnableAll(BOOL enable); static void DestroyAll(); diff --git a/Windows/W32Util/ShellUtil.cpp b/Windows/W32Util/ShellUtil.cpp index bde4d9c216..5ee34c9d57 100644 --- a/Windows/W32Util/ShellUtil.cpp +++ b/Windows/W32Util/ShellUtil.cpp @@ -138,6 +138,10 @@ namespace W32Util thread_->detach(); } + AsyncBrowseDialog::~AsyncBrowseDialog() { + delete thread_; + } + bool AsyncBrowseDialog::GetResult(std::string &filename) { filename = filename_; return result_; diff --git a/Windows/W32Util/ShellUtil.h b/Windows/W32Util/ShellUtil.h index ba7899fc1e..8dcf91d3b3 100644 --- a/Windows/W32Util/ShellUtil.h +++ b/Windows/W32Util/ShellUtil.h @@ -28,6 +28,8 @@ namespace W32Util // For a file (OPEN or SAVE.) AsyncBrowseDialog(Type type, HWND parent, UINT completeMsg, std::wstring title, std::wstring initialFolder, std::wstring filter, std::wstring extension); + ~AsyncBrowseDialog(); + bool GetResult(std::string &filename); Type GetType() { return type_; diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index fb5078cb23..a293932940 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -828,6 +828,23 @@ namespace MainWindow DialogManager::AddDlg(memoryWindow[0]); } + void DestroyDebugWindows() { + DialogManager::RemoveDlg(disasmWindow[0]); + if (disasmWindow[0]) + delete disasmWindow[0]; + disasmWindow[0] = 0; + + DialogManager::RemoveDlg(geDebuggerWindow); + if (geDebuggerWindow) + delete geDebuggerWindow; + geDebuggerWindow = 0; + + DialogManager::RemoveDlg(memoryWindow[0]); + if (memoryWindow[0]) + delete memoryWindow[0]; + memoryWindow[0] = 0; + } + void BrowseAndBoot(std::string defaultPath, bool browseDirectory) { static std::wstring filter = L"All supported file types (*.iso *.cso *.pbp *.elf *.prx *.zip)|*.pbp;*.elf;*.iso;*.cso;*.prx;*.zip|PSP ROMs (*.iso *.cso *.pbp *.elf *.prx)|*.pbp;*.elf;*.iso;*.cso;*.prx|Homebrew/Demos installers (*.zip)|*.zip|All files (*.*)|*.*||"; for (int i = 0; i < (int)filter.length(); i++) { @@ -1334,15 +1351,18 @@ namespace MainWindow break; case ID_DEBUG_DISASSEMBLY: - disasmWindow[0]->Show(true); + if (disasmWindow[0]) + disasmWindow[0]->Show(true); break; case ID_DEBUG_GEDEBUGGER: - geDebuggerWindow->Show(true); + if (geDebuggerWindow) + geDebuggerWindow->Show(true); break; case ID_DEBUG_MEMORYVIEW: - memoryWindow[0]->Show(true); + if (memoryWindow[0]) + memoryWindow[0]->Show(true); break; case ID_DEBUG_EXTRACTFILE: @@ -1549,10 +1569,13 @@ namespace MainWindow break; case WM_USER + 1: - disasmWindow[0]->NotifyMapLoaded(); - memoryWindow[0]->NotifyMapLoaded(); + if (disasmWindow[0]) + disasmWindow[0]->NotifyMapLoaded(); + if (memoryWindow[0]) + memoryWindow[0]->NotifyMapLoaded(); - disasmWindow[0]->UpdateDialog(); + if (disasmWindow[0]) + disasmWindow[0]->UpdateDialog(); SetForegroundWindow(hwndMain); break; diff --git a/Windows/WndMainWindow.h b/Windows/WndMainWindow.h index 71d91faffc..9b4473a4b9 100644 --- a/Windows/WndMainWindow.h +++ b/Windows/WndMainWindow.h @@ -51,6 +51,7 @@ namespace MainWindow void Init(HINSTANCE hInstance); BOOL Show(HINSTANCE hInstance, int nCmdShow); void CreateDebugWindows(); + void DestroyDebugWindows(); void Close(); void UpdateMenus(); void UpdateCommands(); diff --git a/Windows/main.cpp b/Windows/main.cpp index 57cb591fe4..11a5250c2e 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -343,7 +343,6 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin CtrlRegisterList::init(); CGEDebugger::Init(); - DialogManager::AddDlg(memoryWindow[0] = new CMemoryDlg(_hInstance, hwndMain, currentDebugMIPS)); DialogManager::AddDlg(vfpudlg = new CVFPUDlg(_hInstance, hwndMain, currentDebugMIPS)); host = new WindowsHost(hwndMain, hwndDisplay); @@ -380,7 +379,7 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin accel = hAccelTable; break; case WINDOW_CPUDEBUGGER: - wnd = disasmWindow[0]->GetDlgHandle(); + wnd = disasmWindow[0] ? disasmWindow[0]->GetDlgHandle() : 0; accel = hDebugAccelTable; break; case WINDOW_GEDEBUGGER: @@ -405,6 +404,7 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin EmuThread_Stop(); + MainWindow::DestroyDebugWindows(); DialogManager::DestroyAll(); timeEndPeriod(1); delete host;