diff --git a/src/bnusio.cpp b/src/bnusio.cpp index 2d20508..7fcef72 100644 --- a/src/bnusio.cpp +++ b/src/bnusio.cpp @@ -280,7 +280,7 @@ Init () { } auto graphics = openConfigSection (config, "graphics"); if (graphics) { - fpsLimit = readConfigInt (graphics, "fpslimit", fpsLimit); + fpsLimit = (int)readConfigInt (graphics, "fpslimit", fpsLimit); } } diff --git a/src/patches/layeredfs.cpp b/src/patches/layeredfs.cpp index 355358b..0dbd3ab 100644 --- a/src/patches/layeredfs.cpp +++ b/src/patches/layeredfs.cpp @@ -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 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 diff --git a/src/patches/patches.h b/src/patches/patches.h index 7f4a53e..00769cb 100644 --- a/src/patches/patches.h +++ b/src/patches/patches.h @@ -42,14 +42,31 @@ void RegisterBefore (const std::function &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 &initMethod, Menu *menu); void RegisterItem (const std::wstring &item, const std::function &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 &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 &nodeModify, const std::function &initMethod); +void RegisterModify (const std::wstring &query, const std::function &nodeModify); } // namespace TestMode namespace Plugins { // typedefs diff --git a/src/patches/testmode.cpp b/src/patches/testmode.cpp index 9ea3055..baca783 100644 --- a/src/patches/testmode.cpp +++ b/src/patches/testmode.cpp @@ -2,33 +2,175 @@ #include "helpers.h" #include "patches.h" #include +#include 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 registerInit; + pugi::xml_node temp; RegisteredItem (const std::wstring &selectItem, const std::function &initMethod) { this->selectItem = selectItem; this->registerInit = initMethod; } -}; -class RegisteredSingleItem { -public: - std::wstring query; - std::wstring selectItem; - std::function registerInit; - RegisteredSingleItem (const std::wstring query, const std::wstring selectItem, const std::function &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"" + this->selectItem + L""; + 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""); + } + 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 items; + pugi::xml_node temp; + RegisteredMenu (const std::wstring &menuName, const std::wstring &menuId, std::vector 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"", 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"" + L"" + L"" + L"" + L"", + 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 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"", 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"", 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 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 registeredItems = {}; +Menu *modManager = new RegisteredMenu (L"MOD MANAGER", L"ModManagerMenu"); +// std::vector registeredItems = {}; std::vector registeredSingleItems = {}; std::vector 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 &items, - const std::wstring &backId) { - LogMessage (LogLevel::DEBUG, L"Create Menu " + menuName); - const std::wstring menuBasicLine = L""; - 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"" + item + L""; - 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 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"" + item->selectItem + L""; - 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 &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 &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 &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 &nodeModify, const std::function &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 &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); diff --git a/src/patches/versions/JPN39.cpp b/src/patches/versions/JPN39.cpp index ce29670..0193f3d 100644 --- a/src/patches/versions/JPN39.cpp +++ b/src/patches/versions/JPN39.cpp @@ -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"", - [&]() { INSTALL_HOOK (GetLanguage); INSTALL_HOOK (GetRegionLanguage); INSTALL_HOOK (GetCabinetLanguage); } + L"", + [&]() { + INSTALL_HOOK (GetLanguage); + INSTALL_HOOK (GetRegionLanguage); + INSTALL_HOOK (GetCabinetLanguage); + } ); // Unlock Songs TestMode::RegisterItem( - L"", - [&]() { INSTALL_HOOK (IsSongRelease); INSTALL_HOOK (IsSongReleasePlayer); INSTALL_MID_HOOK (DifficultyPanelCrown); } + L"", + [&]() { + 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"", - [&] { INSTALL_HOOK (AvailableMode_Collabo024); } + [&] { INSTALL_HOOK (AvailableMode_Collabo024); }//, modeUnlock ); TestMode::RegisterItem ( L"", - [&] { INSTALL_HOOK (AvailableMode_Collabo025); } + [&] { INSTALL_HOOK (AvailableMode_Collabo025); }//, modeUnlock ); TestMode::RegisterItem ( L"", - [&] { INSTALL_HOOK (AvailableMode_Collabo026); } + [&] { INSTALL_HOOK (AvailableMode_Collabo026); }//, modeUnlock ); TestMode::RegisterItem ( L"", - [&] { INSTALL_HOOK (AvailableMode_AprilFool001); } + [&] { INSTALL_HOOK (AvailableMode_AprilFool001); }//, modeUnlock ); + // TestMode::RegisterItem (modeUnlock); + // InstantResult TestMode::RegisterItem ( L"", @@ -595,9 +640,11 @@ Init () { ); TestMode::RegisterItemAfter( L"/root/menu[@id='OthersMenu']/layout[@type='Center']/select-item[@id='AttractMovieItem']", - L"", + L"", [&](){ INSTALL_MID_HOOK (AttractDemo); } ); + // for (size_t i=0; i < 40; i++) TestMode::RegisterItem(std::format (L"", i + 1)); // Instant Result // TestMode::RegisterModify(