forked from mirror/Archipelago
Some checks failed
Analyze modified files / flake8 (push) Failing after 2m28s
Build / build-win (push) Has been cancelled
Build / build-ubuntu2204 (push) Has been cancelled
ctest / Test C++ ubuntu-latest (push) Has been cancelled
ctest / Test C++ windows-latest (push) Has been cancelled
Analyze modified files / mypy (push) Has been cancelled
Build and Publish Docker Images / Push Docker image to Docker Hub (push) Successful in 5m4s
Native Code Static Analysis / scan-build (push) Failing after 5m2s
type check / pyright (push) Successful in 1m7s
unittests / Test Python 3.11.2 ubuntu-latest (push) Failing after 16m23s
unittests / Test Python 3.12 ubuntu-latest (push) Failing after 28m19s
unittests / Test Python 3.13 ubuntu-latest (push) Failing after 14m49s
unittests / Test hosting with 3.13 on ubuntu-latest (push) Successful in 5m0s
unittests / Test Python 3.13 macos-latest (push) Has been cancelled
unittests / Test Python 3.11 windows-latest (push) Has been cancelled
unittests / Test Python 3.13 windows-latest (push) Has been cancelled
2155 lines
92 KiB
Python
2155 lines
92 KiB
Python
custom_code_loader = [
|
|
# On boot, when the company logos show up, this will trigger and load most of the custom ASM data
|
|
# from ROM offsets 0xFFC000-0xFFFFFF and into the 803FC000-803FFFFF range in RAM.
|
|
0x3C088040, # LUI T0, 0x8040
|
|
0x9108C000, # LBU T0, 0xC000 (T0)
|
|
0x15000007, # BNEZ T0, [forward 0x07]
|
|
0x3C0400FF, # LUI A0, 0x00FF
|
|
0x3484C000, # ORI A0, A0, 0xC000
|
|
0x3C058040, # LUI A1, 0x8040
|
|
0x24A5C000, # ADDIU A1, A1, 0xC000
|
|
0x24064000, # ADDIU A2, R0, 0x4000
|
|
0x0800690B, # J 0x8001A42C
|
|
0x00000000, # NOP
|
|
0x03E00008, # JR RA
|
|
0x00000000, # NOP
|
|
]
|
|
|
|
remote_item_giver = [
|
|
# The essential multiworld function. Every frame wherein the player is in control and not looking at a text box,
|
|
# this thing will check some bytes in RAM to see if an item or DeathLink has been received and trigger the right
|
|
# functions accordingly to either reward items or kill the player.
|
|
|
|
# Primary checks
|
|
# In a demo?
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x9109AA4A, # LBU T1, 0xAA4A (T0)
|
|
# In a cutscene?
|
|
0x910AAE8B, # LBU T2, 0xAE8B (T0)
|
|
0x012A4821, # ADDU T1, T1, T2
|
|
# Will be in a cutscene on next map transition?
|
|
0x910AAE8F, # LBU T2, 0xAE8F (T0)
|
|
0x012A4821, # ADDU T1, T1, T2
|
|
# Reading text while frozen?
|
|
0x910AABCB, # LBU T2, 0xABCB (T0)
|
|
0x012A4821, # ADDU T1, T1, T2
|
|
# Paused the game or in Renon's shop?
|
|
0x910AAE0F, # LBU T2, 0xAE0F (T0)
|
|
0x012A4821, # ADDU T1, T1, T2
|
|
# In a fade transition?
|
|
0x910A8354, # LBU T2, 0x8354 (T0)
|
|
0x012A4821, # ADDU T1, T1, T2
|
|
# One of the pointers to the player object not 00000000?
|
|
0x8D0AAC1C, # LW T2, 0xAC1C (T0)
|
|
0x51400001, # BEQZL T2, [forward 0x01]
|
|
0x25290001, # ADDIU T1, T1, 0x0001
|
|
# Timer till next item at 00?
|
|
0x3C0B801D, # LUI T3, 0x801D
|
|
0x916AAA4E, # LBU T2, 0xAA4E (T3)
|
|
0x012A4821, # ADDU T1, T1, T2
|
|
0x1120000C, # BEQZ T1, [forward 0x0C]
|
|
# If it isn't, decrement it by 1 frame and return.
|
|
0x8D6CAC0C, # LW T4, 0xAC0C (T3)
|
|
0x11400008, # BEQZ T2, [forward 0x08]
|
|
0x254AFFFF, # ADDIU T2, T2, 0xFFFF
|
|
# If the player is holding C-Left while the delay timer has more than 0x10 frames left in it, set the timer to 0x10.
|
|
# This will allow the player to turbo through the received item queue if they so desire.
|
|
0x910D87F7, # LBU T5, 0x87F7 (T0)
|
|
0x31AD0002, # ANDI T5, T5, 0x0002
|
|
0x11A00003, # BEQZ T5, [forward 0x03]
|
|
0x294E0010, # SLTI T6, T2, 0x0010
|
|
0x51C00001, # BEQZL T6, [forward 0x01]
|
|
0x340A0010, # ORI T2, R0, 0x0010
|
|
0xA16AAA4E, # SB T2, 0xAA4E (T3)
|
|
0x03E00008, # JR RA
|
|
0x00000000, # NOP
|
|
# Item-specific checks
|
|
# Textbox in its "map text" state?
|
|
0x1180FFFD, # BEQZ T4, [backward 0x03]
|
|
0x00000000, # NOP
|
|
0x8D8F005C, # LW T7, 0x005C (T4)
|
|
0x11E0FFFA, # BEQZ T7, [backward 0x06]
|
|
0x95980000, # LHU T8, 0x0000 (T4)
|
|
0x1300FFF8, # BGTZ T8, [backward 0x08]
|
|
0x00000000, # NOP
|
|
0x8DED0038, # LW T5, 0x0038 (T7)
|
|
0x11A0FFF5, # BEQZ T5, [backward 0x0B]
|
|
0x00000000, # NOP
|
|
0x91AE0026, # LBU T6, 0x0026 (T5)
|
|
# Non-multiworld item byte occupied?
|
|
0x9164AA4C, # LBU A0, 0xAA4C (T3)
|
|
0x10800007, # BEQZ A0, [forward 0x07]
|
|
# Grab the DeathLink byte now for later comparisons.
|
|
0x9178AA4F, # LBU T8, 0xAA4F (T3)
|
|
# If the textbox state is not 0, call the prepare item textbox function without setting the timer nor clearing the
|
|
# buffer. It will have to be called again on the subsequent frame(s) if that's the case.
|
|
0x15C00004, # BNEZ T6, [forward 0x04]
|
|
0x24090090, # ADDIU T1, R0, 0x0090
|
|
# If the DeathLink byte is set, don't set the delay timer so that we can properly get killed on the next frame.
|
|
0x53000001, # BEQZL T8, [forward 0x01]
|
|
0xA169AA4E, # SB T1, 0xAA4E (T3)
|
|
0xA160AA4C, # SB R0, 0xAA4C (T3)
|
|
0x08021C1C, # J 0x80087070
|
|
0x00000000, # NOP
|
|
# Multiworld item byte occupied?
|
|
0x9164AA4D, # LBU A0, 0xAA4D (T3)
|
|
0x10800025, # BEQZ A0, [forward 0x25]
|
|
0x00000000, # NOP
|
|
# If we're receiving a subweapon (see: ID is between 0x0D-0x10), check if the player is above an abyss or instant
|
|
# death floor type. If they are, don't give the subweapon on that frame so the player's old subweapon can drop to
|
|
# a safe spot.
|
|
0x2408000D, # ADDIU T0, R0, 0x000D
|
|
0x11040006, # BEQ T0, A0, [forward 0x06]
|
|
0x2409000E, # ADDIU T1, R0, 0x000E
|
|
0x11240004, # BEQ T1, A0, [forward 0x04]
|
|
0x2408000F, # ADDIU T0, R0, 0x000F
|
|
0x11040002, # BEQ T0, A0, [forward 0x02]
|
|
0x24090010, # ADDIU T1, R0, 0x0010
|
|
0x1524000A, # BNE T1, A0, [forward 0x0A]
|
|
# Check the floor type beneath the player for 00 (no floor), 07 (floor that kills by being in a distance above it),
|
|
# or 0A (floor that kills by being on it).
|
|
0x3C0A800F, # LUI T2, 0x800F
|
|
0x914A393D, # LBU T2, 0x393D (T2)
|
|
0x11400005, # BEQZ T2, [forward 0x05]
|
|
0x24080007, # ADDIU T0, R0, 0x0007
|
|
0x110A0003, # BEQ T0, T2, [forward 0x03]
|
|
0x2409000A, # ADDIU T1, R0, 0x000A
|
|
0x152A0003, # BNE T1, T2, [forward 0x03]
|
|
0x00000000, # NOP
|
|
0x03E00008, # JR RA
|
|
0x00000000, # NOP
|
|
# If the textbox state is not 0, again, call the item textbox without setting the timer, clearing the buffer, nor
|
|
# increment the multiworld item index. Don't copy the incoming multiworld item text buffer either.
|
|
0x15C00010, # BNEZ T6, [forward 0x10]
|
|
0x24090090, # ADDIU T1, R0, 0x0090
|
|
# If the DeathLink byte is set, don't set the delay timer so that we can properly get killed on the next frame.
|
|
0x53000001, # BEQZL T8, [forward 0x01]
|
|
0xA169AA4E, # SB T1, 0xAA4E (T3)
|
|
0xA160AA4D, # SB R0, 0xAA4D (T3)
|
|
# Increment the multiworld received item index here.
|
|
0x956AABBE, # LHU T2, 0xABBE (T3)
|
|
0x254A0001, # ADDIU T2, T2, 0x0001
|
|
0xA56AABBE, # SH T2, 0xABBE (T3)
|
|
# Copy the "incoming multiworld text buffer" into the primary one used for hijacking the item textbox.
|
|
0x3C088002, # LUI T0, 0x8002
|
|
0x34090000, # ORI T1, R0, 0x0000
|
|
0x340B0042, # ORI T3, R0, 0x0042
|
|
0x112B0005, # BEQ T1, T3, [forward 0x05]
|
|
0x8D0AE6DC, # LW T2, 0xE6DC (T0)
|
|
0xAD0AE5CC, # SW T2, 0xE5CC (T0)
|
|
0x25290001, # ADDIU T1, T1, 0x0001
|
|
0x1000FFFB, # B [backward 0x05]
|
|
0x25080004, # ADDIU T0, T0, 0x0004
|
|
0x08021C1C, # J 0x80087070
|
|
0x00000000, # NOP
|
|
# DeathLink-specific checks
|
|
# Received any DeathLinks?
|
|
0x17000002, # BNEZ T8, [forward 0x02]
|
|
# Is the player already dead?
|
|
0x9169AB84, # LBU T1, 0xAB84 (T3)
|
|
0x03E00008, # JR RA TODO: Ice Traps
|
|
0x312A0080, # ANDI T2, T1, 0x0080
|
|
0x11400002, # BEQZ T2, [forward 0x02]
|
|
0x00000000, # NOP
|
|
0x03E00008, # JR RA
|
|
# If we make it all the way here, kill the player. If Explosive Deathlink is enabled, this is where the Nitro part
|
|
# will begin.
|
|
# Set the delay timer to further ensure we don't get killed again on subsequent frames.
|
|
0x24080010, # ADDIU T0, R0, 0x0010
|
|
0xA168AA4E, # SB T0, 0xAA4E (T3)
|
|
# Give the player the "Death" status and return.
|
|
0x35290080, # ORI T1, T1, 0x0080
|
|
0x03E00008, # JR RA
|
|
0xA169AB84, # SB T1, 0xAB84 (T3)
|
|
]
|
|
|
|
deathlink_nitro_edition = [
|
|
# Alternative to the end of the above DeathLink-specific checks that kills the player with the Nitro explosion
|
|
# instead of the normal death.
|
|
|
|
# Check to see if the player is in an alright state before exploding them. If not, then the Nitro explosion spawn
|
|
# code will be aborted, and they should eventually explode after getting out of that state.
|
|
# Start by trying to get the player's state flags. If we find that something about the player object is not
|
|
# currently created, abort now so we don't try pulling from a null pointer.
|
|
0x8D64ABDC, # LW A0, 0xABDC (T3)
|
|
0x14800003, # BNEZ A0, [forward 0x03]
|
|
0x00000000, # NOP
|
|
0x03E00008, # JR RA
|
|
0x00000000, # NOP
|
|
0x94880000, # LHU T0, 0x0000 (A0)
|
|
0x15000003, # BNEZ T0, [forward 0x03]
|
|
0x8C880034, # LW T0, 0x0034 (A0)
|
|
0x03E00008, # JR RA
|
|
0x00000000, # NOP
|
|
0x15000003, # BNEZ T0, [forward 0x03]
|
|
0x00000000, # NOP
|
|
0x03E00008, # JR RA
|
|
0x00000000, # NOP
|
|
# Now that we have the player flags, check them for any unsafe states. Unsafe states so far include:
|
|
# interacting/going through a door (00200000), knocked back or grabbed by something (00008000),
|
|
# having iframes (20000000).
|
|
0x8D080000, # LW T0, 0x0000 (T0)
|
|
0x3C092020, # LUI T1, 0x2020
|
|
0x35298000, # ORI T1, T1, 0x8000
|
|
0x01095024, # AND T2, T0, T1
|
|
0x1540FFF9, # BNEZ T2, [backward 0x07]
|
|
# If we make it all the way here, explode the player.
|
|
# Set the delay timer to further ensure we don't get exploded again on subsequent frames.
|
|
0x24080010, # ADDIU T0, R0, 0x0010
|
|
0xA168AA4E, # SB T0, 0xAA4E (T3)
|
|
# Create the Nitro explosion actor with the player actor as its parent.
|
|
0x08000904, # J 0x80002410
|
|
0x240500A8, # ADDIU A1, R0, 0x00A8
|
|
]
|
|
|
|
warp_menu_opener = [
|
|
# Enables warping by pausing while holding Z + R. Un-sets the Henry escort begins flag if you warp during it.
|
|
|
|
# If Gameplay Manager Flag 00002000 is set, don't warp or pause the game at all. This flag was added in the JPN
|
|
# and PAL versions to disallow pausing when Child Henry dies (which would crash the game).
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x8D09ABC8, # LW T1, 0xABC8 (T0)
|
|
0x312A2000, # ANDI T2, T1, 0x2000
|
|
0x11400002, # BEQZ T2, [forward 0x02]
|
|
0x00000000, # NOP
|
|
0x080218FB, # J 0x800863EC
|
|
# Check if the player is holding Z and R when the game wants to pause. If they aren't, pause like normal.
|
|
# If they are, run some additional checks to see if the warp menu can be opened at the moment.
|
|
0x3C08800F, # LUI T0, 0x800F
|
|
0x9508FBA0, # LHU T0, 0xFBA0 (T0)
|
|
0x24093010, # ADDIU T1, R0, 0x3010
|
|
0x15090013, # BNE T0, T1, [forward 0x13]
|
|
# Check our custom "can warp" byte for a non-zero value. If zero, don't warp.
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x9109AA4B, # LBU T1, 0xAA4B (T0)
|
|
0x15200010, # BNEZ T1, [forward 0x10]
|
|
# Check if a "Dracula 1 intro cutscene" flag is set. If it is, don't warp as we're likely in the escape sequence.
|
|
0x9109AA8F, # LBU T1, 0xAA4B (T0)
|
|
0x312A0018, # ANDI T2, T1, 0x0018
|
|
0x1540000D, # BNEZ T2, [forward 0x0D]
|
|
0x00000000, # NOP
|
|
# Push T9 and A2 to the stack (since we'll be needing those once we return) and jump to the "Change Game State"
|
|
# function with 2 as the A0 argument (the unused Game State 2 is where the warp menu will be handled).
|
|
0x27BDFFF8, # ADDIU SP, SP, -0x08
|
|
0xAFB90000, # SW T9, 0x0000 (SP)
|
|
0xAFA60004, # SW A2, 0x0004 (SP)
|
|
# Kill the Gameplay Menu Manager pointer and set the delay timer to ensure the remote item giver hack doesn't try
|
|
# reading garbage data from the aftermentioned pointer when coming out of the warp menu. Then change the game state.
|
|
0xAD00AC0C, # SW R0, 0xAC0C (T0)
|
|
0x3419003E, # ORI T9, R0, 0x003E
|
|
0xA119278E, # SB T9, 0x278E (T0)
|
|
0x0C00014F, # JAL 0x8000053C
|
|
0x24040002, # ADDIU A0, R0, 0x0002
|
|
# Pop T9 and A2's numbers back into their registers and return without storing the pause value.
|
|
0x8FB90000, # LW T9, 0x0000 (SP)
|
|
0x8FA60004, # LW A2, 0x0004 (SP)
|
|
0x080218FB, # J 0x800863EC
|
|
0x27BD0008, # ADDIU SP, SP, 0x08
|
|
# Return storing the pause value as normal.
|
|
0x080218FB, # J 0x800863EC
|
|
0xA4782B4E # SH T8, 0x2B4E (V1)
|
|
]
|
|
|
|
give_subweapon_stopper = [
|
|
# Extension to "give subweapon" function to not change the player's weapon if the received item is a Stake or Rose.
|
|
# Can also increment the Ice Trap counter if getting a Rose or jump to prev_subweapon_dropper if applicable.
|
|
0x24090011, # ADDIU T1, R0, 0x0011
|
|
0x11240009, # BEQ T1, A0, [forward 0x09]
|
|
0x24090012, # ADDIU T1, R0, 0x0012
|
|
0x11240003, # BEQ T1, A0, [forward 0x03]
|
|
0x9465618A, # LHU A1, 0x618A (V1)
|
|
0xA46D618A, # SH T5, 0x618A (V1)
|
|
0x0804F0BF, # J 0x8013C2FC
|
|
0x3C098039, # LUI T1, 0x8039
|
|
0x912A9BE2, # LBU T2, 0x9BE2 (T1)
|
|
0x254A0001, # ADDIU T2, T2, 0x0001
|
|
0xA12A9BE2, # SB T2, 0x9BE2 (T1)
|
|
0x0804F0BF, # J 0x8013C2FC
|
|
]
|
|
|
|
file_select_stage_position_setter = [
|
|
# Sets a custom string on a File Select file for the stage number for that stage's actual randomizer position.
|
|
# Rando stage positions can have more than just numbers, so setting the text using a text pool instead of a given
|
|
# number is necessary.
|
|
|
|
# Call the "get message from pool" function with A0 = the start of the pool at 0x0F003A80, and A1 = the stage number
|
|
# minus 1.
|
|
0x3C198008, # LUI T9, 0x8008
|
|
0x37393FA0, # ORI T9, T9, 0x3FA0
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x8D088D8C, # LW T0, 0x8D8C (T0)
|
|
0x0320F809, # JALR RA, T9
|
|
0x25043A80, # ADDIU A0, T0, 0x3A80
|
|
# Call the "set custom formatted text" function on the stage number textbox using the resulting pointer from the
|
|
# above call, and then jump back.
|
|
0x3C198008, # LUI T9, 0x8008
|
|
0x37393864, # ORI T9, T9, 0x3864
|
|
0x8E040014, # LW A0, 0x0014 (S0)
|
|
0x0320F809, # JALR RA, T9
|
|
0x00022825, # OR A1, R0, V0
|
|
0x0BC00493, # J 0x0F00124C
|
|
]
|
|
|
|
pause_menu_stage_position_setter = [
|
|
# Sets a custom string on the Pause Menu for the stage number for that scene's stage's actual randomizer position.
|
|
# Rando stage positions can have more than just numbers, so setting the text using a text pool instead of a given
|
|
# number is necessary.
|
|
|
|
# Call the "get message from pool" function with A0 = the start of the pool at 0x0F003A80, and A1 = the stage number
|
|
# minus 1.
|
|
0x3C0F0F00, # LUI T7, 0x0F00
|
|
0x25EF4D28, # ADDIU T7, T7, 0x4D28
|
|
0x030F1821, # ADDU V1, T8, T7
|
|
0x90650000, # LBU A1, 0x0000 (V1)
|
|
0x3C198008, # LUI T9, 0x8008
|
|
0x37393FA0, # ORI T9, T9, 0x3FA0
|
|
0x27BDFFF8, # ADDIU SP, SP, -0x08
|
|
0xAFA80000, # SW T0, 0x0000 (SP)
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x8D088D4C, # LW T0, 0x8D4C (T0)
|
|
0x0320F809, # JALR RA, T9
|
|
0x25044FB0, # ADDIU A0, T0, 0x4FB0
|
|
# Jump ahead to the "textboxObject_setParams_customFormattedString" block of Reinhardt/Carrie-specific code with
|
|
# the resulting pointer from the above call in A1.
|
|
0x8FA80000, # LW T0, 0x0000 (SP)
|
|
0x27BD0008, # ADDIU SP, SP, 0x08
|
|
0x0BC00220, # J 0x0F000880
|
|
0x00022825, # OR A1, R0, V0
|
|
]
|
|
|
|
pause_menu_extra_scene_checks = [
|
|
# Additional scene-specific checks for displaying the Pause Menu's stage number. Specifically, for the
|
|
# Medusa/Algenie Arena and Fan Meeting Rooms to check which stage's setup it's using.
|
|
0x3C02801D, # LUI V0, 0x801D
|
|
0x9042AAB4, # LBU V0, 0xAAB4 (V0)
|
|
# If we're in the Algenie/Medusa Arena scene, check which alt setup flag is set and consider ourselves actually in
|
|
# either Tunnel or Waterway.
|
|
0x34010013, # ORI AT, R0, 0x0013
|
|
0x14610007, # BNE V1, AT, [forward 0x07]
|
|
0x304F0040, # ANDI T7, V0, 0x0040
|
|
0x55E00004, # BNEZL T7, [forward 0x04]
|
|
0x34080007, # ORI T0, R0, 0x0007 <- Tunnel scene ID
|
|
0x304F0020, # ANDI T7, V0, 0x0020
|
|
0x55E00001, # BNEZL T7, [forward 0x01]
|
|
0x34080008, # ORI T0, R0, 0x0008 <- Waterway scene ID
|
|
0x0BC001FA, # J 0x0F0007E8
|
|
# If we're in the Fan Meeting Room scene, check which alt setup flag is set and consider ourselves actually in
|
|
# either Castle Center Basement or The Outer Wall.
|
|
0x34010019, # ORI AT, R0, 0x0019
|
|
0x14610006, # BNE V1, AT, [forward 0x06]
|
|
0x304F0040, # ANDI T7, V0, 0x0040
|
|
0x55E00004, # BNEZL T7, [forward 0x04]
|
|
0x34080009, # ORI T0, R0, 0x0009 <- CC Basement scene ID
|
|
0x304F0010, # ANDI T7, V0, 0x0010
|
|
0x55E00001, # BNEZL T7, [forward 0x01]
|
|
0x3408002A, # ORI T0, R0, 0x002A <- Outer Wall scene ID
|
|
0x0BC001FA, # J 0x0F0007E8
|
|
0x00000000, # NOP
|
|
]
|
|
|
|
npc_item_rework = [
|
|
# Hack to make NPC items show item textboxes when received.
|
|
0x00180000,
|
|
0x00240000, # Item values
|
|
0x001B0000,
|
|
0x001F0000,
|
|
0x00200000,
|
|
0x00000000,
|
|
0x3C088040, # LUI T0, 0x8040
|
|
0x00044880, # SLL T1, A0, 2
|
|
0x01094021, # ADDIU T0, T0, T1
|
|
0x950AC6E8, # LHU T2, 0xC6E8 (T0)
|
|
0x9519C6EA, # LHU T9, 0xC6EA (T0)
|
|
0x314B00FF, # ANDI T3, T2, 0x00FF
|
|
0x3C0C801D, # LUI T4, 0x801D
|
|
0xA18BAA4C, # SB T3, 0xAA4C (T4)
|
|
# Decrement the Countdown if applicable.
|
|
0x314D8000, # ANDI T5, T2, 0x8000
|
|
0x11A00008, # BEQZ T5, [forward 0x08]
|
|
0x918AAE79, # LBU T2, 0xAE79 (T4)
|
|
0x3C088040, # LUI T0, 0x8040
|
|
0x010A5821, # ADDU T3, T0, T2
|
|
0x916EC4D0, # LBU T6, 0xC4D0 (T3)
|
|
0x018E7821, # ADDU T7, T4, T6
|
|
0x91F8ABA0, # LBU T8, 0xABA0 (T7)
|
|
0x2718FFFF, # ADDIU T8, T8, 0xFFFF
|
|
0xA1F8ABA0, # SB T8, 0xABA0 (T7)
|
|
# Copy from the ROM the off-world Item string corresponding to that NPC Item.
|
|
0x3C0B00FA, # LUI T3, 0x00FA
|
|
# Shift the flag ID up by 8 and add it to 0xFA0000 to get the start address for this NPC Item's string.
|
|
0x00194A00, # SLL T1, T9, 8
|
|
0x01692021, # ADDU A0, T3, T1
|
|
0x3C058001, # LUI A1, 0x8001
|
|
0x34A5E5CC, # ORI A1, A1, 0xE5CC
|
|
# Run the "rom copy" function with all necessary arguments. We should return to the NPC code right after that.
|
|
0x0800690B, # J 0x8001A42C
|
|
0x34060100, # ORI A2, R0, 0x0100
|
|
]
|
|
|
|
double_component_checker = [
|
|
# When checking to see if a bomb component can be placed at a cracked wall, this will run if the code lands at the
|
|
# "no need to set 2" outcome to see if the other can be set.
|
|
|
|
# Mandragora checker
|
|
# Check the "set Mandragora" flag for the wall we are currently looking at.
|
|
0x8E080054, # LW T0, 0x0054 (S0)
|
|
0x15000004, # BNEZ T0, [forward 0x04]
|
|
0x3C09801D, # LUI T1, 0x801D
|
|
0x912AAA7E, # LBU T2, 0xAA7E (T1)
|
|
0x10000003, # B [forward 0x03]
|
|
0x314A0040, # ANDI T2, T2, 0x0040
|
|
0x912AAA84, # LBU T2, 0xAA84 (T1)
|
|
0x314A0080, # ANDI T2, T2, 0x0080
|
|
0x15400005, # BNEZ T2, [forward 0x05]
|
|
# If the flag is not set, check to see if we have Mandragora in the inventory.
|
|
0x912BAB56, # LBU T3, 0xAB56 (T1)
|
|
0x11600003, # BEQZ T3, [forward 0x03]
|
|
0x240C0001, # ADDIU T4, R0, 0x0001
|
|
0x03E00008, # JR RA
|
|
0xA60C004C, # SH T4, 0x004C (S0)
|
|
0x3C0A8000, # LUI T2, 0x8000
|
|
0x354A1E30, # ORI T2, T2, 0x1E30
|
|
0x01400008, # JR T2
|
|
0x00000000, # NOP
|
|
# Nitro checker
|
|
# Check the "set Magical Nitro" flag for the wall we are currently looking at.
|
|
0x8E080054, # LW T0, 0x0054 (S0)
|
|
0x15000004, # BNEZ T0, [forward 0x04]
|
|
0x3C09801D, # LUI T1, 0x801D
|
|
0x912AAA7E, # LBU T2, 0xAA7E (T1)
|
|
0x10000003, # B [forward 0x03]
|
|
0x314A0080, # ANDI T2, T2, 0x0080
|
|
0x912AAA83, # LBU T2, 0xAA83 (T1)
|
|
0x314A0001, # ANDI T2, T2, 0x0001
|
|
0x15400005, # BNEZ T2, [forward 0x05]
|
|
# If the flag is not set, check to see if we have Magical Nitro in the inventory.
|
|
0x912BAB55, # LBU T3, 0xAB55 (T1)
|
|
0x11600003, # BEQZ T3, [forward 0x03]
|
|
0x240C0001, # ADDIU T4, R0, 0x0001
|
|
0x03E00008, # JR RA
|
|
0xA60C004E, # SH T4, 0x004E (S0)
|
|
0x3C0A8000, # LUI T2, 0x8000
|
|
0x354A1E30, # ORI T2, T2, 0x1E30
|
|
0x01400008, # JR T2
|
|
0x00000000, # NOP
|
|
]
|
|
|
|
basement_seal_checker = [
|
|
# This will run specifically for the downstairs crack to see if the seal has been removed before then deciding to
|
|
# let the player set the bomb components or not, giving them the "Furious Nerd Curse" message if not. Unlike in the
|
|
# vanilla game, Magical Nitro and Mandragora is not replenish-able, so an anti-softlock measure is necessary to
|
|
# ensure they aren't wasted trying to blow up a currently-impervious wall.
|
|
0x8E080054, # LW T0, 0x0054 (S0)
|
|
0x1500000B, # BNEZ T0, [forward 0x0B]
|
|
0x3C09801D, # LUI T1, 0x801D
|
|
0x9129AA7D, # LBU T1, 0xAA7D (T1)
|
|
0x31290001, # ANDI T1, T1, 0x0001
|
|
0x15200007, # BNEZ T1, [forward 0x07]
|
|
0x00000000, # NOP
|
|
0x26040008, # ADDIU A0, S0, 0x0008
|
|
0x2605000E, # ADDIU A1, S0, 0x000E
|
|
0x3C0A8000, # LUI T2, 0x8000
|
|
0x354A1E30, # ORI T2, T2, 0x1E30
|
|
0x01400008, # JR T2
|
|
0x24060008, # ADDIU A2, R0, 0x0008
|
|
0x0B8000B0, # J 0x0E0002C0
|
|
0x00000000, # NOP
|
|
]
|
|
|
|
mandragora_with_nitro_setter = [
|
|
# When setting a Nitro, if Mandragora is in the inventory too and the wall's "Mandragora set" flag is not set, this
|
|
# will automatically subtract a Mandragora from the inventory and set its flag so the wall can be blown up in just
|
|
# one interaction instead of two.
|
|
0x8E080054, # LW T0, 0x0054 (S0)
|
|
0x15000004, # BNEZ T0, [forward 0x04]
|
|
0x3C09801C, # LUI T1, 0x801C
|
|
0x340AAA7E, # ORI T2, R0, 0xAA7E
|
|
0x10000003, # B [forward 0x03]
|
|
0x240B0040, # ADDIU T3, R0, 0x0040
|
|
0x340AAA84, # ORI T2, R0, 0xAA84
|
|
0x240B0080, # ADDIU T3, R0, 0x0080
|
|
0x012A6025, # OR T4, T1, T2
|
|
0x918D0000, # LBU T5, 0x0000 (T4)
|
|
0x01AB7024, # AND T6, T5, T3
|
|
0x15C00007, # BNEZ T6, [forward 0x07]
|
|
0x3C09801D, # LUI T1, 0x801D
|
|
0x912FAB56, # LBU T7, 0xAB56 (T1)
|
|
0x11E00004, # BEQZ T7, [forward 0x04]
|
|
0x25EFFFFF, # ADDIU T7, T7, 0xFFFF
|
|
0xA12FAB56, # SB T7, 0xAB56 (T1)
|
|
0x016DC025, # OR T8, T3, T5
|
|
0xA1980000, # SB T8, 0x0000 (T4)
|
|
0x3C0A8000, # LUI T2, 0x8000
|
|
0x354A48C4, # ORI T2, T2, 0x48C4
|
|
0x01400008, # JR T2
|
|
0x00000000, # NOP
|
|
]
|
|
|
|
cutscene_active_checkers = [
|
|
# Returns True (1) if we are NOT currently in a cutscene or False (0) if we are in V0. Custom actor spawn condition
|
|
# for things like the Cornell intro actors in Castle Center.
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x9109AE8B, # LBU T1, 0xAE8B (T0)
|
|
0x11200002, # BEQZ T1, [forward 0x02]
|
|
0x24020000, # ADDIU V0, R0, 0x0000
|
|
0x24020001, # ADDIU V0, R0, 0x0001
|
|
0x03E00008, # JR RA
|
|
0x00000000,
|
|
# Returns True (1) if we are currently in a cutscene or False (0) if we are NOT in V0. Custom actor spawn condition
|
|
# for things like the Cornell intro actors in Castle Center.
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x9109AE8B, # LBU T1, 0xAE8B (T0)
|
|
0x11200002, # BEQZ T1, [forward 0x02]
|
|
0x24020001, # ADDIU V0, R0, 0x0001
|
|
0x24020000, # ADDIU V0, R0, 0x0000
|
|
0x03E00008, # JR RA
|
|
0x00000000,
|
|
]
|
|
|
|
stone_dog_cutscene_checker = [
|
|
# Extension to the custom spawn condition on the Stone Dog actors that checks to see if we are in the
|
|
# "meeting Malus" cutscene and, if we are, allows the Stone Dogs to spawn. Otherwise, the Stone Dogs' other spawn
|
|
# checks will proceed as normal. This fixes an edge case wherein they don't spawn if we entered the scene through
|
|
# the servant entrance door, enabling the Malus chase to be done without the dogs involved.
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x9109AE8B, # LBU T1, 0xAE8B (T0)
|
|
0x340A000E, # ORI T2, R0, 0x000E <- Meeting Malus cutscene ID
|
|
# Jump to the flag check function if we are not in the cutscene. Return now with 1 in V0 if we are.
|
|
0x112A0003, # BEQ T1, T2, [forward 0x03]
|
|
0x00000000, # NOP
|
|
0x03200008, # JR T9
|
|
0x00000000, # NOP
|
|
0x03E00008, # JR RA
|
|
0x24020001, # ADDIU V0, R0, 0x0001
|
|
]
|
|
|
|
renon_cutscene_checker = [
|
|
# Custom spawn condition that blocks the Renon's departure/pre-fight cutscene trigger from spawning if the player
|
|
# did not spend the required 30K to fight him.
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x8D08ABC0, # LW T0, 0xABC0 (T0)
|
|
0x29097531, # SLTI T1, T0, 0x7531
|
|
0x15200002, # BNEZ T1, [forward 0x02]
|
|
0x24020000, # ADDIU V0, R0, 0x0000
|
|
0x24020001, # ADDIU V0, R0, 0x0001
|
|
0x03E00008, # JR RA
|
|
0x00000000,
|
|
]
|
|
|
|
ck_door_music_player = [
|
|
# Plays Castle Keep's song if you spawn in front of the main Castle Keep entrance or Dracula's door (teleporting via
|
|
# the warp menu), haven't started the escape sequence yet (the way this is hooked means checking for the latter
|
|
# shouldn't be necessary), and if we're not in a cutscene (fun fact: this entrance is used in Cornell's intro when
|
|
# Gilles De Rais is climbing the stairs).
|
|
|
|
# Check for spawn entrance 0 or 1. If neither, put us on the routine that doesn't play the song.
|
|
0x10400005, # BEQZ V0, [forward 0x05]
|
|
0x34080001, # ORI T0, R0, 0x0001
|
|
0x10480003, # BEQ V0, T0, [forward 0x03]
|
|
0x00000000, # NOP
|
|
0x080B931D, # J 0x802E4C74
|
|
0x00000000, # NOP
|
|
# Check if there's a cutscene playing. If there isn't, allow Castle Keep's song to play.
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x9109AE8B, # LBU T1, 0xAE8B (T0)
|
|
0x11200003, # BEQZ T1, [forward 0x03]
|
|
0x00000000, # NOP
|
|
0x080B931D, # J 0x802E4C74
|
|
0x00000000, # NOP
|
|
0x080B931A, # J 0x802E4C68
|
|
0x00000000, # NOP
|
|
]
|
|
|
|
drac_condition_checker = [
|
|
# Checks the Special2 counter to see if the required amount of the goal item has been reached and disallows opening
|
|
# Dracula's doors if not.
|
|
0x24020000, # ADDIU V0, R0, 0x0000
|
|
0x3C0A801D, # LUI T2, 0x801D
|
|
0x914BAB48, # LBU T3, 0xAB48 (T2)
|
|
0x296A0000, # SLTI T2, T3, 0x0000
|
|
0x55400001, # BNEZL T2, [forward 0x01]
|
|
0x24020001, # ADDIU V0, R0, 0x0001
|
|
0x03E00008, # JR RA
|
|
0x00000000 # NOP
|
|
]
|
|
|
|
bad_ending_time_checker = [
|
|
# Extra spawn condition for the White Jewel in Dracula's chamber that checks to see if too many days have passed
|
|
# to receive the Good Ending. If so, the Bad Ending flag will be set. The jewel will be allowed to spawn regardless.
|
|
# This should account for being able to completely avoid vampire Vincent's trigger if you get the Castle Keep warp.
|
|
|
|
# Multiply the weeks counter by 7 and add that to the "current day of the week" counter to get the total days
|
|
# passed. If less than 16, don't set the Bad Ending flag.
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x9509AB1C, # LHU T1, 0xAB1C (T0)
|
|
0x950AAB1E, # LHU T2, 0xAB1E (T0)
|
|
0x340B0007, # ORI T3, R0, 0x0007
|
|
0x012B0019, # MULTU T1, T3
|
|
0x00004812, # MFLO T1
|
|
0x012A4821, # ADDU T1, T1, T2
|
|
0x292C0010, # SLTI T4, T1, 0x0010
|
|
0x15800003, # BNEZ T4, [forward 0x03]
|
|
0x9109AA95, # LBU T1, 0xAA95 (T0)
|
|
0x35290080, # ORI T1, T1, 0x0080
|
|
0xA109AA95, # SB T1, 0xAA95 (T0)
|
|
0x03E00008, # JR RA
|
|
0x34020001, # ORI V0, R0, 0x0001
|
|
]
|
|
|
|
continue_cursor_start_checker = [
|
|
# This is used to improve the Game Over screen's "Continue" menu by starting the cursor on whichever checkpoint
|
|
# is most recent instead of always on "Previously saved". If a menu has a cursor start value of 0xFF in its text
|
|
# data, this will read the byte at 0x801CAA31 to determine which option to start the cursor on.
|
|
0x240A00FF, # ADDIU T2, R0, 0x00FF
|
|
0x15480008, # BNE T2, T0, [forward 0x08]
|
|
0x286B0002, # SLTI T3, V1, 0x0002
|
|
0x15600006, # BNEZ T3, [forward 0x05]
|
|
0x8CAA0014, # LW T2, 0x0014 (A1)
|
|
0x8D4B0014, # LW T3, 0x0014 (T2)
|
|
0x3C0A801D, # LUI T2, 0x801D
|
|
0x9148AA31, # LBU T0, 0xAA31 (T2)
|
|
0x01003021, # ADDU A2, T0, R0
|
|
0xA1680073, # SB T0, 0x0073 (T3)
|
|
0x03E00008, # JR RA
|
|
0x30CF00FF # ANDI T7, A2, 0x00FF
|
|
]
|
|
|
|
savepoint_cursor_updater = [
|
|
# Sets the value at 0x801CAA31 to 0x00 after saving to let the Game Over screen's "Continue" menu know to start the
|
|
# cursor on "Previously saved" as well as updates the entrance variable for B warping.
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x9109AB95, # LBU T1, 0xAB95 (T0)
|
|
0x000948C0, # SLL T1, T1, 3
|
|
0x3C0A800C, # LUI T2, 0x800C
|
|
0x01495021, # ADDU T2, T2, T1
|
|
0x914B82EF, # LBU T3, 0x82EF (T2)
|
|
0xA10BAB93, # SB T3, 0xAB93 (T0)
|
|
0xA10BAE7B, # SB T3, 0xAE7B (T0)
|
|
0xA100AA31, # SB R0, 0xAA31 (T0)
|
|
0x03E00008, # JR RA
|
|
]
|
|
|
|
stage_start_cursor_updater = [
|
|
# Sets the value at 0x801CAA31 to 0x01 after entering a stage to let the Game Over screen's "Continue" menu know to
|
|
# start the cursor on "Restart this stage".
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x24090001, # ADDIU T1, R0, 0x0001
|
|
0xA109AA31, # SB T1, 0xAA31 (T0)
|
|
0x03E00008 # JR RA
|
|
]
|
|
|
|
load_clearer = [
|
|
# Un-sets the Death status bitflag when loading either a save or stage beginning state and sets health to full if
|
|
# it's empty, as well as clearing the multiworld buffers so things don't get mucked up on that front. Also updates
|
|
# the "Continue" menu cursor depending on which state was loaded.
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0xFD00AA48, # SD R0, 0xAA48 (T0)
|
|
0xA104AA31, # SB A0, 0xAA31 (T0)
|
|
0x9109AB84, # LBU T1, 0xAB84 (T0)
|
|
0x3129007F, # ANDI T1, T1, 0x007F
|
|
0xA109AB84, # SB T1, 0xAB84 (T0)
|
|
0x950AAB3A, # LHU T2, 0xAB3A (T0)
|
|
0x51400001, # BEQZL T2, [forward 0x01]
|
|
0x240A2710, # ADDIU T2, R0, 0x2710
|
|
0x03E00008, # JR RA
|
|
0xA50AAB3A # SH T2, 0xAB3A (T0)
|
|
]
|
|
|
|
elevator_flag_checker = [
|
|
# Extension to the map-specific elevator checks code that prevents the top elevator in Castle Center from
|
|
# activating if the bottom elevator switch is not turned on.
|
|
|
|
# Check if we are in Scene 0x0F (Castle Center Top Elevator Room). If we aren't, skip to the jump back.
|
|
0x2408000F, # ADDIU T1, R0, 0x000F
|
|
0x15030005, # BNE T0, V1, [forward 0x05]
|
|
# Check if Flag 0x105 is set (Castle Center elevator activated). If it isn't, replace the return value 0
|
|
# (elevator awaiting player) with 2 (elevator will not work at all).
|
|
0x3C09801D, # LUI T1, 0x801D
|
|
0x9129AA80, # LBU T1, 0xAA80 (T1)
|
|
0x312A0004, # ANDI T2, T1, 0x0004
|
|
0x51400001, # BEQZL T2, [forward 0x01]
|
|
0x24020002, # ADDIU V0, R0, 0x0002
|
|
0x08055CFC # J 0x801573F0
|
|
]
|
|
|
|
special2_giver = [
|
|
# Gives a Special2/Crystal/Trophy through the multiworld system, and clears the byte preventing warping.
|
|
# Can be hooked into anything; just make sure the JR T9 is replaced with a jump back to where it should be.
|
|
# It may be further modified to remove the Special2 giving part depending on what Dracula's Condition is.
|
|
0x3C09801D, # LUI T1, 0x801D
|
|
0x24080005, # ADDIU T0, R0, 0x0005
|
|
0xA128AA4C, # SB T0, 0xAA4C (T1)
|
|
0x03200008, # JR T9
|
|
0xA120AA4B, # SB R0, 0xAA4B (T1)
|
|
]
|
|
|
|
special2_giver_lizard_edition = [
|
|
# Special version of the above hack specifically for the Waterway Lizard-man Trio. It turns out the code that
|
|
# resumes the waterway music after they are dead is very spaghetti, so we are instead opting to hook into the code
|
|
# that depletes their combined health bar whenever they get hit.
|
|
|
|
# If the value being stored for the bar's new length value is 0, give their Trophy. Otherwise, return like normal.
|
|
0x15400008, # BNEZ T2, [forward 0x08]
|
|
0xA46A0000, # SH T2, 0x0000 (V1)
|
|
0x3C09801D, # LUI T1, 0x801D
|
|
# Set flag 0x2F7 (normally unused) so we know the lizards were properly exterminated.
|
|
0x9128AABE, # LBU T0, 0xAABE (T1)
|
|
0x34080001, # ORI T0, R0, 0x0001
|
|
0xA128AABE, # SB T0, 0xAABE (T1)
|
|
# Give a Special2 and un-set the "can't warp" byte.
|
|
0x24080005, # ADDIU T0, R0, 0x0005
|
|
0xA120AA4B, # SB R0, 0xAA4B (T1)
|
|
0xA128AA4C, # SB T0, 0xAA4C (T1)
|
|
0x03E00008, # JR RA
|
|
0x00000000, # NOP
|
|
]
|
|
|
|
boss_save_stopper = [
|
|
# Prevents usage of a White Jewel if in a boss fight. Important for the lizard-man trio in Waterway as escaping
|
|
# their fight by saving/reloading can render a Special2 permanently missable.
|
|
0x24080001, # ADDIU T0, R0, 0x0001
|
|
0x15030005, # BNE T0, V1, [forward 0x05]
|
|
0x3C088035, # LUI T0, 0x8035
|
|
0x9108F7D8, # LBU T0, 0xF7D8 (T0)
|
|
0x24090020, # ADDIU T1, R0, 0x0020
|
|
0x51090001, # BEQL T0, T1, [forward 0x01]
|
|
0x24020000, # ADDIU V0, R0, 0x0000
|
|
0x03E00008 # JR RA
|
|
]
|
|
|
|
music_modifier = [
|
|
# Uses the ID of a song about to be played to pull a switcheroo by grabbing a new ID from a custom table to play
|
|
# instead. A hacky way to circumvent song IDs in the compressed overlays' "play song" function calls, but it works!
|
|
0xAFBF001C, # SW RA, 0x001C (SP)
|
|
0x0C004A6B, # JAL 0x800129AC
|
|
0x44800000, # MTC1 R0, F0
|
|
0x10400003, # BEQZ V0, [forward 0x03]
|
|
0x3C088040, # LUI T0, 0x8040
|
|
0x01044821, # ADDU T1, T0, A0
|
|
0x9124CD20, # LBU A0, 0xCD20 (T1)
|
|
0x08004E64 # J 0x80013990
|
|
]
|
|
|
|
music_comparer_modifier = [
|
|
# The same as music_modifier, but for the function that compares the "song to play" ID with the one that's currently
|
|
# playing. This will ensure the randomized music doesn't reset when going through a loading zone in Villa or CC.
|
|
0x3C088040, # LUI T0, 0x8040
|
|
0x01044821, # ADDU T1, T0, A0
|
|
0x9124CD20, # LBU A0, 0xCD20 (T1)
|
|
0x08004A60, # J 0x80012980
|
|
]
|
|
|
|
item_customizer = [
|
|
# Allows changing an item's appearance settings independent of what it actually is by changing things in the item
|
|
# actor's data as it's being created for some other custom functions to then utilize.
|
|
0x000F4202, # SRL T0, T7, 8
|
|
0x31090080, # ANDI T1, T0, 0x0080
|
|
0x01094023, # SUBU T0, T0, T1
|
|
0xA0C80044, # SB T0, 0x0044 (A2)
|
|
0xA0C90045, # SB T1, 0x0045 (A2)
|
|
0x31EF00FF, # ANDI T7, T7, 0x00FF
|
|
0x03E00008, # JR RA
|
|
0xA4CF0038 # SH T7, 0x0038 (A2)
|
|
]
|
|
|
|
pickup_model_switcher = [
|
|
# Determines a pickup's model appearance by checking to see if a different "appearance pickup" ID was written in a
|
|
# specific spot in the actor's data; if one wasn't, then the appearance value will be grabbed from the pickup's
|
|
# entry in the pickup property table like normal instead.
|
|
0x92080044, # LBU T0, 0x0044 (S0)
|
|
0x55000001, # BNEZL T0, [forward 0x01]
|
|
0x01004825, # OR T1, T0, R0
|
|
0x03E00008, # JR RA
|
|
0xAFA7002C, # SW A3, 0x002C (SP)
|
|
]
|
|
|
|
pickup_spawn_height_switcher = [
|
|
# Same as the above, but for the pickup spawn height if it's taking the appearance of a higher-spawning Item instead
|
|
# of the model.
|
|
0x92180044, # LBU T8, 0x0044 (S0)
|
|
0x57000001, # BNEZL T8, [forward 0x01]
|
|
0x03007825, # OR T7, T8, R0
|
|
0x03E00008, # JR RA
|
|
0x01E40019, # MULTU T7, A0
|
|
]
|
|
|
|
pickup_spin_speed_switcher = [
|
|
# Same as the above, but for the pickup spin speed.
|
|
0x92080044, # LBU T0, 0x0044 (S0)
|
|
0x55000001, # BNEZL T0, [forward 0x01]
|
|
0x01004825, # OR T1, T0, R0
|
|
0x03E00008, # JR RA
|
|
0x3C028019, # LUI V0, 0x8019
|
|
]
|
|
|
|
pickup_shine_size_switcher = [
|
|
# Same as the above, but for the size of the shine on the pickup.
|
|
0x92080044, # LBU T0, 0x0044 (S0)
|
|
0x55000001, # BNEZL T0, [forward 0x01]
|
|
0x01007825, # OR T7, T0, R0
|
|
0x03E00008, # JR RA
|
|
0x3C048019, # LUI A0, 0x8019
|
|
]
|
|
|
|
pickup_shine_height_switcher = [
|
|
# Same as the above, but for the height of the shine on the pickup.
|
|
0x92080044, # LBU T0, 0x0044 (S0)
|
|
0x55000001, # BNEZL T0, [forward 0x01]
|
|
0x0100C825, # OR T9, T0, R0
|
|
0x03E00008, # JR RA
|
|
0x24050015, # ADDIU A1, R0, 0x0015
|
|
]
|
|
|
|
three_hit_item_flags_setter = [
|
|
# As the function to create items from the 3HB item lists iterates through said item lists, this will pass unique
|
|
# flag values to each item when calling the "create item instance" function by adding to the flag value the number
|
|
# of passed iterations so far.
|
|
0x96E8000A, # LHU T0, 0x000A (S7)
|
|
0x01124021, # ADDU T0, T0, S2
|
|
0xAFA80010, # SW T0, 0x0010
|
|
0x96E90008, # LHU T1, 0x0008 (S7)
|
|
0x02495006, # SRLV T2, T1, S2
|
|
0x314B0001, # ANDI T3, T2, 0x0001
|
|
0x55600001, # BNEZL T3, [forward 0x01]
|
|
0x34E70800, # ORI A3, A3, 0x0800
|
|
0x08058E56, # J 0x80163958
|
|
]
|
|
|
|
chandelier_item_flags_setter = [
|
|
# Same as the above, but for the unique function made specifically and ONLY for the Villa foyer chandelier's item
|
|
# list. KCEK, why the heck did you have to do this to me!?
|
|
0x96C8000A, # LHU T0, 0x000A (S6)
|
|
0x01144021, # ADDU T0, T0, S4
|
|
0xAFA80010, # SW T0, 0x0010
|
|
0x96C90008, # LHU T1, 0x0008 (S6)
|
|
0x02895006, # SRLV T2, T1, S4
|
|
0x314B0001, # ANDI T3, T2, 0x0001
|
|
0x55600001, # BNEZL T3, [forward 0x01]
|
|
0x34E70800, # ORI A3, A3, 0x0800
|
|
0x08058E56, # J 0x80163958
|
|
]
|
|
|
|
prev_subweapon_spawn_checker = [
|
|
# When picking up a subweapon, this will check to see if it's different from the one the player already had (if
|
|
# they did have one) and jump to the prev_subweapon_dropper hack, which will spawn a subweapon actor of what they
|
|
# had before directly behind them as well as save the player's old subweapon level to it. Also increases the
|
|
# weapon level by multiples if picking up a subweapon with a level higher than 0 saved to it.
|
|
|
|
0x100D0E0F, # Previous sub-weapon pickup IDs.
|
|
# Check if the player's old subweapon ID is 0 or the same as the new one. If the former is true, skip the weapon
|
|
# drop routine entirely. If the latter is true, branch to where we will increment the weapon level.
|
|
0x1180000E, # BEQZ T4, [forward 0x0E]
|
|
0x00000000, # NOP
|
|
0x11850008, # BEQ T4, A1, [forward 0x08]
|
|
# Set the subweapon level to 0 and drop the old subweapon with said old level saved to it.
|
|
0x3C0A8040, # LUI T2, 0x8040
|
|
0x014C5021, # ADDU T2, T2, T4
|
|
0x9144D23F, # LBU A0, 0xD23F (T2)
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x9505AE26, # LHU A1, 0xAE26 (T0)
|
|
0x0C0FF4C0, # JAL 0x803FD300
|
|
0xA500AE26, # SH R0, 0xAE26 (T0)
|
|
0x10000005, # B [forward 0x05]
|
|
# If picking up an instance of the same weapon, increase the weapon level by 1.
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x9509AE26, # LHU T1, 0xAE26 (T0)
|
|
0x25290001, # ADDIU T1, T1, 0x0001
|
|
0xA509AE26, # SH T1, 0xAE26 (T0)
|
|
# Increase the player's subweapon level by the amount we grabbed from the new subweapon pickup and then clear that
|
|
# value for the next Item we receive. This will happen regardless of whether we dropped a subweapon or not.
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x9509AE26, # LHU T1, 0xAE26 (T0)
|
|
0x910AAA20, # LBU T2, 0xAA20 (T0)
|
|
0x012A4821, # ADDU T1, T1, T2
|
|
# Cap the weapon level at 02.
|
|
0x292B0003, # SLTI T3, T1, 0x0003
|
|
0x51600001, # BEQZL T3, [forward 0x01]
|
|
0x34090002, # ORI T1, R0, 0x0002
|
|
0xA509AE26, # SH T1, 0xAE26 (T0)
|
|
0xA500AA20, # SH R0, 0xAA20 (T0)
|
|
# Play the subweapon pickup sound since we hooked into that function call.
|
|
0x0C0059BE, # JAL 0x800166F8
|
|
0x240401F5, # ADDIU A0, R0, 0x01F5
|
|
# Return to the "give subweapon" routine.
|
|
0x08023E9E, # J 0x8008FA78
|
|
]
|
|
|
|
subweapon_surface_checker = [
|
|
# During the process of remotely giving an item received via multiworld, this will check to see if the item being
|
|
# received is a subweapon and, if it is, wait until the player is not above an abyss or instant kill surface before
|
|
# giving it. This is to ensure dropped previous subweapons won't land somewhere inaccessible.
|
|
0x2408000D, # ADDIU T0, R0, 0x000D
|
|
0x11040006, # BEQ T0, A0, [forward 0x06]
|
|
0x2409000E, # ADDIU T1, R0, 0x000E
|
|
0x11240004, # BEQ T1, A0, [forward 0x04]
|
|
0x2408000F, # ADDIU T0, R0, 0x000F
|
|
0x11040002, # BEQ T0, A0, [forward 0x02]
|
|
0x24090010, # ADDIU T1, R0, 0x0010
|
|
0x1524000B, # BNE T1, A0, [forward 0x0B]
|
|
0x3C0A800D, # LUI T2, 0x800D
|
|
0x8D4A7B5C, # LW T2, 0x7B5C (T2)
|
|
0x1140000E, # BEQZ T2, [forward 0x0E]
|
|
0x00000000, # NOP
|
|
0x914A0001, # LBU T2, 0x0001 (T2)
|
|
0x240800A2, # ADDIU T0, R0, 0x00A2
|
|
0x110A000A, # BEQ T0, T2, [forward 0x0A]
|
|
0x24090092, # ADDIU T1, R0, 0x0092
|
|
0x112A0008, # BEQ T1, T2, [forward 0x08]
|
|
0x24080080, # ADDIU T0, R0, 0x0080
|
|
0x110A0006, # BEQ T0, T2, [forward 0x06]
|
|
0x956C00DD, # LHU T4, 0x00DD (T3)
|
|
0xA1600000, # SB R0, 0x0000 (T3)
|
|
0x258C0001, # ADDIU T4, T4, 0x0001
|
|
0x080FF8D0, # J 0x803FE340
|
|
0xA56C00DD, # SH T4, 0x00DD (T3)
|
|
0x00000000, # NOP
|
|
0x03E00008 # JR RA
|
|
]
|
|
|
|
countdown_number_displayer = [
|
|
# Displays a number below the HUD health of however many items are left to find in whichever stage the player is in.
|
|
# Which number in the save file to display depends on which stage map the player is currently on. It can track
|
|
# either items marked progression only or all locations in the stage.
|
|
# Courtesy of Moisés; see print_text_ovl.c in the src folder for the C source code.
|
|
0x27BDFFE8,
|
|
0xAFBF0014,
|
|
0x0C000958,
|
|
0x24040007,
|
|
0x0C020BF8,
|
|
0x00402025,
|
|
0x8FBF0014,
|
|
0x27BD0018,
|
|
0x03E00008,
|
|
0x00000000,
|
|
0x8C820038,
|
|
0x03E00008,
|
|
0x0002102B,
|
|
0x27BDFFD8,
|
|
0xAFA5002C,
|
|
0x00A07025,
|
|
0x3C018040,
|
|
0xC424C4C4,
|
|
0x3C05801D,
|
|
0xAFBF0024,
|
|
0x00AE2821,
|
|
0x3C078040,
|
|
0x240F0002,
|
|
0xAFAF0014,
|
|
0x8CE7C4C0,
|
|
0x90A5ABA0,
|
|
0xAFA00018,
|
|
0x00003025,
|
|
0x0C020D74,
|
|
0xE7A40010,
|
|
0x8FBF0024,
|
|
0x27BD0028,
|
|
0x03E00008,
|
|
0x00000000,
|
|
0x00A03025,
|
|
0x27BDFFE8,
|
|
0x3C05801D,
|
|
0xAFBF0014,
|
|
0x00A62821,
|
|
0x0C020E69,
|
|
0x90A5ABA0,
|
|
0x8FBF0014,
|
|
0x27BD0018,
|
|
0x03E00008,
|
|
0x00000000,
|
|
0x27BDFFE8,
|
|
0xAFBF0014,
|
|
0x3C058040,
|
|
0x3C068040,
|
|
0x8CC6C4C4,
|
|
0x0C020ECF,
|
|
0x8CA5C4C0,
|
|
0x8FBF0014,
|
|
0x27BD0018,
|
|
0x03E00008,
|
|
0x00000000,
|
|
0x27BDFFE8,
|
|
0xAFBF0014,
|
|
0x0C020FC8,
|
|
0x00000000,
|
|
0x8FBF0014,
|
|
0x27BD0018,
|
|
0x03E00008,
|
|
0x00000000,
|
|
0xC2D90000,
|
|
0x42B10000,
|
|
0x00000000,
|
|
0x00000000]
|
|
|
|
countdown_number_manager = [
|
|
# Updates the Countdown number every frame. Which number in the save file it refers to depends on the map ID.
|
|
0x01020203, # Map ID offset table start
|
|
0x03031104,
|
|
0x05090909,
|
|
0x12121209,
|
|
0x00000013,
|
|
0x1010130F,
|
|
0x1009110E,
|
|
0x130D0B0B,
|
|
0x0B0C0C08,
|
|
0x0807070A,
|
|
0x0F0F0613,
|
|
0x13131013,
|
|
0x13130000, # Table end
|
|
# Creates the textbox object and saves the pointer to it.
|
|
0x0C0FF0F0, # JAL 0x803FC3C0
|
|
0x00000000, # NOP
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0xA100AA44, # SB R0, 0xAA44 (T0)
|
|
0x08006DDA, # J 0x8001B768
|
|
0xAD02AA40, # SW V0, 0xAA40 (T0)
|
|
# Initializes the countdown number after checking if the textbox data is created.
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x9109AA44, # LBU T1, 0xAA44 (T0)
|
|
0x15200010, # BNEZ T1, [forward 0x10]
|
|
0x8D04AA40, # LW A0, 0xAA40 (T0)
|
|
0x1080000C, # BEQZ A0, [forward 0x0C]
|
|
0x00000000, # NOP
|
|
0x0C0FF0F9, # JAL 0x803FC3E4
|
|
0x00000000, # NOP
|
|
0x10400008, # BEQZ V0, [forward 0x08]
|
|
0x00000000, # NOP
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0xA102AA44, # SB V0, 0xAA44 (T0)
|
|
0x9109AE79, # LBU T1, 0xAE79 (T0)
|
|
0x3C0A8040, # LUI T2, 0x8040
|
|
0x01495021, # ADDU T2, T2, T1
|
|
0x0C0FF0FD, # JAL 0x803FC3F4
|
|
0x9145C4D0, # LBU A1, 0xC4D0 (T2)
|
|
0x08005F33, # J 0x80017CCC
|
|
0x00000000, # NOP
|
|
# Updates the color of the number depending on what it currently is.
|
|
# 0 = Dark brown Same as the initial count = Green Otherwise = Light brown
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x9109AB91, # LBU T1, 0xAB91 (T0)
|
|
0x3C0A8040, # LUI T2, 0x8040
|
|
0x01495021, # ADDU T2, T2, T1
|
|
0x914BC4D0, # LBU T3, 0xC4D0 (T2)
|
|
0x010B6821, # ADDU T5, T0, T3
|
|
0x91ACABA0, # LBU T4, 0xABA0 (T5)
|
|
0x3C0A8040, # LUI T2, 0x8040
|
|
0x016A5021, # ADDU T2, T3, T2
|
|
0x914EC7D0, # LBU T6, 0xC7D0 (T2)
|
|
0x11800009, # BEQZ T4, [forward 0x09]
|
|
0x24050007, # ADDIU A1, R0, 0x0007
|
|
0x118E0007, # BEQ T4, T6, [forward 0x07]
|
|
0x24050002, # ADDIU A1, R0, 0x0002
|
|
0x24050006, # ADDIU A1, R0, 0x0006
|
|
0x00000000, # NOP
|
|
0x00000000,
|
|
0x00000000,
|
|
0x00000000,
|
|
0x00000000,
|
|
0x0C0FF128, # JAL 0x803FC4A0
|
|
0x8D04AA40, # LW A0, 0xAA40 (T0)
|
|
# Updates the number being displayed.
|
|
0x3C04801D, # LUI A0, 0x801D
|
|
0x8C84AA40, # LW A0, 0xAA40 (A0)
|
|
0x0C0FF112, # JAL 0x803FC448
|
|
0x000B2821, # ADDU A1, R0, T3
|
|
# Updates the position of the number depending on what our "demo number" currently is.
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x8D04AA40, # LW A0, 0xAA40 (T0)
|
|
0x9109AA4A, # LBU T1, 0xAA4A (T0)
|
|
0x340AC2D9, # ORI T2, R0, 0xC2D9
|
|
0x11200009, # BEQZ T1, [forward 0x09]
|
|
0x340B42B1, # ORI T3, R0, 0x42B1
|
|
0x312C0001, # ANDI T4, T1, 0x0001
|
|
0x55800006, # BNEZL T4, [forward 0x06]
|
|
0x340B43B1, # ORI T3, R0, 0x43B1
|
|
0x312C0002, # ANDI T4, T1, 0x0002
|
|
0x11800003, # BEQZ T4, [forward 0x02]
|
|
0x00000000, # NOP
|
|
0x340A42E1, # ORI T2, R0, 0x42E1
|
|
0x340B42CC, # ORI T3, R0, 0x42CC
|
|
0x3C0D8040, # LUI T5, 0x8040
|
|
0xA5AAC4C0, # SH T2, 0xC4C0 (T5)
|
|
0x0C0FF11D, # JAL 0x803FC474
|
|
0xA5ABC4C4, # SH T3, 0xC4C4 (T5)
|
|
0x08005F33, # J 0x80017CCC
|
|
0x00000000, # NOP
|
|
# Changes the number's position when pausing.
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x9109AA4A, # LBU T1, 0xAA4A (T0)
|
|
0x35290002, # ORI T1, T1, 0x0002
|
|
0x08021BA6, # J 0x80086E98
|
|
0xA109AA4A, # SB T1, 0xAA4A (T0)
|
|
# Changes the number's position when un-pausing.
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x9109AA4A, # LBU T1, 0xAA4A (T0)
|
|
0x312900FD, # ANDI T1, T1, 0x00FD
|
|
0x08021B0A, # J 0x80086C28
|
|
0xA109AA4A, # SB T1, 0xAA4A (T0)
|
|
# Hides the number whenever the HUD vanishes (during cutscenes, etc.)
|
|
0xA20A0001, # SB T2, 0x0001 (S0)
|
|
0x3C0B801D, # LUI T3, 0x801D
|
|
0x916CAA4A, # LBU T4, 0xAA4A (T3)
|
|
0x358C0001, # ORI T4, T4, 0x0001
|
|
0x03E00008, # JR RA
|
|
0xA16CAA4A, # SB T4, 0xAA4A (T3)
|
|
0x00000000, # NOP
|
|
# Un-hides the number whenever the HUD re-appears (after a cutscene ends, etc.)
|
|
0xA2000001, # SB R0, 0x0001 (S0)
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x9109AA4A, # LBU T1, 0xAA4A (T0)
|
|
0x312900FE, # ANDI T1, T1, 0x00FE
|
|
0x03E00008, # JR RA
|
|
0xA109AA4A, # SB T1, 0xAA4A (T0)
|
|
0x00000000, # NOP
|
|
# Decrements the Countdown number if the item picked up has a non-zero set in its field 0x45.
|
|
0x92080045, # LBU T0, 0x0045 (S0)
|
|
0x11000009, # BEQZ T0, [forward 0x09]
|
|
0x3C09801D, # LUI T1, 0x801D
|
|
0x912AAE79, # LBU T2, 0xAE79 (T1)
|
|
0x3C0B8040, # LUI T3, 0x8040
|
|
0x016A5821, # ADDU T3, T3, T2
|
|
0x916CC4D0, # LBU T4, 0xC4D0 (T3)
|
|
0x01896821, # ADDU T5, T4, T1
|
|
0x91AEABA0, # LBU T6, 0xABA0 (T5)
|
|
0x25CEFFFF, # ADDIU T6, T6, 0xFFFF
|
|
0xA1AEABA0, # SB T6, 0xABA0 (T5)
|
|
0x03200008 # JR T9
|
|
]
|
|
|
|
new_game_extras = [
|
|
# Upon starting a new game, this will write anything extra to the save file data that the run should have at the
|
|
# start.
|
|
|
|
# The initial Countdown numbers begin here.
|
|
0x24080000, # ADDIU T0, R0, 0x0000
|
|
0x24090014, # ADDIU T1, R0, 0x0014
|
|
0x11090008, # BEQ T0, T1, [forward 0x08]
|
|
0x3C0A8040, # LUI T2, 0x8040
|
|
0x01485021, # ADDU T2, T2, T0
|
|
0x8D4AC7D0, # LW T2, 0xC7D0 (T2)
|
|
0x3C0B801D, # LUI T3, 0x801D
|
|
0x01685821, # ADDU T3, T3, T0
|
|
0xAD6AABA0, # SW T2, 0xABA0 (T3)
|
|
0x1000FFF8, # B [backward 0x08]
|
|
0x25080004, # ADDIU T0, T0, 0x0004
|
|
# start_inventory begins here.
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
# Clear the multiworld buffers and set the "received item index" to 0
|
|
0xA500ABBE, # SH R0, 0xABBE (T0)
|
|
0xFD00AA48, # SD R0, 0xAA48 (T0)
|
|
0x3C0A8040, # LUI T2, 0x8040
|
|
0x3C0B0000, # LUI T3, 0x0000 <- Starting money (upper half)
|
|
0x356B0000, # ORI T3, T3, 0x0000 <- Starting money (lower half)
|
|
0xAD0BAB40, # SW T3, 0xAB40 (T0)
|
|
0x24090000, # ADDIU T1, R0, 0x0000 <- Starting PowerUps
|
|
0xA109AE23, # SB T1, 0xAE23 (T0)
|
|
0x24090000, # ADDIU T1, R0, 0x0000 <- Starting sub-weapon
|
|
0xA109AB3F, # SB T1, 0xAB3F (T0)
|
|
0x24090000, # ADDIU T1, R0, 0x0000 <- Starting sub-weapon level
|
|
0xA109AE27, # SB T1, 0xAE27 (T0)
|
|
0x24090000, # ADDIU T1, R0, 0x0000 <- Starting Ice Traps
|
|
0xA109AA49, # SB T1, 0xAA49 (T0)
|
|
0x240C0000, # ADDIU T4, R0, 0x0000
|
|
0x240D0030, # ADDIU T5, R0, 0x0030
|
|
0x11AC0007, # BEQ T5, T4, [forward 0x07]
|
|
0x3C0A8040, # LUI T2, 0x8040
|
|
0x014C5021, # ADDU T2, T2, T4
|
|
0x814AC7A0, # LB T2, 0xC7A0 <- Starting inventory items
|
|
0xA10AAB44, # SB T2, 0xAB44 (T0)
|
|
0x25080001, # ADDIU T0, T0, 0x0001
|
|
0x1000FFF9, # B [backward 0x07]
|
|
0x258C0001, # ADDIU T4, T4, 0x0001
|
|
0x03E00008 # JR RA
|
|
]
|
|
|
|
shopsanity_stuff = [
|
|
# Everything related to shopsanity.
|
|
# Flag table (in bytes) start
|
|
0x80402010,
|
|
0x08000000,
|
|
0x00000000,
|
|
0x00000000,
|
|
0x00040200,
|
|
# Replacement item table (in halfwords) start
|
|
0x00030003,
|
|
0x00030003,
|
|
0x00030000,
|
|
0x00000000,
|
|
0x00000000,
|
|
0x00000000,
|
|
0x00000000,
|
|
0x00000000,
|
|
0x00000003,
|
|
0x00030000,
|
|
# Switches the vanilla item being bought with the randomized one, if its flag is un-set, and sets its flag.
|
|
0x3C088040, # LUI T0, 0x8040
|
|
0x01044021, # ADDU T0, T0, A0
|
|
0x9109D8CA, # LBU T1, 0xD8CA (T0)
|
|
0x3C0B8039, # LUI T3, 0x8039
|
|
0x916A9C1D, # LBU T2, 0x9C1D (T3)
|
|
0x01496024, # AND T4, T2, T1
|
|
0x15800005, # BNEZ T4, [forward 0x05]
|
|
0x01495025, # OR T2, T2, T1
|
|
0xA16A9C1D, # SB T2, 0x9C1D (T3)
|
|
0x01044021, # ADDU T0, T0, A0
|
|
0x9504D8D8, # LHU A0, 0xD8D8 (T0)
|
|
0x308400FF, # ANDI A0, A0, 0x00FF
|
|
0x0804EFFB, # J 0x8013BFEC
|
|
0x00000000, # NOP
|
|
# Switches the vanilla item model on the buy menu with the randomized item if the randomized item isn't purchased.
|
|
0x3C088040, # LUI T0, 0x8040
|
|
0x01044021, # ADDU T0, T0, A0
|
|
0x9109D8CA, # LBU T1, 0xD8CA (T0)
|
|
0x3C0B8039, # LUI T3, 0x8039
|
|
0x916A9C1D, # LBU T2, 0x9C1D (T3)
|
|
0x01495024, # AND T2, T2, T1
|
|
0x15400005, # BNEZ T2, [forward 0x05]
|
|
0x01044021, # ADDU T0, T0, A0
|
|
0x9504D8D8, # LHU A0, 0xD8D8 (T0)
|
|
0x00046202, # SRL T4, A0, 8
|
|
0x55800001, # BNEZL T4, [forward 0x01]
|
|
0x01802021, # ADDU A0, T4, R0
|
|
0x0804F180, # J 0x8013C600
|
|
0x00000000, # NOP
|
|
# Replacement item names table start.
|
|
0x00010203,
|
|
0x04000000,
|
|
0x00000000,
|
|
0x00000000,
|
|
0x00050600,
|
|
0x00000000,
|
|
# Switches the vanilla item name in the shop menu with the randomized item if the randomized item isn't purchased.
|
|
0x3C088040, # LUI T0, 0x8040
|
|
0x01064021, # ADDU T0, T0, A2
|
|
0x9109D8CA, # LBU T1, 0xD8CA (T0)
|
|
0x3C0B8039, # LUI T3, 0x8039
|
|
0x916A9C1D, # LBU T2, 0x9C1D (T3)
|
|
0x01495024, # AND T2, T2, T1
|
|
0x15400004, # BNEZ T2, [forward 0x04]
|
|
0x00000000, # NOP
|
|
0x9105D976, # LBU A1, 0xD976 (T0)
|
|
0x3C048001, # LUI A0, 8001
|
|
0x3484A100, # ORI A0, A0, 0xA100
|
|
0x0804B39F, # J 0x8012CE7C
|
|
0x00000000, # NOP
|
|
0x00000000,
|
|
0x00000000,
|
|
0x00000000,
|
|
0x00000000,
|
|
0x00000000,
|
|
# Displays "Not purchased." if the selected randomized item is nor purchased, or the current holding amount of that
|
|
# slot's vanilla item if it is.
|
|
0x3C0C8040, # LUI T4, 0x8040
|
|
0x018B6021, # ADDU T4, T4, T3
|
|
0x918DD8CA, # LBU T5, 0xD8CA (T4)
|
|
0x3C0E8039, # LUI T6, 0x8039
|
|
0x91D89C1D, # LBU T8, 0x9C1D (T6)
|
|
0x030DC024, # AND T8, T8, T5
|
|
0x13000003, # BEQZ T8, [forward 0x03]
|
|
0x00000000, # NOP
|
|
0x0804E819, # J 0x8013A064
|
|
0x00000000, # NOP
|
|
0x0804E852, # J 0x8013A148
|
|
0x820F0061, # LB T7, 0x0061 (S0)
|
|
0x00000000, # NOP
|
|
# Displays a custom item description if the selected randomized item is not purchased.
|
|
0x3C088040, # LUI T0, 0x8040
|
|
0x01054021, # ADDU T0, T0, A1
|
|
0x9109D8D0, # LBU T1, 0xD8D0 (T0)
|
|
0x3C0A8039, # LUI T2, 0x8039
|
|
0x914B9C1D, # LBU T3, 0x9C1D (T2)
|
|
0x01695824, # AND T3, T3, T1
|
|
0x15600003, # BNEZ T3, [forward 0x03]
|
|
0x00000000, # NOP
|
|
0x3C048002, # LUI A0, 0x8002
|
|
0x24849C00, # ADDIU A0, A0, 0x9C00
|
|
0x0804B39F # J 0x8012CE7C
|
|
]
|
|
|
|
special_sound_notifs = [
|
|
# Plays a distinct sound whenever you get enough Special1s to unlock a new location or enough Special2s to unlock
|
|
# Dracula's door.
|
|
|
|
# Special2 (should play Fake Dracula's hurt voice clip if the new number of them is equal to the amount required
|
|
# for Dracula's door).
|
|
0x24080000, # ADDIU T0, R0, 0x0000 <- Special2s required
|
|
0x15030003, # BNE T0, V1, [forward 0x03]
|
|
0x00000000, # NOP
|
|
0x0C0059BE, # JAL 0x800166f8
|
|
0x240402E4, # ADDIU A0, R0, 0x02E4
|
|
0x08023F25, # J 0x8008FC94
|
|
0x24020001, # ADDIU V0, R0, 0x0001
|
|
# Special1 (Should play the teleport sound if the new number of them is equal to an amount that would unlock a new
|
|
# warp destination).
|
|
0x24080000, # ADDIU T0, R0, 0x0000 <- Special1s per warp
|
|
0x0068001B, # DIVU V1, T0
|
|
# After dividing the S1s per warp by our current S1 count, if the remainder is not 0, don't play the warp notif.
|
|
0x00005010, # MFHI T2
|
|
0x15400006, # BNEZ T2, [forward 0x06]
|
|
# If the quotient is a higher number than the total number of warps the slot has, don't play the warp notif.
|
|
0x00005812, # MFLO T3
|
|
0x296C0008, # SLTI T4, T3, 0x0000 <- Total warps
|
|
0x11800003, # BEQZ T4, [forward 0x03]
|
|
0x00000000, # NOP
|
|
0x0C0059BE, # JAL 0x800166f8
|
|
0x2404019B, # ADDIU A0, R0, 0x019B
|
|
0x08023F25, # J 0x8008FC94
|
|
0x24020001 # ADDIU V0, R0, 0x0001
|
|
]
|
|
|
|
stage_intro_cs_player = [
|
|
# Plays the Foggy Lake or Villa intro cutscene after transitioning to a different map if the map being transitioned
|
|
# to is the start of their levels respectively. Gets around the fact that they have to be set on the previous
|
|
# loading zone for them to play normally.
|
|
|
|
# If we're going to Foggy Lake's start, and the custom flag we're using to see if we've seen it (0x2F6) isn't set,
|
|
# prime the Foggy Lake ferryman cutscene to play and set the flag.
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x8D09AE78, # LW T1, 0xAE78 (T0)
|
|
0x3C0A0010, # LUI T2, 0x0010
|
|
0x152A0008, # BNE T1, T2, [forward 0x08]
|
|
0x910BAABE, # LBU T3, 0xAABE (T0)
|
|
0x316C0004, # ANDI T4, T3, 0x0004
|
|
0x15800004, # BNEZ T4, [forward 0x04]
|
|
0x356B0004, # ORI T3, T3, 0x0004
|
|
0xA10BAABE, # SB T3, 0xAABE (T0)
|
|
0x340D0010, # ORI T5, R0, 0x0010
|
|
0xA50DAE8E, # SH T5, 0xAE8E (T0)
|
|
0x08006A31, # J 0x8001A8C4
|
|
# If we're going to Villa's start, the Villa intro cutscene flag isn't set (flag 0x55), and the "Dog Wave 3 beaten"
|
|
# flag (0x58) isn't set, prime the Villa intro cutscene to play and set the flag.
|
|
0x3C0A0003, # LUI T2, 0x0003
|
|
0x152A000A, # BNE T1, T2, [forward 0x0A]
|
|
0x910BAA6B, # LBU T3, 0xAA6B (T0)
|
|
0x316C0080, # ANDI T4, T3, 0x0080
|
|
0x15800007, # BNEZ T4, [forward 0x07]
|
|
0x910BAA6A, # LBU T3, 0xAA6A (T0)
|
|
0x316C0004, # ANDI T4, T3, 0x0004
|
|
0x15800004, # BNEZ T4, [forward 0x04]
|
|
0x356B0004, # ORI T3, T3, 0x0004
|
|
0xA10BAA6A, # SB T3, 0xAA6A (T0)
|
|
0x340D0009, # ORI T5, R0, 0x0009
|
|
0xA50DAE8E, # SH T5, 0xAE8E (T0)
|
|
0x08006A31 # J 0x8001A8C4
|
|
]
|
|
|
|
alt_setup_flag_setter = [
|
|
# While loading into a scene, when the game checks to see which entrance to spawn the player at, this will check for
|
|
# the 0x40 and/or 0x80 bits in the spawn ID and, if they are, set one of the three "alternate setup" flags
|
|
# (0x2A1, 0x2A2, or 0x2A3) while un-setting the other two. This allows for scenes to load with different setups,
|
|
# almost as if they were separate scenes entirely, and is useful for things like the Algenie/Medusa arena and the
|
|
# fan meeting room being able to exist as separate scenes in separate stages. Also handles other rando-specific
|
|
# things that should be handled upon scene transition, like setting the remote receive delay timer.
|
|
|
|
# Un-set the "can't warp" byte and set our remote receive delay timer to 30 frames (1 second).
|
|
0x340F003E, # ORI T7, R0, 0x003E
|
|
0xA04F278E, # SB T7, 0x278E (V0)
|
|
0xA040278B, # SB R0, 0x278B (V0)
|
|
# If the "began Malus chase" flag is set and the "finished Malus chase" flag is not, un-set the former so the chase
|
|
# can be re-triggered later.
|
|
0x3C0F801D, # LUI T7, 0x801D
|
|
0x91EAAA72, # LBU T2, 0xAA72 (T7)
|
|
0x314B0020, # ANDI T3, T2, 0x0020
|
|
0x15600004, # BNEZ T3, [forward 0x04]
|
|
0x91ECAA72, # LBU T4, 0xAA72 (T7)
|
|
0x318D0040, # ANDI T5, T4, 0x0040
|
|
0x018D6023, # SUBU T4, T4, T5
|
|
0xA1ECAA72, # SB T4, 0xAA72 (T7)
|
|
# If the "began Henry escort" flag is set and the "finished Henry escort" flag is not, un-set the former so the
|
|
# escort can be re-triggered later.
|
|
0x91EAAA72, # LBU T2, 0xAA72 (T7)
|
|
0x314B0008, # ANDI T3, T2, 0x0008
|
|
0x15600004, # BNEZ T3, [forward 0x04]
|
|
0x91ECAA72, # LBU T4, 0xAA72 (T7)
|
|
0x318D0010, # ANDI T5, T4, 0x0010
|
|
0x018D6023, # SUBU T4, T4, T5
|
|
0xA1ECAA72, # SB T4, 0xAA72 (T7)
|
|
# If the "Waterway Lizard man trio cutscene" flag is set and the custom "defeated Lizard trio" flag is not,
|
|
# un-set the former so the cutscene can be re-triggered later.
|
|
0x91EAAABE, # LBU T2, 0xAABE (T7)
|
|
0x314B0001, # ANDI T3, T2, 0x0001
|
|
0x15600004, # BNEZ T3, [forward 0x04]
|
|
0x91ECAA7B, # LBU T4, 0xAA7B (T7)
|
|
0x318D0080, # ANDI T5, T4, 0x0080
|
|
0x018D6023, # SUBU T4, T4, T5
|
|
0xA1ECAA7B, # SB T4, 0xAA7B (T7)
|
|
# Check if the 0x40 AND 0x80 bits are both set in the spawn ID (it should be exactly 0xC0). If it is, set flag 0x2A3
|
|
# and un-set the other two.
|
|
0x904F2BBB, # LBU T7, 0x2BBB (V0)
|
|
0x31EA00C0, # ANDI T2, T7, 0x00C0
|
|
0x340B00C0, # ORI T3, R0, 0x00C0
|
|
0x154B0008, # BNE T2, T3, [forward 0x08]
|
|
0x904B27F4, # LBU T3, 0x27F4 (V0)
|
|
0x316B009F, # ANDI T3, T3, 0x009F
|
|
0x356B0010, # ORI T3, T3, 0x0010
|
|
0xA04B27F4, # SB T3, 0x27F4 (V0)
|
|
# Un-set the alternate setup bits from the spawn ID and write it back.
|
|
0x31EF003F, # ANDI T7, T7, 0x003F
|
|
0xA04F2BBB, # SB T7, 0x2BBB (V0)
|
|
0x03E00008, # JR RA
|
|
0xA44E28D0, # SH T6, 0x28D0 (V0)
|
|
# Check if the 0x40 bit is set in the spawn ID. If it is, set flag 0x2A1 and un-set the other two.
|
|
0x31EA0040, # ANDI T2, T7, 0x0040
|
|
0x11400008, # BEQZ T2, [forward 0x08]
|
|
0x904B27F4, # LBU T3, 0x27F4 (V0)
|
|
0x316B00CF, # ANDI T3, T3, 0x00CF
|
|
0x356B0040, # ORI T3, T3, 0x0040
|
|
0xA04B27F4, # SB T3, 0x27F4 (V0)
|
|
# Un-set the alternate setup bits from the spawn ID and write it back.
|
|
0x31EF003F, # ANDI T7, T7, 0x003F
|
|
0xA04F2BBB, # SB T7, 0x2BBB (V0)
|
|
0x03E00008, # JR RA
|
|
0xA44E28D0, # SH T6, 0x28D0 (V0)
|
|
# Check if the 0x80 bit is set in the spawn ID. If it is, set flag 0x2A2 and un-set the other two.
|
|
0x31EA0080, # ANDI T2, T7, 0x0080
|
|
0x11400006, # BEQZ T2, [forward 0x06]
|
|
0x904B27F4, # LBU T3, 0x27F4 (V0)
|
|
0x316B00AF, # ANDI T3, T3, 0x00AF
|
|
0x356B0020, # ORI T3, T3, 0x0020
|
|
0xA04B27F4, # SB T3, 0x27F4 (V0)
|
|
# Un-set the alternate setup bits from the spawn ID and write it back.
|
|
0x31EF003F, # ANDI T7, T7, 0x003F
|
|
0xA04F2BBB, # SB T7, 0x2BBB (V0)
|
|
0x03E00008, # JR RA
|
|
0xA44E28D0, # SH T6, 0x28D0 (V0)
|
|
]
|
|
|
|
character_changer = [
|
|
# Changes the character being controlled if the player is holding L while loading into a map by swapping the
|
|
# character ID.
|
|
0x3C08800D, # LUI T0, 0x800D
|
|
0x910B5E21, # LBU T3, 0x5E21 (T0)
|
|
0x31680020, # ANDI T0, T3, 0x0020
|
|
0x3C0A8039, # LUI T2, 0x8039
|
|
0x1100000B, # BEQZ T0, [forward 0x0B]
|
|
0x91499C3D, # LBU T1, 0x9C3D (T2)
|
|
0x11200005, # BEQZ T1, [forward 0x05]
|
|
0x24080000, # ADDIU T0, R0, 0x0000
|
|
0xA1489C3D, # SB T0, 0x9C3D (T2)
|
|
0x25080001, # ADDIU T0, T0, 0x0001
|
|
0xA1489BC2, # SB T0, 0x9BC2 (T2)
|
|
0x10000004, # B [forward 0x04]
|
|
0x24080001, # ADDIU T0, R0, 0x0001
|
|
0xA1489C3D, # SB T0, 0x9C3D (T2)
|
|
0x25080001, # ADDIU T0, T0, 0x0001
|
|
0xA1489BC2, # SB T0, 0x9BC2 (T2)
|
|
# Changes the alternate costume variables if the player is holding C-up.
|
|
0x31680008, # ANDI T0, T3, 0x0008
|
|
0x11000009, # BEQZ T0, [forward 0x09]
|
|
0x91499C24, # LBU T1, 0x9C24 (T2)
|
|
0x312B0040, # ANDI T3, T1, 0x0040
|
|
0x2528FFC0, # ADDIU T0, T1, 0xFFC0
|
|
0x15600003, # BNEZ T3, [forward 0x03]
|
|
0x240C0000, # ADDIU T4, R0, 0x0000
|
|
0x25280040, # ADDIU T0, T1, 0x0040
|
|
0x240C0001, # ADDIU T4, R0, 0x0001
|
|
0xA1489C24, # SB T0, 0x9C24 (T2)
|
|
0xA14C9CEE, # SB T4, 0x9CEE (T2)
|
|
0x080062AA, # J 0x80018AA8
|
|
0x00000000, # NOP
|
|
# Plays the attack sound of the character being changed into to indicate the change was successful.
|
|
0x3C088039, # LUI T0, 0x8039
|
|
0x91099BC2, # LBU T1, 0x9BC2 (T0)
|
|
0xA1009BC2, # SB R0, 0x9BC2 (T0)
|
|
0xA1009BC1, # SB R0, 0x9BC1 (T0)
|
|
0x11200006, # BEQZ T1, [forward 0x06]
|
|
0x2529FFFF, # ADDIU T1, T1, 0xFFFF
|
|
0x240402F6, # ADDIU A0, R0, 0x02F6
|
|
0x55200001, # BNEZL T1, [forward 0x01]
|
|
0x240402F8, # ADDIU A0, R0, 0x02F8
|
|
0x08004FAB, # J 0x80013EAC
|
|
0x00000000, # NOP
|
|
0x03E00008 # JR RA
|
|
]
|
|
|
|
panther_dash = [
|
|
# Changes various movement parameters when holding C-right so the player will move way faster.
|
|
# Increases movement speed and speeds up the running animation.
|
|
0x3C08800D, # LUI T0, 0x800D
|
|
0x91085E21, # LBU T0, 0x5E21 (T0)
|
|
0x31080001, # ANDI T0, T0, 0x0001
|
|
0x24093FEA, # ADDIU T1, R0, 0x3FEA
|
|
0x11000004, # BEQZ T0, [forward 0x04]
|
|
0x240B0010, # ADDIU T3, R0, 0x0010
|
|
0x3C073F20, # LUI A3, 0x3F20
|
|
0x240940AA, # ADDIU T1, R0, 0x40AA
|
|
0x240B000A, # ADDIU T3, R0, 0x000A
|
|
0x3C0C8035, # LUI T4, 0x8035
|
|
0xA18B07AE, # SB T3, 0x07AE (T4)
|
|
0xA18B07C2, # SB T3, 0x07C2 (T4)
|
|
0x3C0A8034, # LUI T2, 0x8034
|
|
0x03200008, # JR T9
|
|
0xA5492BD8, # SH T1, 0x2BD8 (T2)
|
|
0x00000000, # NOP
|
|
# Increases the turning speed so that handling is better.
|
|
0x3C08800D, # LUI T0, 0x800D
|
|
0x91085E21, # LBU T0, 0x5E21 (T0)
|
|
0x31080001, # ANDI T0, T0, 0x0001
|
|
0x11000002, # BEQZ T0, [forward 0x02]
|
|
0x240A00D9, # ADDIU T2, R0, 0x00D9
|
|
0x240A00F0, # ADDIU T2, R0, 0x00F0
|
|
0x3C0B8039, # LUI T3, 0x8039
|
|
0x916B9C3D, # LBU T3, 0x9C3D (T3)
|
|
0x11600003, # BEQZ T3, [forward 0x03]
|
|
0xD428DD58, # LDC1 F8, 0xDD58 (AT)
|
|
0x03E00008, # JR RA
|
|
0xA02ADD59, # SB T2, 0xDD59 (AT)
|
|
0xD428D798, # LDC1 F8, 0xD798 (AT)
|
|
0x03E00008, # JR RA
|
|
0xA02AD799, # SB T2, 0xD799 (AT)
|
|
0x00000000, # NOP
|
|
# Increases crouch-walking x and z speed.
|
|
0x3C08800D, # LUI T0, 0x800D
|
|
0x91085E21, # LBU T0, 0x5E21 (T0)
|
|
0x31080001, # ANDI T0, T0, 0x0001
|
|
0x11000002, # BEQZ T0, [forward 0x02]
|
|
0x240A00C5, # ADDIU T2, R0, 0x00C5
|
|
0x240A00F8, # ADDIU T2, R0, 0x00F8
|
|
0x3C0B8039, # LUI T3, 0x8039
|
|
0x916B9C3D, # LBU T3, 0x9C3D (T3)
|
|
0x15600005, # BNEZ T3, [forward 0x05]
|
|
0x00000000, # NOP
|
|
0xA02AD801, # SB T2, 0xD801 (AT)
|
|
0xA02AD809, # SB T2, 0xD809 (AT)
|
|
0x03E00008, # JR RA
|
|
0xD430D800, # LDC1 F16, 0xD800 (AT)
|
|
0xA02ADDC1, # SB T2, 0xDDC1 (AT)
|
|
0xA02ADDC9, # SB T2, 0xDDC9 (AT)
|
|
0x03E00008, # JR RA
|
|
0xD430DDC0 # LDC1 F16, 0xDDC0 (AT)
|
|
]
|
|
|
|
panther_jump_preventer = [
|
|
# Optional hack to prevent jumping while moving at the increased panther dash speed as a way to prevent logic
|
|
# sequence breaks that would otherwise be impossible without it. Such sequence breaks are never considered in logic
|
|
# either way.
|
|
|
|
# Decreases a "can running jump" value by 1 per frame unless it's at 0, or while in the sliding state. When the
|
|
# player lets go of C-right, their running speed should have returned to a normal amount by the time it hits 0.
|
|
0x9208007F, # LBU T0, 0x007F (S0)
|
|
0x24090008, # ADDIU T1, R0, 0x0008
|
|
0x11090005, # BEQ T0, T1, [forward 0x05]
|
|
0x3C088039, # LUI T0, 0x8039
|
|
0x91099BC1, # LBU T1, 0x9BC1 (T0)
|
|
0x11200002, # BEQZ T1, [forward 0x02]
|
|
0x2529FFFF, # ADDIU T1, T1, 0xFFFF
|
|
0xA1099BC1, # SB T1, 0x9BC1 (T0)
|
|
0x080FF413, # J 0x803FD04C
|
|
0x00000000, # NOP
|
|
# Increases the "can running jump" value by 2 per frame while panther dashing unless it's at 8 or higher, at which
|
|
# point the player should be at the max panther dash speed.
|
|
0x00074402, # SRL T0, A3, 16
|
|
0x29083F7F, # SLTI T0, T0, 0x3F7F
|
|
0x11000006, # BEQZ T0, [forward 0x06]
|
|
0x3C098039, # LUI T1, 0x8039
|
|
0x912A9BC1, # LBU T2, 0x9BC1 (T1)
|
|
0x254A0002, # ADDIU T2, T2, 0x0002
|
|
0x294B0008, # SLTI T3, T2, 0x0008
|
|
0x55600001, # BNEZL T3, [forward 0x01]
|
|
0xA12A9BC1, # SB T2, 0x9BC1 (T1)
|
|
0x03200008, # JR T9
|
|
0x00000000, # NOP
|
|
# Makes running jumps only work while the "can running jump" value is at 0. Otherwise, their state won't change.
|
|
0x3C010001, # LUI AT, 0x0001
|
|
0x3C088039, # LUI T0, 0x8039
|
|
0x91089BC1, # LBU T0, 0x9BC1 (T0)
|
|
0x55000001, # BNEZL T0, [forward 0x01]
|
|
0x3C010000, # LUI AT, 0x0000
|
|
0x03E00008 # JR RA
|
|
]
|
|
|
|
shimmy_speed_modifier = [
|
|
# Increases the player's speed while shimmying as long as they are not holding down Z. If they are holding Z, it
|
|
# will be the normal speed, allowing it to still be used to set up any tricks that might require the normal speed
|
|
# (like Left Tower Skip in original CV64).
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x910887F6, # LBU T0, 0x87F6 (T0)
|
|
0x31090020, # ANDI T1, T0, 0x0020
|
|
0x3C0A800C, # LUI T2, 0x800C
|
|
0x340B4580, # ORI T3, R0, 0x4580
|
|
0x55200001, # BNEZL T1, [forward 0x01]
|
|
0x340B46FF, # ORI T3, R0, 0x46FF
|
|
0xA54BE170, # SH T3, 0xE170 (T2)
|
|
0x08028E94, # J 0x800A3A50
|
|
0xA54BE174, # SH T3, 0xE174 (T2)
|
|
]
|
|
|
|
cornell_detransformer = [
|
|
# Enables Wolf Cornell to transform back to human by pressing L while skipping the "greater than 10 jewels" check.
|
|
0x10000006, # B [forward 0x06]
|
|
# Repurposed human Cornell check that we will branch to if the jewel check fails. If we are NOT Wolf Cornell, bar
|
|
# transforming. If we are, branch to the next part of the code that would run if the jewel check passes.
|
|
0x3C03801D, # LUI V1, 0x801D
|
|
0x846AAB36, # LH T2, 0xAB36 (V1)
|
|
0x24010004, # ADDIU AT, R0, 0x0004
|
|
0x11410013, # BEQ T2, AT, [forward 0x13]
|
|
0x00000000, # NOP
|
|
0x10000048, # B [forward 0x48]
|
|
0x8C6BAC28, # LW T3, 0xAC28 (V1)
|
|
0x3C02800F, # LUI V0, 0x800F
|
|
0x244235F0, # ADDIU V0, V0, 0x35F0
|
|
0x8D6C0000, # LW T4, 0x0000 (T3)
|
|
0x000C69C0, # SLL T5, T4, 7
|
|
0x05A00042, # BLTZ T5, [forward 0x42]
|
|
]
|
|
|
|
gondola_spider_cutscene_checker = [
|
|
# Checks for flag 0xAD (the Spider Women cutscene flag) before activating the Tunnel gondolas, restoring their
|
|
# original behavior from CV64.
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x9109AA75, # LBU T1, 0xAA75 (T0)
|
|
0x312A0004, # ANDI T2, T1, 0x0004
|
|
0x15400003, # BNEZ T2, [forward 0x03]
|
|
0x00000000, # NOP
|
|
0x03E00008, # JR RA
|
|
0x00000000, # NOP
|
|
0x08051DBF, # J 0x801476FC
|
|
0x00000000, # NOP
|
|
]
|
|
|
|
gondola_skipper = [
|
|
# Upon stepping on one of the gondolas in Tunnel to activate it, this will instantly teleport you to the other end
|
|
# of the gondola course depending on which one activated, skipping the entire 3-minute wait to get there.
|
|
|
|
# Access the gondola's actor list entry and check to see if it's the blue one specifically. This will determine
|
|
# what spawn spot we send the player to and what color to make the fade transition.
|
|
0x8CA80070, # LW T0, 0x0070 (A1)
|
|
0x95090018, # LHU T1, 0x0018 (T0)
|
|
# If it's gondola number 5 (the blue one), que up the blue gondola's transition settings.
|
|
0x240A0005, # ADDIU T2, R0, 0x0005 <- Blue gondola's palette ID
|
|
0x152A0004, # BNE T1, T2, [forward 0x04]
|
|
0x3C0C3080, # LUI T4, 0x3080 <- Blue gondola fade color
|
|
0x358C9700, # ORI T4, T4, 0x9700
|
|
0x10000003, # B [forward 0x03]
|
|
0x240B000A, # ADDIU T3, R0, 0x000A <- Blue gondola destination ID
|
|
# If not number 5, que up the red gondola's transition settings.
|
|
0x3C0C7A00, # LUI T4, 0x7A00 <- Red gondola fade color
|
|
0x240B000B, # ADDIU T3, R0, 0x000B <- Red gondola destination ID
|
|
# Store the values.
|
|
0x2409000C, # ADDIU T5, R0, 0x000C <- Fade out and in time
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0xA509AE80, # SH T1, 0xAE80 (T0)
|
|
0xA509AE82, # SH T1, 0xAE82 (T0)
|
|
0xAD0CAE7C, # SW T4, 0xAE7C (T0)
|
|
0x08051DBF, # J 0x801476FC
|
|
0xA50BAE7A, # SH T3, 0xAE7A (T0)
|
|
]
|
|
|
|
ambience_silencer = [
|
|
# Silences scene-specific ambience when loading into a different scene, so we don't have to live with, say, Tower of
|
|
# Science/Clock Tower machinery noises everywhere until either resetting, dying, or going into a scene that is
|
|
# normally set up to disable said noises. We can only silence a few sounds at a time, so we will be very selective
|
|
# about it by checking to see if said sounds are actually playing.
|
|
|
|
# In addition, during the map loading process, if this detects the scene ID being transitioned to as FF, it will
|
|
# write back the past spawn ID so that the map will still reload while keeping the scene and spawn IDs unchanged.
|
|
# Useful for things like setting a transition to lead back to itself.
|
|
|
|
# Run the "set fade settings" function like normal upon beginning a scene transition.
|
|
0x0C004156, # JAL 0x80010558
|
|
0x00000000, # NOP
|
|
# Check if the scene ID being transitioned to is 0xFF. If it is, write back the scene ID being transitioned from.
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x9109AB91, # LBU T1, 0xAB91 (T0)
|
|
0x910CAE79, # LBU T4, 0xAE79 (T0)
|
|
0x340B00FF, # ORI T3, R0, 0x00FF
|
|
0x518B0001, # BEQL T4, T3, [forward 0x01]
|
|
0xA109AE79, # SB T1, 0xAE79 (T0)
|
|
0x9110AE79, # LBU S0, 0xAE79 (T0)
|
|
# Silence the Foggy Lake ship noises if we're not transitioning to the above or below decks scenes.
|
|
0x240A0010, # ADDIU T2, R0, 0x0010
|
|
0x120A000F, # BEQ S0, T2, [forward 0x0F]
|
|
0x240A0011, # ADDIU T2, R0, 0x0011
|
|
0x120A000D, # BEQ S0, T2, [froward 0x0D]
|
|
0x00000000, # NOP
|
|
0x0C00545C, # JAL 0x80015170
|
|
0x240401A0, # ADDIU A0, R0, 0x01A0
|
|
0x10400003, # BEQZ V0, [forward 0x03]
|
|
0x00000000, # NOP
|
|
0x0C0059BE, # JAL 0x800166F8
|
|
0x340481A0, # ORI A0, R0, 0x81A0
|
|
0x0C00545C, # JAL 0x80015170
|
|
0x240401A1, # ADDIU A0, R0, 0x01A1
|
|
0x10400003, # BEQZ V0, [forward 0x03]
|
|
0x00000000, # NOP
|
|
0x0C0059BE, # JAL 0x800166F8
|
|
0x340481A1, # ORI A0, R0, 0x81A1
|
|
# Silence the common "wind ambience" noise if we're transitioning to a non-Castle Wall scene.
|
|
0x240A0001, # ADDIU T2, R0, 0x0001
|
|
0x120A0009, # BEQ S0, T2, [forward 0x09]
|
|
0x240A0002, # ADDIU T2, R0, 0x0002
|
|
0x120A0007, # BEQ S0, T2, [froward 0x07]
|
|
0x00000000, # NOP
|
|
0x0C00545C, # JAL 0x80015170
|
|
0x24040136, # ADDIU A0, R0, 0x0136
|
|
0x10400003, # BEQZ V0, [forward 0x03]
|
|
0x00000000, # NOP
|
|
0x0C0059BE, # JAL 0x800166F8
|
|
0x34048136, # ORI A0, R0, 0x8136
|
|
# Silence all Gardener and Child Henry escort noises in case we're transitioning from the Maze Garden scene
|
|
# (the "Jaws Theme" instruments that are separate sounds and the Gardener's proximity chainsaw sound).
|
|
# No need to check this scene because they should always be silenced no matter what.
|
|
0x0C00545C, # JAL 0x80015170
|
|
0x24040371, # ADDIU A0, R0, 0x0371
|
|
0x10400003, # BEQZ V0, [forward 0x03]
|
|
0x00000000, # NOP
|
|
0x0C0059BE, # JAL 0x800166F8
|
|
0x34048371, # ORI A0, R0, 0x8371
|
|
0x0C00545C, # JAL 0x80015170
|
|
0x24040372, # ADDIU A0, R0, 0x0372
|
|
0x10400003, # BEQZ V0, [forward 0x03]
|
|
0x00000000, # NOP
|
|
0x0C0059BE, # JAL 0x800166F8
|
|
0x34048372, # ORI A0, R0, 0x8372
|
|
0x0C00545C, # JAL 0x80015170
|
|
0x24040358, # ADDIU A0, R0, 0x0358
|
|
0x10400003, # BEQZ V0, [forward 0x03]
|
|
0x00000000, # NOP
|
|
0x0C0059BE, # JAL 0x800166F8
|
|
0x34048358, # ORI A0, R0, 0x8358
|
|
# Silence the Outer Wall wind noises if we're transitioning to a scene that's not Outer Wall.
|
|
0x240A002A, # ADDIU T2, R0, 0x002A
|
|
0x120A000D, # BEQ S0, T2, [froward 0x0D]
|
|
0x00000000, # NOP
|
|
0x0C00545C, # JAL 0x80015170
|
|
0x240401BF, # ADDIU A0, R0, 0x01BF
|
|
0x10400003, # BEQZ V0, [forward 0x03]
|
|
0x00000000, # NOP
|
|
0x0C0059BE, # JAL 0x800166F8
|
|
0x340481BF, # ORI A0, R0, 0x81BF
|
|
0x0C00545C, # JAL 0x80015170
|
|
0x24040172, # ADDIU A0, R0, 0x0172
|
|
0x10400003, # BEQZ V0, [forward 0x03]
|
|
0x00000000, # NOP
|
|
0x0C0059BE, # JAL 0x800166F8
|
|
0x34048172, # ORI A0, R0, 0x8172
|
|
# Silence the Fan Meeting Room fans if we're transitioning to a scene that's not the Fan Meeting Room.
|
|
0x240A0019, # ADDIU T2, R0, 0x0019
|
|
0x120A0007, # BEQ S0, T2, [froward 0x07]
|
|
0x00000000, # NOP
|
|
0x0C00545C, # JAL 0x80015170
|
|
0x240401ED, # ADDIU A0, R0, 0x01ED
|
|
0x10400003, # BEQZ V0, [forward 0x03]
|
|
0x00000000, # NOP
|
|
0x0C0059BE, # JAL 0x800166F8
|
|
0x340481ED, # ORI A0, R0, 0x81ED
|
|
# Silence the Tower of Execuiton lava noises if we're transitioning to a non-Tower of Execution scene.
|
|
0x240A001E, # ADDIU T2, R0, 0x001E
|
|
0x120A0011, # BEQ S0, T2, [forward 0x11]
|
|
0x240A001F, # ADDIU T2, R0, 0x001F
|
|
0x120A000F, # BEQ S0, T2, [forward 0x0F]
|
|
0x240A0020, # ADDIU T2, R0, 0x0020
|
|
0x120A000D, # BEQ S0, T2, [froward 0x0D]
|
|
0x00000000, # NOP
|
|
0x0C00545C, # JAL 0x80015170
|
|
0x240401BB, # ADDIU A0, R0, 0x01BB
|
|
0x10400003, # BEQZ V0, [forward 0x03]
|
|
0x00000000, # NOP
|
|
0x0C0059BE, # JAL 0x800166F8
|
|
0x340481BB, # ORI A0, R0, 0x81BB
|
|
0x0C00545C, # JAL 0x80015170
|
|
0x24040369, # ADDIU A0, R0, 0x0369
|
|
0x10400003, # BEQZ V0, [forward 0x03]
|
|
0x00000000, # NOP
|
|
0x0C0059BE, # JAL 0x800166F8
|
|
0x34048369, # ORI A0, R0, 0x8369
|
|
# Silence the machinery humming from Tower of Science if we're transitioning to a non-Tower of Science scene.
|
|
0x240A0021, # ADDIU T2, R0, 0x0021
|
|
0x120A0009, # BEQ S0, T2, [forward 0x09]
|
|
0x240A0022, # ADDIU T2, R0, 0x0022
|
|
0x120A0007, # BEQ S0, T2, [forward 0x07]
|
|
0x00000000, # NOP
|
|
0x0C00545C, # JAL 0x80015170
|
|
0x24040368, # ADDIU A0, R0, 0x0368
|
|
0x10400003, # BEQZ V0, [forward 0x03]
|
|
0x00000000, # NOP
|
|
0x0C0059BE, # JAL 0x800166F8
|
|
0x34048368, # ORI A0, R0, 0x8368
|
|
# Silence the gear noises from Clock Tower and Tower of Science if we're transitioning to a
|
|
# non-Tower of Science/Clock Tower scene.
|
|
0x240A0021, # ADDIU T2, R0, 0x0021
|
|
0x120A000F, # BEQ S0, T2, [forward 0x0F]
|
|
0x240A0022, # ADDIU T2, R0, 0x0022
|
|
0x120A000D, # BEQ S0, T2, [forward 0x0D]
|
|
0x240A0017, # ADDIU T2, R0, 0x0017
|
|
0x120A000B, # BEQ S0, T2, [forward 0x0B]
|
|
0x240A0028, # ADDIU T2, R0, 0x0028
|
|
0x120A0009, # BEQ S0, T2, [forward 0x09]
|
|
0x240A0029, # ADDIU T2, R0, 0x0029
|
|
0x120A0007, # BEQ S0, T2, [froward 0x07]
|
|
0x00000000, # NOP
|
|
0x0C00545C, # JAL 0x80015170
|
|
0x24040188, # ADDIU A0, R0, 0x0188
|
|
0x10400003, # BEQZ V0, [forward 0x03]
|
|
0x00000000, # NOP
|
|
0x0C0059BE, # JAL 0x800166F8
|
|
0x34048188, # ORI A0, R0, 0x8188
|
|
0x08006BCA # J 0x8001AF28
|
|
]
|
|
|
|
multiworld_item_name_loader = [
|
|
# When picking up an item from another world, this will load from ROM the custom message for that item explaining
|
|
# in the item textbox what the item is and who it's for. The flag index it calculates determines from what part of
|
|
# the ROM to load the item name from. If the item being picked up is a white jewel or a contract, it will always
|
|
# load from a part of the ROM that has nothing in it to ensure their set "flag" values don't yield unintended names.
|
|
# If picking up a subweapon, this will also grab the custom "subweapon levels to increase" value from said weapon
|
|
# and store it somewhere easy to read later.
|
|
|
|
# As we're picking up a pickup, before running the prepare item textbox function, copy from the ROM the off-world
|
|
# Item string corresponding to that pickup.
|
|
0x3C0800FA, # LUI T0, 0x00FA
|
|
0x9609005A, # LHU T1, 0x005A (S0)
|
|
# Shift the flag ID up by 8 and add it to 0xFA0000 to get the start address for this pickup's string.
|
|
0x00094A00, # SLL T1, T1, 8
|
|
0x01092021, # ADDU A0, T0, T1
|
|
0x3C058001, # LUI A1, 0x8001
|
|
0x34A5E5CC, # ORI A1, A1, 0xE5CC
|
|
# Run the "rom copy" function with all necessary arguments.
|
|
0x0C00690B, # JAL 0x8001A42C
|
|
0x34060100, # ORI A2, R0, 0x0100
|
|
# Grab and store the subweapon level we stored on the pickup.
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x92090053, # LBU T1, 0x0053 (S0)
|
|
0xA109AA20, # SB T1, 0xAA20 (T0)
|
|
0x96030038, # LHU V1, 0x0038 (S0)
|
|
# Return to and continue the pickup routine like normal.
|
|
0x3C048019, # LUI A0, 0x8019
|
|
0x00037880, # SLL T7, T7, V1
|
|
0x01E37821, # ADDU T7, T7, V1
|
|
0x08061F2A, # J 0x80187CA8
|
|
0x000F7880, # SLL T7, T7, 2
|
|
0x00000000,
|
|
0x00000000,
|
|
# Redirect the text to the multiworld message buffer if a message exists in it. Skip this if we're looking at a
|
|
# White Jewel, as White Jewel identifiers occupy the same value as event flag IDs on other pickups.
|
|
0x10A00007, # BEQZ A1, [forward 0x07]
|
|
0x3C088002, # LUI T0, 0x8002
|
|
0x9108E5CC, # LBU T0, 0xE5CD (T0)
|
|
0x11000004, # BEQZ T0, [forward 0x04]
|
|
0x00000000, # NOP
|
|
0x3C048001, # LUI A0, 0x8001
|
|
0x3484E5CE, # ORI A0, A0, 0xE5CE
|
|
0x24050000, # ADDIU A1, R0, 0x0000
|
|
0x08020FE8, # J 0x80083FA0
|
|
0x00000000,
|
|
# Change the Y screen position and number of lines of the textbox depending on how many line breaks there are.
|
|
# If we have a value of 0 lines, skip this routine entirely and go straight to the set text function.
|
|
0x3C088002, # LUI T0, 0x8002
|
|
0x9108E5CC, # LBU T0, 0xE5CC (T0)
|
|
0x1100000C, # BEQZ T0, [forward 0x0C]
|
|
# If the number of lines is 5 or higher, set it down to the max of 4.
|
|
0x29090005, # SLTI T1, T0, 0x0005
|
|
0x51200001, # BEQZL T1, [forward 0x01]
|
|
0x34080004, # ORI T0, R0, 0x0004
|
|
0xAFA80018, # SW T0, 0x0018 (SP)
|
|
# Add 16.0f times the number of lines we have to the textbox Y value to raise it higher on-screen.
|
|
0x3C0A4180, # LUI T2, 0x4180
|
|
0x448A1800, # MTC1 T2, F3
|
|
0x2508FFFF, # ADDIU T0, T0, 0xFFFF
|
|
0x44885000, # MTC1 T0, F10
|
|
0x468052A0, # CVT.S.W F10, F10
|
|
0x460A18C2, # MUL.S F3, F3, F10
|
|
0x46032100, # ADD.S F4, F4, F3
|
|
0xE7A40010, # SWC1 F4, 0x0010 (SP)
|
|
0x08020C02, # J 0x80083008
|
|
0x00000000,
|
|
# Change the textbox's background X and Y size depending on how many line breaks there are.
|
|
# If we have a value of 0 lines, skip this routine entirely and go straight to the set background size function.
|
|
0x3C088002, # LUI T0, 0x8002
|
|
0x9108E5CC, # LBU T0, 0xE5CC (T0)
|
|
0x1100000D, # BEQZ T0, [forward 0x0D]
|
|
# If the number of lines is 5 or higher, set it down to the max of 4.
|
|
0x29090005, # SLTI T1, T0, 0x0005
|
|
0x51200001, # BEQZL T1, [forward 0x01]
|
|
0x34080004, # ORI T0, R0, 0x0004
|
|
# Extend the background X size from 150.0f to 190.0f (its PAL version size)
|
|
0x3C05433E, # LUI A1, 0x433E
|
|
# Add 16.0f times the number of lines we have to the background Y size to extend it further downward.
|
|
0x3C0A4180, # LUI T2, 0x4180
|
|
0x448A1800, # MTC1 T2, F3
|
|
0x44862000, # MTC1 A2, F4
|
|
0x2508FFFF, # ADDIU T0, T0, 0xFFFF
|
|
0x44885000, # MTC1 T0, F10
|
|
0x468052A0, # CVT.S.W F10, F10
|
|
0x460A18C2, # MUL.S F3, F3, F10
|
|
0x46032100, # ADD.S F4, F4, F3
|
|
0x44062000, # MFC1 A2, F4
|
|
0x08020F94, # J 0x80083E50
|
|
0x00000000,
|
|
# Change the textbox's "open" timer depending on how many line breaks there are.
|
|
# If we have a value of 0 lines, skip this routine entirely.
|
|
0x3C098002, # LUI T1, 0x8002
|
|
0x9128E5CC, # LBU T0, 0xE5CC (T1)
|
|
0x11000008, # BEQZ T0, [forward 0x08]
|
|
0x44814000, # MTC1 AT, F8
|
|
# Add 0.75 seconds to the "textbox remaining open timer" for every line there is minus 1.
|
|
0x3C0A3F40, # LUI T2, 0x3F40
|
|
0x448A1800, # MTC1 T2, F3
|
|
0x2508FFFF, # ADDIU T0, T0, 0xFFFF
|
|
0x44885000, # MTC1 T0, F10
|
|
0x468052A0, # CVT.S.W F10, F10
|
|
0x460A18C2, # MUL.S F3, F3, F10
|
|
0x46034200, # ADD.S F8, F8, F3
|
|
0x03E00008, # JR RA
|
|
# At this point, neuter the multiworld text buffer by clearing the lines counter, since it's no longer needed.
|
|
0xA120E5CC, # SB R0, 0xE5CC (T1)
|
|
]
|
|
|
|
ice_trap_initializer = [
|
|
# During a map load, creates the module that allows the ice block model to appear while in the frozen state if not
|
|
# on the intro narration map (map 0x16).
|
|
0x3C088039, # LUI T0, 0x8039
|
|
0x91089EE1, # LBU T0, 0x9EE1 (T0)
|
|
0x24090016, # ADDIU T1, R0, 0x0016
|
|
0x11090004, # BEQ T0, T1, [forward 0x04]
|
|
0x3C048034, # LUI A0, 0x8034
|
|
0x24842ACC, # ADDIU A0, A0, 0x2ACC
|
|
0x08000660, # J 0x80001980
|
|
0x24052125, # ADDIU A1, R0, 0x2125
|
|
0x03E00008 # JR RA
|
|
]
|
|
|
|
the_deep_freezer = [
|
|
# Writes 000C0000 into the player state to freeze the player on the spot if Ice Traps have been received, writes the
|
|
# Ice Trap code into the pointer value (0x20B8, which is also Camilla's boss code),and decrements the Ice Traps
|
|
# remaining counter.
|
|
0x3C0B8039, # LUI T3, 0x8039
|
|
0x91699BE2, # LBU T3, 0x9BE2 (T0)
|
|
0x1120000F, # BEQZ T1, [forward 0x0F]
|
|
0x3C088034, # LUI T0, 0x8034
|
|
0x910827A9, # LBU T0, 0x27A9 (T0)
|
|
0x240A000C, # ADDIU T2, R0, 0x000C
|
|
0x110A000B, # BEQ T0, T2, [forward 0x0B]
|
|
0x240A0002, # ADDIU T2, R0, 0x0002
|
|
0x110A0009, # BEQ T0, T2, [forward 0x09]
|
|
0x240A0008, # ADDIU T2, R0, 0x0008
|
|
0x110A0007, # BEQ T0, T2, [forward 0x07]
|
|
0x2529FFFF, # ADDIU T1, T1, 0xFFFF
|
|
0xA1699BE2, # SB T1, 0x9BE2 (T3)
|
|
0x3C088034, # LUI T0, 0x8034
|
|
0x3C09000C, # LUI T1, 0x000C
|
|
0xAD0927A8, # SW T1, 0x27A8 (T0)
|
|
0x240820B8, # ADDIU T0, R0, 0x20B8
|
|
0xA5689E6E, # SH T0, 0x9E6E (T3)
|
|
0x03E00008 # JR RA
|
|
]
|
|
|
|
freeze_verifier = [
|
|
# Verifies for the ice chunk module that a freeze should spawn the ice model. The player must be in the frozen state
|
|
# (0x000C) and 0x20B8 must be in either the freeze pointer value or the current boss ID (Camilla's); otherwise, we
|
|
# weill assume that the freeze happened due to a vampire grab or Actrise shard tornado and not spawn the ice chunk.
|
|
0x8C4E000C, # LW T6, 0x000C (V0)
|
|
0x00803025, # OR A2, A0, R0
|
|
0x8DC30008, # LW V1, 0x0008 (T6)
|
|
0x3C088039, # LUI T0, 0x8039
|
|
0x240920B8, # ADDIU T1, R0, 0x20B8
|
|
0x950A9E72, # LHU T2, 0x9E72 (T0)
|
|
0x3C0C8034, # LUI T4, 0x8034
|
|
0x918C27A9, # LBU T4, 0x27A9 (T4)
|
|
0x240D000C, # ADDIU T5, R0, 0x000C
|
|
0x158D0004, # BNE T4, T5, [forward 0x04]
|
|
0x3C0B0F00, # LUI T3, 0x0F00
|
|
0x112A0005, # BEQ T1, T2, [forward 0x05]
|
|
0x950A9E78, # LHU T2, 0x9E78 (T0)
|
|
0x112A0003, # BEQ T1, T2, [forward 0x03]
|
|
0x357996A0, # ORI T9, T3, 0x96A0
|
|
0x03200008, # JR T9
|
|
0x00000000, # NOP
|
|
0x35799640, # ORI T9, T3, 0x9640
|
|
0x03200008, # JR T9
|
|
]
|
|
|
|
sea_monster_sunk_path_flag_unsetter = [
|
|
# Un-sets the "debris path sunk" flag that gets set when the Sea Monster battle begins to normally ensure you cannot
|
|
# escape back to the save platform, allowing it to be traversed again if the player leaves and comes back.
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x9109AA8B, # LBU T1, 0xAA8B (T0)
|
|
0x312900F7, # ANDI T1, T1, 0x00F7
|
|
0x03200008, # JR T9
|
|
0xA109AA8B # SB T1, 0xAA8B (T0)
|
|
]
|
|
|
|
door_map_music_player = [
|
|
# Put this in a door's extra check condition to open, and it will play the current map's song while always returning
|
|
# that it's fine for the door to open. Good for the locked Tower of Science control room doors to start the music
|
|
# when going backwards from the end of the stage, since killing the Security Crystal stops it.
|
|
0x27BDFFE0, # ADDIU SP, SP, -0x20
|
|
0xAFBF0014, # SW RA, 0x0014 (SP)
|
|
0x0C006938, # JAL 0x8001A4E0
|
|
0xAFA40004, # SW A0, 0x0004 (SP)
|
|
0x0C053DF2, # JAL 0x8014F7C8
|
|
0x8FA40004, # LW A0, 0x0004 (SP)
|
|
0x8FBF0014, # LW RA, 0x0014 (SP)
|
|
0x27BD0020, # ADDIU SP, SP, 0x20
|
|
0x03E00008, # JR RA
|
|
]
|
|
|
|
pink_sorcery_diamond_customizer = [
|
|
# Gives each item that drops from the pink Tower of Sorcery diamond its own unique flag and additional settings
|
|
# attributes.
|
|
0x03104000,
|
|
0x03114000,
|
|
0x03124000,
|
|
0x00000000,
|
|
0x00104080, # SLL T0, S0, 2
|
|
0x3C09802F, # LUI T1, 0x802F
|
|
0x01094821, # ADDU T1, T0, T1
|
|
0x952AAC30, # LHU T2, 0xAC30 (T1)
|
|
0x9527AC32, # LHU A3, 0xAC32 (T1)
|
|
0x08058E56, # J 0x80163958
|
|
0xAFAA0010 # SW T2, 0x0010 (SP)
|
|
]
|
|
|
|
crypt_crests_checker = [
|
|
# Checks if the player is able to open the Villa crypt door from the inside by looking at the "crest inserted" flags
|
|
# and the inventory Crest Half A and B counters. If they are, then will also determine which crests should be
|
|
# subtracted from the inventory and have their flag be set.
|
|
|
|
# Verify that we are able to open the door.
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x9109AB5B, # LBU T1, 0xAB5B (T0)
|
|
0x910AAB5C, # LBU T2, 0xAB5C (T0)
|
|
0x910BAA73, # LBU T3, 0xAA73 (T0)
|
|
0x316C0080, # ANDI T4, T3, 0x0080
|
|
0x316D0040, # ANDI T5, T3, 0x0040
|
|
# Check to see if either the Crest A flag is set or we have Crest A. If neither are true, we can't open it.
|
|
0x15800005, # BNEZ T4, [forward 0x05]
|
|
0x00000000, # NOP
|
|
0x15200003, # BNEZ T1, [forward 0x03]
|
|
0x00000000, # NOP
|
|
0x03E00008, # JR RA
|
|
0x34020001, # ORI V0, R0, 0x0001
|
|
# Check to see if either the Crest B flag is set or we have Crest B. If neither are true, we can't open it.
|
|
0x15A00005, # BNEZ T5, [forward 0x05]
|
|
0x00000000, # NOP
|
|
0x15400003, # BNEZ T2, [forward 0x03]
|
|
0x00000000, # NOP
|
|
0x03E00008, # JR RA
|
|
0x34020001, # ORI V0, R0, 0x0001
|
|
# If we made it here, we can open the door. Before exiting the routine, however, see if there are crests we can be
|
|
# "placing" from here.
|
|
# If the Crest A flag is not set, subtract Crest A from the inventory and set its flag.
|
|
0x15800004, # BNEZ T4, [forward 0x04]
|
|
0x2529FFFF, # ADDIU T1, T1, 0xFFFF
|
|
0xA109AB5B, # SB T1, 0xAB5B (T0)
|
|
0x356B0080, # ORI T3, T3, 0x0080
|
|
0xA10BAA73, # SB T3, 0xAA73 (T0)
|
|
# If the Crest B flag is not set, subtract Crest B from the inventory and set its flag.
|
|
0x15A00004, # BNEZ T5, [forward 0x04]
|
|
0x254AFFFF, # ADDIU T2, T2, 0xFFFF
|
|
0xA10AAB5C, # SB T2, 0xAB5C (T0)
|
|
0x356B0040, # ORI T3, T3, 0x0040
|
|
0xA10BAA73, # SB T3, 0xAA73 (T0)
|
|
0x03E00008, # JR RA
|
|
0x34020000 # ORI V0, R0, 0x0000
|
|
]
|
|
|
|
art_tower_knight_spawn_check = [
|
|
# Checks if the player's current Z position is higher than -476.375f and, if it is, returns 0 to allow an actor
|
|
# assigned to this check to spawn. Used for the Hell Knights in Art Tower's hallway between the two key doors to
|
|
# ensure they don't lock the doors with the player behind Door 2 in our new spawn spot there.
|
|
0x3C088019, # LUI T0, 0x8019
|
|
0x8D0860E8, # LW T0, 0x60E8 (T0)
|
|
0x3C09C3EE, # LUI T1, 0xC3EE
|
|
0x35293000, # ORI T1, T1, 0x3000
|
|
0x0128502A, # SLT T2, T1, T0
|
|
0x24020000, # ADDIU V0, R0, 0x0000
|
|
0x51400001, # BEQZL T2, [forward 0x01]
|
|
0x24020001, # ADDIU V0, R0, 0x0001
|
|
0x03E00008, # JR RA
|
|
0x00000000
|
|
]
|
|
|
|
castle_sitting_henry_checker = [
|
|
# Teleports Henry to his "all children rescued" cutscene during the "sitting to watch the castle crumble"
|
|
# cutscene after beating Dracula instead of the usual castle crumbling sequence. This cutscene also opens with the
|
|
# castle crumbling, so it feels more natural for him to go directly here.
|
|
|
|
# Check the current character value for Henry. If true, switch the spawn point for the current map to 1
|
|
# (for blue skies) and play his cutscene.
|
|
0x3C0B801D, # LUI T3, 0x801D
|
|
0x8568AB34, # LH T0, 0xAB34 (T3)
|
|
0x34090003, # ORI T1, R0, 0x00003
|
|
0x15090006, # BNE T0, T1, [forward 0x06]
|
|
0x340A0031, # ORI T2, R0, 0x0031
|
|
0xA56AAE8E, # SH T2, 0xAE8E (T3)
|
|
0x340A001C, # ORI T2, R0, 0x001C
|
|
0xA56AAE78, # SH T2, 0xAE78 (T3)
|
|
0x340A0002, # ORI T2, R0, 0x0002
|
|
0xA56AAE7A, # SH T2, 0xAE7A (T3)
|
|
0x03E00008, # JR RA
|
|
0x00000000, # NOP
|
|
]
|
|
|
|
castle_crumbling_cornell_checker = [
|
|
# Teleports Cornell to his regular ending cutscene during the castle crumbling sequence after beating Centipede
|
|
# Dracula.
|
|
|
|
# Check the current character value for Cornell. If true, switch the scene to Cornell's ending forest and play
|
|
# his cutscene.
|
|
0x84482874, # LH T0, 0x2874 (V0)
|
|
0x34090002, # ORI T1, R0, 0x00002
|
|
0x15090005, # BNE T0, T1, [forward 0x05]
|
|
0x34090003, # ORI T1, R0, 0x0003
|
|
0x340A002D, # ORI T2, R0, 0x002D
|
|
0xA44A2BB8, # SH T2, 0x2BB8 (V0)
|
|
0x340A0030, # ORI T2, R0, 0x0030
|
|
0xA44A2BCE, # SH T2, 0x2BCE (V0)
|
|
0x0B8007A0, # J 0x0E001E80
|
|
0x00000000, # NOP
|
|
]
|
|
|
|
malus_bad_end_cornell_henry_checker = [
|
|
# Teleports Cornell and Henry to their respective "bad ending" cutscenes after Malus appears following Fake
|
|
# Dracula's defeat. Cornell doesn't have a bad ending normally, so we'll just give him Reinhardt's. Henry will
|
|
# have his usual ending but with no children rescued.
|
|
|
|
# Check the current character value for Cornell. If true, play his cutscene.
|
|
0x340A0002, # ORI T2, R0, 0x0002
|
|
0x14CA0003, # BNE A2, T2, [forward 0x03]
|
|
0x340A0003, # ORI T2, R0, 0x0003
|
|
0x0B8002FA, # J 0x0E000BE8
|
|
0xAC482BCC, # SW T0, 0x2BCC (V0)
|
|
# Check the current character value for Henry. If true, play his cutscene.
|
|
0x14CA0002, # BNE A2, T2, [forward 0x02]
|
|
0x34090031, # ORI T1, R0, 0x0031
|
|
0xAC492BCC, # SW T1, 0x2BCC (V0)
|
|
0x0B8002FA, # J 0x0E000BE8
|
|
0x00000000 # NOP
|
|
]
|
|
|
|
dracula_ultimate_non_cornell_checker = [
|
|
# Teleports all non-Cornell characters to their respective "good ending" cutscenes during the Dracula Ultimate
|
|
# Defeated cutscene.
|
|
|
|
# Check the current character value for Reinhardt. If true, switch the scene to Reinhardt/Carrie/Henry's endings and
|
|
# play his cutscene.
|
|
0x3C08801D, # LUI T0, 0x801D
|
|
0x9509AB34, # LHU T1, 0xAB34 (T0)
|
|
0x340A0000, # ORI T2, R0, 0x0000
|
|
0x152A0004, # BNE T1, T2, [forward 0x04]
|
|
0x340B001C, # ORI T3, R0, 0x001C
|
|
0x340C0000, # ORI T4, R0, 0x0000
|
|
0x1000000C, # B [forward 0x0C]
|
|
0x340D002E, # ORI T5, R0, 0x002E
|
|
# Check the current character value for Carrie. If true, switch the scene to Reinhardt/Carrie/Henry's endings and
|
|
# play her cutscene.
|
|
0x340A0001, # ORI T2, R0, 0x0001
|
|
0x152A0004, # BNE T1, T2, [forward 0x04]
|
|
0x340B001C, # ORI T3, R0, 0x001C
|
|
0x340C0002, # ORI T4, R0, 0x0012
|
|
0x10000006, # B [forward 0x06]
|
|
0x340D002C, # ORI T5, R0, 0x002C
|
|
# Check the current character value for Henry. If true, switch the scene to Reinhardt/Carrie/Henry's endings and
|
|
# play his cutscene.
|
|
0x340A0003, # ORI T2, R0, 0x0003
|
|
0x152A0006, # BNE T1, T2, [forward 0x06]
|
|
0x340B001C, # ORI T3, R0, 0x001C
|
|
0x340C0002, # ORI T4, R0, 0x0002
|
|
0x340D0031, # ORI T5, R0, 0x0031
|
|
0xA50BAE78, # SH T3, 0xAE78 (T0)
|
|
0xA50CAE7A, # SH T4, 0xAE7A (T0)
|
|
0xA50DAE8E, # SH T5, 0xAE8E (T0)
|
|
0x03E00008, # JR RA
|
|
0x00000000 # NOP
|
|
]
|