diff --git a/Source/Core/Core/Boot/Boot.cpp b/Source/Core/Core/Boot/Boot.cpp index 349ea0893c..fa297d70e6 100644 --- a/Source/Core/Core/Boot/Boot.cpp +++ b/Source/Core/Core/Boot/Boot.cpp @@ -67,7 +67,8 @@ void CBoot::UpdateDebugger_MapLoaded() } bool CBoot::FindMapFile(std::string* existing_map_file, - std::string* writable_map_file) + std::string* writable_map_file, + std::string* title_id) { std::string title_id_str; size_t name_begin_index; @@ -109,6 +110,9 @@ bool CBoot::FindMapFile(std::string* existing_map_file, if (writable_map_file) *writable_map_file = File::GetUserPath(D_MAPS_IDX) + title_id_str + ".map"; + if (title_id) + *title_id = title_id_str; + bool found = false; static const std::string maps_directories[] = { File::GetUserPath(D_MAPS_IDX), diff --git a/Source/Core/Core/Boot/Boot.h b/Source/Core/Core/Boot/Boot.h index 973e94cbcd..c97099d24f 100644 --- a/Source/Core/Core/Boot/Boot.h +++ b/Source/Core/Core/Boot/Boot.h @@ -36,9 +36,12 @@ public: // If writable_map_file is not nullptr, it is set to the path to where a map // file should be saved. // + // If title_id is not nullptr, it is set to the title id + // // Returns true if a map file exists, false if none could be found. static bool FindMapFile(std::string* existing_map_file, - std::string* writable_map_file); + std::string* writable_map_file, + std::string* title_id = nullptr); private: static void RunFunction(u32 _iAddr); diff --git a/Source/Core/Core/PowerPC/PPCSymbolDB.cpp b/Source/Core/Core/PowerPC/PPCSymbolDB.cpp index b88d7f1362..9afa79178a 100644 --- a/Source/Core/Core/PowerPC/PPCSymbolDB.cpp +++ b/Source/Core/Core/PowerPC/PPCSymbolDB.cpp @@ -63,7 +63,7 @@ void PPCSymbolDB::AddKnownSymbol(u32 startAddr, u32 size, const std::string& nam // already got it, let's just update name, checksum & size to be sure. Symbol *tempfunc = &iter->second; tempfunc->name = name; - tempfunc->hash = SignatureDB::ComputeCodeChecksum(startAddr, startAddr + size); + tempfunc->hash = SignatureDB::ComputeCodeChecksum(startAddr, startAddr + size - 4); tempfunc->type = type; tempfunc->size = size; } @@ -235,7 +235,16 @@ bool PPCSymbolDB::LoadMap(const std::string& filename) u32 address, vaddress, size, unknown; char name[512]; - sscanf(line, "%08x %08x %08x %i %511s", &address, &size, &vaddress, &unknown, name); + // some entries in the table have a function name followed by " (entry of " followed by a container name, followed by ")" + // instead of a space followed by a number followed by a space followed by a name + if (strlen(line) > 27 && line[27] != ' ' && strstr(line, "(entry of ")) + { + sscanf(line, "%08x %08x %08x %511s", &address, &size, &vaddress, name); + } + else + { + sscanf(line, "%08x %08x %08x %i %511s", &address, &size, &vaddress, &unknown, name); + } const char *namepos = strstr(line, name); if (namepos != nullptr) //would be odd if not :P @@ -250,7 +259,7 @@ bool PPCSymbolDB::LoadMap(const std::string& filename) } // Check if this is a valid entry. - if (strcmp(name, ".text") != 0 || strcmp(name, ".init") != 0 || strlen(name) > 0) + if (strcmp(name, ".text") != 0 && strcmp(name, ".init") != 0 && strlen(name) > 0) { AddKnownSymbol(vaddress | 0x80000000, size, name); // ST_FUNCTION } diff --git a/Source/Core/Core/PowerPC/SignatureDB.cpp b/Source/Core/Core/PowerPC/SignatureDB.cpp index 7496361681..d20a041e58 100644 --- a/Source/Core/Core/PowerPC/SignatureDB.cpp +++ b/Source/Core/Core/PowerPC/SignatureDB.cpp @@ -77,7 +77,7 @@ bool SignatureDB::Save(const std::string& filename) //Adds a known function to the hash database u32 SignatureDB::Add(u32 startAddr, u32 size, const std::string& name) { - u32 hash = ComputeCodeChecksum(startAddr, startAddr + size); + u32 hash = ComputeCodeChecksum(startAddr, startAddr + size - 4); DBFunc temp_dbfunc; temp_dbfunc.size = size; @@ -134,7 +134,8 @@ void SignatureDB::Initialize(PPCSymbolDB *symbol_db, const std::string& prefix) { for (const auto& symbol : symbol_db->Symbols()) { - if ((symbol.second.name.substr(0, prefix.size()) == prefix) || prefix.empty()) + if ((prefix.empty() && (!symbol.second.name.empty()) && symbol.second.name.substr(0, 3) != "zz_" && symbol.second.name.substr(0, 1) != ".") || + ((!prefix.empty()) && symbol.second.name.substr(0, prefix.size()) == prefix)) { DBFunc temp_dbfunc; temp_dbfunc.name = symbol.second.name; diff --git a/Source/Core/DolphinWX/Debugger/CodeWindow.cpp b/Source/Core/DolphinWX/Debugger/CodeWindow.cpp index debf26345d..fb69650567 100644 --- a/Source/Core/DolphinWX/Debugger/CodeWindow.cpp +++ b/Source/Core/DolphinWX/Debugger/CodeWindow.cpp @@ -752,8 +752,12 @@ void CCodeWindow::UpdateButtonStates() GetMenuBar()->Enable(IDM_SCANFUNCTIONS, Initialized); GetMenuBar()->Enable(IDM_LOADMAPFILE, Initialized); GetMenuBar()->Enable(IDM_SAVEMAPFILE, Initialized); + GetMenuBar()->Enable(IDM_LOADMAPFILEAS, Initialized); + GetMenuBar()->Enable(IDM_SAVEMAPFILEAS, Initialized); GetMenuBar()->Enable(IDM_SAVEMAPFILEWITHCODES, Initialized); GetMenuBar()->Enable(IDM_CREATESIGNATUREFILE, Initialized); + GetMenuBar()->Enable(IDM_APPENDSIGNATUREFILE, Initialized); + GetMenuBar()->Enable(IDM_COMBINESIGNATUREFILES, Initialized); GetMenuBar()->Enable(IDM_RENAME_SYMBOLS, Initialized); GetMenuBar()->Enable(IDM_USESIGNATUREFILE, Initialized); GetMenuBar()->Enable(IDM_PATCHHLEFUNCTIONS, Initialized); diff --git a/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp b/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp index 099d184bee..cba74774da 100644 --- a/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp +++ b/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp @@ -146,11 +146,19 @@ void CCodeWindow::Save() void CCodeWindow::CreateMenuSymbols(wxMenuBar *pMenuBar) { wxMenu *pSymbolsMenu = new wxMenu; - pSymbolsMenu->Append(IDM_CLEARSYMBOLS, _("&Clear symbols")); - pSymbolsMenu->Append(IDM_SCANFUNCTIONS, _("&Generate symbol map")); + pSymbolsMenu->Append(IDM_CLEARSYMBOLS, _("&Clear symbols"), + _("Remove names from all functions and variables.")); + pSymbolsMenu->Append(IDM_SCANFUNCTIONS, _("&Generate symbol map"), + _("Recognise standard functions from sys\\totaldb.dsy, and use generic zz_ names for other functions.")); pSymbolsMenu->AppendSeparator(); - pSymbolsMenu->Append(IDM_LOADMAPFILE, _("&Load symbol map")); - pSymbolsMenu->Append(IDM_SAVEMAPFILE, _("&Save symbol map")); + pSymbolsMenu->Append(IDM_LOADMAPFILE, _("&Load symbol map"), + _("Try to load this game's function names automatically - but doesn't check .map files stored on the disc image yet.")); + pSymbolsMenu->Append(IDM_SAVEMAPFILE, _("&Save symbol map"), + _("Save the function names for each address to a .map file in your user settings map folder, named after the title id.")); + pSymbolsMenu->Append(IDM_LOADMAPFILEAS, _("Choose symbol map file to load..."), + _("Load any .map file containing the function names and addresses for this game.")); + pSymbolsMenu->Append(IDM_SAVEMAPFILEAS, _("Save symbol map &as..."), + _("Save the function names and addresses for this game as a .map file. If you want to open it in IDA pro, use the .idc script.")); pSymbolsMenu->AppendSeparator(); pSymbolsMenu->Append(IDM_SAVEMAPFILEWITHCODES, _("Save code"), _("Save the entire disassembled code. This may take a several seconds" @@ -161,8 +169,14 @@ void CCodeWindow::CreateMenuSymbols(wxMenuBar *pMenuBar) ); pSymbolsMenu->AppendSeparator(); - pSymbolsMenu->Append(IDM_CREATESIGNATUREFILE, _("&Create signature file...")); - pSymbolsMenu->Append(IDM_USESIGNATUREFILE, _("&Use signature file...")); + pSymbolsMenu->Append(IDM_CREATESIGNATUREFILE, _("&Create signature file..."), + _("Create a .dsy file that can be used to recognise these same functions in other games.")); + pSymbolsMenu->Append(IDM_APPENDSIGNATUREFILE, _("Append to &existing signature file..."), + _("Add any named functions missing from a .dsy file, so it can also recognise these additional functions in other games.")); + pSymbolsMenu->Append(IDM_COMBINESIGNATUREFILES, _("Combine &2 signature files..."), + _("Make a new .dsy file which can recognise more functions, by combining two existing files. The first input file has priority.")); + pSymbolsMenu->Append(IDM_USESIGNATUREFILE, _("&Use signature file..."), + _("Must use Generate symbol map first! Recognise names of any standard library functions used in multiple games, by loading them from a .dsy file.")); pSymbolsMenu->AppendSeparator(); pSymbolsMenu->Append(IDM_PATCHHLEFUNCTIONS, _("&Patch HLE functions")); pSymbolsMenu->Append(IDM_RENAME_SYMBOLS, _("&Rename symbols from file...")); @@ -222,9 +236,10 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event) if (!Core::IsRunning()) return; - std::string existing_map_file, writable_map_file; + std::string existing_map_file, writable_map_file, title_id_str; bool map_exists = CBoot::FindMapFile(&existing_map_file, - &writable_map_file); + &writable_map_file, + &title_id_str); switch (event.GetId()) { case IDM_CLEARSYMBOLS: @@ -240,6 +255,7 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event) { db.Apply(&g_symbolDB); Parent->StatusBarMessage("Generated symbol names from '%s'", TOTALDB); + db.List(); } else { @@ -268,9 +284,38 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event) HLE::PatchFunctions(); NotifyMapLoaded(); break; + case IDM_LOADMAPFILEAS: + { + const wxString path = wxFileSelector( + _("Load map file"), File::GetUserPath(D_MAPS_IDX), + title_id_str + ".map", ".map", + "Dolphin Map File (*.map)|*.map|All files (*.*)|*.*", + wxFD_OPEN | wxFD_FILE_MUST_EXIST, this); + + if (!path.IsEmpty()) + { + g_symbolDB.LoadMap(WxStrToStr(path)); + Parent->StatusBarMessage("Loaded symbols from '%s'", path.c_str()); + } + HLE::PatchFunctions(); + NotifyMapLoaded(); + } + break; case IDM_SAVEMAPFILE: g_symbolDB.SaveMap(writable_map_file); break; + case IDM_SAVEMAPFILEAS: + { + const wxString path = wxFileSelector( + _("Save map file as"), File::GetUserPath(D_MAPS_IDX), + title_id_str + ".map", ".map", + "Dolphin Map File (*.map)|*.map|All files (*.*)|*.*", + wxFD_SAVE | wxFD_OVERWRITE_PROMPT, this); + + if (!path.IsEmpty()) + g_symbolDB.SaveMap(WxStrToStr(path)); + } + break; case IDM_SAVEMAPFILEWITHCODES: g_symbolDB.SaveMap(writable_map_file, true); break; @@ -323,14 +368,43 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event) std::string prefix(WxStrToStr(input_prefix.GetValue())); wxString path = wxFileSelector( - _("Save signature as"), wxEmptyString, wxEmptyString, wxEmptyString, - "Dolphin Signature File (*.dsy)|*.dsy;", wxFD_SAVE, + _("Save signature as"), File::GetSysDirectory(), wxEmptyString, wxEmptyString, + "Dolphin Signature File (*.dsy)|*.dsy;", wxFD_SAVE | wxFD_OVERWRITE_PROMPT, this); if (!path.IsEmpty()) { SignatureDB db; db.Initialize(&g_symbolDB, prefix); db.Save(WxStrToStr(path)); + db.List(); + } + } + } + break; + case IDM_APPENDSIGNATUREFILE: + { + wxTextEntryDialog input_prefix( + this, + _("Only export symbols with prefix:\n(Blank for all symbols)"), + wxGetTextFromUserPromptStr, + wxEmptyString); + + if (input_prefix.ShowModal() == wxID_OK) + { + std::string prefix(WxStrToStr(input_prefix.GetValue())); + + wxString path = wxFileSelector( + _("Append signature to"), File::GetSysDirectory(), wxEmptyString, wxEmptyString, + "Dolphin Signature File (*.dsy)|*.dsy;", wxFD_SAVE, + this); + if (!path.IsEmpty()) + { + SignatureDB db; + db.Initialize(&g_symbolDB, prefix); + db.List(); + db.Load(WxStrToStr(path)); + db.Save(WxStrToStr(path)); + db.List(); } } } @@ -338,7 +412,7 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event) case IDM_USESIGNATUREFILE: { wxString path = wxFileSelector( - _("Apply signature file"), wxEmptyString, wxEmptyString, wxEmptyString, + _("Apply signature file"), File::GetSysDirectory(), wxEmptyString, wxEmptyString, "Dolphin Signature File (*.dsy)|*.dsy;", wxFD_OPEN | wxFD_FILE_MUST_EXIST, this); if (!path.IsEmpty()) @@ -346,9 +420,38 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event) SignatureDB db; db.Load(WxStrToStr(path)); db.Apply(&g_symbolDB); + db.List(); + NotifyMapLoaded(); + } + } + break; + case IDM_COMBINESIGNATUREFILES: + { + wxString path1 = wxFileSelector( + _("Choose priority input file"), File::GetSysDirectory(), wxEmptyString, wxEmptyString, + "Dolphin Signature File (*.dsy)|*.dsy;", wxFD_OPEN | wxFD_FILE_MUST_EXIST, + this); + if (!path1.IsEmpty()) + { + SignatureDB db; + wxString path2 = wxFileSelector( + _("Choose secondary input file"), File::GetSysDirectory(), wxEmptyString, wxEmptyString, + "Dolphin Signature File (*.dsy)|*.dsy;", wxFD_OPEN | wxFD_FILE_MUST_EXIST, + this); + if (!path2.IsEmpty()) + { + db.Load(WxStrToStr(path2)); + db.Load(WxStrToStr(path1)); + + path2 = wxFileSelector( + _("Save combined output file as"), File::GetSysDirectory(), wxEmptyString, ".dsy", + "Dolphin Signature File (*.dsy)|*.dsy;", wxFD_SAVE | wxFD_OVERWRITE_PROMPT, + this); + db.Save(WxStrToStr(path2)); + db.List(); + } } } - NotifyMapLoaded(); break; case IDM_PATCHHLEFUNCTIONS: HLE::PatchFunctions(); diff --git a/Source/Core/DolphinWX/Globals.h b/Source/Core/DolphinWX/Globals.h index 42ae34b87a..3df4f95996 100644 --- a/Source/Core/DolphinWX/Globals.h +++ b/Source/Core/DolphinWX/Globals.h @@ -214,9 +214,11 @@ enum // Symbols IDM_CLEARSYMBOLS, IDM_SCANFUNCTIONS, - IDM_LOADMAPFILE, - IDM_SAVEMAPFILE, IDM_SAVEMAPFILEWITHCODES, + IDM_LOADMAPFILE, IDM_LOADMAPFILEAS, + IDM_SAVEMAPFILE, IDM_SAVEMAPFILEWITHCODES, IDM_SAVEMAPFILEAS, IDM_CREATESIGNATUREFILE, + IDM_APPENDSIGNATUREFILE, + IDM_COMBINESIGNATUREFILES, IDM_RENAME_SYMBOLS, IDM_USESIGNATUREFILE, IDM_PATCHHLEFUNCTIONS, diff --git a/Tools/ReadDolphinMap.idc b/Tools/ReadDolphinMap.idc new file mode 100644 index 0000000000..a092b4c35d --- /dev/null +++ b/Tools/ReadDolphinMap.idc @@ -0,0 +1,62 @@ +/* ReadDolphinMap.idc + + Loads .map files generated by dolphin. + Carl Kenner, 2012 +*/ + +#include + +static main(void) +{ + auto fh; + auto fname; + auto pusha, popa; + auto start, end; + auto success; + auto count; + auto line; + auto ea; // column 1 + auto name; // column 30 + auto p; + auto code; + + fname = AskFile(0,"*.map","Load a .map file from Dolphin emulator..."); + + fh = fopen(fname, "r"); + if (fh == 0) { + Message("Can't open %s\n", fname); + return; + } + + Message("Loading %s dolphin map file:\n", fname); + + for (count = 0; 1; count++) { + line = readstr(fh); + if (line == -1) + break; + if (strlen(line)>30 && line[0]!=" ") { + ea = xtol(substr(line,0,8)); + name = substr(line,29,strlen(line)-1); + if (substr(name,0,3)!="zz_") { + if (!MakeNameEx(ea,name,SN_NOCHECK | SN_PUBLIC | SN_NON_AUTO |SN_NOWARN)) { + MakeNameEx(ea,name+"_2",SN_NOCHECK | SN_PUBLIC | SN_NON_AUTO ); + } + Message("ea='%x', name='%s'\n", ea, name); + } else { + MakeNameEx(ea,name,SN_NOCHECK | SN_PUBLIC | SN_AUTO | SN_WEAK | SN_NOWARN); + } + } else if (strlen(line)>30) { + ea = xtol(substr(line,18,18+8)); + p = strstr(line, " \t"); + if (p>=30 && ea!=0) { + name = substr(line,30,p); + code = substr(line,p+2,strlen(line)); + SetFunctionCmt(ea, code, 0); + if (!MakeNameEx(ea,name,SN_NOCHECK | SN_PUBLIC | SN_NON_AUTO |SN_NOWARN)) { + MakeNameEx(ea,name+"_2",SN_NOCHECK | SN_PUBLIC | SN_NON_AUTO ); + } + } + } + } + Message("Dolphin map file done.\n"); +}