mirror of
https://github.com/esuo1198/TaikoArcadeLoader.git
synced 2026-10-10 16:18:30 +03:00
TestMode Refactor
layeredfs hooks on demand
This commit is contained in:
+1
-1
@@ -280,7 +280,7 @@ Init () {
|
||||
}
|
||||
auto graphics = openConfigSection (config, "graphics");
|
||||
if (graphics) {
|
||||
fpsLimit = readConfigInt (graphics, "fpslimit", fpsLimit);
|
||||
fpsLimit = (int)readConfigInt (graphics, "fpslimit", fpsLimit);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -282,7 +282,7 @@ HOOK (HANDLE, CreateFileAHook, PROC_ADDRESS ("kernel32.dll", "CreateFileA"), LPC
|
||||
|
||||
void
|
||||
Init () {
|
||||
LogMessage (LogLevel::INFO, "Init LayeredFs patches");
|
||||
// LogMessage (LogLevel::INFO, "Init LayeredFs patches");
|
||||
|
||||
const auto configPath = std::filesystem::current_path () / "config.toml";
|
||||
const std::unique_ptr<toml_table_t, void (*) (toml_table_t *)> config_ptr (openConfig (configPath), toml_free);
|
||||
@@ -291,7 +291,11 @@ Init () {
|
||||
useLayeredFs = readConfigBool (layeredFs, "enabled", useLayeredFs);
|
||||
}
|
||||
register_cipher (&aes_desc);
|
||||
INSTALL_HOOK (CreateFileAHook);
|
||||
if (useLayeredFs || !beforeHandlers.empty () || !afterHandlers.empty ()) {
|
||||
LogMessage (LogLevel::INFO, "using LayeredFs! Data_mods={} beforHandlers={} afterHandlers={}",
|
||||
useLayeredFs ? "enabled" : "disabled", beforeHandlers.size (), afterHandlers.size ());
|
||||
INSTALL_HOOK (CreateFileAHook);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -42,14 +42,31 @@ void RegisterBefore (const std::function<std::string (const std::string, const s
|
||||
void RegisterAfter (const std::function<std::string (const std::string, const std::string)> &fileHandler);
|
||||
} // namespace LayeredFs
|
||||
namespace TestMode {
|
||||
class Applicable {
|
||||
public:
|
||||
virtual pugi::xml_node *Apply (pugi::xml_node *doc, pugi::xml_node *node) = 0;
|
||||
};
|
||||
class Menu : public Applicable {
|
||||
public:
|
||||
virtual void RegisterItem (Applicable *item) = 0;
|
||||
};
|
||||
typedef u64 (*RefTestModeMain) (u64);
|
||||
void Init ();
|
||||
void Append (const pugi::xml_node &node, const wchar_t *attr, const std::wstring &append);
|
||||
void SetupAccessor (u64 appAccessor, RefTestModeMain refTestMode);
|
||||
int ReadTestModeValue (const wchar_t *itemId);
|
||||
Menu *CreateMenu (const std::wstring &menuName, const std::wstring &menuId);
|
||||
void RegisterItem (const std::wstring &item, const std::function<void ()> &initMethod, Menu *menu);
|
||||
void RegisterItem (const std::wstring &item, const std::function<void ()> &initMethod);
|
||||
void RegisterItem (const std::wstring &item, Menu *menu);
|
||||
void RegisterItem (const std::wstring &item);
|
||||
void RegisterItem (Applicable *item, Menu *menu);
|
||||
void RegisterItem (Applicable *item);
|
||||
void RegisterItemAfter (const std::wstring &query, const std::wstring &item, const std::function<void()> &initMethod);
|
||||
void RegisterItemAfter (const std::wstring &query, const std::wstring &item);
|
||||
void RegisterItemAfter (const std::wstring &query, Applicable *item);
|
||||
void RegisterModify (const std::wstring &query, const std::function<void (pugi::xml_node &)> &nodeModify, const std::function<void ()> &initMethod);
|
||||
void RegisterModify (const std::wstring &query, const std::function<void (pugi::xml_node &)> &nodeModify);
|
||||
} // namespace TestMode
|
||||
namespace Plugins {
|
||||
// typedefs
|
||||
|
||||
+240
-108
@@ -2,33 +2,175 @@
|
||||
#include "helpers.h"
|
||||
#include "patches.h"
|
||||
#include <exception>
|
||||
#include <format>
|
||||
|
||||
extern GameVersion gameVersion;
|
||||
|
||||
bool chsPatch = false;
|
||||
#define MIN(a, b) ((a)<(b)?(a):(b))
|
||||
|
||||
namespace patches::TestMode {
|
||||
class RegisteredItem {
|
||||
std::wstring
|
||||
mergeCondition (std::wstring original, std::wstring addition, std::wstring value) {
|
||||
size_t pos = original.find (L"/");
|
||||
if (pos < 0) return original;
|
||||
std::wstring b = original.substr (0, pos - 1);
|
||||
if (b == L"False") {
|
||||
if (value.starts_with (L"!")) value = value.substr (1, value.size () - 1);
|
||||
else value = L"!" + value;
|
||||
}
|
||||
|
||||
if (original.ends_with(L")")) return replace (original, L")", std::format (L" or {}:{})", addition, value));
|
||||
else return std::format (L"{}/({} or {}:{})", b, original.substr (pos + 1, original.size () - pos - 1), addition, value);
|
||||
}
|
||||
void
|
||||
addConditionValue (pugi::xml_node *node, std::wstring key, std::wstring addition, std::wstring value) {
|
||||
pugi::xml_attribute attr = node->attribute (key.c_str ());
|
||||
if (attr != nullptr) {
|
||||
attr.set_value (mergeCondition(attr.value (), addition, value).c_str ());
|
||||
} else node->append_attribute (key.c_str ()) = std::format(L"True/{}:{}", addition, value).c_str ();
|
||||
}
|
||||
|
||||
class RegisteredItem : public Applicable {
|
||||
public:
|
||||
std::wstring selectItem;
|
||||
std::function<void ()> registerInit;
|
||||
pugi::xml_node temp;
|
||||
RegisteredItem (const std::wstring &selectItem, const std::function<void ()> &initMethod) {
|
||||
this->selectItem = selectItem;
|
||||
this->registerInit = initMethod;
|
||||
}
|
||||
};
|
||||
class RegisteredSingleItem {
|
||||
public:
|
||||
std::wstring query;
|
||||
std::wstring selectItem;
|
||||
std::function<void()> registerInit;
|
||||
RegisteredSingleItem (const std::wstring query, const std::wstring selectItem, const std::function<void()> &initMethod) {
|
||||
this->query = query;
|
||||
this->selectItem = selectItem;
|
||||
this->registerInit = initMethod;
|
||||
pugi::xml_node *
|
||||
Apply (pugi::xml_node *doc, pugi::xml_node *node) override {
|
||||
pugi::xml_document itemDoc;
|
||||
std::wstring itemLine = L"<root>" + this->selectItem + L"</root>";
|
||||
bool success = itemDoc.load_string (itemLine.c_str ());
|
||||
if (!success) {
|
||||
LogMessage (LogLevel::ERROR, L"Failed to parse item: {}\n", this->selectItem);
|
||||
itemDoc.load_string (L"<root><text-item label=\"@Color/Red;!!!ERROR APPLYING ITEM!!!@Color/Default;\"/></root>");
|
||||
}
|
||||
if (success) this->registerInit ();
|
||||
std::wstring layoutName = L"layout";
|
||||
if (layoutName == node->name ()) {
|
||||
temp = node->append_copy (itemDoc.first_child ().first_child ());
|
||||
return &temp;
|
||||
} else {
|
||||
pugi::xml_node breakItem = node->parent ().insert_child_after (L"break-item", *node);
|
||||
temp = node->parent ().insert_copy_after (itemDoc.first_child ().first_child (), breakItem);
|
||||
return &temp;
|
||||
}
|
||||
}
|
||||
};
|
||||
class RegisteredModify {
|
||||
class RegisteredMenu : public Menu {
|
||||
public:
|
||||
std::wstring menuName;
|
||||
std::wstring menuId;
|
||||
std::vector<Applicable *> items;
|
||||
pugi::xml_node temp;
|
||||
RegisteredMenu (const std::wstring &menuName, const std::wstring &menuId, std::vector<Applicable *> items = {}) {
|
||||
this->menuName = menuName;
|
||||
this->menuId = menuId;
|
||||
this->items = items;
|
||||
}
|
||||
void
|
||||
RegisterItem (Applicable *item) override {
|
||||
this->items.push_back (item);
|
||||
}
|
||||
pugi::xml_node *
|
||||
Apply (pugi::xml_node *doc, pugi::xml_node *node) override {
|
||||
size_t size = items.size ();
|
||||
if (size == 0) return node;
|
||||
size_t maxPage = size <= 14 ? 1 : (size / 13 + (size % 13 > 0));
|
||||
LogMessage (LogLevel::DEBUG, "Render testmode menu with items(size={}, page={})", size, maxPage);
|
||||
std::wstring parentId = node->parent ().parent ().attribute (L"id").value ();
|
||||
|
||||
pugi::xml_document menuItem;
|
||||
menuItem.load_string (std::format (L"<root><menu-item label=\"{}\" menu=\"{}\"/></root>", this->menuName, this->menuId).c_str ());
|
||||
std::wstring layoutName = L"layout";
|
||||
if (layoutName == node->name ()) {
|
||||
temp = node->append_copy (menuItem.first_child ().first_child ());
|
||||
} else {
|
||||
pugi::xml_node menuBreakItem = node->parent ().insert_child_after (L"break-item", *node);
|
||||
temp = node->parent ().insert_copy_after (menuItem.first_child ().first_child (), menuBreakItem);
|
||||
}
|
||||
|
||||
pugi::xml_document menu;
|
||||
menu.load_string (std::format (
|
||||
L"<root><menu id=\"{}\">"
|
||||
L"<layout type=\"Header\"><break-item/><text-item label=\"{}\"/><break-item/>"
|
||||
L"</layout><layout type=\"Center\" padding-x=\"23\"></layout>"
|
||||
L"<layout type=\"Footer\"><data-item data=\"FooterTextData\" param-offset-x=\"-20\"/></layout>"
|
||||
L"</menu></root>",
|
||||
this->menuId, this->menuName
|
||||
).c_str ());
|
||||
pugi::xpath_query query = pugi::xpath_query (L"/root/menu/layout[@type='Center']");
|
||||
pugi::xml_node passing = menu.select_node (query).node ();
|
||||
std::vector<pugi::xml_node> refs = {};
|
||||
|
||||
for (size_t page = 0; page < maxPage; page ++) {
|
||||
LogMessage (LogLevel::DEBUG, "Render testmode menu page ({}/{})", page + 1, maxPage);
|
||||
|
||||
pugi::xml_node ref = passing;
|
||||
size_t maxIndex = MIN(size - page * 13, 13);
|
||||
for (size_t index = 0; index < maxIndex; index ++) {
|
||||
LogMessage (LogLevel::DEBUG, "Render testmode menu page ({}/{}) item ({}/{})", page + 1, maxPage, index + 1, maxIndex);
|
||||
if (index >= refs.size ()) {
|
||||
passing = *(items[page * 13 + index]->Apply (doc, &passing));
|
||||
if (size > 14) {
|
||||
addConditionValue (&passing, L"invisible", std::format (L"{}Pagenation", this->menuId), std::format(L"!{}", page + 1));
|
||||
addConditionValue (&passing, L"disable", std::format (L"{}Pagenation", this->menuId), std::format(L"!{}", page + 1));
|
||||
}
|
||||
refs.push_back (passing);
|
||||
} else {
|
||||
pugi::xml_node ref = refs[index];
|
||||
ref = *(items[page * 13 + index]->Apply (doc, &ref));
|
||||
addConditionValue (&ref, L"invisible", std::format (L"{}Pagenation", this->menuId), std::format(L"!{}", page + 1));
|
||||
addConditionValue (&ref, L"disable", std::format (L"{}Pagenation", this->menuId), std::format(L"!{}", page + 1));
|
||||
ref.parent ().remove_child (ref.previous_sibling ());
|
||||
refs[index] = ref;
|
||||
}
|
||||
}
|
||||
if (size == 14) passing = *(items[13]->Apply (doc, &passing));
|
||||
}
|
||||
passing = passing.parent ().last_child ();
|
||||
LogMessage (LogLevel::DEBUG, "Begin render testmode footer");
|
||||
size_t maxIndex = size == 14 ? 14 : MIN(size, 13);
|
||||
for (size_t i = 0; i < 15 - maxIndex; i++) passing = passing.parent ().insert_child_after (L"break-item", passing);
|
||||
if (maxPage > 1) {
|
||||
pugi::xml_document pagenation;
|
||||
pagenation.load_string (std::format (L"<root><select-item label=\"PAGE\" param-offset-x=\"23\" prefix=\"(\" suffix=\"/{})\" param-color=\"Color/Yellow\" id=\"{}Pagenation\" min=\"1\" max=\"{}\" default=\"1\"/></root>", maxPage, this->menuId, maxPage).c_str ());
|
||||
passing = passing.parent ().insert_copy_after (pagenation.first_child ().first_child (), passing);
|
||||
}
|
||||
|
||||
passing = passing.parent ().insert_child_after (L"break-item", passing);
|
||||
pugi::xml_document exit;
|
||||
exit.load_string (std::format (L"<root><menu-item label=\"EXIT\" menu=\"{}\"/></root>", parentId).c_str ());
|
||||
passing = passing.parent ().insert_copy_after (exit.first_child ().first_child (), passing);
|
||||
|
||||
LogMessage (LogLevel::DEBUG, L"Insert testmode menu menuId: {}, fromId: {}", this->menuId, parentId);
|
||||
pugi::xml_node root = doc->first_child ();
|
||||
root.insert_copy_after (menu.first_child ().first_child (), root.first_child ());
|
||||
return &temp;
|
||||
}
|
||||
};
|
||||
class RegisteredSingleItem : Applicable {
|
||||
public:
|
||||
std::wstring query;
|
||||
Applicable *item;
|
||||
RegisteredSingleItem (const std::wstring query, Applicable *item) {
|
||||
this->query = query;
|
||||
this->item = item;
|
||||
}
|
||||
pugi::xml_node *
|
||||
Apply (pugi::xml_node *doc, pugi::xml_node *node) override {
|
||||
pugi::xpath_query insertQuery = pugi::xpath_query (this->query.c_str ());
|
||||
try {
|
||||
if (pugi::xml_node insertNode = doc->select_node (insertQuery).node ()) return this->item->Apply (doc, &insertNode);
|
||||
} catch ([[maybe_unused]] std::exception &e) { LogMessage (LogLevel::ERROR, L"Failed to find node by xpath: {}\n", this->query); }
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
class RegisteredModify : Applicable {
|
||||
public:
|
||||
std::wstring query;
|
||||
std::function<void (pugi::xml_node &)> nodeModify;
|
||||
@@ -38,9 +180,21 @@ public:
|
||||
this->nodeModify = nodeModify;
|
||||
this->registerInit = initMethod;
|
||||
}
|
||||
pugi::xml_node *
|
||||
Apply (pugi::xml_node *doc, pugi::xml_node *node) override {
|
||||
pugi::xpath_query modifyQuery = pugi::xpath_query (this->query.c_str ());
|
||||
try {
|
||||
if (pugi::xml_node modifyNode = node->select_node (modifyQuery).node ()) {
|
||||
this->nodeModify (modifyNode);
|
||||
this->registerInit ();
|
||||
}
|
||||
} catch ([[maybe_unused]] std::exception &e) { LogMessage (LogLevel::ERROR, L"Failed to find node by xpath: {}\n", this->query); }
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<RegisteredItem *> registeredItems = {};
|
||||
Menu *modManager = new RegisteredMenu (L"MOD MANAGER", L"ModManagerMenu");
|
||||
// std::vector<RegisteredItem *> registeredItems = {};
|
||||
std::vector<RegisteredSingleItem *> registeredSingleItems = {};
|
||||
std::vector<RegisteredModify *> registeredModifies = {};
|
||||
std::wstring moddedInitial = L"";
|
||||
@@ -49,50 +203,6 @@ std::wstring modded = L"";
|
||||
u64 appAccessor = 0;
|
||||
RefTestModeMain refTestMode = nullptr;
|
||||
|
||||
pugi::xml_document &
|
||||
CreateMenu (pugi::xml_document &menuMain, const std::wstring &menuId, const std::wstring &menuName, const std::vector<std::wstring> &items,
|
||||
const std::wstring &backId) {
|
||||
LogMessage (LogLevel::DEBUG, L"Create Menu " + menuName);
|
||||
const std::wstring menuBasicLine = L"<menu id=\"" + menuId + L"\"></menu>";
|
||||
if (menuMain.load_string (menuBasicLine.c_str ())) {
|
||||
pugi::xml_node menu = menuMain.first_child ();
|
||||
pugi::xml_node menuHeader = menu.append_child (L"layout");
|
||||
pugi::xml_node menuCenter = menu.append_child (L"layout");
|
||||
pugi::xml_node menuFooter = menu.append_child (L"layout");
|
||||
// Mod Manager Menu Header
|
||||
menuHeader.append_attribute (L"type") = L"Header";
|
||||
menuHeader.append_child (L"break-item");
|
||||
pugi::xml_node menuTitle = menuHeader.append_child (L"text-item");
|
||||
const std::wstring menuNameFull = L" " + menuName;
|
||||
menuTitle.append_attribute (L"label") = menuNameFull.c_str ();
|
||||
menuHeader.append_child (L"break-item");
|
||||
menuHeader.append_child (L"break-item");
|
||||
pugi::xml_node menuTitleData = menuHeader.append_child (L"data-item");
|
||||
menuTitleData.append_attribute (L"data") = L"HeaderTextData";
|
||||
menuTitleData.append_attribute (L"param-offset-x") = L"-15";
|
||||
menuHeader.append_child (L"break-item");
|
||||
// Mod Manager Menu Center
|
||||
menuCenter.append_attribute (L"type") = L"Center";
|
||||
menuCenter.append_attribute (L"padding-x") = L"23";
|
||||
for (const std::wstring& item : items) {
|
||||
std::wstring itemLine = L"<root>" + item + L"</root>";
|
||||
if (pugi::xml_document menuItem; menuItem.load_string (itemLine.c_str ())) menuCenter.append_copy (menuItem.first_child ().first_child ());
|
||||
else LogMessage (LogLevel::ERROR, L"Failed to parse option line: " + item);
|
||||
menuCenter.append_child (L"break-item");
|
||||
}
|
||||
menuCenter.append_child (L"break-item");
|
||||
pugi::xml_node menuCenterExit = menuCenter.append_child (L"menu-item");
|
||||
menuCenterExit.append_attribute (L"label") = L"EXIT";
|
||||
menuCenterExit.append_attribute (L"menu") = backId.c_str ();
|
||||
// Mod Manager Menu Footer
|
||||
menuFooter.append_attribute (L"type") = L"Footer";
|
||||
pugi::xml_node menuFooterData = menuFooter.append_child (L"data-item");
|
||||
menuFooterData.append_attribute (L"data") = L"FooterTextData";
|
||||
menuFooterData.append_attribute (L"param-offset-x") = L"-20";
|
||||
}
|
||||
return menuMain;
|
||||
}
|
||||
|
||||
std::wstring
|
||||
ReadXMLFileSwitcher (std::wstring &fileName) {
|
||||
const std::size_t pos = fileName.rfind (L"/");
|
||||
@@ -122,7 +232,7 @@ HOOK_DYNAMIC (void, TestModeSetMenuHook, u64 testModeLibrary, const wchar_t *lFi
|
||||
const std::wstring modFileName
|
||||
= replace (replace (replace (fileName, L"lize_asia.xml", L"lize_mod.xml"), L"lize_china.xml", L"lize_mod.xml"), L"lize.xml",
|
||||
L"lize_mod.xml");
|
||||
const auto dongleQuery = pugi::xpath_query (L"/root/menu[@id='TopMenu']/layout[@type='Center']/select-item[@id='DongleItem']");
|
||||
const pugi::xpath_query dongleQuery = pugi::xpath_query (L"/root/menu[@id='TopMenu']/layout[@type='Center']/select-item[@id='DongleItem']");
|
||||
const pugi::xml_node dongleItem = doc.select_node (dongleQuery).node ();
|
||||
pugi::xml_node talItem = dongleItem.parent ().append_copy (dongleItem);
|
||||
talItem.attribute (L"label").set_value (L"TAIKOARCADELOADER");
|
||||
@@ -137,7 +247,7 @@ HOOK_DYNAMIC (void, TestModeSetMenuHook, u64 testModeLibrary, const wchar_t *lFi
|
||||
} else fileName = moddedInitial;
|
||||
} else if (fileName.ends_with (L"TestMode.xml") || fileName.ends_with (L"TestMode_asia.xml") || fileName.ends_with (L"TestMode_china.xml")) {
|
||||
if (modded == L"") {
|
||||
if (!registeredItems.empty () || !registeredModifies.empty ()) {
|
||||
if (!((RegisteredMenu*)modManager)->items.empty () || registeredSingleItems.empty () || !registeredModifies.empty ()) {
|
||||
fileName = ReadXMLFileSwitcher (fileName);
|
||||
if (pugi::xml_document doc; !doc.load_file (fileName.c_str ())) {
|
||||
LogMessage (LogLevel::ERROR, L"Loading TestMode structure failed! path: " + fileName);
|
||||
@@ -146,57 +256,25 @@ HOOK_DYNAMIC (void, TestModeSetMenuHook, u64 testModeLibrary, const wchar_t *lFi
|
||||
const std::wstring modFileName
|
||||
= replace (replace (replace (fileName, L"Mode_asia.xml", L"Mode_mod.xml"), L"Mode_china.xml", L"Mode_mod.xml"), L"Mode.xml",
|
||||
L"Mode_mod.xml");
|
||||
if (!registeredItems.empty ()) {
|
||||
const auto menuQuery
|
||||
if (!((RegisteredMenu*)modManager)->items.empty ()) {
|
||||
LogMessage (LogLevel::DEBUG, "Begin generate Mod Manager menu");
|
||||
pugi::xpath_query menuQuery
|
||||
= pugi::xpath_query (L"/root/menu[@id='TopMenu']/layout[@type='Center']/menu-item[@menu='GameOptionsMenu']");
|
||||
pugi::xml_node menuItem = doc.select_node (menuQuery).node ();
|
||||
menuItem = menuItem.next_sibling ();
|
||||
pugi::xml_node modMenuEntry = menuItem.parent ().insert_child_after (L"menu-item", menuItem);
|
||||
modMenuEntry.append_attribute (L"label") = L"MOD MANAGER";
|
||||
modMenuEntry.append_attribute (L"menu") = L"ModManagerMenu";
|
||||
menuItem.parent ().insert_child_after (L"break-item", modMenuEntry);
|
||||
|
||||
pugi::xml_document modMenu;
|
||||
std::vector<std::wstring> toInsertItems = {};
|
||||
for (const RegisteredItem *item : registeredItems) {
|
||||
toInsertItems.push_back (item->selectItem);
|
||||
item->registerInit ();
|
||||
}
|
||||
CreateMenu (modMenu, L"ModManagerMenu", L"MOD MANAGER", toInsertItems, L"TopMenu");
|
||||
const auto topMenuQuery = pugi::xpath_query (L"/root/menu[@id='TopMenu']");
|
||||
const pugi::xml_node topMenu = doc.select_node (topMenuQuery).node ();
|
||||
topMenu.parent ().insert_copy_after (modMenu.first_child (), topMenu);
|
||||
pugi::xml_node menuItem = doc.select_node (menuQuery).node ();
|
||||
modManager->Apply (&doc, &menuItem);
|
||||
LogMessage (LogLevel::DEBUG, "End generate Mod Manager menu");
|
||||
}
|
||||
|
||||
if (!registeredSingleItems.empty()) {
|
||||
for (RegisteredSingleItem *item : registeredSingleItems) {
|
||||
pugi::xpath_query singleQuery = pugi::xpath_query(item->query.c_str());
|
||||
try {
|
||||
pugi::xml_node singleNode = doc.select_node(singleQuery).node();
|
||||
if (singleNode) {
|
||||
pugi::xml_document singleItemDoc;
|
||||
std::wstring itemLine = L"<root>" + item->selectItem + L"</root>";
|
||||
if (singleItemDoc.load_string(itemLine.c_str())) {
|
||||
pugi::xml_node breakItem = singleNode.parent().insert_child_after(L"break-item", singleNode);
|
||||
singleNode.parent().insert_copy_after(singleItemDoc.first_child().first_child(), breakItem);
|
||||
item->registerInit();
|
||||
} else {
|
||||
LogMessage (LogLevel::ERROR, L"Failed to parse option line: {}\n", item->selectItem);
|
||||
}
|
||||
}
|
||||
} catch ([[maybe_unused]] std::exception &e) { LogMessage (LogLevel::ERROR, L"Failed to append node by xpath: {}\n", item->query); }
|
||||
}
|
||||
LogMessage (LogLevel::DEBUG, "Begin Apply Single Items");
|
||||
for (RegisteredSingleItem *item : registeredSingleItems) item->Apply (&doc, &doc);
|
||||
LogMessage (LogLevel::DEBUG, "End Apply Single Items");
|
||||
}
|
||||
|
||||
if (!registeredModifies.empty ()) {
|
||||
for (const RegisteredModify *modify : registeredModifies) { auto modifyQuery = pugi::xpath_query (modify->query.c_str ());
|
||||
try {
|
||||
if (pugi::xml_node modifyNode = doc.select_node (modifyQuery).node ()) {
|
||||
modify->nodeModify (modifyNode);
|
||||
modify->registerInit ();
|
||||
}
|
||||
} catch ([[maybe_unused]] std::exception &e) { LogMessage (LogLevel::ERROR, L"Failed to find node by xpath: {}\n", modify->query); }
|
||||
}
|
||||
LogMessage (LogLevel::DEBUG, "Begin Apply Modify Items");
|
||||
for (RegisteredModify *modify : registeredModifies) modify->Apply (&doc, &doc);
|
||||
LogMessage (LogLevel::DEBUG, "End Apply Modify Items");
|
||||
}
|
||||
|
||||
[[maybe_unused]] auto _ = doc.save_file (modFileName.c_str ());
|
||||
@@ -387,24 +465,78 @@ ReadTestModeValue (const wchar_t *itemId) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
Menu *
|
||||
CreateMenu (const std::wstring &menuName, const std::wstring &menuId) {
|
||||
LogMessage (LogLevel::DEBUG, L"Create MenuName: {} MenuId: {}", menuName, menuId);
|
||||
return new RegisteredMenu (menuName, menuId);
|
||||
}
|
||||
|
||||
void
|
||||
RegisterItem (const std::wstring &item, const std::function<void ()> &initMethod, Menu *menu) {
|
||||
LogMessage (LogLevel::DEBUG, L"Register Item: {}", item);
|
||||
menu->RegisterItem (new RegisteredItem (item, initMethod));
|
||||
}
|
||||
|
||||
void
|
||||
RegisterItem (const std::wstring &item, const std::function<void ()> &initMethod) {
|
||||
LogMessage (LogLevel::DEBUG, L"Register \n Item: {}", item);
|
||||
registeredItems.push_back (new RegisteredItem (item, initMethod));
|
||||
LogMessage (LogLevel::DEBUG, L"Register Item: {}", item);
|
||||
modManager->RegisterItem (new RegisteredItem (item, initMethod));
|
||||
}
|
||||
|
||||
void
|
||||
RegisterItem (const std::wstring &item, Menu *menu) {
|
||||
LogMessage (LogLevel::DEBUG, L"Register Item: {}", item);
|
||||
menu->RegisterItem (new RegisteredItem (item, [](){}));
|
||||
}
|
||||
|
||||
void
|
||||
RegisterItem (const std::wstring &item) {
|
||||
LogMessage (LogLevel::DEBUG, L"Register Item: {}", item);
|
||||
modManager->RegisterItem (new RegisteredItem (item, [](){}));
|
||||
}
|
||||
|
||||
void
|
||||
RegisterItem (Applicable *item, Menu *menu) {
|
||||
LogMessage (LogLevel::DEBUG, L"Register Item");
|
||||
menu->RegisterItem (item);
|
||||
}
|
||||
|
||||
void
|
||||
RegisterItem (Applicable *item) {
|
||||
LogMessage (LogLevel::DEBUG, L"Register Item");
|
||||
modManager->RegisterItem (item);
|
||||
}
|
||||
|
||||
void
|
||||
RegisterItemAfter (const std::wstring &query, const std::wstring &item, const std::function<void()> &initMethod) {
|
||||
LogMessage (LogLevel::DEBUG, L"Register \n Query: {} \n Item: {}", query, item);
|
||||
registeredSingleItems.push_back (new RegisteredSingleItem (query, item, initMethod));
|
||||
LogMessage (LogLevel::DEBUG, L"Register Query: {} Item: {}", query, item);
|
||||
registeredSingleItems.push_back (new RegisteredSingleItem (query, new RegisteredItem (item, initMethod)));
|
||||
}
|
||||
|
||||
void
|
||||
RegisterItemAfter (const std::wstring &query, const std::wstring &item) {
|
||||
LogMessage (LogLevel::DEBUG, L"Register Query: {} Item: {}", query, item);
|
||||
registeredSingleItems.push_back (new RegisteredSingleItem (query, new RegisteredItem (item, [](){})));
|
||||
}
|
||||
|
||||
void
|
||||
RegisterItemAfter (const std::wstring &query, Applicable *item) {
|
||||
LogMessage (LogLevel::DEBUG, L"Register Query: {} Item: ptr", query);
|
||||
registeredSingleItems.push_back (new RegisteredSingleItem (query, item));
|
||||
}
|
||||
|
||||
void
|
||||
RegisterModify (const std::wstring &query, const std::function<void (pugi::xml_node &)> &nodeModify, const std::function<void ()> &initMethod) {
|
||||
LogMessage (LogLevel::DEBUG, L"Register \n Modify: {}", query);
|
||||
LogMessage (LogLevel::DEBUG, L"Register Modify: {}", query);
|
||||
registeredModifies.push_back (new RegisteredModify (query, nodeModify, initMethod));
|
||||
}
|
||||
|
||||
void
|
||||
RegisterModify (const std::wstring &query, const std::function<void (pugi::xml_node &)> &nodeModify) {
|
||||
LogMessage (LogLevel::DEBUG, L"Register Modify: {}", query);
|
||||
registeredModifies.push_back (new RegisteredModify (query, nodeModify, [](){}));
|
||||
}
|
||||
|
||||
void
|
||||
Append (const pugi::xml_node &node, const wchar_t *attr, const std::wstring &append) {
|
||||
pugi::xml_attribute attribute = node.attribute (attr);
|
||||
|
||||
@@ -394,10 +394,38 @@ MID_HOOK (AttractDemo, ASLR (0x14045A720), SafetyHookContext &ctx) {
|
||||
if (TestMode::ReadTestModeValue (L"AttractDemoItem") == 1) ctx.r14 = 0;
|
||||
}
|
||||
|
||||
HOOK (float, InitPlay, ASLR (0x1401345A0), u64 a1, i64 a2, i32 a3) {
|
||||
LogMessage (LogLevel::DEBUG, "Enter InitPlay");
|
||||
float result = originalInitPlay (a1, a2, a3);
|
||||
LogMessage (LogLevel::DEBUG, "Exit InitPlay");
|
||||
HOOK (u64, EnsoGameManagerInitialize, ASLR (0x1400E2520), u64 a1, u64 a2, u64 a3) {
|
||||
LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerInitialize");
|
||||
u64 result = originalEnsoGameManagerInitialize (a1, a2, a3);
|
||||
LogMessage (LogLevel::DEBUG, "End EnsoGameManagerInitialize result={}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
HOOK (u64, EnsoGameManagerLoading, ASLR (0x1400E2750), u64 a1, u64 a2, u64 a3) {
|
||||
LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerLoading");
|
||||
u64 result = originalEnsoGameManagerLoading (a1, a2, a3);
|
||||
LogMessage (LogLevel::DEBUG, "End EnsoGameManagerLoading result={}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
HOOK (bool, EnsoGameManagerPreparing, ASLR (0x1400E2990), u64 a1) {
|
||||
LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerPreparing");
|
||||
bool result = originalEnsoGameManagerPreparing (a1); // crashes here
|
||||
LogMessage (LogLevel::DEBUG, "End EnsoGameManagerPreparing result={}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
HOOK (u64, EnsoGameManagerStart, ASLR (0x1400E2A10), u64 a1, u64 a2, u64 a3) {
|
||||
LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerStart");
|
||||
u64 result = originalEnsoGameManagerStart (a1, a2, a3);
|
||||
LogMessage (LogLevel::DEBUG, "End EnsoGameManagerStart result={}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
HOOK (u64, EnsoGameManagerChechEnsoEnd, ASLR (0x1400E2A10), u64 a1, u64 a2, u64 a3) {
|
||||
LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerChechEnsoEnd");
|
||||
u64 result = originalEnsoGameManagerChechEnsoEnd (a1, a2, a3);
|
||||
LogMessage (LogLevel::DEBUG, "End EnsoGameManagerChechEnsoEnd result={}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -464,7 +492,11 @@ Init () {
|
||||
// Hook to get AppAccessor and ComponentAccessor
|
||||
INSTALL_HOOK (DeviceCheck);
|
||||
INSTALL_HOOK (luaL_newstate);
|
||||
INSTALL_HOOK (InitPlay);
|
||||
INSTALL_HOOK (EnsoGameManagerInitialize);
|
||||
INSTALL_HOOK (EnsoGameManagerLoading);
|
||||
INSTALL_HOOK (EnsoGameManagerPreparing);
|
||||
INSTALL_HOOK (EnsoGameManagerStart);
|
||||
INSTALL_HOOK (EnsoGameManagerChechEnsoEnd);
|
||||
|
||||
// Apply common config patch
|
||||
WRITE_MEMORY (ASLR (0x140494533), i32, xRes);
|
||||
@@ -525,13 +557,23 @@ Init () {
|
||||
|
||||
// Fix Language
|
||||
TestMode::RegisterItem(
|
||||
L"<select-item label=\"FIX LANGUAGE\" param-offset-x=\"35\" replace-text=\"0:OFF, 1:ON\" group=\"Setting\" id=\"ModFixLanguage\" max=\"1\" min=\"0\" default=\"1\"/>",
|
||||
[&]() { INSTALL_HOOK (GetLanguage); INSTALL_HOOK (GetRegionLanguage); INSTALL_HOOK (GetCabinetLanguage); }
|
||||
L"<select-item label=\"FIX LANGUAGE\" param-offset-x=\"35\" replace-text=\"0:OFF, 1:ON\" "
|
||||
L"group=\"Setting\" id=\"ModFixLanguage\" max=\"1\" min=\"0\" default=\"1\"/>",
|
||||
[&]() {
|
||||
INSTALL_HOOK (GetLanguage);
|
||||
INSTALL_HOOK (GetRegionLanguage);
|
||||
INSTALL_HOOK (GetCabinetLanguage);
|
||||
}
|
||||
);
|
||||
// Unlock Songs
|
||||
TestMode::RegisterItem(
|
||||
L"<select-item label=\"UNLOCK SONGS\" param-offset-x=\"35\" replace-text=\"0:OFF, 1:ON, 2:FORCE\" group=\"Setting\" id=\"ModUnlockSongs\" max=\"2\" min=\"0\" default=\"1\"/>",
|
||||
[&]() { INSTALL_HOOK (IsSongRelease); INSTALL_HOOK (IsSongReleasePlayer); INSTALL_MID_HOOK (DifficultyPanelCrown); }
|
||||
L"<select-item label=\"UNLOCK SONGS\" param-offset-x=\"35\" replace-text=\"0:OFF, 1:ON, "
|
||||
L"2:FORCE\" group=\"Setting\" id=\"ModUnlockSongs\" max=\"2\" min=\"0\" default=\"1\"/>",
|
||||
[&]() {
|
||||
INSTALL_HOOK (IsSongRelease);
|
||||
INSTALL_HOOK (IsSongReleasePlayer);
|
||||
INSTALL_MID_HOOK (DifficultyPanelCrown);
|
||||
}
|
||||
);
|
||||
// Freeze Timer
|
||||
TestMode::RegisterItem (
|
||||
@@ -540,26 +582,29 @@ Init () {
|
||||
[&] { INSTALL_MID_HOOK (FreezeTimer); }
|
||||
);
|
||||
// Mode Unlock
|
||||
// TestMode::Menu *modeUnlock = TestMode::CreateMenu (L"MODE UNLOCK", L"ModeUnlockMenu");
|
||||
TestMode::RegisterItem (
|
||||
L"<select-item label=\"KIMETSU MODE\" param-offset-x=\"35\" replace-text=\"0:DEFAULT, 1:ENABLE, "
|
||||
L"2:CARD ONLY\" group=\"Setting\" id=\"ModModeCollabo024\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
[&] { INSTALL_HOOK (AvailableMode_Collabo024); }
|
||||
[&] { INSTALL_HOOK (AvailableMode_Collabo024); }//, modeUnlock
|
||||
);
|
||||
TestMode::RegisterItem (
|
||||
L"<select-item label=\"ONE PIECE MODE\" param-offset-x=\"35\" replace-text=\"0:DEFAULT, "
|
||||
L"1:ENABLE, 2:CARD ONLY\" group=\"Setting\" id=\"ModModeCollabo025\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
[&] { INSTALL_HOOK (AvailableMode_Collabo025); }
|
||||
[&] { INSTALL_HOOK (AvailableMode_Collabo025); }//, modeUnlock
|
||||
);
|
||||
TestMode::RegisterItem (
|
||||
L"<select-item label=\"AI SOSHINA MODE\" param-offset-x=\"35\" replace-text=\"0:DEFAULT, "
|
||||
L"1:ENABLE, 2:CARD ONLY\" group=\"Setting\" id=\"ModModeCollabo026\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
[&] { INSTALL_HOOK (AvailableMode_Collabo026); }
|
||||
[&] { INSTALL_HOOK (AvailableMode_Collabo026); }//, modeUnlock
|
||||
);
|
||||
TestMode::RegisterItem (
|
||||
L"<select-item label=\"AOHARU MODE\" param-offset-x=\"35\" replace-text=\"0:DEFAULT, 1:ENABLE, "
|
||||
L"2:CARD ONLY\" group=\"Setting\" id=\"ModModeAprilFool001\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
[&] { INSTALL_HOOK (AvailableMode_AprilFool001); }
|
||||
[&] { INSTALL_HOOK (AvailableMode_AprilFool001); }//, modeUnlock
|
||||
);
|
||||
// TestMode::RegisterItem (modeUnlock);
|
||||
// InstantResult
|
||||
TestMode::RegisterItem (
|
||||
L"<select-item label=\"INSTANT RESULT\" param-offset-x=\"35\" replace-text=\"0:OFF, 1:ON\" "
|
||||
L"group=\"Setting\" id=\"ModInstantResult\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
@@ -595,9 +640,11 @@ Init () {
|
||||
);
|
||||
TestMode::RegisterItemAfter(
|
||||
L"/root/menu[@id='OthersMenu']/layout[@type='Center']/select-item[@id='AttractMovieItem']",
|
||||
L"<select-item label=\"ATTRACT DEMO\" disable=\"True/ModFixLanguage:0\" param-offset-x=\"35\" replace-text=\"0:ON, 1:OFF\" group=\"Setting\" id=\"AttractDemoItem\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
L"<select-item label=\"ATTRACT DEMO\" disable=\"True/(ModFixLanguage:0 or LanguageItem:0)\" param-offset-x=\"35\" "
|
||||
L"replace-text=\"0:ON, 1:OFF\" group=\"Setting\" id=\"AttractDemoItem\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
[&](){ INSTALL_MID_HOOK (AttractDemo); }
|
||||
);
|
||||
// for (size_t i=0; i < 40; i++) TestMode::RegisterItem(std::format (L"<text-item label=\"TEST{}\"/>", i + 1));
|
||||
|
||||
// Instant Result
|
||||
// TestMode::RegisterModify(
|
||||
|
||||
Reference in New Issue
Block a user