Skip to content

Commit

Permalink
Fixed Door Transition Bug & More
Browse files Browse the repository at this point in the history
- Fixed bug causing VARIA door transition code to be run on every door
- Fixed crash going through elevators caused by aforementioned bug
- Made errors raise exceptions instead of just printing to console
- Incremented version number by 0.0.1
  • Loading branch information
SolventMercury committed Feb 2, 2022
1 parent 84726e6 commit 19a91bf
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 25 deletions.
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = SuperDuperMetroid
version = 2.2.1
version = 2.2.2
author = Samuel Roy
description = A Super Metroid patching utility
long_description = file: README.md
Expand Down
2 changes: 1 addition & 1 deletion src/SuperDuperMetroid/IPS_Patcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def apply_ips_patch(ips_path, rom_file):
pass
print(f"Finished applying patch {ips_path} successfully.")
else:
print(f"CRITICAL ERROR: Provided IPS file {ips_path} does not match the format specification!")
raise ValueError(f"CRITICAL ERROR: Provided IPS file {ips_path} does not match the format specification!")
ips_file.close()


Expand Down
46 changes: 24 additions & 22 deletions src/SuperDuperMetroid/ROM_Patcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ def conform_message_to_format(self, message_text, message_box_size):
# Tell the user if their message contains unsupported characters
if len(message_text) > len(stripped_message):
print(
"Warning Message box text "
"WARNING: Message box text "
+ message_text
+ " contains unsupported characters. These will be stripped from the message.\nMessage boxes support the latin alphabet (will be converted to uppercase only), the arabic numerals 0-9, spaces, and a limited set of miscellaneous characters: ?!,.'&-%"
)
Expand All @@ -206,7 +206,7 @@ def conform_message_to_format(self, message_text, message_box_size):
# We'll also include a warning if this happens.
if len(message_text) > maxMessageLengths(message_box_size):
print(
f"Warning: Message box text {message_text} exceeds maximum length of message box. Message will be cut to first 19 characters."
f"WARNING: Message box text {message_text} exceeds maximum length of message box. Message will be cut to first 19 characters."
)
message_text = message_text[: maxMessageLengths(message_box_size)]
return message_text
Expand Down Expand Up @@ -247,22 +247,22 @@ def generate_messagebox(self, message_text, message_box_size):
messag_hex = (padding_hex * 3) + message_hex + (padding_hex * 3)
else:
print(
f"Warning: You are attempting to create a message with size paramater {message_box_size}, which is not a supported size.\nSupported sizes are Small and Large"
f"WARNING: You are attempting to create a message with size paramater {message_box_size}, which is not a supported size.\nSupported sizes are Small and Large"
)
return

# Record our addition of this message.
if message_box_size == "Small":
if message_text in smallMessagePointerTable.keys():
print(
f"Warning: The message {message_text} has already been added to this ROM.\nPlease consult the current maintainer of this patcher."
f"WARNING: The message {message_text} has already been added to this ROM.\nPlease consult the current maintainer of this patcher."
)
else:
self.smallMessagePointerTable[message_text] = message_text
elif message_box_size == "Large":
if message_text in largeMessagePointerTable.keys():
print(
f"Warning: The message {message_text} has already been added to this ROM.\nPlease consult the current maintainer of this patcher."
f"WARNING: The message {message_text} has already been added to this ROM.\nPlease consult the current maintainer of this patcher."
)
else:
self.largeMessagePointerTable[message_text] = message_text
Expand Down Expand Up @@ -594,7 +594,7 @@ def get_all_necessary_pickup_routines(item_list, item_get_routines_dict, startin
item_get_routines_dict[pickup.item_name] = equipment_gets[pickup.pickup_effect]
# Otherwise add new effect
else:
print("ERROR: Custom item pickup behaviors are not yet implemented.")
raise NotImplementedError("ERROR: Custom item pickup behaviors are not yet implemented.")

# This is a command that will do nothing, used for items that are meant to go to other players.
# 60 is hex for the RTS instruction. In other words when called it will immediately return.
Expand All @@ -616,7 +616,7 @@ def write_door_asm_routines(rom_file, door_data_list):
rom_file.seek(base_address + file_offset)
# As an efficiency measure,
# We hardcode in the door ASM which I believe is likely to be most common.
most_basic_door_asm = hex_to_data("2040F660")
most_basic_door_asm = hex_to_data("60")
most_basic_door_asm_address = base_address
rom_file.write(most_basic_door_asm)
current_address += len(most_basic_door_asm)
Expand All @@ -630,17 +630,18 @@ def write_door_asm_routines(rom_file, door_data_list):
if door_data.extra_asm_pointer != 0x0000:
door_routine.append(0x20)
door_routine += door_data.extra_asm_pointer.to_bytes(2, "little")
# Rectify door directional mismatches
# Relies on door_transition.ips
if door_data.door_mismatch:
door_routine += bytearray([0x20, 0x00, 0xF6, 0xA9])
door_routine += door_data.override_x.to_bytes(2, "little")
door_routine += bytearray([0x8D, 0xF6, 0x0A, 0xA9])
door_routine += door_data.override_y.to_bytes(2, "little")
door_routine += bytearray([0x8D, 0xFA, 0x0A])
# Apply iframes after going through a door
else:
door_routine += bytearray([0x20, 0x40, 0xF6])
if door_data.door_redirect:
# Rectify door directional mismatches
# Relies on door_transition.ips
if door_data.door_mismatch:
door_routine += bytearray([0x20, 0x00, 0xF6, 0xA9])
door_routine += door_data.override_x.to_bytes(2, "little")
door_routine += bytearray([0x8D, 0xF6, 0x0A, 0xA9])
door_routine += door_data.override_y.to_bytes(2, "little")
door_routine += bytearray([0x8D, 0xFA, 0x0A])
# Apply iframes after going through a door
else:
door_routine += bytearray([0x20, 0x40, 0xF6])
door_routine.append(0x60)

if door_routine == most_basic_door_asm:
Expand Down Expand Up @@ -1064,7 +1065,7 @@ def write_kazuto_more_efficient_items_hack(rom_file, item_types_list):
try:
assert len(current_item_gfx_data) == item_gfx_length
except:
print(
raise ValueError(
f"ERROR: Invalid-size graphics data supplied for item type {item_type.item_name}:\n {current_item_gfx_data} should be only 14(0x0E) bytes, is instead {str(len(current_item_gfx_data))}."
)
return
Expand Down Expand Up @@ -1247,13 +1248,14 @@ def patch_rom(rom_file, output_path, item_list=None, player_name=None, recipient
if item_list is None:
item_list = gen_vanilla_game()
starting_items = None
print("Item list was not supplied to ROM patcher. Generating Vanilla placement with no starting items.")
print(
"WARNING: Item list was not supplied to ROM patcher. Generating Vanilla placement with no starting items."
)
else:
try:
assert len(item_list) >= 100
except:
print("ERROR: Non-Empty item list didn't meet length requirement. Aborting ROM Patch.")
return
raise ValueError("ERROR: Non-Empty item list didn't meet length requirement. Aborting ROM Patch.")

# Now write our new routines to memory.
# First we append new routines to free space
Expand Down
5 changes: 4 additions & 1 deletion src/SuperDuperMetroid/SM_Room_Header_Data.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ def __init__(self, door_hex):

# Boolean - marks whether this door has a direction mismatch with the destination door
self.door_mismatch = False
# Boolean - marks whether this door has had its destination altered
self.door_redirect = False
# Defines an override position for Samus in the case of incompatible door transition
self.override_x = 0x0000
self.override_y = 0x0000
Expand Down Expand Up @@ -121,6 +123,8 @@ def change_destination(self, dest_room_addr, dest_door_index):
self.distance_to_spawn = vanilla_source_room_door_data.distance_to_spawn
self.door_asm_pointer = vanilla_source_room_door_data.door_asm_pointer

self.door_redirect = True

# Validate the door directions
# If the door that leads to our destination in Vanilla has a different direction from this door,
# Then there is a door mismatch.
Expand Down Expand Up @@ -207,7 +211,6 @@ def to_string(self):
print(pad_hex(int_to_hex(self.distance_to_spawn), 4))
print(pad_hex(int_to_hex(self.door_asm_pointer), 4))
print("")
pass


class SMRooms:
Expand Down

0 comments on commit 19a91bf

Please sign in to comment.