diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt
index 7e4f4af32a..f5d6699324 100644
--- a/Source/Core/Core/CMakeLists.txt
+++ b/Source/Core/Core/CMakeLists.txt
@@ -198,6 +198,7 @@ set(SRCS
PowerPC/Profiler.cpp
PowerPC/SignatureDB/CSVSignatureDB.cpp
PowerPC/SignatureDB/DSYSignatureDB.cpp
+ PowerPC/SignatureDB/MEGASignatureDB.cpp
PowerPC/SignatureDB/SignatureDB.cpp
PowerPC/JitInterface.cpp
PowerPC/CachedInterpreter/CachedInterpreter.cpp
diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj
index 94d0478192..69a7f542bf 100644
--- a/Source/Core/Core/Core.vcxproj
+++ b/Source/Core/Core/Core.vcxproj
@@ -282,6 +282,7 @@
+
@@ -509,6 +510,7 @@
+
diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters
index 969068de75..ca147279eb 100644
--- a/Source/Core/Core/Core.vcxproj.filters
+++ b/Source/Core/Core/Core.vcxproj.filters
@@ -728,6 +728,7 @@
+
IOS\USB\Bluetooth
@@ -1360,6 +1361,7 @@
+
IOS\USB\Bluetooth
diff --git a/Source/Core/Core/PowerPC/SignatureDB/MEGASignatureDB.cpp b/Source/Core/Core/PowerPC/SignatureDB/MEGASignatureDB.cpp
new file mode 100644
index 0000000000..bdc3e7349a
--- /dev/null
+++ b/Source/Core/Core/PowerPC/SignatureDB/MEGASignatureDB.cpp
@@ -0,0 +1,169 @@
+// Copyright 2017 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include "Core/PowerPC/SignatureDB/MEGASignatureDB.h"
+
+#include
+#include
+#include
+#include
+
+#include "Common/FileUtil.h"
+#include "Common/Logging/Log.h"
+#include "Common/StringUtil.h"
+
+#include "Core/PowerPC/PPCSymbolDB.h"
+#include "Core/PowerPC/PowerPC.h"
+
+static constexpr size_t INSTRUCTION_HEXSTRING_LENGTH = 8;
+
+MEGASignatureDB::MEGASignatureDB() = default;
+MEGASignatureDB::~MEGASignatureDB() = default;
+
+bool MEGASignatureDB::Load(const std::string& file_path)
+{
+ std::string line;
+ std::ifstream ifs;
+ OpenFStream(ifs, file_path, std::ios_base::in);
+
+ if (!ifs)
+ return false;
+ for (size_t i = 1; std::getline(ifs, line); ++i)
+ {
+ std::istringstream iss(line);
+ MEGASignature sig;
+
+ if (GetCode(&sig, &iss) && GetName(&sig, &iss) && GetRefs(&sig, &iss))
+ {
+ m_signatures.push_back(sig);
+ }
+ else
+ {
+ WARN_LOG(OSHLE, "MEGA database failed to parse line %zu", i);
+ }
+ }
+ return true;
+}
+
+void MEGASignatureDB::Apply(PPCSymbolDB* symbol_db) const
+{
+ for (auto& it : symbol_db->AccessSymbols())
+ {
+ u32 hash = it.first;
+ auto& symbol = it.second;
+ for (const auto& sig : m_signatures)
+ {
+ if (Compare(symbol.address, symbol.size, sig))
+ {
+ symbol.name = sig.name;
+ INFO_LOG(OSHLE, "Found %s at %08x (size: %08x)!", sig.name.c_str(), symbol.address,
+ symbol.size);
+ break;
+ }
+ }
+ }
+ symbol_db->Index();
+}
+
+void MEGASignatureDB::List() const
+{
+ for (const auto& entry : m_signatures)
+ {
+ DEBUG_LOG(OSHLE, "%s : %zu bytes", entry.name.c_str(), entry.code.size() * sizeof(u32));
+ }
+ INFO_LOG(OSHLE, "%zu functions known in current MEGA database.", m_signatures.size());
+}
+
+bool MEGASignatureDB::GetCode(MEGASignature* sig, std::istringstream* iss) const
+{
+ std::string code;
+ if ((*iss >> code) && (code.length() % INSTRUCTION_HEXSTRING_LENGTH) == 0)
+ {
+ for (size_t i = 0; i < code.length(); i += INSTRUCTION_HEXSTRING_LENGTH)
+ {
+ std::string instruction = code.substr(i, INSTRUCTION_HEXSTRING_LENGTH);
+ u32 num = static_cast(strtoul(instruction.c_str(), nullptr, 16));
+ if (num != 0 || instruction == "........")
+ {
+ sig->code.emplace_back(num);
+ }
+ else
+ {
+ WARN_LOG(OSHLE, "MEGA database failed to parse code");
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+bool MEGASignatureDB::GetFunctionName(std::istringstream* iss, std::string* name) const
+{
+ std::string buffer;
+
+ std::getline(*iss, buffer);
+ size_t next = buffer.find(" ^");
+ *name = StripSpaces(buffer.substr(0, next));
+
+ if (name->empty())
+ return false;
+
+ if (next == std::string::npos)
+ next = buffer.length();
+ iss->str(buffer.substr(next));
+ iss->clear();
+ return true;
+}
+
+bool MEGASignatureDB::GetName(MEGASignature* sig, std::istringstream* iss) const
+{
+ std::string unknown;
+ return (*iss >> unknown) && GetFunctionName(iss, &sig->name);
+}
+
+bool MEGASignatureDB::GetRefs(MEGASignature* sig, std::istringstream* iss) const
+{
+ std::string num, ref;
+ u32 ref_count = 1;
+ while (*iss && (*iss >> num) && !num.empty())
+ {
+ num = num.substr(1);
+ const char* ptr = num.c_str();
+ char* endptr;
+ u64 offset = strtoul(ptr, &endptr, 16);
+
+ if (ptr == endptr || offset > std::numeric_limits::max())
+ {
+ WARN_LOG(OSHLE, "MEGA database failed to parse reference %u offset", ref_count);
+ return false;
+ }
+
+ if (!GetFunctionName(iss, &ref))
+ {
+ WARN_LOG(OSHLE, "MEGA database failed to parse reference %u name", ref_count);
+ return false;
+ }
+ sig->refs.emplace_back(static_cast(offset), ref);
+
+ ref_count += 1;
+ num.clear();
+ ref.clear();
+ }
+ return true;
+}
+
+bool MEGASignatureDB::Compare(u32 address, u32 size, const MEGASignature& sig) const
+{
+ if (size != sig.code.size() * sizeof(u32))
+ return false;
+
+ for (size_t i = 0; i < sig.code.size(); ++i)
+ {
+ if (sig.code[i] != 0 &&
+ PowerPC::HostRead_U32(static_cast(address + i * sizeof(u32))) != sig.code[i])
+ return false;
+ }
+ return true;
+}
diff --git a/Source/Core/Core/PowerPC/SignatureDB/MEGASignatureDB.h b/Source/Core/Core/PowerPC/SignatureDB/MEGASignatureDB.h
new file mode 100644
index 0000000000..05d7d8e0ff
--- /dev/null
+++ b/Source/Core/Core/PowerPC/SignatureDB/MEGASignatureDB.h
@@ -0,0 +1,57 @@
+// Copyright 2017 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include
+#include
+#include
+
+#include "Common/CommonTypes.h"
+
+class PPCSymbolDB;
+
+struct MEGASignatureReference
+{
+ MEGASignatureReference(u32 ref_offset, std::string ref_name)
+ : offset(ref_offset), name(std::move(ref_name))
+ {
+ }
+ u32 offset;
+ std::string name;
+};
+
+struct MEGASignature
+{
+ std::vector code;
+ std::string name;
+ std::vector refs;
+};
+
+// MEGA files from Megazig's WiiTools IDA plugin
+// -> https://github.com/Megazig/WiiTools
+//
+// Each line contains a function signature composed of:
+// - Hexstring representation with "." acting as a wildcard
+// - Name, represented as follow: ":0000 function_name"
+// - References located in the hexstring at offset: "^offset reference_name"
+class MEGASignatureDB
+{
+public:
+ MEGASignatureDB();
+ ~MEGASignatureDB();
+
+ bool Load(const std::string& file_path);
+ void Apply(PPCSymbolDB* symbol_db) const;
+ void List() const;
+
+private:
+ bool GetCode(MEGASignature* sig, std::istringstream* iss) const;
+ bool GetFunctionName(std::istringstream* iss, std::string* name) const;
+ bool GetName(MEGASignature* sig, std::istringstream* iss) const;
+ bool GetRefs(MEGASignature* sig, std::istringstream* iss) const;
+ bool Compare(u32 address, u32 size, const MEGASignature& sig) const;
+
+ std::vector m_signatures;
+};
diff --git a/Source/Core/Core/PowerPC/SignatureDB/SignatureDB.cpp b/Source/Core/Core/PowerPC/SignatureDB/SignatureDB.cpp
index 5581f490fd..a10cfc38a5 100644
--- a/Source/Core/Core/PowerPC/SignatureDB/SignatureDB.cpp
+++ b/Source/Core/Core/PowerPC/SignatureDB/SignatureDB.cpp
@@ -38,7 +38,7 @@ bool SignatureDB::Save(const std::string& file_path)
}
// Adds a known function to the hash database
-u32 SignatureDB::Add(u32 startAddr, u32 size, const std::string& name)
+/*u32 SignatureDB::Add(u32 startAddr, u32 size, const std::string& name)
{
u32 hash = ComputeCodeChecksum(startAddr, startAddr + size - 4);
@@ -51,7 +51,7 @@ u32 SignatureDB::Add(u32 startAddr, u32 size, const std::string& name)
m_database[hash] = temp_dbfunc;
return hash;
-}
+}*/
void SignatureDB::List()
{
diff --git a/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp b/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp
index 41ac840b9c..4c125c26e9 100644
--- a/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp
+++ b/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp
@@ -34,6 +34,7 @@
#include "Core/PowerPC/PPCSymbolDB.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/PowerPC/Profiler.h"
+#include "Core/PowerPC/SignatureDB/MEGASignatureDB.h"
#include "Core/PowerPC/SignatureDB/SignatureDB.h"
#include "DolphinWX/Debugger/BreakpointWindow.h"
@@ -390,6 +391,22 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event)
}
}
break;
+ case IDM_USE_MEGA_SIGNATURE_FILE:
+ {
+ wxString path = wxFileSelector(
+ _("Apply MEGA signature file"), File::GetSysDirectory(), wxEmptyString, wxEmptyString,
+ _("MEGA Signature File (*.mega)") + "|*.mega|" + wxGetTranslation(wxALL_FILES),
+ wxFD_OPEN | wxFD_FILE_MUST_EXIST, this);
+ if (!path.IsEmpty())
+ {
+ MEGASignatureDB db;
+ db.Load(WxStrToStr(path));
+ db.Apply(&g_symbolDB);
+ db.List();
+ NotifyMapLoaded();
+ }
+ }
+ break;
case IDM_PATCH_HLE_FUNCTIONS:
HLE::PatchFunctions();
Repopulate();
diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp
index 1090ede910..151c8fc02b 100644
--- a/Source/Core/DolphinWX/FrameTools.cpp
+++ b/Source/Core/DolphinWX/FrameTools.cpp
@@ -243,6 +243,7 @@ void CFrame::BindDebuggerMenuBarUpdateEvents()
Bind(wxEVT_UPDATE_UI, &WxEventUtils::OnEnableIfCoreInitialized, IDM_COMBINE_SIGNATURE_FILES);
Bind(wxEVT_UPDATE_UI, &WxEventUtils::OnEnableIfCoreInitialized, IDM_RENAME_SYMBOLS);
Bind(wxEVT_UPDATE_UI, &WxEventUtils::OnEnableIfCoreInitialized, IDM_USE_SIGNATURE_FILE);
+ Bind(wxEVT_UPDATE_UI, &WxEventUtils::OnEnableIfCoreInitialized, IDM_USE_MEGA_SIGNATURE_FILE);
Bind(wxEVT_UPDATE_UI, &WxEventUtils::OnEnableIfCoreInitialized, IDM_PATCH_HLE_FUNCTIONS);
Bind(wxEVT_UPDATE_UI, &WxEventUtils::OnEnableIfCoreUninitialized, IDM_JIT_NO_BLOCK_CACHE);
diff --git a/Source/Core/DolphinWX/Globals.h b/Source/Core/DolphinWX/Globals.h
index 6035172987..8465d091c3 100644
--- a/Source/Core/DolphinWX/Globals.h
+++ b/Source/Core/DolphinWX/Globals.h
@@ -228,6 +228,7 @@ enum
IDM_COMBINE_SIGNATURE_FILES,
IDM_RENAME_SYMBOLS,
IDM_USE_SIGNATURE_FILE,
+ IDM_USE_MEGA_SIGNATURE_FILE,
IDM_PATCH_HLE_FUNCTIONS,
// JIT
diff --git a/Source/Core/DolphinWX/MainMenuBar.cpp b/Source/Core/DolphinWX/MainMenuBar.cpp
index 12bb706927..3f671b66fd 100644
--- a/Source/Core/DolphinWX/MainMenuBar.cpp
+++ b/Source/Core/DolphinWX/MainMenuBar.cpp
@@ -464,6 +464,10 @@ wxMenu* MainMenuBar::CreateSymbolsMenu() const
IDM_USE_SIGNATURE_FILE, _("Apply Signat&ure File..."),
_("Must use Generate Symbols first! Recognise names of any standard library functions "
"used in multiple games, by loading them from a .dsy file."));
+ symbols_menu->Append(
+ IDM_USE_MEGA_SIGNATURE_FILE, _("Apply &MEGA Signature File..."),
+ _("Must use Generate Symbol Map first! Recognise names of any standard library functions "
+ "used in multiple games, by loading them from a .mega file."));
symbols_menu->AppendSeparator();
symbols_menu->Append(IDM_PATCH_HLE_FUNCTIONS, _("&Patch HLE Functions"));
symbols_menu->Append(IDM_RENAME_SYMBOLS, _("&Rename Symbols from File..."));