From a3eef9fc3b8b9230e1a7e47e05ce64f0f4359d68 Mon Sep 17 00:00:00 2001
From: TheBrokenRail <connor24nolan@live.com>
Date: Mon, 11 Apr 2022 22:52:38 -0400
Subject: [PATCH] Add "Fix Pause Menu"

---
 .../available-feature-flags                   |  1 +
 mods/src/misc/misc.cpp                        | 31 +++++++++++++++++++
 mods/src/options/options.cpp                  |  5 +++
 symbols/include/symbols/minecraft.h           | 10 ++++++
 4 files changed, 47 insertions(+)

diff --git a/launcher/data/client/lib/minecraft-pi-reborn-client/available-feature-flags b/launcher/data/client/lib/minecraft-pi-reborn-client/available-feature-flags
index 145096d3..9ae44aee 100644
--- a/launcher/data/client/lib/minecraft-pi-reborn-client/available-feature-flags
+++ b/launcher/data/client/lib/minecraft-pi-reborn-client/available-feature-flags
@@ -32,3 +32,4 @@ TRUE Improved Cursor Rendering
 FALSE Disable V-Sync
 TRUE Fix Options Screen
 FALSE Force Touch Inventory
+TRUE Fix Pause Menu
diff --git a/mods/src/misc/misc.cpp b/mods/src/misc/misc.cpp
index 81b1f000..0948227d 100644
--- a/mods/src/misc/misc.cpp
+++ b/mods/src/misc/misc.cpp
@@ -45,6 +45,31 @@ static void Minecraft_update_injection(unsigned char *minecraft) {
     }
 }
 
+// Add Missing Buttons To Pause Menu
+static void PauseScreen_init_injection(unsigned char *screen) {
+    // Call Original Method
+    (*PauseScreen_init)(screen);
+
+    // Check If Server
+    unsigned char *minecraft = *(unsigned char **) (screen + Screen_minecraft_property_offset);
+    unsigned char *rak_net_instance = *(unsigned char **) (minecraft + Minecraft_rak_net_instance_property_offset);
+    if (rak_net_instance != NULL) {
+        unsigned char *rak_net_instance_vtable = *(unsigned char**) rak_net_instance;
+        RakNetInstance_isServer_t RakNetInstance_isServer = *(RakNetInstance_isServer_t *) (rak_net_instance_vtable + RakNetInstance_isServer_vtable_offset);
+        if ((*RakNetInstance_isServer)(rak_net_instance)) {
+            // Add Button
+            std::vector<unsigned char *> *rendered_buttons = (std::vector<unsigned char *> *) (screen + Screen_rendered_buttons_property_offset);
+            std::vector<unsigned char *> *selectable_buttons = (std::vector<unsigned char *> *) (screen + Screen_selectable_buttons_property_offset);
+            unsigned char *button = *(unsigned char **) (screen + PauseScreen_server_visibility_button_property_offset);
+            rendered_buttons->push_back(button);
+            selectable_buttons->push_back(button);
+
+            // Update Button Text
+            (*PauseScreen_updateServerVisibilityText)(screen);
+        }
+    }
+}
+
 // Init
 void _init_misc_cpp() {
     // Implement AppPlatform::readAssetFile So Translations Work
@@ -54,4 +79,10 @@ void _init_misc_cpp() {
 
     // Handle Custom Update Behavior
     overwrite_calls((void *) Minecraft_update, (void *) Minecraft_update_injection);
+
+    // Fix Pause Menu
+    if (feature_has("Fix Pause Menu", server_disabled)) {
+        // Add Missing Buttons To Pause Menu
+        patch_address(PauseScreen_init_vtable_addr, (void *) PauseScreen_init_injection);
+    }
 }
diff --git a/mods/src/options/options.cpp b/mods/src/options/options.cpp
index c0ca9ba7..c89eb033 100644
--- a/mods/src/options/options.cpp
+++ b/mods/src/options/options.cpp
@@ -199,6 +199,11 @@ void _init_options_cpp() {
     patch((void *) 0x1931c, nop_patch);
     patch((void *) 0x1973c, nop_patch);
 
+    // Unsplit Touch Controls Breaks Things, Never Load/Save It
+    unsigned char cmp_r0_r0_patch[4] = {0x00, 0x00, 0x50, 0xe1}; // "cmp r0, r0"
+    patch((void *) 0x19378, cmp_r0_r0_patch);
+    patch((void *) 0x197cc, nop_patch);
+
     // Replace "feedback_vibration" Loading/Saving With "gfx_ao"
     {
         // Replace String
diff --git a/symbols/include/symbols/minecraft.h b/symbols/include/symbols/minecraft.h
index b138736c..9de311a4 100644
--- a/symbols/include/symbols/minecraft.h
+++ b/symbols/include/symbols/minecraft.h
@@ -495,6 +495,16 @@ static void *StartMenuScreen_init_vtable_addr = (void *) 0x105194;
 
 static uint32_t StartMenuScreen_options_button_property_offset = 0x98; // Button
 
+// PauseScreen
+
+static Screen_init_t PauseScreen_init = (Screen_init_t) 0x36810;
+static void *PauseScreen_init_vtable_addr = (void *) 0x104b2c;
+
+typedef void (*PauseScreen_updateServerVisibilityText_t)(unsigned char *screen);
+static PauseScreen_updateServerVisibilityText_t PauseScreen_updateServerVisibilityText = (PauseScreen_updateServerVisibilityText_t) 0x366b8;
+
+static uint32_t PauseScreen_server_visibility_button_property_offset = 0x60; // Button *
+
 // Touch::IngameBlockSelectionScreen
 
 #define TOUCH_INGAME_BLOCK_SELECTION_SCREEN_SIZE 0x16c