Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python
- """Super Meat Boy Patcher version 1.1. Performs binary patches on
- the Super Meat Boy executable for various purposes.
- Works with Python 2.x, NOT 3.x currently.
- For Windows (32/64bit) and Linux (64bit):
- Removes randomness from Larry ensuring 3 cycles.
- For Windows (32/64bit):
- Removes Glitch Girl randomness, allows Glitch Girl
- to spawn more often.
- Usage: run with python, GUI should show automatically.
- GPL v2, or above if you wish.
- d265f27.
- """
- # Larry Script - What it does:
- # SMB has a GetRandomInt() function. Larry has two functions,
- # RaptureBoss::UpdateMaggot(RaptureBoss::Maggot*) and
- # RaptureBoss::RenderMaggot(RaptureBoss::Maggot*), that call it.
- # UpdateMaggot has 5 calls to GetRandomInt, RenderMaggot has 1.
- # We replace these function calls with specified return values,
- # removing RNG from Larry.
- # GetRandomInt() is trivial to find in the Linux executable due to it
- # being unstripped, below is the location of GetRandomInt() for Windows:
- # 0x4047d0 or SuperMeatBoy.eye+47d0 (Cheat Engine)
- # The values were randomly guessed by myself just to achieve the 3
- # cycle, so may not be perfectly accurate.
- # Glitch Girl - What it does:
- # Glitch Girl has a GetRandomInt() call, we replace it with a particular
- # result to ensure she always spawns if possible.
- # To increase when she can possibly spawn we remove some jmp instructions
- # for if she shouldn't spawn.
- import struct
- import Tkinter as tk
- import tkFileDialog
- import tkMessageBox
- LINUX_64_LARRY_STRING = "Linux executable with larry script."
- LINUX_64_NO_LARRY_STRING = "Linux executable without larry script."
- WINDOWS_LARRY_STRING = "Windows executable with larry script."
- WINDOWS_NO_LARRY_STRING = "Windows executable without larry script."
- UNKNOWN_LARRY_STRING = "Unknown executable. Couldn't find larry script positions."
- WINDOWS_GLITCH_STRING = "Has patched Glitch Girl RNG."
- WINDOWS_NO_GLITCH_STRING = "Has normal Glitch Girl RNG."
- UNKNOWN_GLITCH_STRING = "Unknown Glitch Girl RNG data."
- WINDOWS_MULTIPLE_GLITCH_STRING = "Ignores GG spawn requirements."
- WINDOWS_NO_MULTIPLE_GLITCH_STRING = "Does not ignore GG spawn requirements."
- UNKNOWN_MULTIPLE_GLITCH_STRING = "Unknown multiple Glitch Girls data."
- NO_EXECUTABLE_FILE_STRING = "BACKUP EXECUTABLE BEFORE USE!\nNo executable currently selected."
- def create_mov_instruction(value):
- """Generates a mov instruction to work as a return value.
- mov $0x(hex of value),%eax
- Example:
- create_mov_instruction(1):
- b8 01 00 00 00 mov $0x1,%eax"""
- return "\xb8" + struct.pack("I", value)
- # Binary information.
- # The following are the instructions we need to patch, with extra bytes so we select the correct ones.
- # Calls 1 - 5 are from UpdateMaggot, in order. Call 6 is from RenderMaggot.
- ############################################################################################
- # WINDOWS file information.
- # _EXTRA is extra instructions past the instruction we want so we can search effectively.
- WINDOWS_LARRY_1_EXTRA = "\x83\xc4\x08\x56\x8b\xcf\xe8\xd7\xfb\xff\xff"
- WINDOWS_LARRY_2_EXTRA = "\x89\x44\x24\x38\xdb\x44\x24\x38\xeb\x17"
- WINDOWS_LARRY_3_EXTRA = "\x89\x44\x24\x38\xdb\x44\x24\x38"
- WINDOWS_LARRY_4_EXTRA = "\x8b\x0d\xbc\x54\x6d\x00\x89\x44\x24\x38"
- WINDOWS_LARRY_5_EXTRA = "\x83\xc4\x08\x83\xf8\x32\x7e\x39\x33\xc9"
- WINDOWS_LARRY_6_EXTRA = "\x83\xc4\x08\x83\xf8\x32\x7d\x14\x89\x9e\xd8\x00\x00\x00"
- # The instruction we are patching out.
- WINDOWS_LARRY_1_UNPATCHED_START = "\xe8\xd2\x7f\xf7\xff"
- WINDOWS_LARRY_2_UNPATCHED_START = "\xe8\xa6\x7f\xf7\xff"
- WINDOWS_LARRY_3_UNPATCHED_START = "\xe8\x8d\x7f\xf7\xff"
- WINDOWS_LARRY_4_UNPATCHED_START = "\xe8\x63\x7f\xf7\xff"
- WINDOWS_LARRY_5_UNPATCHED_START = "\xe8\x81\x7e\xf7\xff"
- WINDOWS_LARRY_6_UNPATCHED_START = "\xe8\xcf\x86\xf7\xff"
- WINDOWS_UNPATCHED_LARRY_1 = WINDOWS_LARRY_1_UNPATCHED_START + WINDOWS_LARRY_1_EXTRA
- WINDOWS_UNPATCHED_LARRY_2 = WINDOWS_LARRY_2_UNPATCHED_START + WINDOWS_LARRY_2_EXTRA
- WINDOWS_UNPATCHED_LARRY_3 = WINDOWS_LARRY_3_UNPATCHED_START + WINDOWS_LARRY_3_EXTRA
- WINDOWS_UNPATCHED_LARRY_4 = WINDOWS_LARRY_4_UNPATCHED_START + WINDOWS_LARRY_4_EXTRA
- WINDOWS_UNPATCHED_LARRY_5 = WINDOWS_LARRY_5_UNPATCHED_START + WINDOWS_LARRY_5_EXTRA
- WINDOWS_UNPATCHED_LARRY_6 = WINDOWS_LARRY_6_UNPATCHED_START + WINDOWS_LARRY_6_EXTRA
- # Here the magic happens, the replacement call values. Select whatever generates 3 cycles.
- WINDOWS_LARRY_RETURN_1 = 1000
- WINDOWS_LARRY_RETURN_2 = 1000
- WINDOWS_LARRY_RETURN_3 = 10
- WINDOWS_LARRY_RETURN_4 = 100
- WINDOWS_LARRY_RETURN_5 = 1000
- WINDOWS_LARRY_RETURN_6 = 10
- WINDOWS_LARRY_1_PATCHED_START = create_mov_instruction(WINDOWS_LARRY_RETURN_1)
- WINDOWS_LARRY_2_PATCHED_START = create_mov_instruction(WINDOWS_LARRY_RETURN_2)
- WINDOWS_LARRY_3_PATCHED_START = create_mov_instruction(WINDOWS_LARRY_RETURN_3)
- WINDOWS_LARRY_4_PATCHED_START = create_mov_instruction(WINDOWS_LARRY_RETURN_4)
- WINDOWS_LARRY_5_PATCHED_START = create_mov_instruction(WINDOWS_LARRY_RETURN_5)
- WINDOWS_LARRY_6_PATCHED_START = create_mov_instruction(WINDOWS_LARRY_RETURN_6)
- WINDOWS_PATCHED_LARRY_1 = WINDOWS_LARRY_1_PATCHED_START + WINDOWS_LARRY_1_EXTRA
- WINDOWS_PATCHED_LARRY_2 = WINDOWS_LARRY_2_PATCHED_START + WINDOWS_LARRY_2_EXTRA
- WINDOWS_PATCHED_LARRY_3 = WINDOWS_LARRY_3_PATCHED_START + WINDOWS_LARRY_3_EXTRA
- WINDOWS_PATCHED_LARRY_4 = WINDOWS_LARRY_4_PATCHED_START + WINDOWS_LARRY_4_EXTRA
- WINDOWS_PATCHED_LARRY_5 = WINDOWS_LARRY_5_PATCHED_START + WINDOWS_LARRY_5_EXTRA
- WINDOWS_PATCHED_LARRY_6 = WINDOWS_LARRY_6_PATCHED_START + WINDOWS_LARRY_6_EXTRA
- WINDOWS_PATCHED_LARRY_STRINGS = [WINDOWS_PATCHED_LARRY_1, WINDOWS_PATCHED_LARRY_2,
- WINDOWS_PATCHED_LARRY_3, WINDOWS_PATCHED_LARRY_4,
- WINDOWS_PATCHED_LARRY_5, WINDOWS_PATCHED_LARRY_6]
- WINDOWS_UNPATCHED_LARRY_STRINGS = [WINDOWS_UNPATCHED_LARRY_1, WINDOWS_UNPATCHED_LARRY_2,
- WINDOWS_UNPATCHED_LARRY_3, WINDOWS_UNPATCHED_LARRY_4,
- WINDOWS_UNPATCHED_LARRY_5, WINDOWS_UNPATCHED_LARRY_6]
- # Glitch RNG.
- WINDOWS_GLITCH_EXTRA = "\x83\xc4\x08\x33\xd2\x3b\xc6\x0f\x9c\xc2\x5e\x5f\x8b\xc2"
- WINDOWS_GLITCH_UNPATCHED_START = "\xe8\x2e\x4b\xfe\xff"
- WINDOWS_GLITCH_UNPATCHED = WINDOWS_GLITCH_UNPATCHED_START + WINDOWS_GLITCH_EXTRA
- WINDOWS_GLITCH_PATCHED_VALUE = 0 # The number we replace the call instruction with.
- WINDOWS_GLITCH_PATCHED_START = create_mov_instruction(WINDOWS_GLITCH_PATCHED_VALUE)
- WINDOWS_GLITCH_PATCHED = WINDOWS_GLITCH_PATCHED_START + WINDOWS_GLITCH_EXTRA
- # Multiple Glitch.
- # Okay, the following is tricky. The checks that occur to make sure you
- # only get glitch girl at the appropriate times start at around
- # 41fc52: 75 5d jne 0x41fcb1
- # So if we replace this conditional jump with an unconditional jump to
- # the start of the place where glitch girl rng occurs, namely 41fc96
- # Then glitch girl occurs more frequently.
- # This is now
- # 41fc52: eb 42 jmp 0x41fc96
- # This was hand-coded assembly, figure it out if you have to.
- WINDOWS_MULTIPLE_GLITCH_EXTRA = "\x83\xfe\x09\x74\x58\x83\xfe\x07\x74\x53\x8b\xcf\xe8\xeb\xe6\xff\xff"
- WINDOWS_MULTIPLE_GLITCH_UNPATCHED_START = "\x75\x5d"
- WINDOWS_MULTIPLE_GLITCH_UNPATCHED = WINDOWS_MULTIPLE_GLITCH_UNPATCHED_START + WINDOWS_MULTIPLE_GLITCH_EXTRA
- WINDOWS_MULTIPLE_GLITCH_PATCHED_START = "\xeb\x42"
- WINDOWS_MULTIPLE_GLITCH_PATCHED = WINDOWS_MULTIPLE_GLITCH_PATCHED_START + WINDOWS_MULTIPLE_GLITCH_EXTRA
- ############################################################################################
- # LINUX file information.
- # The actual instruction we want to remove is the following (slightly different for each call)
- # 4848c2: e8 29 9c 13 00 callq 5be4f0 <GetRandomINT>
- LINUX_64_LARRY_1_EXTRA = "\x66\x81\xa3\xa4\x01\x00\x00\x00\xf0\x48\x8d\xbb\xa0\x00\x00\x00"
- LINUX_64_LARRY_2_EXTRA = "\xf3\x0f\x2a\xc0\xf3\x0f\x59\x05\xf9\xcb\x13\x00"
- LINUX_64_LARRY_3_EXTRA = "\x48\x8b\x3d\x31\x8d\x39\x00\x41\x89\xc4\xbe\x01\x00\x00\x00"
- LINUX_64_LARRY_4_EXTRA = "\xf3\x0f\x2a\xc0\xf3\x0f\x59\x05\xe5\xca\x13\x00"
- LINUX_64_LARRY_5_EXTRA = "\x83\xf8\x32\x0f\x8f\x27\x04\x00\x00\xc7\x83\xf8\x00\x00\x00\x04"
- LINUX_64_LARRY_6_EXTRA = "\x83\xf8\x31\x0f\x8e\xa8\x02\x00\x00\xc7\x83\xf8\x00\x00\x00\x08"
- LINUX_64_LARRY_1_UNPATCHED_START = "\xe8\x29\x9c\x13\x00"
- LINUX_64_LARRY_2_UNPATCHED_START = "\xe8\x85\x9b\x13\x00"
- LINUX_64_LARRY_3_UNPATCHED_START = "\xe8\x58\x9b\x13\x00"
- LINUX_64_LARRY_4_UNPATCHED_START = "\xe8\x71\x9a\x13\x00"
- LINUX_64_LARRY_5_UNPATCHED_START = "\xe8\x80\x99\x13\x00"
- LINUX_64_LARRY_6_UNPATCHED_START = "\xe8\x1e\x8d\x13\x00"
- LINUX_64_UNPATCHED_LARRY_1 = LINUX_64_LARRY_1_UNPATCHED_START + LINUX_64_LARRY_1_EXTRA
- LINUX_64_UNPATCHED_LARRY_2 = LINUX_64_LARRY_2_UNPATCHED_START + LINUX_64_LARRY_2_EXTRA
- LINUX_64_UNPATCHED_LARRY_3 = LINUX_64_LARRY_3_UNPATCHED_START + LINUX_64_LARRY_3_EXTRA
- LINUX_64_UNPATCHED_LARRY_4 = LINUX_64_LARRY_4_UNPATCHED_START + LINUX_64_LARRY_4_EXTRA
- LINUX_64_UNPATCHED_LARRY_5 = LINUX_64_LARRY_5_UNPATCHED_START + LINUX_64_LARRY_5_EXTRA
- LINUX_64_UNPATCHED_LARRY_6 = LINUX_64_LARRY_6_UNPATCHED_START + LINUX_64_LARRY_6_EXTRA
- # Here the magic happens, the replacement call values. Select whatever generates 3 cycles.
- LINUX_64_LARRY_RETURN_1 = 1000
- LINUX_64_LARRY_RETURN_2 = 1000
- LINUX_64_LARRY_RETURN_3 = 10
- LINUX_64_LARRY_RETURN_4 = 1000
- LINUX_64_LARRY_RETURN_5 = 1000
- LINUX_64_LARRY_RETURN_6 = 10
- LINUX_64_LARRY_1_PATCHED_START = create_mov_instruction(LINUX_64_LARRY_RETURN_1)
- LINUX_64_LARRY_2_PATCHED_START = create_mov_instruction(LINUX_64_LARRY_RETURN_2)
- LINUX_64_LARRY_3_PATCHED_START = create_mov_instruction(LINUX_64_LARRY_RETURN_3)
- LINUX_64_LARRY_4_PATCHED_START = create_mov_instruction(LINUX_64_LARRY_RETURN_4)
- LINUX_64_LARRY_5_PATCHED_START = create_mov_instruction(LINUX_64_LARRY_RETURN_5)
- LINUX_64_LARRY_6_PATCHED_START = create_mov_instruction(LINUX_64_LARRY_RETURN_6)
- LINUX_64_PATCHED_LARRY_1 = LINUX_64_LARRY_1_PATCHED_START + LINUX_64_LARRY_1_EXTRA
- LINUX_64_PATCHED_LARRY_2 = LINUX_64_LARRY_2_PATCHED_START + LINUX_64_LARRY_2_EXTRA
- LINUX_64_PATCHED_LARRY_3 = LINUX_64_LARRY_3_PATCHED_START + LINUX_64_LARRY_3_EXTRA
- LINUX_64_PATCHED_LARRY_4 = LINUX_64_LARRY_4_PATCHED_START + LINUX_64_LARRY_4_EXTRA
- LINUX_64_PATCHED_LARRY_5 = LINUX_64_LARRY_5_PATCHED_START + LINUX_64_LARRY_5_EXTRA
- LINUX_64_PATCHED_LARRY_6 = LINUX_64_LARRY_6_PATCHED_START + LINUX_64_LARRY_6_EXTRA
- LINUX_64_PATCHED_LARRY_STRINGS = [LINUX_64_PATCHED_LARRY_1, LINUX_64_PATCHED_LARRY_2,
- LINUX_64_PATCHED_LARRY_3, LINUX_64_PATCHED_LARRY_4,
- LINUX_64_PATCHED_LARRY_5, LINUX_64_PATCHED_LARRY_6]
- LINUX_64_UNPATCHED_LARRY_STRINGS = [LINUX_64_UNPATCHED_LARRY_1, LINUX_64_UNPATCHED_LARRY_2,
- LINUX_64_UNPATCHED_LARRY_3, LINUX_64_UNPATCHED_LARRY_4,
- LINUX_64_UNPATCHED_LARRY_5, LINUX_64_UNPATCHED_LARRY_6]
- def write_instruction(open_file, position, instruction):
- """Writes the instruct at the specified position of the file."""
- open_file.seek(position)
- open_file.write(instruction)
- open_file.flush()
- def check_for_patched_larry(contents):
- """Checks the contents of the file for linux/windows patched and unpatched larry instructions.
- Returns (string, [location1, location2, location3, location4, location5, location6])
- string can be LINUX_64_LARRY_STRING, LINUX_64_NO_LARRY_STRING, WINDOWS_LARRY_STRING,
- WINDOWS_NO_LARRY_STRING, UNKNOWN_LARRY_STRING
- If UNKNOWN_LARRY_STRING then it is an empty list.
- """
- results = check_for_strings(contents, LINUX_64_PATCHED_LARRY_STRINGS)
- if results[0]: # Found all of the strings.
- return (LINUX_64_LARRY_STRING, results[1])
- results = check_for_strings(contents, LINUX_64_UNPATCHED_LARRY_STRINGS)
- if results[0]: # Found all of the strings.
- return (LINUX_64_NO_LARRY_STRING, results[1])
- results = check_for_strings(contents, WINDOWS_PATCHED_LARRY_STRINGS)
- if results[0]: # Found all of the strings.
- return (WINDOWS_LARRY_STRING, results[1])
- results = check_for_strings(contents, WINDOWS_UNPATCHED_LARRY_STRINGS)
- if results[0]: # Found all of the strings.
- return (WINDOWS_NO_LARRY_STRING, results[1])
- # Couldn't find any of the correct results, so...
- return (UNKNOWN_LARRY_STRING, [])
- def check_for_patched_glitch(contents):
- """Checks the contents of the file for windows patched and unpatched glitch instructions.
- Returns (string, location)
- string can be WINDOWS_NO_GLITCH_STRING, WINDOWS_GLITCH_STRING
- If UNKNOWN_GLITCH_STRING then location is None
- """
- location = contents.find(WINDOWS_GLITCH_PATCHED)
- if location != -1: # Found this string.
- return (WINDOWS_GLITCH_STRING, location)
- location = contents.find(WINDOWS_GLITCH_UNPATCHED)
- if location != -1: # Found this string.
- return (WINDOWS_NO_GLITCH_STRING, location)
- # Couldn't find any of the correct results, so...
- return (UNKNOWN_GLITCH_STRING, None)
- def check_for_patched_multiple_glitch(contents):
- """Checks the contents of the file for windows patched and unpatched MULTIPLE_GLITCH instructions.
- Returns (string, location)
- string can be WINDOWS_NO_MULTIPLE_GLITCH_STRING, WINDOWS_MULTIPLE_GLITCH_STRING
- If UNKNOWN_MULTIPLE_GLITCH_STRING then location is None
- """
- location = contents.find(WINDOWS_MULTIPLE_GLITCH_PATCHED)
- if location != -1: # Found this string.
- return (WINDOWS_MULTIPLE_GLITCH_STRING, location)
- location = contents.find(WINDOWS_MULTIPLE_GLITCH_UNPATCHED)
- if location != -1: # Found this string.
- return (WINDOWS_NO_MULTIPLE_GLITCH_STRING, location)
- # Couldn't find any of the correct results, so...
- return (UNKNOWN_MULTIPLE_GLITCH_STRING, None)
- def check_for_strings(contents, strings):
- """Checks for strings in contents. If any not there returns (False,)
- otherwise if all are there returns (True, [location for string in strings])
- """
- results = []
- for string in strings:
- location = contents.find(string)
- if location == -1: # String wasn't found in file.
- return (False,)
- results.append(location)
- return (True, results)
- def unpatch_glitch(open_file, os, position):
- """os is either "linux_64" or "windows", positions is a list of positions."""
- if os == "windows":
- write_instruction(open_file, position, WINDOWS_GLITCH_UNPATCHED_START)
- def patch_glitch(open_file, os, position):
- """os is either "linux_64" or "windows", positions is a list of positions."""
- if os == "windows":
- write_instruction(open_file, position, WINDOWS_GLITCH_PATCHED_START)
- def unpatch_multiple_glitch(open_file, os, position):
- """os is either "linux_64" or "windows", positions is a list of positions."""
- if os == "windows":
- write_instruction(open_file, position, WINDOWS_MULTIPLE_GLITCH_UNPATCHED_START)
- def patch_multiple_glitch(open_file, os,position):
- """os is either "linux_64" or "windows", positions is a list of positions."""
- if os == "windows":
- write_instruction(open_file, position, WINDOWS_MULTIPLE_GLITCH_PATCHED_START)
- def unpatch_larry(open_file, os, positions):
- """os is either "linux_64" or "windows", positions is a list of positions."""
- if os == "linux_64":
- write_instruction(open_file, positions[0], LINUX_64_LARRY_1_UNPATCHED_START)
- write_instruction(open_file, positions[1], LINUX_64_LARRY_2_UNPATCHED_START)
- write_instruction(open_file, positions[2], LINUX_64_LARRY_3_UNPATCHED_START)
- write_instruction(open_file, positions[3], LINUX_64_LARRY_4_UNPATCHED_START)
- write_instruction(open_file, positions[4], LINUX_64_LARRY_5_UNPATCHED_START)
- write_instruction(open_file, positions[5], LINUX_64_LARRY_6_UNPATCHED_START)
- elif os == "windows":
- write_instruction(open_file, positions[0], WINDOWS_LARRY_1_UNPATCHED_START)
- write_instruction(open_file, positions[1], WINDOWS_LARRY_2_UNPATCHED_START)
- write_instruction(open_file, positions[2], WINDOWS_LARRY_3_UNPATCHED_START)
- write_instruction(open_file, positions[3], WINDOWS_LARRY_4_UNPATCHED_START)
- write_instruction(open_file, positions[4], WINDOWS_LARRY_5_UNPATCHED_START)
- write_instruction(open_file, positions[5], WINDOWS_LARRY_6_UNPATCHED_START)
- def patch_larry(open_file, os, positions):
- """os is either "linux_64" or "windows", positions is a list of positions."""
- if os == "linux_64":
- write_instruction(open_file, positions[0], LINUX_64_LARRY_1_PATCHED_START)
- write_instruction(open_file, positions[1], LINUX_64_LARRY_2_PATCHED_START)
- write_instruction(open_file, positions[2], LINUX_64_LARRY_3_PATCHED_START)
- write_instruction(open_file, positions[3], LINUX_64_LARRY_4_PATCHED_START)
- write_instruction(open_file, positions[4], LINUX_64_LARRY_5_PATCHED_START)
- write_instruction(open_file, positions[5], LINUX_64_LARRY_6_PATCHED_START)
- elif os == "windows":
- write_instruction(open_file, positions[0], WINDOWS_LARRY_1_PATCHED_START)
- write_instruction(open_file, positions[1], WINDOWS_LARRY_2_PATCHED_START)
- write_instruction(open_file, positions[2], WINDOWS_LARRY_3_PATCHED_START)
- write_instruction(open_file, positions[3], WINDOWS_LARRY_4_PATCHED_START)
- write_instruction(open_file, positions[4], WINDOWS_LARRY_5_PATCHED_START)
- write_instruction(open_file, positions[5], WINDOWS_LARRY_6_PATCHED_START)
- class Patcher(tk.Frame):
- def __init__(self):
- tk.Frame.__init__(self, None)
- self.grid()
- self.master.title("SMB Patcher - d265f27")
- self.file = None
- self.larry = None
- self.glitch = None
- self.multiple_glitch = None
- self.populateWindow()
- def populateWindow(self):
- self.label = tk.Label(self, text=NO_EXECUTABLE_FILE_STRING)
- self.label.pack(padx=5, pady=5)
- self.selectFileButton = tk.Button(self, text="Choose executable", command=self.getFilename)
- self.selectFileButton.pack(padx=5, pady=5)
- self.patchLarryFrame = tk.Frame(self)
- self.patchLarryLabel = tk.Label(self.patchLarryFrame, text="Remove Larry RNG")
- self.patchLarryLabel.pack(padx=5, pady=5, side=tk.LEFT)
- self.patchLarryButton = tk.Button(self.patchLarryFrame, text="Patch", command=self.patchLarry, state='disabled')
- self.patchLarryButton.pack(padx=5, pady=5, side=tk.LEFT)
- self.unpatchLarryButton = tk.Button(self.patchLarryFrame, text="Reset", command=self.unpatchLarry, state='disabled')
- self.unpatchLarryButton.pack(padx=5, pady=5, side=tk.RIGHT)
- self.patchLarryFrame.pack(padx=5, pady=5)
- self.patchGlitchFrame = tk.Frame(self)
- self.patchGlitchLabel = tk.Label(self.patchGlitchFrame, text="Remove Glitch Girl RNG")
- self.patchGlitchLabel.pack(padx=5, pady=5, side=tk.LEFT)
- self.patchGlitchButton = tk.Button(self.patchGlitchFrame, text="Patch", command=self.patchGlitch, state='disabled')
- self.patchGlitchButton.pack(padx=5, pady=5, side=tk.LEFT)
- self.unpatchGlitchButton = tk.Button(self.patchGlitchFrame, text="Reset", command=self.unpatchGlitch, state='disabled')
- self.unpatchGlitchButton.pack(padx=5, pady=5, side=tk.RIGHT)
- self.patchGlitchFrame.pack(padx=5, pady=5)
- self.patchMultipleGlitchFrame = tk.Frame(self)
- self.patchMultipleGlitchLabel = tk.Label(self.patchMultipleGlitchFrame, text="Ignore GG Spawn requirements")
- self.patchMultipleGlitchLabel.pack(padx=5, pady=5, side=tk.LEFT)
- self.patchMultipleGlitchButton = tk.Button(self.patchMultipleGlitchFrame, text="Patch", command=self.patchMultipleGlitch, state='disabled')
- self.patchMultipleGlitchButton.pack(padx=5, pady=5, side=tk.LEFT)
- self.unpatchMultipleGlitchButton = tk.Button(self.patchMultipleGlitchFrame, text="Reset", command=self.unpatchMultipleGlitch, state='disabled')
- self.unpatchMultipleGlitchButton.pack(padx=5, pady=5, side=tk.RIGHT)
- self.patchMultipleGlitchFrame.pack(padx=5, pady=5)
- def reset_info(self):
- if self.file is not None:
- self.file.seek(0)
- self.contents = self.file.read()
- self.larry = check_for_patched_larry(self.contents)
- self.glitch = check_for_patched_glitch(self.contents)
- self.multiple_glitch = check_for_patched_multiple_glitch(self.contents)
- self.label['text'] = self.larry[0] + '\n' + self.glitch[0] + '\n' + self.multiple_glitch[0]
- # Update the buttons.
- if self.larry[0] != UNKNOWN_LARRY_STRING:
- self.patchLarryButton['state'] = tk.NORMAL
- self.unpatchLarryButton['state'] = tk.NORMAL
- else:
- self.patchLarryButton['state'] = tk.DISABLED
- self.unpatchLarryButton['state'] = tk.DISABLED
- if self.glitch[0] != UNKNOWN_GLITCH_STRING:
- self.patchGlitchButton['state'] = tk.NORMAL
- self.unpatchGlitchButton['state'] = tk.NORMAL
- else:
- self.patchGlitchButton['state'] = tk.DISABLED
- self.unpatchGlitchButton['state'] = tk.DISABLED
- if self.multiple_glitch[0] != UNKNOWN_MULTIPLE_GLITCH_STRING:
- self.patchMultipleGlitchButton['state'] = tk.NORMAL
- self.unpatchMultipleGlitchButton['state'] = tk.NORMAL
- else:
- self.patchMultipleGlitchButton['state'] = tk.DISABLED
- self.unpatchMultipleGlitchButton['state'] = tk.DISABLED
- else:
- self.patchMultipleGlitchButton['state'] = tk.DISABLED
- self.unpatchMultipleGlitchButton['state'] = tk.DISABLED
- self.patchGlitchButton['state'] = tk.DISABLED
- self.unpatchGlitchButton['state'] = tk.DISABLED
- self.patchLarryButton['state'] = tk.DISABLED
- self.unpatchLarryButton['state'] = tk.DISABLED
- self.label['text'] = NO_EXECUTABLE_FILE_STRING
- def getFilename(self):
- if self.file is not None:
- self.file.close()
- self.file = tkFileDialog.askopenfile(mode='r+b', parent=self, title='Select SMB Executable')
- self.reset_info()
- def patchLarry(self):
- if self.larry[0] == LINUX_64_LARRY_STRING or self.larry[0] == LINUX_64_NO_LARRY_STRING:
- patch_larry(self.file, "linux_64", self.larry[1])
- if self.larry[0] == WINDOWS_LARRY_STRING or self.larry[0] == WINDOWS_NO_LARRY_STRING:
- patch_larry(self.file, "windows", self.larry[1])
- self.reset_info()
- def unpatchLarry(self):
- if self.larry[0] == LINUX_64_LARRY_STRING or self.larry[0] == LINUX_64_NO_LARRY_STRING:
- unpatch_larry(self.file, "linux_64", self.larry[1])
- if self.larry[0] == WINDOWS_LARRY_STRING or self.larry[0] == WINDOWS_NO_LARRY_STRING:
- unpatch_larry(self.file, "windows", self.larry[1])
- self.reset_info()
- def patchGlitch(self):
- if self.glitch[0] == WINDOWS_GLITCH_STRING or self.glitch[0] == WINDOWS_NO_GLITCH_STRING:
- patch_glitch(self.file, "windows", self.glitch[1])
- self.reset_info()
- def unpatchGlitch(self):
- if self.glitch[0] == WINDOWS_GLITCH_STRING or self.glitch[0] == WINDOWS_NO_GLITCH_STRING:
- unpatch_glitch(self.file, "windows", self.glitch[1])
- self.reset_info()
- def patchMultipleGlitch(self):
- if self.multiple_glitch[0] == WINDOWS_MULTIPLE_GLITCH_STRING or self.multiple_glitch[0] == WINDOWS_NO_MULTIPLE_GLITCH_STRING:
- patch_multiple_glitch(self.file, "windows", self.multiple_glitch[1])
- self.reset_info()
- def unpatchMultipleGlitch(self):
- if self.multiple_glitch[0] == WINDOWS_MULTIPLE_GLITCH_STRING or self.multiple_glitch[0] == WINDOWS_NO_MULTIPLE_GLITCH_STRING:
- unpatch_multiple_glitch(self.file, "windows", self.multiple_glitch[1])
- self.reset_info()
- if __name__ == "__main__":
- patcher = Patcher()
- patcher.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement