import Utils from worlds.Files import APDeltaPatch from .Aesthetics import generate_shuffled_header_data, generate_shuffled_ow_palettes from .Levels import level_info_dict, full_bowser_rooms, standard_bowser_rooms, submap_boss_rooms, ow_boss_rooms from .Names.TextBox import generate_goal_text, title_text_mapping, generate_text_box USHASH = 'cdd3c8c37322978ca8669b34bc89c804' ROM_PLAYER_LIMIT = 65535 import hashlib import os import math ability_rom_data = { 0xBC0003: [[0x1F2C, 0x7]], # Run 0x80 0xBC0004: [[0x1F2C, 0x6]], # Carry 0x40 0xBC0005: [[0x1F2C, 0x2]], # Swim 0x04 0xBC0006: [[0x1F2C, 0x3]], # Spin Jump 0x08 0xBC0007: [[0x1F2C, 0x5]], # Climb 0x20 0xBC0008: [[0x1F2C, 0x1]], # Yoshi 0x02 0xBC0009: [[0x1F2C, 0x4]], # P-Switch 0x10 #0xBC000A: [[]] 0xBC000B: [[0x1F2D, 0x3]], # P-Balloon 0x08 0xBC000D: [[0x1F2D, 0x4]], # Super Star 0x10 } item_rom_data = { 0xBC0001: [0x18E4, 0x1], # 1-Up Mushroom 0xBC0002: [0x1F24, 0x1, 0x1F], # Yoshi Egg 0xBC0012: [0x1F26, 0x1, 0x09], # Boss Token 0xBC000E: [0x1F28, 0x1, 0x1C], # Yellow Switch Palace 0xBC000F: [0x1F27, 0x1, 0x1C], # Green Switch Palace 0xBC0010: [0x1F2A, 0x1, 0x1C], # Red Switch Palace 0xBC0011: [0x1F29, 0x1, 0x1C], # Blue Switch Palace } trap_rom_data = { 0xBC0013: [0x0086, 0x1, 0x0E], # Ice Trap 0xBC0014: [0x18BD, 0x7F, 0x18], # Stun Trap 0xBC0016: [0x0F31, 0x1], # Timer Trap } class SMWDeltaPatch(APDeltaPatch): hash = USHASH game = "Super Mario World" patch_file_ending = ".apsmw" @classmethod def get_source_data(cls) -> bytes: return get_base_rom_bytes() class LocalRom: def __init__(self, file, patch=True, vanillaRom=None, name=None, hash=None): self.name = name self.hash = hash self.orig_buffer = None with open(file, 'rb') as stream: self.buffer = Utils.read_snes_rom(stream) def read_bit(self, address: int, bit_number: int) -> bool: bitflag = (1 << bit_number) return ((self.buffer[address] & bitflag) != 0) def read_byte(self, address: int) -> int: return self.buffer[address] def read_bytes(self, startaddress: int, length: int) -> bytes: return self.buffer[startaddress:startaddress + length] def write_byte(self, address: int, value: int): self.buffer[address] = value def write_bytes(self, startaddress: int, values): self.buffer[startaddress:startaddress + len(values)] = values def write_to_file(self, file): with open(file, 'wb') as outfile: outfile.write(self.buffer) def read_from_file(self, file): with open(file, 'rb') as stream: self.buffer = bytearray(stream.read()) def handle_ability_code(rom): # Lock Abilities #rom.write_byte(0xC581, 0x01) # No Stars #rom.write_byte(0x62E6, 0x01) # No Star Music #rom.write_byte(0xC300, 0x01) # No P-Balloons #rom.write_byte(0xC305, 0x01) # No P-Balloons # Run rom.write_bytes(0x5977, bytearray([0x22, 0x10, 0xBA, 0x03])) # JSL $03BA10 rom.write_bytes(0x597B, bytearray([0xEA] * 0x04)) RUN_SUB_ADDR = 0x01BA10 rom.write_bytes(RUN_SUB_ADDR + 0x00, bytearray([0xDA])) # PHX rom.write_bytes(RUN_SUB_ADDR + 0x01, bytearray([0x08])) # PHP rom.write_bytes(RUN_SUB_ADDR + 0x02, bytearray([0x90, 0x03])) # BCC +0x03 rom.write_bytes(RUN_SUB_ADDR + 0x04, bytearray([0xC8])) # INY rom.write_bytes(RUN_SUB_ADDR + 0x05, bytearray([0xA9, 0x70])) # LDA #70 rom.write_bytes(RUN_SUB_ADDR + 0x07, bytearray([0xAA])) # TAX rom.write_bytes(RUN_SUB_ADDR + 0x08, bytearray([0xAD, 0x2C, 0x1F])) # LDA $1F2C rom.write_bytes(RUN_SUB_ADDR + 0x0B, bytearray([0x89, 0x80])) # BIT #80 rom.write_bytes(RUN_SUB_ADDR + 0x0D, bytearray([0xF0, 0x04])) # BEQ +0x04 rom.write_bytes(RUN_SUB_ADDR + 0x0F, bytearray([0x8A])) # TXA rom.write_bytes(RUN_SUB_ADDR + 0x10, bytearray([0x8D, 0xE4, 0x13])) # STA $13E4 rom.write_bytes(RUN_SUB_ADDR + 0x13, bytearray([0x8A])) # TXA rom.write_bytes(RUN_SUB_ADDR + 0x14, bytearray([0x28])) # PLP rom.write_bytes(RUN_SUB_ADDR + 0x15, bytearray([0xFA])) # PLX rom.write_bytes(RUN_SUB_ADDR + 0x16, bytearray([0x6B])) # RTL # End Run # Purple Block Carry rom.write_bytes(0x726F, bytearray([0x22, 0x28, 0xBA, 0x03])) # JSL $03BA28 rom.write_bytes(0x7273, bytearray([0xEA] * 0x02)) PURPLE_BLOCK_CARRY_SUB_ADDR = 0x01BA28 rom.write_bytes(PURPLE_BLOCK_CARRY_SUB_ADDR + 0x00, bytearray([0x08])) # PHP rom.write_bytes(PURPLE_BLOCK_CARRY_SUB_ADDR + 0x01, bytearray([0xAD, 0x2C, 0x1F])) # LDA $1F2C rom.write_bytes(PURPLE_BLOCK_CARRY_SUB_ADDR + 0x04, bytearray([0x89, 0x40])) # BIT #40 rom.write_bytes(PURPLE_BLOCK_CARRY_SUB_ADDR + 0x06, bytearray([0xF0, 0x09])) # BEQ +0x09 rom.write_bytes(PURPLE_BLOCK_CARRY_SUB_ADDR + 0x08, bytearray([0x28])) # PLP rom.write_bytes(PURPLE_BLOCK_CARRY_SUB_ADDR + 0x09, bytearray([0xAD, 0x8F, 0x14])) # LDA $148F rom.write_bytes(PURPLE_BLOCK_CARRY_SUB_ADDR + 0x0C, bytearray([0x0D, 0x7A, 0x18])) # ORA $187A rom.write_bytes(PURPLE_BLOCK_CARRY_SUB_ADDR + 0x0F, bytearray([0x80, 0x03])) # BRA +0x03 rom.write_bytes(PURPLE_BLOCK_CARRY_SUB_ADDR + 0x11, bytearray([0x28])) # PLP rom.write_bytes(PURPLE_BLOCK_CARRY_SUB_ADDR + 0x12, bytearray([0xA9, 0x01])) # LDA #01 rom.write_bytes(PURPLE_BLOCK_CARRY_SUB_ADDR + 0x14, bytearray([0x6B])) # RTL # End Purple Block Carry # Springboard Carry rom.write_bytes(0xE6DA, bytearray([0x22, 0x40, 0xBA, 0x03])) # JSL $03BA40 rom.write_bytes(0xE6DE, bytearray([0xEA] * 0x04)) SPRINGBOARD_CARRY_SUB_ADDR = 0x01BA40 rom.write_bytes(SPRINGBOARD_CARRY_SUB_ADDR + 0x00, bytearray([0x48])) # PHA rom.write_bytes(SPRINGBOARD_CARRY_SUB_ADDR + 0x01, bytearray([0x08])) # PHP rom.write_bytes(SPRINGBOARD_CARRY_SUB_ADDR + 0x02, bytearray([0xAD, 0x2C, 0x1F])) # LDA $1F2C rom.write_bytes(SPRINGBOARD_CARRY_SUB_ADDR + 0x05, bytearray([0x89, 0x40])) # BIT #40 rom.write_bytes(SPRINGBOARD_CARRY_SUB_ADDR + 0x07, bytearray([0xF0, 0x08])) # BEQ +0x08 rom.write_bytes(SPRINGBOARD_CARRY_SUB_ADDR + 0x09, bytearray([0xA9, 0x0B])) # LDA #0B rom.write_bytes(SPRINGBOARD_CARRY_SUB_ADDR + 0x0B, bytearray([0x9D, 0xC8, 0x14])) # STA $14C8, X rom.write_bytes(SPRINGBOARD_CARRY_SUB_ADDR + 0x0E, bytearray([0x9E, 0x02, 0x16])) # STZ $1602, X rom.write_bytes(SPRINGBOARD_CARRY_SUB_ADDR + 0x11, bytearray([0x28])) # PLP rom.write_bytes(SPRINGBOARD_CARRY_SUB_ADDR + 0x12, bytearray([0x68])) # PLA rom.write_bytes(SPRINGBOARD_CARRY_SUB_ADDR + 0x13, bytearray([0x6B])) # RTL # End Springboard Carry # Shell Carry rom.write_bytes(0xAA66, bytearray([0xAD, 0x2C, 0x1F])) # LDA $1F2C rom.write_bytes(0xAA69, bytearray([0x89, 0x40])) # BIT #40 rom.write_bytes(0xAA6B, bytearray([0xF0, 0x07])) # BEQ +0x07 rom.write_bytes(0xAA6D, bytearray([0x22, 0x60, 0xBA, 0x03])) # JSL $03BA60 rom.write_bytes(0xAA71, bytearray([0xEA] * 0x02)) SHELL_CARRY_SUB_ADDR = 0x01BA60 rom.write_bytes(SHELL_CARRY_SUB_ADDR + 0x00, bytearray([0x08])) # PHP rom.write_bytes(SHELL_CARRY_SUB_ADDR + 0x01, bytearray([0xA9, 0x0B])) # LDA #0B rom.write_bytes(SHELL_CARRY_SUB_ADDR + 0x03, bytearray([0x9D, 0xC8, 0x14])) # STA $14C8, X rom.write_bytes(SHELL_CARRY_SUB_ADDR + 0x06, bytearray([0xEE, 0x70, 0x14])) # INC $1470 rom.write_bytes(SHELL_CARRY_SUB_ADDR + 0x09, bytearray([0xA9, 0x0B])) # LDA #08 rom.write_bytes(SHELL_CARRY_SUB_ADDR + 0x0B, bytearray([0x8D, 0x98, 0x14])) # STA $1498 rom.write_bytes(SHELL_CARRY_SUB_ADDR + 0x0E, bytearray([0x28])) # PLP rom.write_bytes(SHELL_CARRY_SUB_ADDR + 0x0F, bytearray([0x6B])) # RTL # End Shell Carry # Yoshi Carry rom.write_bytes(0xF309, bytearray([0x22, 0x70, 0xBA, 0x03])) # JSL $03BA70 rom.write_bytes(0xF30D, bytearray([0xEA] * 0x06)) YOSHI_CARRY_SUB_ADDR = 0x01BA70 rom.write_bytes(YOSHI_CARRY_SUB_ADDR + 0x00, bytearray([0x08])) # PHP rom.write_bytes(YOSHI_CARRY_SUB_ADDR + 0x01, bytearray([0xAD, 0x2C, 0x1F])) # LDA $1F2C rom.write_bytes(YOSHI_CARRY_SUB_ADDR + 0x04, bytearray([0x89, 0x40])) # BIT #40 rom.write_bytes(YOSHI_CARRY_SUB_ADDR + 0x06, bytearray([0xF0, 0x0A])) # BEQ +0x0A rom.write_bytes(YOSHI_CARRY_SUB_ADDR + 0x08, bytearray([0xA9, 0x12])) # LDA #12 rom.write_bytes(YOSHI_CARRY_SUB_ADDR + 0x0A, bytearray([0x8D, 0xA3, 0x14])) # STA $14A3 rom.write_bytes(YOSHI_CARRY_SUB_ADDR + 0x0D, bytearray([0xA9, 0x21])) # LDA #21 rom.write_bytes(YOSHI_CARRY_SUB_ADDR + 0x0F, bytearray([0x8D, 0xFC, 0x1D])) # STA $1DFC rom.write_bytes(YOSHI_CARRY_SUB_ADDR + 0x12, bytearray([0x28])) # PLP rom.write_bytes(YOSHI_CARRY_SUB_ADDR + 0x13, bytearray([0x6B])) # RTL # End Yoshi Carry # Climb rom.write_bytes(0x4D72, bytearray([0x5C, 0x88, 0xBA, 0x03])) # JML $03BA88 rom.write_bytes(0x4D76, bytearray([0xEA] * 0x03)) CLIMB_SUB_ADDR = 0x01BA88 rom.write_bytes(CLIMB_SUB_ADDR + 0x00, bytearray([0x08])) # PHP rom.write_bytes(CLIMB_SUB_ADDR + 0x01, bytearray([0xAD, 0x2C, 0x1F])) # LDA $1F2C rom.write_bytes(CLIMB_SUB_ADDR + 0x04, bytearray([0x89, 0x20])) # BIT #20 rom.write_bytes(CLIMB_SUB_ADDR + 0x06, bytearray([0xF0, 0x09])) # BEQ +0x09 rom.write_bytes(CLIMB_SUB_ADDR + 0x08, bytearray([0xA5, 0x8B])) # LDA $8B rom.write_bytes(CLIMB_SUB_ADDR + 0x0A, bytearray([0x85, 0x74])) # STA $74 rom.write_bytes(CLIMB_SUB_ADDR + 0x0C, bytearray([0x28])) # PLP rom.write_bytes(CLIMB_SUB_ADDR + 0x0D, bytearray([0x5C, 0x17, 0xDB, 0x00])) # JML $00DB17 rom.write_bytes(CLIMB_SUB_ADDR + 0x11, bytearray([0x28])) # PLP rom.write_bytes(CLIMB_SUB_ADDR + 0x12, bytearray([0x5C, 0x76, 0xCD, 0x00])) # JML $00CD76 # End Climb # Climb Rope rom.write_bytes(0xDA33, bytearray([0x22, 0x70, 0xBC, 0x03])) # JSL $03BC70 CLIMB_ROPE_SUB_ADDR = 0x01BC70 rom.write_bytes(CLIMB_ROPE_SUB_ADDR + 0x00, bytearray([0x08])) # PHP rom.write_bytes(CLIMB_ROPE_SUB_ADDR + 0x01, bytearray([0xAD, 0x2C, 0x1F])) # LDA $1F2C rom.write_bytes(CLIMB_ROPE_SUB_ADDR + 0x04, bytearray([0x89, 0x20])) # BIT #20 rom.write_bytes(CLIMB_ROPE_SUB_ADDR + 0x06, bytearray([0xF0, 0x07])) # BEQ +0x07 rom.write_bytes(CLIMB_ROPE_SUB_ADDR + 0x08, bytearray([0x28])) # PLP rom.write_bytes(CLIMB_ROPE_SUB_ADDR + 0x09, bytearray([0xA9, 0xB0])) # LDA #B0 rom.write_bytes(CLIMB_ROPE_SUB_ADDR + 0x0B, bytearray([0x85, 0x7D])) # STA $7D rom.write_bytes(CLIMB_ROPE_SUB_ADDR + 0x0D, bytearray([0x80, 0x01])) # BRA +0x01 rom.write_bytes(CLIMB_ROPE_SUB_ADDR + 0x0F, bytearray([0x28])) # PLP rom.write_bytes(CLIMB_ROPE_SUB_ADDR + 0x10, bytearray([0x6B])) # RTL # End Climb Rope # P-Switch rom.write_bytes(0xAB1A, bytearray([0x22, 0xA0, 0xBA, 0x03])) # JSL $03BAA0 rom.write_bytes(0xAB1E, bytearray([0xEA] * 0x01)) P_SWITCH_SUB_ADDR = 0x01BAA0 rom.write_bytes(P_SWITCH_SUB_ADDR + 0x00, bytearray([0x08])) # PHP rom.write_bytes(P_SWITCH_SUB_ADDR + 0x01, bytearray([0xAD, 0x2C, 0x1F])) # LDA $1F2C rom.write_bytes(P_SWITCH_SUB_ADDR + 0x04, bytearray([0x89, 0x10])) # BIT #10 rom.write_bytes(P_SWITCH_SUB_ADDR + 0x06, bytearray([0xF0, 0x04])) # BEQ +0x04 rom.write_bytes(P_SWITCH_SUB_ADDR + 0x08, bytearray([0xA9, 0xB0])) # LDA #B0 rom.write_bytes(P_SWITCH_SUB_ADDR + 0x0A, bytearray([0x80, 0x02])) # BRA +0x02 rom.write_bytes(P_SWITCH_SUB_ADDR + 0x0C, bytearray([0xA9, 0x01])) # LDA #01 rom.write_bytes(P_SWITCH_SUB_ADDR + 0x0E, bytearray([0x99, 0xAD, 0x14])) # STA $14AD rom.write_bytes(P_SWITCH_SUB_ADDR + 0x11, bytearray([0x28])) # PLP rom.write_bytes(P_SWITCH_SUB_ADDR + 0x12, bytearray([0x6B])) # RTL # End P-Switch # Spin Jump rom.write_bytes(0x5645, bytearray([0xAD, 0x2C, 0x1F])) # LDA $1F2C rom.write_bytes(0x5648, bytearray([0x89, 0x08])) # BIT #08 rom.write_bytes(0x564A, bytearray([0xF0, 0x12])) # BEQ +0x12 rom.write_bytes(0x564C, bytearray([0x22, 0xB8, 0xBA, 0x03])) # JSL $03BAB8 SPIN_JUMP_SUB_ADDR = 0x01BAB8 rom.write_bytes(SPIN_JUMP_SUB_ADDR + 0x00, bytearray([0x08])) # PHP rom.write_bytes(SPIN_JUMP_SUB_ADDR + 0x01, bytearray([0x1A])) # INC rom.write_bytes(SPIN_JUMP_SUB_ADDR + 0x02, bytearray([0x8D, 0x0D, 0x14])) # STA $140D rom.write_bytes(SPIN_JUMP_SUB_ADDR + 0x05, bytearray([0xA9, 0x04])) # LDA #04 rom.write_bytes(SPIN_JUMP_SUB_ADDR + 0x07, bytearray([0x8D, 0xFC, 0x1D])) # STA $1DFC rom.write_bytes(SPIN_JUMP_SUB_ADDR + 0x0A, bytearray([0xA4, 0x76])) # LDY #76 rom.write_bytes(SPIN_JUMP_SUB_ADDR + 0x0C, bytearray([0x28])) # PLP rom.write_bytes(SPIN_JUMP_SUB_ADDR + 0x0D, bytearray([0x6B])) # RTL # End Spin Jump # Spin Jump from Water rom.write_bytes(0x6A89, bytearray([0x22, 0xF8, 0xBB, 0x03])) # JSL $03BBF8 rom.write_bytes(0x6A8D, bytearray([0xEA] * 0x05)) SPIN_JUMP_WATER_SUB_ADDR = 0x01BBF8 rom.write_bytes(SPIN_JUMP_WATER_SUB_ADDR + 0x00, bytearray([0x08])) # PHP rom.write_bytes(SPIN_JUMP_WATER_SUB_ADDR + 0x01, bytearray([0xAD, 0x2C, 0x1F])) # LDA $1F2C rom.write_bytes(SPIN_JUMP_WATER_SUB_ADDR + 0x04, bytearray([0x89, 0x08])) # BIT #08 rom.write_bytes(SPIN_JUMP_WATER_SUB_ADDR + 0x06, bytearray([0xF0, 0x09])) # BEQ +0x09 rom.write_bytes(SPIN_JUMP_WATER_SUB_ADDR + 0x08, bytearray([0x1A])) # INC rom.write_bytes(SPIN_JUMP_WATER_SUB_ADDR + 0x09, bytearray([0x8D, 0x0D, 0x14])) # STA $140D rom.write_bytes(SPIN_JUMP_WATER_SUB_ADDR + 0x0C, bytearray([0xA9, 0x04])) # LDA #04 rom.write_bytes(SPIN_JUMP_WATER_SUB_ADDR + 0x0E, bytearray([0x8D, 0xFC, 0x1D])) # STA $1DFC rom.write_bytes(SPIN_JUMP_WATER_SUB_ADDR + 0x11, bytearray([0x28])) # PLP rom.write_bytes(SPIN_JUMP_WATER_SUB_ADDR + 0x12, bytearray([0x6B])) # RTL # End Spin Jump from Water # Spin Jump from Springboard rom.write_bytes(0xE693, bytearray([0x22, 0x0C, 0xBC, 0x03])) # JSL $03BC0C rom.write_bytes(0xE697, bytearray([0xEA] * 0x01)) SPIN_JUMP_SPRING_SUB_ADDR = 0x01BC0C rom.write_bytes(SPIN_JUMP_SPRING_SUB_ADDR + 0x00, bytearray([0x08])) # PHP rom.write_bytes(SPIN_JUMP_SPRING_SUB_ADDR + 0x01, bytearray([0xAD, 0x2C, 0x1F])) # LDA $1F2C rom.write_bytes(SPIN_JUMP_SPRING_SUB_ADDR + 0x04, bytearray([0x89, 0x08])) # BIT #08 rom.write_bytes(SPIN_JUMP_SPRING_SUB_ADDR + 0x06, bytearray([0xF0, 0x05])) # BEQ +0x05 rom.write_bytes(SPIN_JUMP_SPRING_SUB_ADDR + 0x08, bytearray([0xA9, 0x01])) # LDA #01 rom.write_bytes(SPIN_JUMP_SPRING_SUB_ADDR + 0x0A, bytearray([0x8D, 0x0D, 0x14])) # STA $140D rom.write_bytes(SPIN_JUMP_SPRING_SUB_ADDR + 0x0D, bytearray([0x28])) # PLP rom.write_bytes(SPIN_JUMP_SPRING_SUB_ADDR + 0x0E, bytearray([0x6B])) # RTL # End Spin Jump from Springboard # Swim rom.write_bytes(0x5A25, bytearray([0x22, 0xC8, 0xBA, 0x03])) # JSL $03BAC8 rom.write_bytes(0x5A29, bytearray([0xEA] * 0x04)) SWIM_SUB_ADDR = 0x01BAC8 rom.write_bytes(SWIM_SUB_ADDR + 0x00, bytearray([0x48])) # PHA rom.write_bytes(SWIM_SUB_ADDR + 0x01, bytearray([0x08])) # PHP rom.write_bytes(SWIM_SUB_ADDR + 0x02, bytearray([0xAD, 0x2C, 0x1F])) # LDA $1F2C rom.write_bytes(SWIM_SUB_ADDR + 0x05, bytearray([0x89, 0x04])) # BIT #04 rom.write_bytes(SWIM_SUB_ADDR + 0x07, bytearray([0xF0, 0x0C])) # BEQ +0x0C rom.write_bytes(SWIM_SUB_ADDR + 0x09, bytearray([0x28])) # PLP rom.write_bytes(SWIM_SUB_ADDR + 0x0A, bytearray([0x68])) # PLA rom.write_bytes(SWIM_SUB_ADDR + 0x0B, bytearray([0xDD, 0x84, 0xD9])) # CMP $D489, X rom.write_bytes(SWIM_SUB_ADDR + 0x0E, bytearray([0xB0, 0x03])) # BCS +0x03 rom.write_bytes(SWIM_SUB_ADDR + 0x10, bytearray([0xBD, 0x84, 0xD9])) # LDA $D489, X rom.write_bytes(SWIM_SUB_ADDR + 0x13, bytearray([0x80, 0x0A])) # BRA +0x0A rom.write_bytes(SWIM_SUB_ADDR + 0x15, bytearray([0x28])) # PLP rom.write_bytes(SWIM_SUB_ADDR + 0x16, bytearray([0x68])) # PLA rom.write_bytes(SWIM_SUB_ADDR + 0x17, bytearray([0xDD, 0xBE, 0xDE])) # CMP $DEBE, X rom.write_bytes(SWIM_SUB_ADDR + 0x1A, bytearray([0xB0, 0x03])) # BCS +0x03 rom.write_bytes(SWIM_SUB_ADDR + 0x1C, bytearray([0xBD, 0xBE, 0xDE])) # LDA $DEBE, X rom.write_bytes(SWIM_SUB_ADDR + 0x1F, bytearray([0x6B])) # RTL # End Swim # Item Swim rom.write_bytes(0x59D7, bytearray([0x22, 0xE8, 0xBA, 0x03])) # JSL $03BAE8 rom.write_bytes(0x59DB, bytearray([0xEA] * 0x02)) SWIM_SUB_ADDR = 0x01BAE8 rom.write_bytes(SWIM_SUB_ADDR + 0x00, bytearray([0x48])) # PHA rom.write_bytes(SWIM_SUB_ADDR + 0x01, bytearray([0x08])) # PHP rom.write_bytes(SWIM_SUB_ADDR + 0x02, bytearray([0xAD, 0x2C, 0x1F])) # LDA $1F2C rom.write_bytes(SWIM_SUB_ADDR + 0x05, bytearray([0x89, 0x04])) # BIT #04 rom.write_bytes(SWIM_SUB_ADDR + 0x07, bytearray([0xF0, 0x0A])) # BEQ +0x0A rom.write_bytes(SWIM_SUB_ADDR + 0x09, bytearray([0x28])) # PLP rom.write_bytes(SWIM_SUB_ADDR + 0x0A, bytearray([0x68])) # PLA rom.write_bytes(SWIM_SUB_ADDR + 0x0B, bytearray([0xC9, 0xF0])) # CMP #F0 rom.write_bytes(SWIM_SUB_ADDR + 0x0D, bytearray([0xB0, 0x02])) # BCS +0x02 rom.write_bytes(SWIM_SUB_ADDR + 0x0F, bytearray([0xA9, 0xF0])) # LDA #F0 rom.write_bytes(SWIM_SUB_ADDR + 0x11, bytearray([0x80, 0x08])) # BRA +0x08 rom.write_bytes(SWIM_SUB_ADDR + 0x13, bytearray([0x28])) # PLP rom.write_bytes(SWIM_SUB_ADDR + 0x14, bytearray([0x68])) # PLA rom.write_bytes(SWIM_SUB_ADDR + 0x15, bytearray([0xC9, 0xFF])) # CMP #FF rom.write_bytes(SWIM_SUB_ADDR + 0x17, bytearray([0xB0, 0x02])) # BCS +0x02 rom.write_bytes(SWIM_SUB_ADDR + 0x19, bytearray([0xA9, 0x00])) # LDA #00 rom.write_bytes(SWIM_SUB_ADDR + 0x1B, bytearray([0x6B])) # RTL # End Item Swim # Yoshi rom.write_bytes(0x109FB, bytearray([0x22, 0x08, 0xBB, 0x03])) # JSL $03BB08 rom.write_bytes(0x109FF, bytearray([0xEA] * 0x02)) YOSHI_SUB_ADDR = 0x01BB08 rom.write_bytes(YOSHI_SUB_ADDR + 0x00, bytearray([0x08])) # PHP rom.write_bytes(YOSHI_SUB_ADDR + 0x01, bytearray([0xAD, 0x2C, 0x1F])) # LDA $1F2C rom.write_bytes(YOSHI_SUB_ADDR + 0x04, bytearray([0x89, 0x02])) # BIT #02 rom.write_bytes(YOSHI_SUB_ADDR + 0x06, bytearray([0xF0, 0x06])) # BEQ +0x06 rom.write_bytes(YOSHI_SUB_ADDR + 0x08, bytearray([0x28])) # PLP rom.write_bytes(YOSHI_SUB_ADDR + 0x09, bytearray([0xB9, 0xA1, 0x88])) # LDA $88A1, Y rom.write_bytes(YOSHI_SUB_ADDR + 0x0C, bytearray([0x80, 0x04])) # BRA +0x04 rom.write_bytes(YOSHI_SUB_ADDR + 0x0E, bytearray([0x28])) # PLP rom.write_bytes(YOSHI_SUB_ADDR + 0x0F, bytearray([0xB9, 0xA2, 0x88])) # LDA $88A2, Y rom.write_bytes(YOSHI_SUB_ADDR + 0x12, bytearray([0x9D, 0x1C, 0x15])) # STA $151C, X rom.write_bytes(YOSHI_SUB_ADDR + 0x15, bytearray([0x6B])) # RTL # End Yoshi # Baby Yoshi rom.write_bytes(0xA2B8, bytearray([0x22, 0x20, 0xBB, 0x03])) # JSL $03BB20 rom.write_bytes(0xA2BC, bytearray([0xEA] * 0x01)) rom.write_bytes(0x1C05F, bytearray([0x22, 0x20, 0xBB, 0x03])) # JSL $03BB20 rom.write_bytes(0x1C063, bytearray([0xEA] * 0x01)) YOSHI_SUB_ADDR = 0x01BB20 rom.write_bytes(YOSHI_SUB_ADDR + 0x00, bytearray([0x08])) # PHP rom.write_bytes(YOSHI_SUB_ADDR + 0x01, bytearray([0x9C, 0x1E, 0x14])) # STZ $141E rom.write_bytes(YOSHI_SUB_ADDR + 0x04, bytearray([0xAD, 0x2C, 0x1F])) # LDA $1F2C rom.write_bytes(YOSHI_SUB_ADDR + 0x07, bytearray([0x89, 0x02])) # BIT #02 rom.write_bytes(YOSHI_SUB_ADDR + 0x09, bytearray([0xF0, 0x05])) # BEQ +0x05 rom.write_bytes(YOSHI_SUB_ADDR + 0x0B, bytearray([0x28])) # PLP rom.write_bytes(YOSHI_SUB_ADDR + 0x0C, bytearray([0xA9, 0x35])) # LDA #35 rom.write_bytes(YOSHI_SUB_ADDR + 0x0E, bytearray([0x80, 0x03])) # BRA +0x03 rom.write_bytes(YOSHI_SUB_ADDR + 0x10, bytearray([0x28])) # PLP rom.write_bytes(YOSHI_SUB_ADDR + 0x11, bytearray([0xA9, 0x70])) # LDA #70 rom.write_bytes(YOSHI_SUB_ADDR + 0x13, bytearray([0x6B])) # RTL # End Baby Yoshi # Midway Gate rom.write_bytes(0x72E4, bytearray([0x22, 0x38, 0xBB, 0x03])) # JSL $03BB38 MIDWAY_GATE_SUB_ADDR = 0x01BB38 rom.write_bytes(MIDWAY_GATE_SUB_ADDR + 0x00, bytearray([0x08])) # PHP rom.write_bytes(MIDWAY_GATE_SUB_ADDR + 0x01, bytearray([0xAD, 0x2D, 0x1F])) # LDA $1F2D rom.write_bytes(MIDWAY_GATE_SUB_ADDR + 0x04, bytearray([0x89, 0x01])) # BIT #01 rom.write_bytes(MIDWAY_GATE_SUB_ADDR + 0x06, bytearray([0xF0, 0x07])) # BEQ +0x07 rom.write_bytes(MIDWAY_GATE_SUB_ADDR + 0x08, bytearray([0x28])) # PLP rom.write_bytes(MIDWAY_GATE_SUB_ADDR + 0x09, bytearray([0xA9, 0x01])) # LDA #01 rom.write_bytes(MIDWAY_GATE_SUB_ADDR + 0x0B, bytearray([0x85, 0x19])) # STA $19 rom.write_bytes(MIDWAY_GATE_SUB_ADDR + 0x0D, bytearray([0x80, 0x01])) # BRA +0x01 rom.write_bytes(MIDWAY_GATE_SUB_ADDR + 0x0F, bytearray([0x28])) # PLP rom.write_bytes(MIDWAY_GATE_SUB_ADDR + 0x10, bytearray([0x6B])) # RTL # End Midway Gate # Mushroom rom.write_bytes(0x5156, bytearray([0x22, 0x50, 0xBB, 0x03])) # JSL $03BB50 rom.write_bytes(0x515A, bytearray([0xEA] * 0x04)) MUSHROOM_SUB_ADDR = 0x01BB50 rom.write_bytes(MUSHROOM_SUB_ADDR + 0x00, bytearray([0x08])) # PHP rom.write_bytes(MUSHROOM_SUB_ADDR + 0x01, bytearray([0xAD, 0x2D, 0x1F])) # LDA $1F2D rom.write_bytes(MUSHROOM_SUB_ADDR + 0x04, bytearray([0x89, 0x01])) # BIT #01 rom.write_bytes(MUSHROOM_SUB_ADDR + 0x06, bytearray([0xF0, 0x05])) # BEQ +0x05 rom.write_bytes(MUSHROOM_SUB_ADDR + 0x08, bytearray([0x28])) # PLP rom.write_bytes(MUSHROOM_SUB_ADDR + 0x09, bytearray([0xE6, 0x19])) # INC $19 rom.write_bytes(MUSHROOM_SUB_ADDR + 0x0B, bytearray([0x80, 0x01])) # BRA +0x01 rom.write_bytes(MUSHROOM_SUB_ADDR + 0x0D, bytearray([0x28])) # PLP rom.write_bytes(MUSHROOM_SUB_ADDR + 0x0E, bytearray([0xA9, 0x00])) # LDA #00 rom.write_bytes(MUSHROOM_SUB_ADDR + 0x10, bytearray([0x85, 0x71])) # STA $72 rom.write_bytes(MUSHROOM_SUB_ADDR + 0x12, bytearray([0x64, 0x9D])) # STZ $9D rom.write_bytes(MUSHROOM_SUB_ADDR + 0x14, bytearray([0x6B])) # RTL # End Mushroom # Take Damage rom.write_bytes(0x5142, bytearray([0x22, 0x65, 0xBB, 0x03])) # JSL $03BB65 rom.write_bytes(0x5146, bytearray([0x60] * 0x01)) # RTS DAMAGE_SUB_ADDR = 0x01BB65 rom.write_bytes(DAMAGE_SUB_ADDR + 0x00, bytearray([0x8D, 0x97, 0x14])) # STA $1497 rom.write_bytes(DAMAGE_SUB_ADDR + 0x03, bytearray([0x80, 0xF4])) # BRA -0x0C # End Take Damage # Fire Flower Cycle rom.write_bytes(0x5187, bytearray([0x22, 0x6A, 0xBB, 0x03])) # JSL $03BB6A rom.write_bytes(0x518B, bytearray([0x60] * 0x01)) # RTS PALETTE_CYCLE_SUB_ADDR = 0x01BB6A rom.write_bytes(PALETTE_CYCLE_SUB_ADDR + 0x00, bytearray([0xCE, 0x9B, 0x14])) # DEC $149B rom.write_bytes(PALETTE_CYCLE_SUB_ADDR + 0x03, bytearray([0xF0, 0xEF])) # BEQ -0x11 rom.write_bytes(PALETTE_CYCLE_SUB_ADDR + 0x05, bytearray([0x6B])) # RTL # End Fire Flower Cycle # Pipe Exit rom.write_bytes(0x526D, bytearray([0x22, 0x70, 0xBB, 0x03])) # JSL $03BB70 rom.write_bytes(0x5271, bytearray([0x60, 0xEA] * 0x01)) # RTS, NOP PIPE_EXIT_SUB_ADDR = 0x01BB70 rom.write_bytes(PIPE_EXIT_SUB_ADDR + 0x00, bytearray([0x9C, 0x19, 0x14])) # STZ $1419 rom.write_bytes(PIPE_EXIT_SUB_ADDR + 0x03, bytearray([0xA9, 0x00])) # LDA #00 rom.write_bytes(PIPE_EXIT_SUB_ADDR + 0x05, bytearray([0x85, 0x71])) # STA $72 rom.write_bytes(PIPE_EXIT_SUB_ADDR + 0x07, bytearray([0x64, 0x9D])) # STZ $9D rom.write_bytes(PIPE_EXIT_SUB_ADDR + 0x09, bytearray([0x6B])) # RTL # End Pipe Exit # Cape Transform rom.write_bytes(0x5168, bytearray([0x22, 0x7A, 0xBB, 0x03])) # JSL $03BB7A rom.write_bytes(0x516C, bytearray([0xEA] * 0x01)) # RTS, NOP rom.write_bytes(0x516D, bytearray([0xF0, 0xD1])) # BEQ -0x2F CAPE_TRANSFORM_SUB_ADDR = 0x01BB7A rom.write_bytes(CAPE_TRANSFORM_SUB_ADDR + 0x00, bytearray([0xA5, 0x19])) # LDA $19 rom.write_bytes(CAPE_TRANSFORM_SUB_ADDR + 0x02, bytearray([0x4A])) # LSR rom.write_bytes(CAPE_TRANSFORM_SUB_ADDR + 0x03, bytearray([0xD0, 0xDF])) # BNE -0x21 rom.write_bytes(CAPE_TRANSFORM_SUB_ADDR + 0x05, bytearray([0x6B])) # RTL # End Cape Transform # Fire Flower rom.write_bytes(0xC5F7, bytearray([0x22, 0x80, 0xBB, 0x03])) # JSL $03BB80 FIRE_FLOWER_SUB_ADDR = 0x01BB80 rom.write_bytes(FIRE_FLOWER_SUB_ADDR + 0x00, bytearray([0x08])) # PHP rom.write_bytes(FIRE_FLOWER_SUB_ADDR + 0x01, bytearray([0xAD, 0x2D, 0x1F])) # LDA $1F2D rom.write_bytes(FIRE_FLOWER_SUB_ADDR + 0x04, bytearray([0x89, 0x02])) # BIT #02 rom.write_bytes(FIRE_FLOWER_SUB_ADDR + 0x06, bytearray([0xF0, 0x07])) # BEQ +0x07 rom.write_bytes(FIRE_FLOWER_SUB_ADDR + 0x08, bytearray([0x28])) # PLP rom.write_bytes(FIRE_FLOWER_SUB_ADDR + 0x09, bytearray([0xA9, 0x03])) # LDA #03 rom.write_bytes(FIRE_FLOWER_SUB_ADDR + 0x0B, bytearray([0x85, 0x19])) # STA $19 rom.write_bytes(FIRE_FLOWER_SUB_ADDR + 0x0D, bytearray([0x80, 0x01])) # BRA +0x01 rom.write_bytes(FIRE_FLOWER_SUB_ADDR + 0x0F, bytearray([0x28])) # PLP rom.write_bytes(FIRE_FLOWER_SUB_ADDR + 0x10, bytearray([0x6B])) # RTL # End Fire Flower # Cape rom.write_bytes(0xC598, bytearray([0x22, 0x91, 0xBB, 0x03])) # JSL $03BB91 CAPE_SUB_ADDR = 0x01BB91 rom.write_bytes(CAPE_SUB_ADDR + 0x00, bytearray([0x08])) # PHP rom.write_bytes(CAPE_SUB_ADDR + 0x01, bytearray([0xAD, 0x2D, 0x1F])) # LDA $1F2D rom.write_bytes(CAPE_SUB_ADDR + 0x04, bytearray([0x89, 0x04])) # BIT #04 rom.write_bytes(CAPE_SUB_ADDR + 0x06, bytearray([0xF0, 0x07])) # BEQ +0x07 rom.write_bytes(CAPE_SUB_ADDR + 0x08, bytearray([0x28])) # PLP rom.write_bytes(CAPE_SUB_ADDR + 0x09, bytearray([0xA9, 0x02])) # LDA #02 rom.write_bytes(CAPE_SUB_ADDR + 0x0B, bytearray([0x85, 0x19])) # STA $19 rom.write_bytes(CAPE_SUB_ADDR + 0x0D, bytearray([0x80, 0x01])) # BRA +0x01 rom.write_bytes(CAPE_SUB_ADDR + 0x0F, bytearray([0x28])) # PLP rom.write_bytes(CAPE_SUB_ADDR + 0x10, bytearray([0x6B])) # RTL # End Cape # P-Balloon rom.write_bytes(0xC2FF, bytearray([0x22, 0xA2, 0xBB, 0x03])) # JSL $03BBA2 rom.write_bytes(0xC303, bytearray([0xEA] * 0x06)) P_BALLOON_SUB_ADDR = 0x01BBA2 rom.write_bytes(P_BALLOON_SUB_ADDR + 0x00, bytearray([0x08])) # PHP rom.write_bytes(P_BALLOON_SUB_ADDR + 0x01, bytearray([0xAD, 0x2D, 0x1F])) # LDA $1F2D rom.write_bytes(P_BALLOON_SUB_ADDR + 0x04, bytearray([0x89, 0x08])) # BIT #08 rom.write_bytes(P_BALLOON_SUB_ADDR + 0x06, bytearray([0xF0, 0x0D])) # BEQ +0x0D rom.write_bytes(P_BALLOON_SUB_ADDR + 0x08, bytearray([0x28])) # PLP rom.write_bytes(P_BALLOON_SUB_ADDR + 0x09, bytearray([0xA9, 0x09])) # LDA #09 rom.write_bytes(P_BALLOON_SUB_ADDR + 0x0B, bytearray([0x8D, 0xF3, 0x13])) # STA $13F3 rom.write_bytes(P_BALLOON_SUB_ADDR + 0x0E, bytearray([0xA9, 0xFF])) # LDA #FF rom.write_bytes(P_BALLOON_SUB_ADDR + 0x10, bytearray([0x8D, 0x91, 0x18])) # STA $1891 rom.write_bytes(P_BALLOON_SUB_ADDR + 0x13, bytearray([0x80, 0x0B])) # BRA +0x0B rom.write_bytes(P_BALLOON_SUB_ADDR + 0x15, bytearray([0x28])) # PLP rom.write_bytes(P_BALLOON_SUB_ADDR + 0x16, bytearray([0xA9, 0x01])) # LDA #01 rom.write_bytes(P_BALLOON_SUB_ADDR + 0x18, bytearray([0x8D, 0xF3, 0x13])) # STA $13F3 rom.write_bytes(P_BALLOON_SUB_ADDR + 0x1B, bytearray([0xA9, 0x01])) # LDA #01 rom.write_bytes(P_BALLOON_SUB_ADDR + 0x1D, bytearray([0x8D, 0x91, 0x18])) # STA $1891 rom.write_bytes(P_BALLOON_SUB_ADDR + 0x20, bytearray([0x6B])) # RTL # End P-Balloon # Star rom.write_bytes(0xC580, bytearray([0x22, 0xC8, 0xBB, 0x03])) # JSL $03BBC8 rom.write_bytes(0xC584, bytearray([0xEA] * 0x01)) STAR_SUB_ADDR = 0x01BBC8 rom.write_bytes(STAR_SUB_ADDR + 0x00, bytearray([0x08])) # PHP rom.write_bytes(STAR_SUB_ADDR + 0x01, bytearray([0xAD, 0x2D, 0x1F])) # LDA $1F2D rom.write_bytes(STAR_SUB_ADDR + 0x04, bytearray([0x89, 0x10])) # BIT #10 rom.write_bytes(STAR_SUB_ADDR + 0x06, bytearray([0xF0, 0x08])) # BEQ +0x08 rom.write_bytes(STAR_SUB_ADDR + 0x08, bytearray([0x28])) # PLP rom.write_bytes(STAR_SUB_ADDR + 0x09, bytearray([0xA9, 0xFF])) # LDA #FF rom.write_bytes(STAR_SUB_ADDR + 0x0B, bytearray([0x8D, 0x90, 0x14])) # STA $1490 rom.write_bytes(STAR_SUB_ADDR + 0x0E, bytearray([0x80, 0x06])) # BRA +0x06 rom.write_bytes(STAR_SUB_ADDR + 0x10, bytearray([0x28])) # PLP rom.write_bytes(STAR_SUB_ADDR + 0x11, bytearray([0xA9, 0x01])) # LDA #01 rom.write_bytes(STAR_SUB_ADDR + 0x13, bytearray([0x8D, 0x90, 0x14])) # STA $1490 rom.write_bytes(STAR_SUB_ADDR + 0x16, bytearray([0x6B])) # RTL # End Star # Star Timer rom.write_bytes(0x62E3, bytearray([0x22, 0xE0, 0xBB, 0x03])) # JSL $03BBE0 STAR_TIMER_SUB_ADDR = 0x01BBE0 rom.write_bytes(STAR_TIMER_SUB_ADDR + 0x00, bytearray([0x08])) # PHP rom.write_bytes(STAR_TIMER_SUB_ADDR + 0x01, bytearray([0xAD, 0x2D, 0x1F])) # LDA $1F2D rom.write_bytes(STAR_TIMER_SUB_ADDR + 0x04, bytearray([0x89, 0x10])) # BIT #10 rom.write_bytes(STAR_TIMER_SUB_ADDR + 0x06, bytearray([0xF0, 0x07])) # BEQ +0x07 rom.write_bytes(STAR_TIMER_SUB_ADDR + 0x08, bytearray([0x28])) # PLP rom.write_bytes(STAR_TIMER_SUB_ADDR + 0x09, bytearray([0xA5, 0x13])) # LDA $13 rom.write_bytes(STAR_TIMER_SUB_ADDR + 0x0B, bytearray([0xC0, 0x1E])) # CPY #1E rom.write_bytes(STAR_TIMER_SUB_ADDR + 0x0D, bytearray([0x80, 0x05])) # BRA +0x05 rom.write_bytes(STAR_TIMER_SUB_ADDR + 0x0F, bytearray([0x28])) # PLP rom.write_bytes(STAR_TIMER_SUB_ADDR + 0x10, bytearray([0xA5, 0x13])) # LDA $13 rom.write_bytes(STAR_TIMER_SUB_ADDR + 0x12, bytearray([0xC0, 0x01])) # CPY #01 rom.write_bytes(STAR_TIMER_SUB_ADDR + 0x14, bytearray([0x6B])) # RTL # End Star Timer return def handle_yoshi_box(rom): rom.write_bytes(0xEC3D, bytearray([0xEA] * 0x03)) # NOP Lines that cause Yoshi Rescue Box normally rom.write_bytes(0x2B20F, bytearray([0x20, 0x60, 0xDC])) # JSR $05DC60 YOSHI_BOX_SUB_ADDR = 0x02DC60 rom.write_bytes(YOSHI_BOX_SUB_ADDR + 0x00, bytearray([0x08])) # PHP rom.write_bytes(YOSHI_BOX_SUB_ADDR + 0x01, bytearray([0xAD, 0x26, 0x14])) # LDA $1426 rom.write_bytes(YOSHI_BOX_SUB_ADDR + 0x04, bytearray([0xC9, 0x03])) # CMP #03 rom.write_bytes(YOSHI_BOX_SUB_ADDR + 0x06, bytearray([0xF0, 0x06])) # BEQ +0x06 rom.write_bytes(YOSHI_BOX_SUB_ADDR + 0x08, bytearray([0x28])) # PLP rom.write_bytes(YOSHI_BOX_SUB_ADDR + 0x09, bytearray([0xB9, 0xD9, 0xA5])) # LDA $A5B9, Y rom.write_bytes(YOSHI_BOX_SUB_ADDR + 0x0C, bytearray([0x80, 0x08])) # BRA +0x08 rom.write_bytes(YOSHI_BOX_SUB_ADDR + 0x0E, bytearray([0x28])) # PLP rom.write_bytes(YOSHI_BOX_SUB_ADDR + 0x0F, bytearray([0xDA])) # PHX rom.write_bytes(YOSHI_BOX_SUB_ADDR + 0x10, bytearray([0xBB])) # TYX rom.write_bytes(YOSHI_BOX_SUB_ADDR + 0x11, bytearray([0xBF, 0x00, 0xC2, 0x7E])) # LDA $7EC200, X rom.write_bytes(YOSHI_BOX_SUB_ADDR + 0x15, bytearray([0xFA])) # PLX rom.write_bytes(YOSHI_BOX_SUB_ADDR + 0x16, bytearray([0x60])) # RTS return def handle_bowser_damage(rom): rom.write_bytes(0x1A509, bytearray([0x20, 0x50, 0xBC])) # JSR $03BC50 BOWSER_BALLS_SUB_ADDR = 0x01BC50 rom.write_bytes(BOWSER_BALLS_SUB_ADDR + 0x00, bytearray([0x08])) # PHP rom.write_bytes(BOWSER_BALLS_SUB_ADDR + 0x01, bytearray([0xAD, 0x48, 0x0F])) # LDA $F48 rom.write_bytes(BOWSER_BALLS_SUB_ADDR + 0x04, bytearray([0xCF, 0xA1, 0xBF, 0x03])) # CMP $03BFA1 rom.write_bytes(BOWSER_BALLS_SUB_ADDR + 0x08, bytearray([0x90, 0x06])) # BCC +0x06 rom.write_bytes(BOWSER_BALLS_SUB_ADDR + 0x0A, bytearray([0x28])) # PLP rom.write_bytes(BOWSER_BALLS_SUB_ADDR + 0x0B, bytearray([0xEE, 0xB8, 0x14])) # INC $14B8 rom.write_bytes(BOWSER_BALLS_SUB_ADDR + 0x0E, bytearray([0x80, 0x01])) # BRA +0x01 rom.write_bytes(BOWSER_BALLS_SUB_ADDR + 0x10, bytearray([0x28])) # PLP rom.write_bytes(BOWSER_BALLS_SUB_ADDR + 0x11, bytearray([0x60])) # RTS return def handle_level_shuffle(rom, active_level_dict): rom.write_bytes(0x37600, bytearray([0x00] * 0x800)) # Duplicate Level Table rom.write_bytes(0x2D89C, bytearray([0x00, 0xF6, 0x06])) # Level Load Pointer rom.write_bytes(0x20F46, bytearray([0x00, 0xF6, 0x06])) # Mid Gate Pointer rom.write_bytes(0x20E7B, bytearray([0x00, 0xF6, 0x06])) # Level Name Pointer rom.write_bytes(0x21543, bytearray([0x00, 0xF6, 0x06])) # Also Level Name Pointer? rom.write_bytes(0x20F64, bytearray([0x00, 0xF6, 0x06])) # Level Beaten Pointer ### Fix Translevel Check rom.write_bytes(0x2D8AE, bytearray([0x20, 0x00, 0xDD])) # JSR $DD00 rom.write_bytes(0x2D8B1, bytearray([0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA])) # NOP NOP NOP NOP NOP rom.write_bytes(0x2D7CB, bytearray([0x20, 0x00, 0xDD])) # JSR $DD00 rom.write_bytes(0x2D7CE, bytearray([0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA])) # NOP NOP NOP NOP NOP rom.write_bytes(0x2DD00, bytearray([0xDA])) # PHX rom.write_bytes(0x2DD01, bytearray([0x08])) # PHP rom.write_bytes(0x2DD02, bytearray([0xE2, 0x30])) # SEP #30 rom.write_bytes(0x2DD04, bytearray([0xAE, 0xBF, 0x13])) # LDX $13BF rom.write_bytes(0x2DD07, bytearray([0xE0, 0x25])) # CPX #25 rom.write_bytes(0x2DD09, bytearray([0x90, 0x04])) # BCC $DD0F rom.write_bytes(0x2DD0B, bytearray([0xA2, 0x01])) # LDX #01 rom.write_bytes(0x2DD0D, bytearray([0x80, 0x02])) # BRA $DD11 rom.write_bytes(0x2DD0F, bytearray([0xA2, 0x00])) # LDX #00 rom.write_bytes(0x2DD11, bytearray([0x86, 0x0F])) # STX $0F rom.write_bytes(0x2DD13, bytearray([0x28])) # PLP rom.write_bytes(0x2DD14, bytearray([0xFA])) # PLX rom.write_bytes(0x2DD15, bytearray([0x60])) # RTS ### End Fix Translevel Check ### Fix Snake Blocks rom.write_bytes(0x192FB, bytearray([0x20, 0x1D, 0xBC])) # JSR $03BC1D SNAKE_BLOCKS_SUB_ADDR = 0x01BC1D rom.write_bytes(SNAKE_BLOCKS_SUB_ADDR + 0x00, bytearray([0x08])) # PHP rom.write_bytes(SNAKE_BLOCKS_SUB_ADDR + 0x01, bytearray([0xAD, 0xBF, 0x13])) # LDA $13BF rom.write_bytes(SNAKE_BLOCKS_SUB_ADDR + 0x04, bytearray([0xC9, 0x20])) # CMP #20 rom.write_bytes(SNAKE_BLOCKS_SUB_ADDR + 0x06, bytearray([0xF0, 0x05])) # BEQ +0x05 rom.write_bytes(SNAKE_BLOCKS_SUB_ADDR + 0x08, bytearray([0x28])) # PLP rom.write_bytes(SNAKE_BLOCKS_SUB_ADDR + 0x09, bytearray([0xA9, 0x01])) # LDA #01 rom.write_bytes(SNAKE_BLOCKS_SUB_ADDR + 0x0B, bytearray([0x80, 0x03])) # BRA +0x03 rom.write_bytes(SNAKE_BLOCKS_SUB_ADDR + 0x0D, bytearray([0x28])) # PLP rom.write_bytes(SNAKE_BLOCKS_SUB_ADDR + 0x0E, bytearray([0xA9, 0x00])) # LDA #00 rom.write_bytes(SNAKE_BLOCKS_SUB_ADDR + 0x10, bytearray([0x60])) # RTS ### End Fix Snake Blocks for level_id, level_data in level_info_dict.items(): if level_id not in active_level_dict.keys(): continue tile_id = active_level_dict[level_id] tile_data = level_info_dict[tile_id] if level_id > 0x80: level_id = level_id - 0x50 rom.write_byte(tile_data.levelIDAddress, level_id) rom.write_byte(0x2D608 + level_id, tile_data.eventIDValue) for level_id, tile_id in active_level_dict.items(): rom.write_byte(0x37F70 + level_id, tile_id) def handle_collected_paths(rom): rom.write_bytes(0x1F5B, bytearray([0x22, 0x30, 0xBC, 0x03])) # JSL $03BC30 rom.write_bytes(0x1F5F, bytearray([0xEA] * 0x02)) COLLECTED_PATHS_SUB_ADDR = 0x01BC30 rom.write_bytes(COLLECTED_PATHS_SUB_ADDR + 0x00, bytearray([0x08])) # PHP rom.write_bytes(COLLECTED_PATHS_SUB_ADDR + 0x01, bytearray([0xAD, 0x00, 0x01])) # LDA $0100 rom.write_bytes(COLLECTED_PATHS_SUB_ADDR + 0x04, bytearray([0xC9, 0x0B])) # CMP #0B rom.write_bytes(COLLECTED_PATHS_SUB_ADDR + 0x06, bytearray([0xD0, 0x04])) # BNE +0x04 rom.write_bytes(COLLECTED_PATHS_SUB_ADDR + 0x08, bytearray([0x22, 0xAD, 0xDA, 0x04])) # JSL $04DAAD rom.write_bytes(COLLECTED_PATHS_SUB_ADDR + 0x0C, bytearray([0x28])) # PLP rom.write_bytes(COLLECTED_PATHS_SUB_ADDR + 0x0D, bytearray([0xEE, 0x00, 0x01])) # INC $0100 rom.write_bytes(COLLECTED_PATHS_SUB_ADDR + 0x10, bytearray([0xAD, 0xAF, 0x0D])) # LDA $0DAF rom.write_bytes(COLLECTED_PATHS_SUB_ADDR + 0x13, bytearray([0x6B])) # RTL def handle_vertical_scroll(rom): rom.write_bytes(0x285BA, bytearray([0x22, 0x90, 0xBC, 0x03])) # JSL $03BC90 VERTICAL_SCROLL_SUB_ADDR = 0x01BC90 rom.write_bytes(VERTICAL_SCROLL_SUB_ADDR + 0x00, bytearray([0x4A])) # LSR rom.write_bytes(VERTICAL_SCROLL_SUB_ADDR + 0x01, bytearray([0x4A])) # LSR rom.write_bytes(VERTICAL_SCROLL_SUB_ADDR + 0x02, bytearray([0x4A])) # LSR rom.write_bytes(VERTICAL_SCROLL_SUB_ADDR + 0x03, bytearray([0x4A])) # LSR rom.write_bytes(VERTICAL_SCROLL_SUB_ADDR + 0x04, bytearray([0x08])) # PHP rom.write_bytes(VERTICAL_SCROLL_SUB_ADDR + 0x05, bytearray([0xC9, 0x02])) # CMP #02 rom.write_bytes(VERTICAL_SCROLL_SUB_ADDR + 0x07, bytearray([0xD0, 0x02])) # BNE +0x02 rom.write_bytes(VERTICAL_SCROLL_SUB_ADDR + 0x09, bytearray([0xA9, 0x01])) # LDA #01 rom.write_bytes(VERTICAL_SCROLL_SUB_ADDR + 0x0B, bytearray([0x28])) # PLP rom.write_bytes(VERTICAL_SCROLL_SUB_ADDR + 0x0C, bytearray([0x6B])) # RTL def handle_music_shuffle(rom, world, player): from .Aesthetics import generate_shuffled_level_music, generate_shuffled_ow_music, level_music_address_data, ow_music_address_data shuffled_level_music = generate_shuffled_level_music(world, player) for i in range(len(shuffled_level_music)): rom.write_byte(level_music_address_data[i], shuffled_level_music[i]) shuffled_ow_music = generate_shuffled_ow_music(world, player) for i in range(len(shuffled_ow_music)): for addr in ow_music_address_data[i]: rom.write_byte(addr, shuffled_ow_music[i]) def handle_mario_palette(rom, world, player): from .Aesthetics import mario_palettes, fire_mario_palettes, ow_mario_palettes chosen_palette = world.mario_palette[player].value rom.write_bytes(0x32C8, bytes(mario_palettes[chosen_palette])) rom.write_bytes(0x32F0, bytes(fire_mario_palettes[chosen_palette])) rom.write_bytes(0x359C, bytes(ow_mario_palettes[chosen_palette])) def handle_swap_donut_gh_exits(rom): rom.write_bytes(0x2567C, bytes([0xC0])) rom.write_bytes(0x25873, bytes([0xA9])) rom.write_bytes(0x25875, bytes([0x85])) rom.write_bytes(0x25954, bytes([0x92])) rom.write_bytes(0x25956, bytes([0x0A])) rom.write_bytes(0x25E31, bytes([0x00, 0x00, 0xD8, 0x04, 0x24, 0x00, 0x98, 0x04, 0x48, 0x00, 0xD8, 0x03, 0x6C, 0x00, 0x56, 0x03, 0x90, 0x00, 0x56, 0x03, 0xB4, 0x00, 0x56, 0x03, 0x10, 0x05, 0x18, 0x05, 0x28, 0x09, 0x24, 0x05, 0x38, 0x0B, 0x14, 0x07, 0xEC, 0x09, 0x12, 0x05, 0xF0, 0x09, 0xD2, 0x04, 0xF4, 0x09, 0x92, 0x04])) rom.write_bytes(0x26371, bytes([0x32])) def handle_bowser_rooms(rom, world, player: int): if world.bowser_castle_rooms[player] == "random_two_room": chosen_rooms = world.per_slot_randoms[player].sample(standard_bowser_rooms, 2) rom.write_byte(0x3A680, chosen_rooms[0].roomID) rom.write_byte(0x3A684, chosen_rooms[0].roomID) rom.write_byte(0x3A688, chosen_rooms[0].roomID) rom.write_byte(0x3A68C, chosen_rooms[0].roomID) for i in range(1, len(chosen_rooms)): rom.write_byte(chosen_rooms[i-1].exitAddress, chosen_rooms[i].roomID) rom.write_byte(chosen_rooms[len(chosen_rooms)-1].exitAddress, 0xBD) elif world.bowser_castle_rooms[player] == "random_five_room": chosen_rooms = world.per_slot_randoms[player].sample(standard_bowser_rooms, 5) rom.write_byte(0x3A680, chosen_rooms[0].roomID) rom.write_byte(0x3A684, chosen_rooms[0].roomID) rom.write_byte(0x3A688, chosen_rooms[0].roomID) rom.write_byte(0x3A68C, chosen_rooms[0].roomID) for i in range(1, len(chosen_rooms)): rom.write_byte(chosen_rooms[i-1].exitAddress, chosen_rooms[i].roomID) rom.write_byte(chosen_rooms[len(chosen_rooms)-1].exitAddress, 0xBD) elif world.bowser_castle_rooms[player] == "gauntlet": chosen_rooms = standard_bowser_rooms.copy() world.per_slot_randoms[player].shuffle(chosen_rooms) rom.write_byte(0x3A680, chosen_rooms[0].roomID) rom.write_byte(0x3A684, chosen_rooms[0].roomID) rom.write_byte(0x3A688, chosen_rooms[0].roomID) rom.write_byte(0x3A68C, chosen_rooms[0].roomID) for i in range(1, len(chosen_rooms)): rom.write_byte(chosen_rooms[i-1].exitAddress, chosen_rooms[i].roomID) rom.write_byte(chosen_rooms[len(chosen_rooms)-1].exitAddress, 0xBD) elif world.bowser_castle_rooms[player] == "labyrinth": bowser_rooms_copy = full_bowser_rooms.copy() entrance_point = bowser_rooms_copy.pop(0) world.per_slot_randoms[player].shuffle(bowser_rooms_copy) rom.write_byte(entrance_point.exitAddress, bowser_rooms_copy[0].roomID) for i in range(0, len(bowser_rooms_copy) - 1): rom.write_byte(bowser_rooms_copy[i].exitAddress, bowser_rooms_copy[i+1].roomID) rom.write_byte(bowser_rooms_copy[len(bowser_rooms_copy)-1].exitAddress, 0xBD) def handle_boss_shuffle(rom, world, player): if world.boss_shuffle[player] == "simple": submap_boss_rooms_copy = submap_boss_rooms.copy() ow_boss_rooms_copy = ow_boss_rooms.copy() world.per_slot_randoms[player].shuffle(submap_boss_rooms_copy) world.per_slot_randoms[player].shuffle(ow_boss_rooms_copy) for i in range(len(submap_boss_rooms_copy)): rom.write_byte(submap_boss_rooms[i].exitAddress, submap_boss_rooms_copy[i].roomID) for i in range(len(ow_boss_rooms_copy)): rom.write_byte(ow_boss_rooms[i].exitAddress, ow_boss_rooms_copy[i].roomID) if ow_boss_rooms[i].exitAddressAlt is not None: rom.write_byte(ow_boss_rooms[i].exitAddressAlt, ow_boss_rooms_copy[i].roomID) elif world.boss_shuffle[player] == "full": for i in range(len(submap_boss_rooms)): chosen_boss = world.per_slot_randoms[player].choice(submap_boss_rooms) rom.write_byte(submap_boss_rooms[i].exitAddress, chosen_boss.roomID) for i in range(len(ow_boss_rooms)): chosen_boss = world.per_slot_randoms[player].choice(ow_boss_rooms) rom.write_byte(ow_boss_rooms[i].exitAddress, chosen_boss.roomID) if ow_boss_rooms[i].exitAddressAlt is not None: rom.write_byte(ow_boss_rooms[i].exitAddressAlt, chosen_boss.roomID) elif world.boss_shuffle[player] == "singularity": chosen_submap_boss = world.per_slot_randoms[player].choice(submap_boss_rooms) chosen_ow_boss = world.per_slot_randoms[player].choice(ow_boss_rooms) for i in range(len(submap_boss_rooms)): rom.write_byte(submap_boss_rooms[i].exitAddress, chosen_submap_boss.roomID) for i in range(len(ow_boss_rooms)): rom.write_byte(ow_boss_rooms[i].exitAddress, chosen_ow_boss.roomID) if ow_boss_rooms[i].exitAddressAlt is not None: rom.write_byte(ow_boss_rooms[i].exitAddressAlt, chosen_ow_boss.roomID) def patch_rom(world, rom, player, active_level_dict): goal_text = generate_goal_text(world, player) rom.write_bytes(0x2A6E2, goal_text) rom.write_byte(0x2B1D8, 0x80) intro_text = generate_text_box("Bowser has stolen all of Mario's abilities. Can you help Mario travel across Dinosaur land to get them back and save the Princess from him?") rom.write_bytes(0x2A5D9, intro_text) handle_bowser_rooms(rom, world, player) handle_boss_shuffle(rom, world, player) # Prevent Title Screen Deaths rom.write_byte(0x1C6A, 0x80) # Title Screen Text player_name_bytes = bytearray() player_name = world.get_player_name(player) for i in range(16): char = " " if i < len(player_name): char = world.get_player_name(player)[i] upper_char = char.upper() if upper_char not in title_text_mapping: for byte in title_text_mapping["."]: player_name_bytes.append(byte) else: for byte in title_text_mapping[upper_char]: player_name_bytes.append(byte) rom.write_bytes(0x2B7F1, player_name_bytes) # MARIO A rom.write_bytes(0x2B726, player_name_bytes) # MARIO A rom.write_bytes(0x2B815, bytearray([0xFC, 0x38] * 0x10)) # MARIO B rom.write_bytes(0x2B74A, bytearray([0xFC, 0x38] * 0x10)) # MARIO B rom.write_bytes(0x2B839, bytearray([0x71, 0x31, 0x74, 0x31, 0x2D, 0x31, 0x84, 0x30, 0x82, 0x30, 0x6F, 0x31, 0x73, 0x31, 0x70, 0x31, 0x71, 0x31, 0x75, 0x31, 0x83, 0x30, 0xFC, 0x38, 0xFC, 0x38, 0xFC, 0x38, 0xFC, 0x38, 0xFC, 0x38])) # MARIO C rom.write_bytes(0x2B76E, bytearray([0xFC, 0x38] * 0x10)) # MARIO C rom.write_bytes(0x2B79E, bytearray([0xFC, 0x38] * 0x05)) # EMPTY rom.write_bytes(0x2B7AE, bytearray([0xFC, 0x38] * 0x05)) # EMPTY rom.write_bytes(0x2B8A8, bytearray([0xFC, 0x38] * 0x0D)) # 2 PLAYER GAME rom.write_bytes(0x2B85D, bytearray([0xFC, 0x38] * 0x0A)) # ERASE rom.write_bytes(0x2B88E, bytearray([0x2C, 0x31, 0x73, 0x31, 0x75, 0x31, 0x82, 0x30, 0x30, 0x31, 0xFC, 0x38, 0x31, 0x31, 0x73, 0x31, 0x73, 0x31, 0x7C, 0x30, 0xFC, 0x38, 0xFC, 0x38, 0xFC, 0x38])) # 1 Player Game rom.write_bytes(0x2B6D7, bytearray([0xFC, 0x38, 0xFC, 0x38, 0x16, 0x38, 0x18, 0x38, 0x0D, 0x38, 0xFC, 0x38, 0x0B, 0x38, 0x22, 0x38, 0xFC, 0x38, 0x19, 0x38, 0x18, 0x38, 0x1B, 0x38, 0x22, 0x38, 0x10, 0x38, 0x18, 0x38, 0x17, 0x38, 0x0E, 0x38, 0xFC, 0x38, 0xFC, 0x38])) # Mod by PoryGone # Title Options rom.write_bytes(0x1E6A, bytearray([0x01])) rom.write_bytes(0x1E6C, bytearray([0x01])) rom.write_bytes(0x1E6E, bytearray([0x01])) # Always allow Start+Select rom.write_bytes(0x2267, bytearray([0xEA, 0xEA])) # Always bring up save prompt on beating a level if world.autosave[player]: rom.write_bytes(0x20F93, bytearray([0x00])) if world.overworld_speed[player] == "fast": rom.write_bytes(0x21414, bytearray([0x20, 0x10])) elif world.overworld_speed[player] == "slow": rom.write_bytes(0x21414, bytearray([0x05, 0x05])) # Starting Life Count rom.write_bytes(0x1E25, bytearray([world.starting_life_count[player].value - 1])) # Repurpose Bonus Stars counter for Boss Token or Yoshi Eggs rom.write_bytes(0x3F1AA, bytearray([0x00] * 0x20)) # Delete Routine that would copy Mario position data over repurposed Luigi save data rom.write_bytes(0x20F9F, bytearray([0xEA] * 0x3D)) # Prevent Switch Palaces setting the Switch Palace flags rom.write_bytes(0x6EC9A, bytearray([0xEA, 0xEA])) rom.write_bytes(0x6EB1, bytearray([0xEA, 0xEA])) rom.write_bytes(0x6EB4, bytearray([0xEA, 0xEA, 0xEA])) handle_ability_code(rom) handle_yoshi_box(rom) handle_bowser_damage(rom) handle_collected_paths(rom) handle_vertical_scroll(rom) # Handle Level Shuffle handle_level_shuffle(rom, active_level_dict) # Handle Music Shuffle if world.music_shuffle[player] != "none": handle_music_shuffle(rom, world, player) generate_shuffled_ow_palettes(rom, world, player) generate_shuffled_header_data(rom, world, player) if world.swap_donut_gh_exits[player]: handle_swap_donut_gh_exits(rom) handle_mario_palette(rom, world, player) # Store all relevant option results in ROM rom.write_byte(0x01BFA0, world.goal[player].value) if world.goal[player].value == 0: rom.write_byte(0x01BFA1, world.bosses_required[player].value) else: rom.write_byte(0x01BFA1, 0x7F) required_yoshi_eggs = max(math.floor( world.number_of_yoshi_eggs[player].value * (world.percentage_of_yoshi_eggs[player].value / 100.0)), 1) rom.write_byte(0x01BFA2, required_yoshi_eggs) #rom.write_byte(0x01BFA3, world.display_sent_item_popups[player].value) rom.write_byte(0x01BFA4, world.display_received_item_popups[player].value) rom.write_byte(0x01BFA5, world.death_link[player].value) rom.write_byte(0x01BFA6, world.dragon_coin_checks[player].value) rom.write_byte(0x01BFA7, world.swap_donut_gh_exits[player].value) from Main import __version__ rom.name = bytearray(f'SMW{__version__.replace(".", "")[0:3]}_{player}_{world.seed:11}\0', 'utf8')[:21] rom.name.extend([0] * (21 - len(rom.name))) rom.write_bytes(0x7FC0, rom.name) def get_base_rom_bytes(file_name: str = "") -> bytes: base_rom_bytes = getattr(get_base_rom_bytes, "base_rom_bytes", None) if not base_rom_bytes: file_name = get_base_rom_path(file_name) base_rom_bytes = bytes(Utils.read_snes_rom(open(file_name, "rb"))) basemd5 = hashlib.md5() basemd5.update(base_rom_bytes) if USHASH != basemd5.hexdigest(): raise Exception('Supplied Base Rom does not match known MD5 for US(1.0) release. ' 'Get the correct game and version, then dump it') get_base_rom_bytes.base_rom_bytes = base_rom_bytes return base_rom_bytes def get_base_rom_path(file_name: str = "") -> str: options = Utils.get_options() if not file_name: file_name = options["smw_options"]["rom_file"] if not os.path.exists(file_name): file_name = Utils.local_path(file_name) return file_name