Links Awakening: Implement New Game (#1334)
Adds Link's Awakening: DX. Fully imports and forks LADXR, with permission - https://github.com/daid/LADXR
This commit is contained in:
436
worlds/ladx/LADXR/patches/aesthetics.py
Normal file
436
worlds/ladx/LADXR/patches/aesthetics.py
Normal file
@@ -0,0 +1,436 @@
|
||||
from ..assembler import ASM
|
||||
from ..utils import formatText, setReplacementName
|
||||
from ..roomEditor import RoomEditor
|
||||
from .. import entityData
|
||||
import os
|
||||
import bsdiff4
|
||||
|
||||
def imageTo2bpp(filename):
|
||||
import PIL.Image
|
||||
baseimg = PIL.Image.new('P', (1,1))
|
||||
baseimg.putpalette((
|
||||
128, 0, 128,
|
||||
0, 0, 0,
|
||||
128, 128, 128,
|
||||
255, 255, 255,
|
||||
))
|
||||
img = PIL.Image.open(filename)
|
||||
img = img.quantize(colors=4, palette=baseimg)
|
||||
print (f"Palette: {img.getpalette()}")
|
||||
assert (img.size[0] % 8) == 0
|
||||
tileheight = 8 if img.size[1] == 8 else 16
|
||||
assert (img.size[1] % tileheight) == 0
|
||||
|
||||
cols = img.size[0] // 8
|
||||
rows = img.size[1] // tileheight
|
||||
result = bytearray(rows * cols * tileheight * 2)
|
||||
index = 0
|
||||
for ty in range(rows):
|
||||
for tx in range(cols):
|
||||
for y in range(tileheight):
|
||||
a = 0
|
||||
b = 0
|
||||
for x in range(8):
|
||||
c = img.getpixel((tx * 8 + x, ty * 16 + y))
|
||||
if c & 1:
|
||||
a |= 0x80 >> x
|
||||
if c & 2:
|
||||
b |= 0x80 >> x
|
||||
result[index] = a
|
||||
result[index+1] = b
|
||||
index += 2
|
||||
return result
|
||||
|
||||
|
||||
def updateGraphics(rom, bank, offset, data):
|
||||
if offset + len(data) > 0x4000:
|
||||
updateGraphics(rom, bank, offset, data[:0x4000-offset])
|
||||
updateGraphics(rom, bank + 1, 0, data[0x4000 - offset:])
|
||||
else:
|
||||
rom.banks[bank][offset:offset+len(data)] = data
|
||||
if bank < 0x34:
|
||||
rom.banks[bank-0x20][offset:offset + len(data)] = data
|
||||
|
||||
|
||||
def gfxMod(rom, filename):
|
||||
if os.path.exists(filename + ".names"):
|
||||
for line in open(filename + ".names", "rt"):
|
||||
if ":" in line:
|
||||
k, v = line.strip().split(":", 1)
|
||||
setReplacementName(k, v)
|
||||
|
||||
ext = os.path.splitext(filename)[1].lower()
|
||||
if ext == ".bin":
|
||||
updateGraphics(rom, 0x2C, 0, open(filename, "rb").read())
|
||||
elif ext in (".png", ".bmp"):
|
||||
updateGraphics(rom, 0x2C, 0, imageTo2bpp(filename))
|
||||
elif ext == ".bdiff":
|
||||
updateGraphics(rom, 0x2C, 0, prepatch(rom, 0x2C, 0, filename))
|
||||
elif ext == ".json":
|
||||
import json
|
||||
data = json.load(open(filename, "rt"))
|
||||
|
||||
for patch in data:
|
||||
if "gfx" in patch:
|
||||
updateGraphics(rom, int(patch["bank"], 16), int(patch["offset"], 16), imageTo2bpp(os.path.join(os.path.dirname(filename), patch["gfx"])))
|
||||
if "name" in patch:
|
||||
setReplacementName(patch["item"], patch["name"])
|
||||
else:
|
||||
updateGraphics(rom, 0x2C, 0, imageTo2bpp(filename))
|
||||
|
||||
|
||||
def createGfxImage(rom, filename):
|
||||
import PIL.Image
|
||||
bank_count = 8
|
||||
img = PIL.Image.new("P", (32 * 8, 32 * 8 * bank_count))
|
||||
img.putpalette((
|
||||
128, 0, 128,
|
||||
0, 0, 0,
|
||||
128, 128, 128,
|
||||
255, 255, 255,
|
||||
))
|
||||
for bank_nr in range(bank_count):
|
||||
bank = rom.banks[0x2C + bank_nr]
|
||||
for tx in range(32):
|
||||
for ty in range(16):
|
||||
for y in range(16):
|
||||
a = bank[tx * 32 + ty * 32 * 32 + y * 2]
|
||||
b = bank[tx * 32 + ty * 32 * 32 + y * 2 + 1]
|
||||
for x in range(8):
|
||||
c = 0
|
||||
if a & (0x80 >> x):
|
||||
c |= 1
|
||||
if b & (0x80 >> x):
|
||||
c |= 2
|
||||
img.putpixel((tx*8+x, bank_nr * 32 * 8 + ty*16+y), c)
|
||||
img.save(filename)
|
||||
|
||||
def prepatch(rom, bank, offset, filename):
|
||||
bank_count = 8
|
||||
base_sheet = []
|
||||
result = []
|
||||
for bank_nr in range(bank_count):
|
||||
base_sheet[0x4000 * bank_nr:0x4000 * (bank_nr + 1) - 1] = rom.banks[0x2C + bank_nr]
|
||||
with open(filename, "rb") as patch:
|
||||
file = patch.read()
|
||||
result = bsdiff4.patch(src_bytes=bytes(base_sheet), patch_bytes=file)
|
||||
return result
|
||||
|
||||
def noSwordMusic(rom):
|
||||
# Skip no-sword music override
|
||||
# Instead of loading the sword level, we put the value 1 in the A register, indicating we have a sword.
|
||||
rom.patch(2, 0x0151, ASM("ld a, [$DB4E]"), ASM("ld a, $01"), fill_nop=True)
|
||||
rom.patch(2, 0x3AEF, ASM("ld a, [$DB4E]"), ASM("ld a, $01"), fill_nop=True)
|
||||
rom.patch(3, 0x0996, ASM("ld a, [$DB4E]"), ASM("ld a, $01"), fill_nop=True)
|
||||
rom.patch(3, 0x0B35, ASM("ld a, [$DB44]"), ASM("ld a, $01"), fill_nop=True)
|
||||
|
||||
|
||||
def removeNagMessages(rom):
|
||||
# Remove "this object is heavy, bla bla", and other nag messages when touching an object
|
||||
rom.patch(0x02, 0x32BB, ASM("ld a, [$C14A]"), ASM("ld a, $01"), fill_nop=True) # crystal blocks
|
||||
rom.patch(0x02, 0x32EC, ASM("ld a, [$C5A6]"), ASM("ld a, $01"), fill_nop=True) # cracked blocks
|
||||
rom.patch(0x02, 0x32D3, ASM("jr nz, $25"), ASM("jr $25"), fill_nop=True) # stones/pots
|
||||
rom.patch(0x02, 0x2B88, ASM("jr nz, $0F"), ASM("jr $0F"), fill_nop=True) # ice blocks
|
||||
|
||||
|
||||
def removeLowHPBeep(rom):
|
||||
rom.patch(2, 0x233A, ASM("ld hl, $FFF3\nld [hl], $04"), b"", fill_nop=True) # Remove health beep
|
||||
|
||||
|
||||
def slowLowHPBeep(rom):
|
||||
rom.patch(2, 0x2338, ASM("ld a, $30"), ASM("ld a, $60")) # slow slow hp beep
|
||||
|
||||
|
||||
def removeFlashingLights(rom):
|
||||
# Remove the switching between two backgrounds at mamu, always show the spotlights.
|
||||
rom.patch(0x00, 0x01EB, ASM("ldh a, [$E7]\nrrca\nand $80"), ASM("ld a, $80"), fill_nop=True)
|
||||
# Remove flashing colors from shopkeeper killing you after stealing and the mad batter giving items.
|
||||
rom.patch(0x24, 0x3B77, ASM("push bc"), ASM("ret"))
|
||||
|
||||
|
||||
def forceLinksPalette(rom, index):
|
||||
# This forces the link sprite into a specific palette index ignoring the tunic options.
|
||||
rom.patch(0, 0x1D8C,
|
||||
ASM("ld a, [$DC0F]\nand a\njr z, $03\ninc a"),
|
||||
ASM("ld a, $%02X" % (index)), fill_nop=True)
|
||||
rom.patch(0, 0x1DD2,
|
||||
ASM("ld a, [$DC0F]\nand a\njr z, $03\ninc a"),
|
||||
ASM("ld a, $%02X" % (index)), fill_nop=True)
|
||||
# Fix the waking up from bed palette
|
||||
if index == 1:
|
||||
rom.patch(0x21, 0x33FC, "A222", "FF05")
|
||||
elif index == 2:
|
||||
rom.patch(0x21, 0x33FC, "A222", "3F14")
|
||||
elif index == 3:
|
||||
rom.patch(0x21, 0x33FC, "A222", "037E")
|
||||
for n in range(6):
|
||||
rom.patch(0x05, 0x1261 + n * 2, "00", f"{index:02x}")
|
||||
|
||||
|
||||
def fastText(rom):
|
||||
rom.patch(0x00, 0x24CA, ASM("jp $2485"), ASM("call $2485"))
|
||||
|
||||
|
||||
def noText(rom):
|
||||
for idx in range(len(rom.texts)):
|
||||
if not isinstance(rom.texts[idx], int) and (idx < 0x217 or idx > 0x21A):
|
||||
rom.texts[idx] = rom.texts[idx][-1:]
|
||||
|
||||
|
||||
def reduceMessageLengths(rom, rnd):
|
||||
# Into text from Marin. Got to go fast, so less text. (This intro text is very long)
|
||||
rom.texts[0x01] = formatText(rnd.choice([
|
||||
"Let's a go!",
|
||||
"Remember, sword goes on A!",
|
||||
"Avoid the heart piece of shame!",
|
||||
"Marin? No, this is Zelda. Welcome to Hyrule",
|
||||
"Why are you in my bed?",
|
||||
"This is not a Mario game!",
|
||||
"MuffinJets was here...",
|
||||
"Remember, there are no bugs in LADX",
|
||||
"#####, #####, you got to wake up!\nDinner is ready.",
|
||||
"Go find the stepladder",
|
||||
"Pizza power!",
|
||||
"Eastmost penninsula is the secret",
|
||||
"There is no cow level",
|
||||
"You cannot lift rocks with your bear hands",
|
||||
"Thank you, daid!",
|
||||
"There, there now. Just relax. You've been asleep for almost nine hours now."
|
||||
]))
|
||||
|
||||
# Reduce length of a bunch of common texts
|
||||
rom.texts[0xEA] = formatText("You've got a Guardian Acorn!")
|
||||
rom.texts[0xEB] = rom.texts[0xEA]
|
||||
rom.texts[0xEC] = rom.texts[0xEA]
|
||||
rom.texts[0x08] = formatText("You got a Piece of Power!")
|
||||
rom.texts[0xEF] = formatText("You found a {SEASHELL}!")
|
||||
rom.texts[0xA7] = formatText("You've got the {COMPASS}!")
|
||||
|
||||
rom.texts[0x07] = formatText("You need the {NIGHTMARE_KEY}!")
|
||||
rom.texts[0x8C] = formatText("You need a {KEY}!") # keyhole block
|
||||
|
||||
rom.texts[0x09] = formatText("Ahhh... It has the Sleepy {TOADSTOOL}, it does! We'll mix it up something in a jiffy, we will!")
|
||||
rom.texts[0x0A] = formatText("The last thing I kin remember was bitin' into a big juicy {TOADSTOOL}... Then, I had the darndest dream... I was a raccoon! Yeah, sounds strange, but it sure was fun!")
|
||||
rom.texts[0x0F] = formatText("You pick the {TOADSTOOL}... As you hold it over your head, a mellow aroma flows into your nostrils.")
|
||||
rom.texts[0x13] = formatText("You've learned the ^{SONG1}!^ This song will always remain in your heart!")
|
||||
rom.texts[0x18] = formatText("Will you give me 28 {RUPEES} for my secret?", ask="Give Don't")
|
||||
rom.texts[0x19] = formatText("How about it? 42 {RUPEES} for my little secret...", ask="Give Don't")
|
||||
rom.texts[0x1e] = formatText("...You're so cute! I'll give you a 7 {RUPEE} discount!")
|
||||
rom.texts[0x2d] = formatText("{ARROWS_10}\n10 {RUPEES}!", ask="Buy Don't")
|
||||
rom.texts[0x32] = formatText("{SHIELD}\n20 {RUPEES}!", ask="Buy Don't")
|
||||
rom.texts[0x33] = formatText("Ten {BOMB}\n10 {RUPEES}", ask="Buy Don't")
|
||||
rom.texts[0x3d] = formatText("It's a {SHIELD}! There is space for your name!")
|
||||
rom.texts[0x42] = formatText("It's 30 {RUPEES}! You can play the game three more times with this!")
|
||||
rom.texts[0x45] = formatText("How about some fishing, little buddy? I'll only charge you 10 {RUPEES}...", ask="Fish Not Now")
|
||||
rom.texts[0x4b] = formatText("Wow! Nice Fish! It's a lunker!! I'll give you a 20 {RUPEE} prize! Try again?", ask="Cast Not Now")
|
||||
rom.texts[0x4e] = formatText("You're short of {RUPEES}? Don't worry about it. You just come back when you have more money, little buddy.")
|
||||
rom.texts[0x4f] = formatText("You've got a {HEART_PIECE}! Press SELECT on the Subscreen to see.")
|
||||
rom.texts[0x8e] = formatText("Well, it's an {OCARINA}, but you don't know how to play it...")
|
||||
rom.texts[0x90] = formatText("You found the {POWER_BRACELET}! At last, you can pick up pots and stones!")
|
||||
rom.texts[0x91] = formatText("You got your {SHIELD} back! Press the button and repel enemies with it!")
|
||||
rom.texts[0x93] = formatText("You've got the {HOOKSHOT}! Its chain stretches long when you use it!")
|
||||
rom.texts[0x94] = formatText("You've got the {MAGIC_ROD}! Now you can burn things! Burn it! Burn, baby burn!")
|
||||
rom.texts[0x95] = formatText("You've got the {PEGASUS_BOOTS}! If you hold down the Button, you can dash!")
|
||||
rom.texts[0x96] = formatText("You've got the {OCARINA}! You should learn to play many songs!")
|
||||
rom.texts[0x97] = formatText("You've got the {FEATHER}! It feels like your body is a lot lighter!")
|
||||
rom.texts[0x98] = formatText("You've got a {SHOVEL}! Now you can feel the joy of digging!")
|
||||
rom.texts[0x99] = formatText("You've got some {MAGIC_POWDER}! Try sprinkling it on a variety of things!")
|
||||
rom.texts[0x9b] = formatText("You found your {SWORD}! It must be yours because it has your name engraved on it!")
|
||||
rom.texts[0x9c] = formatText("You've got the {FLIPPERS}! If you press the B Button while you swim, you can dive underwater!")
|
||||
rom.texts[0x9e] = formatText("You've got a new {SWORD}! You should put your name on it right away!")
|
||||
rom.texts[0x9f] = formatText("You've got a new {SWORD}! You should put your name on it right away!")
|
||||
rom.texts[0xa0] = formatText("You found the {MEDICINE}! You should apply this and see what happens!")
|
||||
rom.texts[0xa1] = formatText("You've got the {TAIL_KEY}! Now you can open the Tail Cave gate!")
|
||||
rom.texts[0xa2] = formatText("You've got the {SLIME_KEY}! Now you can open the gate in Ukuku Prairie!")
|
||||
rom.texts[0xa3] = formatText("You've got the {ANGLER_KEY}!")
|
||||
rom.texts[0xa4] = formatText("You've got the {FACE_KEY}!")
|
||||
rom.texts[0xa5] = formatText("You've got the {BIRD_KEY}!")
|
||||
rom.texts[0xa6] = formatText("At last, you got a {MAP}! Press the START Button to look at it!")
|
||||
rom.texts[0xa8] = formatText("You found a {STONE_BEAK}! Let's find the owl statue that belongs to it.")
|
||||
rom.texts[0xa9] = formatText("You've got the {NIGHTMARE_KEY}! Now you can open the door to the Nightmare's Lair!")
|
||||
rom.texts[0xaa] = formatText("You got a {KEY}! You can open a locked door.")
|
||||
rom.texts[0xab] = formatText("You got 20 {RUPEES}! JOY!", center=True)
|
||||
rom.texts[0xac] = formatText("You got 50 {RUPEES}! Very Nice!", center=True)
|
||||
rom.texts[0xad] = formatText("You got 100 {RUPEES}! You're Happy!", center=True)
|
||||
rom.texts[0xae] = formatText("You got 200 {RUPEES}! You're Ecstatic!", center=True)
|
||||
rom.texts[0xdc] = formatText("Ribbit! Ribbit! I'm Mamu, on vocals! But I don't need to tell you that, do I? Everybody knows me! Want to hang out and listen to us jam? For 300 Rupees, we'll let you listen to a previously unreleased cut! What do you do?", ask="Pay Leave")
|
||||
rom.texts[0xe8] = formatText("You've found a {GOLD_LEAF}! Press START to see how many you've collected!")
|
||||
rom.texts[0xed] = formatText("You've got the Mirror Shield! You can now turnback the beams you couldn't block before!")
|
||||
rom.texts[0xee] = formatText("You've got a more Powerful {POWER_BRACELET}! Now you can almost lift a whale!")
|
||||
rom.texts[0xf0] = formatText("Want to go on a raft ride for a hundred {RUPEES}?", ask="Yes No Way")
|
||||
|
||||
|
||||
def allowColorDungeonSpritesEverywhere(rom):
|
||||
# Set sprite set numbers $01-$40 to map to the color dungeon sprites
|
||||
rom.patch(0x00, 0x2E6F, "00", "15")
|
||||
# Patch the spriteset loading code to load the 4 entries from the normal table instead of skipping this for color dungeon specific exception weirdness
|
||||
rom.patch(0x00, 0x0DA4, ASM("jr nc, $05"), ASM("jr nc, $41"))
|
||||
rom.patch(0x00, 0x0DE5, ASM("""
|
||||
ldh a, [$F7]
|
||||
cp $FF
|
||||
jr nz, $06
|
||||
ld a, $01
|
||||
ldh [$91], a
|
||||
jr $40
|
||||
"""), ASM("""
|
||||
jr $0A ; skip over the rest of the code
|
||||
cp $FF ; check if color dungeon
|
||||
jp nz, $0DAB
|
||||
inc d
|
||||
jp $0DAA
|
||||
"""), fill_nop=True)
|
||||
# Disable color dungeon specific tile load hacks
|
||||
rom.patch(0x00, 0x06A7, ASM("jr nz, $22"), ASM("jr $22"))
|
||||
rom.patch(0x00, 0x2E77, ASM("jr nz, $0B"), ASM("jr $0B"))
|
||||
|
||||
# Finally fill in the sprite data for the color dungeon
|
||||
for n in range(22):
|
||||
data = bytearray()
|
||||
for m in range(4):
|
||||
idx = rom.banks[0x20][0x06AA + 44 * m + n * 2]
|
||||
bank = rom.banks[0x20][0x06AA + 44 * m + n * 2 + 1]
|
||||
if idx == 0 and bank == 0:
|
||||
v = 0xFF
|
||||
elif bank == 0x35:
|
||||
v = idx - 0x40
|
||||
elif bank == 0x31:
|
||||
v = idx
|
||||
elif bank == 0x2E:
|
||||
v = idx + 0x40
|
||||
else:
|
||||
assert False, "%02x %02x" % (idx, bank)
|
||||
data += bytes([v])
|
||||
rom.room_sprite_data_indoor[0x200 + n] = data
|
||||
|
||||
# Patch the graphics loading code to use DMA and load all sets that need to be reloaded, not just the first and last
|
||||
rom.patch(0x00, 0x06FA, 0x07AF, ASM("""
|
||||
;We enter this code with the right bank selected for tile data copy,
|
||||
;d = tile row (source addr = (d*$100+$4000))
|
||||
;e = $00
|
||||
;$C197 = index of sprite set to update (target addr = ($8400 + $100 * [$C197]))
|
||||
ld a, d
|
||||
add a, $40
|
||||
ldh [$51], a
|
||||
xor a
|
||||
ldh [$52], a
|
||||
ldh [$54], a
|
||||
ld a, [$C197]
|
||||
add a, $84
|
||||
ldh [$53], a
|
||||
ld a, $0F
|
||||
ldh [$55], a
|
||||
|
||||
; See if we need to do anything next
|
||||
ld a, [$C10E] ; check the 2nd update flag
|
||||
and a
|
||||
jr nz, getNext
|
||||
ldh [$91], a ; no 2nd update flag, so clear primary update flag
|
||||
ret
|
||||
getNext:
|
||||
ld hl, $C197
|
||||
inc [hl]
|
||||
res 2, [hl]
|
||||
ld a, [$C10D]
|
||||
cp [hl]
|
||||
ret nz
|
||||
xor a ; clear the 2nd update flag when we prepare to update the last spriteset
|
||||
ld [$C10E], a
|
||||
ret
|
||||
"""), fill_nop=True)
|
||||
rom.patch(0x00, 0x0738, "00" * (0x073E - 0x0738), ASM("""
|
||||
; we get here by some color dungeon specific code jumping to this position
|
||||
; We still need that color dungeon specific code as it loads background tiles
|
||||
xor a
|
||||
ldh [$91], a
|
||||
ldh [$93], a
|
||||
ret
|
||||
"""))
|
||||
rom.patch(0x00, 0x073E, "00" * (0x07AF - 0x073E), ASM("""
|
||||
;If we get here, only the 2nd flag is filled and the primary is not. So swap those around.
|
||||
ld a, [$C10D] ;copy the index number
|
||||
ld [$C197], a
|
||||
xor a
|
||||
ld [$C10E], a ; clear the 2nd update flag
|
||||
inc a
|
||||
ldh [$91], a ; set the primary update flag
|
||||
ret
|
||||
"""), fill_nop=True)
|
||||
|
||||
|
||||
def updateSpriteData(rom):
|
||||
# Change the special sprite change exceptions
|
||||
rom.patch(0x00, 0x0DAD, 0x0DDB, ASM("""
|
||||
; Check for indoor
|
||||
ld a, d
|
||||
and a
|
||||
jr nz, noChange
|
||||
ldh a, [$F6] ; hMapRoom
|
||||
cp $C9
|
||||
jr nz, sirenRoomEnd
|
||||
ld a, [$D8C9] ; wOverworldRoomStatus + ROOM_OW_SIREN
|
||||
and $20
|
||||
jr z, noChange
|
||||
ld hl, $7837
|
||||
jp $0DFE
|
||||
sirenRoomEnd:
|
||||
ldh a, [$F6] ; hMapRoom
|
||||
cp $D8
|
||||
jr nz, noChange
|
||||
ld a, [$D8FD] ; wOverworldRoomStatus + ROOM_OW_WALRUS
|
||||
and $20
|
||||
jr z, noChange
|
||||
ld hl, $783B
|
||||
jp $0DFE
|
||||
noChange:
|
||||
"""), fill_nop=True)
|
||||
rom.patch(0x20, 0x3837, "A4FF8BFF", "A461FF72")
|
||||
rom.patch(0x20, 0x383B, "A44DFFFF", "A4C5FF70")
|
||||
|
||||
# For each room update the sprite load data based on which entities are in there.
|
||||
for room_nr in range(0x316):
|
||||
if room_nr == 0x2FF:
|
||||
continue
|
||||
values = [None, None, None, None]
|
||||
if room_nr == 0x00E: # D7 entrance opening
|
||||
values[2] = 0xD6
|
||||
values[3] = 0xD7
|
||||
if 0x211 <= room_nr <= 0x21E: # D7 throwing ball thing.
|
||||
values[0] = 0x66
|
||||
r = RoomEditor(rom, room_nr)
|
||||
for obj in r.objects:
|
||||
if obj.type_id == 0xC5 and room_nr < 0x100: # Pushable Gravestone
|
||||
values[3] = 0x82
|
||||
for x, y, entity in r.entities:
|
||||
sprite_data = entityData.SPRITE_DATA[entity]
|
||||
if callable(sprite_data):
|
||||
sprite_data = sprite_data(r)
|
||||
if sprite_data is None:
|
||||
continue
|
||||
for m in range(0, len(sprite_data), 2):
|
||||
idx, value = sprite_data[m:m+2]
|
||||
if values[idx] is None:
|
||||
values[idx] = value
|
||||
elif isinstance(values[idx], set) and isinstance(value, set):
|
||||
values[idx] = values[idx].intersection(value)
|
||||
assert len(values[idx]) > 0
|
||||
elif isinstance(values[idx], set) and value in values[idx]:
|
||||
values[idx] = value
|
||||
elif isinstance(value, set) and values[idx] in value:
|
||||
pass
|
||||
elif values[idx] == value:
|
||||
pass
|
||||
else:
|
||||
assert False, "Room: %03x cannot load graphics for entity: %02x (Index: %d Failed: %s, Active: %s)" % (room_nr, entity, idx, value, values[idx])
|
||||
|
||||
data = bytearray()
|
||||
for v in values:
|
||||
if isinstance(v, set):
|
||||
v = next(iter(v))
|
||||
elif v is None:
|
||||
v = 0xff
|
||||
data.append(v)
|
||||
|
||||
if room_nr < 0x100:
|
||||
rom.room_sprite_data_overworld[room_nr] = data
|
||||
else:
|
||||
rom.room_sprite_data_indoor[room_nr - 0x100] = data
|
||||
125
worlds/ladx/LADXR/patches/bank34.py
Normal file
125
worlds/ladx/LADXR/patches/bank34.py
Normal file
@@ -0,0 +1,125 @@
|
||||
import os
|
||||
import binascii
|
||||
from ..assembler import ASM
|
||||
from ..utils import formatText
|
||||
|
||||
ItemNameLookupTable = 0x0100
|
||||
ItemNameLookupSize = 2
|
||||
TotalRoomCount = 0x316
|
||||
|
||||
AnItemText = "an item"
|
||||
ItemNameStringBufferStart = ItemNameLookupTable + \
|
||||
TotalRoomCount * ItemNameLookupSize
|
||||
|
||||
|
||||
def addBank34(rom, item_list):
|
||||
my_path = os.path.dirname(__file__)
|
||||
rom.patch(0x34, 0x0000, ItemNameLookupTable, ASM("""
|
||||
; Get the pointer in the lookup table, doubled as it's two bytes
|
||||
ld hl, $2080
|
||||
push de
|
||||
call OffsetPointerByRoomNumber
|
||||
pop de
|
||||
add hl, hl
|
||||
|
||||
ldi a, [hl] ; hl = *hl
|
||||
ld h, [hl]
|
||||
ld l, a
|
||||
|
||||
; If there's no data, bail
|
||||
ld a, l
|
||||
or h
|
||||
jp z, SwitchBackTo3E
|
||||
|
||||
ld de, wCustomMessage
|
||||
; Copy "Got " to de
|
||||
ld a, 71
|
||||
ld [de], a
|
||||
inc de
|
||||
ld a, 111
|
||||
ld [de], a
|
||||
inc de
|
||||
ld a, 116
|
||||
ld [de], a
|
||||
inc de
|
||||
ld a, 32
|
||||
ld [de], a
|
||||
inc de
|
||||
; Copy in our item name
|
||||
call MessageCopyString
|
||||
SwitchBackTo3E:
|
||||
; Bail
|
||||
ld a, $3e ; Set bank number
|
||||
jp $080C ; switch bank
|
||||
|
||||
; this should be shared but I got link errors
|
||||
OffsetPointerByRoomNumber:
|
||||
ldh a, [$F6] ; map room
|
||||
ld e, a
|
||||
ld a, [$DBA5] ; is indoor
|
||||
ld d, a
|
||||
ldh a, [$F7] ; mapId
|
||||
cp $FF
|
||||
jr nz, .notColorDungeon
|
||||
|
||||
ld d, $03
|
||||
jr .notCavesA
|
||||
|
||||
.notColorDungeon:
|
||||
cp $1A
|
||||
jr nc, .notCavesA
|
||||
cp $06
|
||||
jr c, .notCavesA
|
||||
inc d
|
||||
.notCavesA:
|
||||
add hl, de
|
||||
ret
|
||||
""" + open(os.path.join(my_path, "bank3e.asm/message.asm"), "rt").read(), 0x4000), fill_nop=True)
|
||||
|
||||
nextItemLookup = ItemNameStringBufferStart
|
||||
nameLookup = {
|
||||
|
||||
}
|
||||
|
||||
name = AnItemText
|
||||
|
||||
def add_or_get_name(name):
|
||||
nonlocal nextItemLookup
|
||||
if name in nameLookup:
|
||||
return nameLookup[name]
|
||||
if len(name) + 1 + nextItemLookup >= 0x4000:
|
||||
return nameLookup[AnItemText]
|
||||
asm = ASM(f'db "{name}", $ff\n')
|
||||
rom.patch(0x34, nextItemLookup, None, asm)
|
||||
patch_len = len(binascii.unhexlify(asm))
|
||||
nameLookup[name] = nextItemLookup + 0x4000
|
||||
nextItemLookup += patch_len
|
||||
return nameLookup[name]
|
||||
|
||||
item_text_addr = add_or_get_name(AnItemText)
|
||||
#error_text_addr = add_or_get_name("Please report this check to #bug-reports in the AP discord")
|
||||
def swap16(x):
|
||||
assert x <= 0xFFFF
|
||||
return (x >> 8) | ((x & 0xFF) << 8)
|
||||
|
||||
def to_hex_address(x):
|
||||
return f"{swap16(x):04x}"
|
||||
|
||||
# Set defaults for every room
|
||||
for i in range(TotalRoomCount):
|
||||
rom.patch(0x34, ItemNameLookupTable + i *
|
||||
ItemNameLookupSize, None, to_hex_address(0))
|
||||
|
||||
for item in item_list:
|
||||
if not item.custom_item_name:
|
||||
continue
|
||||
assert item.room < TotalRoomCount, item.room
|
||||
# Item names of exactly 255 characters will cause overwrites to occur in the text box
|
||||
# assert len(item.custom_item_name) < 0x100
|
||||
# Custom text is only 95 bytes long, restrict to 50
|
||||
addr = add_or_get_name(item.custom_item_name[:50])
|
||||
rom.patch(0x34, ItemNameLookupTable + item.room *
|
||||
ItemNameLookupSize, None, to_hex_address(addr))
|
||||
if item.extra:
|
||||
rom.patch(0x34, ItemNameLookupTable + item.extra *
|
||||
ItemNameLookupSize, None, to_hex_address(addr))
|
||||
303
worlds/ladx/LADXR/patches/bank3e.asm/bowwow.asm
Normal file
303
worlds/ladx/LADXR/patches/bank3e.asm/bowwow.asm
Normal file
@@ -0,0 +1,303 @@
|
||||
CheckIfLoadBowWow:
|
||||
; Check has bowwow flag
|
||||
ld a, [$DB56]
|
||||
cp $01
|
||||
jr nz, .noLoadBowwow
|
||||
|
||||
ldh a, [$F6] ; load map number
|
||||
cp $22
|
||||
jr z, .loadBowwow
|
||||
cp $23
|
||||
jr z, .loadBowwow
|
||||
cp $24
|
||||
jr z, .loadBowwow
|
||||
cp $32
|
||||
jr z, .loadBowwow
|
||||
cp $33
|
||||
jr z, .loadBowwow
|
||||
cp $34
|
||||
jr z, .loadBowwow
|
||||
|
||||
.noLoadBowwow:
|
||||
ld e, $00
|
||||
ret
|
||||
|
||||
.loadBowwow:
|
||||
ld e, $01
|
||||
ret
|
||||
|
||||
|
||||
; Special handler for when Bowwow tries to eat an entity.
|
||||
; Our target entity index is loaded in BC.
|
||||
BowwowEat:
|
||||
; Load the entity type into A
|
||||
ld hl, $C3A0 ; entity type
|
||||
add hl, bc
|
||||
ld a, [hl]
|
||||
|
||||
; Check if we need special handling for bosses
|
||||
cp $59 ; Moldorm
|
||||
jr z, BowwowHurtEnemy
|
||||
cp $5C ; Genie
|
||||
jr z, BowwowEatGenie
|
||||
cp $5B ; SlimeEye
|
||||
jp z, BowwowEatSlimeEye
|
||||
cp $65 ; AnglerFish
|
||||
jr z, BowwowHurtEnemy
|
||||
cp $5D ; SlimeEel
|
||||
jp z, BowwowEatSlimeEel
|
||||
cp $5A ; Facade
|
||||
jr z, BowwowHurtEnemy
|
||||
cp $63 ; Eagle
|
||||
jr z, BowwowHurtEnemy
|
||||
cp $62 ; Hot head
|
||||
jp z, BowwowEatHotHead
|
||||
cp $F9 ; Hardhit beetle
|
||||
jr z, BowwowHurtEnemy
|
||||
cp $E6 ; Nightmare (all forms)
|
||||
jp z, BowwowEatNightmare
|
||||
|
||||
; Check for special handling for minibosses
|
||||
cp $87 ; Lanmola
|
||||
jr z, BowwowHurtEnemy
|
||||
; cp $88 ; Armos knight
|
||||
; No special handling, just eat him, solves the fight real quick.
|
||||
cp $81 ; rolling bones
|
||||
jr z, BowwowHurtEnemy
|
||||
cp $89 ; Hinox
|
||||
jr z, BowwowHurtEnemy
|
||||
cp $8E ; Cue ball
|
||||
jr z, BowwowHurtEnemy
|
||||
;cp $5E ; Gnoma
|
||||
;jr z, BowwowHurtEnemy
|
||||
cp $5F ; Master stalfos
|
||||
jr z, BowwowHurtEnemy
|
||||
cp $92 ; Smasher
|
||||
jp z, BowwowEatSmasher
|
||||
cp $BC ; Grim Creeper
|
||||
jp z, BowwowEatGrimCreeper
|
||||
cp $BE ; Blaino
|
||||
jr z, BowwowHurtEnemy
|
||||
cp $F8 ; Giant buzz blob
|
||||
jr z, BowwowHurtEnemy
|
||||
cp $F4 ; Avalaunch
|
||||
jr z, BowwowHurtEnemy
|
||||
|
||||
; Some enemies
|
||||
cp $E9 ; Color dungeon shell
|
||||
jr z, BowwowHurtEnemy
|
||||
cp $EA ; Color dungeon shell
|
||||
jr z, BowwowHurtEnemy
|
||||
cp $EB ; Color dungeon shell
|
||||
jr z, BowwowHurtEnemy
|
||||
|
||||
; Play SFX
|
||||
ld a, $03
|
||||
ldh [$F2], a
|
||||
; Call normal "destroy entity and drop item" handler
|
||||
jp $3F50
|
||||
|
||||
BowwowHurtEnemy:
|
||||
; Hurt enemy with damage type zero (sword)
|
||||
ld a, $00
|
||||
ld [$C19E], a
|
||||
rst $18
|
||||
; Play SFX
|
||||
ld a, $03
|
||||
ldh [$F2], a
|
||||
ret
|
||||
|
||||
BowwowEatGenie:
|
||||
; Get private state to find out if this is a bottle or the genie
|
||||
ld hl, $C2B0
|
||||
add hl, bc
|
||||
ld a, [hl]
|
||||
; Prepare loading state from hl
|
||||
ld hl, $C290
|
||||
add hl, bc
|
||||
|
||||
cp $00
|
||||
jr z, .bottle
|
||||
cp $01
|
||||
jr z, .ghost
|
||||
ret
|
||||
|
||||
.ghost:
|
||||
; Get current state
|
||||
ld a, [hl]
|
||||
cp $04 ; Flying around without bottle
|
||||
jr z, BowwowHurtEnemy
|
||||
ret
|
||||
|
||||
.bottle:
|
||||
; Get current state
|
||||
ld a, [hl]
|
||||
cp $03 ; Hopping around in bottle
|
||||
jr z, BowwowHurtEnemy
|
||||
ret
|
||||
|
||||
BowwowEatSlimeEye:
|
||||
; On set privateCountdown2 to $0C to split, when privateState1 is $04 and state is $03
|
||||
ld hl, $C290 ; state
|
||||
add hl, bc
|
||||
ld a, [hl]
|
||||
cp $03
|
||||
jr nz, .skipSplit
|
||||
|
||||
ld hl, $C2B0 ; private state1
|
||||
add hl, bc
|
||||
ld a, [hl]
|
||||
cp $04
|
||||
jr nz, .skipSplit
|
||||
|
||||
ld hl, $C300 ; private countdown 2
|
||||
add hl, bc
|
||||
ld [hl], $0C
|
||||
|
||||
.skipSplit:
|
||||
jp BowwowHurtEnemy
|
||||
|
||||
BowwowEatSlimeEel:
|
||||
; Get private state to find out if this is the tail or the head
|
||||
ld hl, $C2B0
|
||||
add hl, bc
|
||||
ld a, [hl]
|
||||
cp $01 ; not the head, so, skip.
|
||||
ret nz
|
||||
|
||||
; Check if we are pulled out of the wall
|
||||
ld hl, $C290
|
||||
add hl, bc
|
||||
ld a, [hl]
|
||||
cp $03 ; pulled out of the wall
|
||||
jr nz, .knockOutOfWall
|
||||
|
||||
ld hl, $D204
|
||||
ld a, [hl]
|
||||
cp $07
|
||||
jr nc, .noExtraDamage
|
||||
inc [hl]
|
||||
.noExtraDamage:
|
||||
jp BowwowHurtEnemy
|
||||
|
||||
.knockOutOfWall:
|
||||
ld [hl], $03 ; set state to $03
|
||||
ld hl, $C210 ; Y position
|
||||
add hl, bc
|
||||
ld a, [hl]
|
||||
ld [hl], $60
|
||||
cp $48
|
||||
jp nc, BowwowHurtEnemy
|
||||
ld [hl], $30
|
||||
jp BowwowHurtEnemy
|
||||
|
||||
|
||||
BowwowEatHotHead:
|
||||
; Load health of hothead
|
||||
ld hl, $C360
|
||||
add hl, bc
|
||||
ld a, [hl]
|
||||
cp $20
|
||||
jr c, .lowHp
|
||||
ld [hl], $20
|
||||
.lowHp:
|
||||
jp BowwowHurtEnemy
|
||||
|
||||
BowwowEatSmasher:
|
||||
; Check if this is the ball or the monster
|
||||
ld hl, $C440
|
||||
add hl, bc
|
||||
ld a, [hl]
|
||||
and a
|
||||
ret nz
|
||||
jp BowwowHurtEnemy
|
||||
|
||||
BowwowEatGrimCreeper:
|
||||
; Check if this is the main enemy or the smaller ones. Only kill the small ones
|
||||
ld hl, $C2B0
|
||||
add hl, bc
|
||||
ld a, [hl]
|
||||
and a
|
||||
ret z
|
||||
jp BowwowHurtEnemy
|
||||
|
||||
BowwowEatNightmare:
|
||||
; Check if this is the staircase.
|
||||
ld hl, $C390
|
||||
add hl, bc
|
||||
ld a, [hl]
|
||||
cp $02
|
||||
ret z
|
||||
|
||||
; Prepare loading state from hl
|
||||
ld hl, $C290
|
||||
add hl, bc
|
||||
|
||||
ld a, [$D219] ; which form has the nightmare
|
||||
cp $01
|
||||
jr z, .slimeForm
|
||||
cp $02
|
||||
jr z, .agahnimForm
|
||||
cp $03 ; moldormForm
|
||||
jp z, BowwowHurtEnemy
|
||||
cp $04 ; ganon and lanmola
|
||||
jp z, BowwowHurtEnemy
|
||||
cp $05 ; dethl
|
||||
jp z, BowwowHurtEnemy
|
||||
; 0 is the intro form
|
||||
ret
|
||||
|
||||
.slimeForm:
|
||||
ld a, [hl]
|
||||
cp $02
|
||||
jr z, .canHurtSlime
|
||||
cp $03
|
||||
ret nz
|
||||
|
||||
.canHurtSlime:
|
||||
; We need quite some custom handling, normally the nightmare checks very directly if you use powder.
|
||||
; No idea why this insta kills the slime form...
|
||||
; Change state to hurt state
|
||||
ld [hl], $07
|
||||
; Set flash count
|
||||
ld hl, $C420
|
||||
add hl, bc
|
||||
ld [hl], $14
|
||||
; play proper sfx
|
||||
ld a, $07
|
||||
ldh [$F3], a
|
||||
ld a, $37
|
||||
ldh [$F2], a
|
||||
; No idea why this is done, but it happens when you use powder on the slime
|
||||
ld a, $03
|
||||
ld [$D220], a
|
||||
ret
|
||||
|
||||
.agahnimForm:
|
||||
ld a, [hl]
|
||||
; only damage in states 2 to 4
|
||||
cp $02
|
||||
ret c
|
||||
cp $04
|
||||
ret nc
|
||||
|
||||
; Decrease health
|
||||
ld a, [$D220]
|
||||
inc a
|
||||
ld [$D220], a
|
||||
; If dead, do stuff
|
||||
cp $04
|
||||
jr c, .agahnimNotDeadYet
|
||||
ld [hl], $07
|
||||
ld hl, $C2E0
|
||||
add hl, bc
|
||||
ld [hl], $C0
|
||||
ld a, $36
|
||||
ldh [$F2], a
|
||||
.agahnimNotDeadYet:
|
||||
ld hl, $C420
|
||||
add hl, bc
|
||||
ld [hl], $14
|
||||
ld a, $07
|
||||
ldh [$F3], a
|
||||
ret
|
||||
993
worlds/ladx/LADXR/patches/bank3e.asm/chest.asm
Normal file
993
worlds/ladx/LADXR/patches/bank3e.asm/chest.asm
Normal file
@@ -0,0 +1,993 @@
|
||||
RenderChestItem:
|
||||
ldh a, [$F1] ; active sprite
|
||||
and $80
|
||||
jr nz, .renderLargeItem
|
||||
|
||||
ld de, ItemSpriteTable
|
||||
call $3C77 ; RenderActiveEntitySprite
|
||||
ret
|
||||
.renderLargeItem:
|
||||
ld de, LargeItemSpriteTable
|
||||
dec d
|
||||
dec d
|
||||
call $3BC0 ; RenderActiveEntitySpritePair
|
||||
|
||||
; If we are an instrument
|
||||
ldh a, [$F1]
|
||||
cp $8E
|
||||
ret c
|
||||
cp $96
|
||||
ret nc
|
||||
|
||||
; But check if we are not state >3 before that, else the fade-out at the instrument room breaks.
|
||||
ldh a, [$F0] ; hActiveEntityState
|
||||
cp $03
|
||||
ret nc
|
||||
|
||||
; Call the color cycling code
|
||||
xor a
|
||||
ld [$DC82], a
|
||||
ld [$DC83], a
|
||||
ld a, $3e
|
||||
call $0AD2
|
||||
ret
|
||||
|
||||
GiveItemFromChestMultiworld:
|
||||
call IncreaseCheckCounter
|
||||
; Check our "item is for other player" flag
|
||||
ld hl, $7300
|
||||
call OffsetPointerByRoomNumber
|
||||
ld a, [hl]
|
||||
ld hl, $0055
|
||||
cp [hl]
|
||||
ret nz
|
||||
|
||||
GiveItemFromChest:
|
||||
ldh a, [$F1] ; Load active sprite variant
|
||||
|
||||
rst 0 ; JUMP TABLE
|
||||
dw ChestPowerBracelet; CHEST_POWER_BRACELET
|
||||
dw ChestShield ; CHEST_SHIELD
|
||||
dw ChestBow ; CHEST_BOW
|
||||
dw ChestWithItem ; CHEST_HOOKSHOT
|
||||
dw ChestWithItem ; CHEST_MAGIC_ROD
|
||||
dw ChestWithItem ; CHEST_PEGASUS_BOOTS
|
||||
dw ChestWithItem ; CHEST_OCARINA
|
||||
dw ChestWithItem ; CHEST_FEATHER
|
||||
dw ChestWithItem ; CHEST_SHOVEL
|
||||
dw ChestMagicPowder ; CHEST_MAGIC_POWDER_BAG
|
||||
dw ChestBomb ; CHEST_BOMB
|
||||
dw ChestSword ; CHEST_SWORD
|
||||
dw Flippers ; CHEST_FLIPPERS
|
||||
dw NoItem ; CHEST_MAGNIFYING_LENS
|
||||
dw ChestWithItem ; Boomerang (used to be unused)
|
||||
dw SlimeKey ; ?? right side of your trade quest item
|
||||
dw Medicine ; CHEST_MEDICINE
|
||||
dw TailKey ; CHEST_TAIL_KEY
|
||||
dw AnglerKey ; CHEST_ANGLER_KEY
|
||||
dw FaceKey ; CHEST_FACE_KEY
|
||||
dw BirdKey ; CHEST_BIRD_KEY
|
||||
dw GoldenLeaf ; CHEST_GOLD_LEAF
|
||||
dw ChestWithCurrentDungeonItem ; CHEST_MAP
|
||||
dw ChestWithCurrentDungeonItem ; CHEST_COMPASS
|
||||
dw ChestWithCurrentDungeonItem ; CHEST_STONE_BEAK
|
||||
dw ChestWithCurrentDungeonItem ; CHEST_NIGHTMARE_KEY
|
||||
dw ChestWithCurrentDungeonItem ; CHEST_SMALL_KEY
|
||||
dw AddRupees50 ; CHEST_RUPEES_50
|
||||
dw AddRupees20 ; CHEST_RUPEES_20
|
||||
dw AddRupees100 ; CHEST_RUPEES_100
|
||||
dw AddRupees200 ; CHEST_RUPEES_200
|
||||
dw AddRupees500 ; CHEST_RUPEES_500
|
||||
dw AddSeashell ; CHEST_SEASHELL
|
||||
dw NoItem ; CHEST_MESSAGE
|
||||
dw NoItem ; CHEST_GEL
|
||||
dw AddKey ; KEY1
|
||||
dw AddKey ; KEY2
|
||||
dw AddKey ; KEY3
|
||||
dw AddKey ; KEY4
|
||||
dw AddKey ; KEY5
|
||||
dw AddKey ; KEY6
|
||||
dw AddKey ; KEY7
|
||||
dw AddKey ; KEY8
|
||||
dw AddKey ; KEY9
|
||||
dw AddMap ; MAP1
|
||||
dw AddMap ; MAP2
|
||||
dw AddMap ; MAP3
|
||||
dw AddMap ; MAP4
|
||||
dw AddMap ; MAP5
|
||||
dw AddMap ; MAP6
|
||||
dw AddMap ; MAP7
|
||||
dw AddMap ; MAP8
|
||||
dw AddMap ; MAP9
|
||||
dw AddCompass ; COMPASS1
|
||||
dw AddCompass ; COMPASS2
|
||||
dw AddCompass ; COMPASS3
|
||||
dw AddCompass ; COMPASS4
|
||||
dw AddCompass ; COMPASS5
|
||||
dw AddCompass ; COMPASS6
|
||||
dw AddCompass ; COMPASS7
|
||||
dw AddCompass ; COMPASS8
|
||||
dw AddCompass ; COMPASS9
|
||||
dw AddStoneBeak ; STONE_BEAK1
|
||||
dw AddStoneBeak ; STONE_BEAK2
|
||||
dw AddStoneBeak ; STONE_BEAK3
|
||||
dw AddStoneBeak ; STONE_BEAK4
|
||||
dw AddStoneBeak ; STONE_BEAK5
|
||||
dw AddStoneBeak ; STONE_BEAK6
|
||||
dw AddStoneBeak ; STONE_BEAK7
|
||||
dw AddStoneBeak ; STONE_BEAK8
|
||||
dw AddStoneBeak ; STONE_BEAK9
|
||||
dw AddNightmareKey ; NIGHTMARE_KEY1
|
||||
dw AddNightmareKey ; NIGHTMARE_KEY2
|
||||
dw AddNightmareKey ; NIGHTMARE_KEY3
|
||||
dw AddNightmareKey ; NIGHTMARE_KEY4
|
||||
dw AddNightmareKey ; NIGHTMARE_KEY5
|
||||
dw AddNightmareKey ; NIGHTMARE_KEY6
|
||||
dw AddNightmareKey ; NIGHTMARE_KEY7
|
||||
dw AddNightmareKey ; NIGHTMARE_KEY8
|
||||
dw AddNightmareKey ; NIGHTMARE_KEY9
|
||||
dw AddToadstool ; Toadstool
|
||||
dw NoItem ; $51
|
||||
dw NoItem ; $52
|
||||
dw NoItem ; $53
|
||||
dw NoItem ; $54
|
||||
dw NoItem ; $55
|
||||
dw NoItem ; $56
|
||||
dw NoItem ; $57
|
||||
dw NoItem ; $58
|
||||
dw NoItem ; $59
|
||||
dw NoItem ; $5A
|
||||
dw NoItem ; $5B
|
||||
dw NoItem ; $5C
|
||||
dw NoItem ; $5D
|
||||
dw NoItem ; $5E
|
||||
dw NoItem ; $5F
|
||||
dw NoItem ; $60
|
||||
dw NoItem ; $61
|
||||
dw NoItem ; $62
|
||||
dw NoItem ; $63
|
||||
dw NoItem ; $64
|
||||
dw NoItem ; $65
|
||||
dw NoItem ; $66
|
||||
dw NoItem ; $67
|
||||
dw NoItem ; $68
|
||||
dw NoItem ; $69
|
||||
dw NoItem ; $6A
|
||||
dw NoItem ; $6B
|
||||
dw NoItem ; $6C
|
||||
dw NoItem ; $6D
|
||||
dw NoItem ; $6E
|
||||
dw NoItem ; $6F
|
||||
dw NoItem ; $70
|
||||
dw NoItem ; $71
|
||||
dw NoItem ; $72
|
||||
dw NoItem ; $73
|
||||
dw NoItem ; $74
|
||||
dw NoItem ; $75
|
||||
dw NoItem ; $76
|
||||
dw NoItem ; $77
|
||||
dw NoItem ; $78
|
||||
dw NoItem ; $79
|
||||
dw NoItem ; $7A
|
||||
dw NoItem ; $7B
|
||||
dw NoItem ; $7C
|
||||
dw NoItem ; $7D
|
||||
dw NoItem ; $7E
|
||||
dw NoItem ; $7F
|
||||
dw PieceOfHeart ; Heart piece
|
||||
dw GiveBowwow
|
||||
dw Give10Arrows
|
||||
dw Give1Arrow
|
||||
dw UpgradeMaxPowder
|
||||
dw UpgradeMaxBombs
|
||||
dw UpgradeMaxArrows
|
||||
dw GiveRedTunic
|
||||
dw GiveBlueTunic
|
||||
dw GiveExtraHeart
|
||||
dw TakeHeart
|
||||
dw GiveSong1
|
||||
dw GiveSong2
|
||||
dw GiveSong3
|
||||
dw GiveInstrument
|
||||
dw GiveInstrument
|
||||
dw GiveInstrument
|
||||
dw GiveInstrument
|
||||
dw GiveInstrument
|
||||
dw GiveInstrument
|
||||
dw GiveInstrument
|
||||
dw GiveInstrument
|
||||
dw GiveRooster
|
||||
dw GiveTradeItem1
|
||||
dw GiveTradeItem2
|
||||
dw GiveTradeItem3
|
||||
dw GiveTradeItem4
|
||||
dw GiveTradeItem5
|
||||
dw GiveTradeItem6
|
||||
dw GiveTradeItem7
|
||||
dw GiveTradeItem8
|
||||
dw GiveTradeItem9
|
||||
dw GiveTradeItem10
|
||||
dw GiveTradeItem11
|
||||
dw GiveTradeItem12
|
||||
dw GiveTradeItem13
|
||||
dw GiveTradeItem14
|
||||
|
||||
NoItem:
|
||||
ret
|
||||
|
||||
ChestPowerBracelet:
|
||||
ld hl, $DB43 ; power bracelet level
|
||||
jr ChestIncreaseItemLevel
|
||||
|
||||
ChestShield:
|
||||
ld hl, $DB44 ; shield level
|
||||
jr ChestIncreaseItemLevel
|
||||
|
||||
ChestSword:
|
||||
ld hl, $DB4E ; sword level
|
||||
jr ChestIncreaseItemLevel
|
||||
|
||||
ChestIncreaseItemLevel:
|
||||
ld a, [hl]
|
||||
cp $02
|
||||
jr z, DoNotIncreaseItemLevel
|
||||
inc [hl]
|
||||
DoNotIncreaseItemLevel:
|
||||
jp ChestWithItem
|
||||
|
||||
ChestBomb:
|
||||
ld a, [$DB4D] ; bomb count
|
||||
add a, $10
|
||||
daa
|
||||
ld hl, $DB77 ; max bombs
|
||||
cp [hl]
|
||||
jr c, .bombsNotFull
|
||||
ld a, [hl]
|
||||
.bombsNotFull:
|
||||
ld [$DB4D], a
|
||||
jp ChestWithItem
|
||||
|
||||
ChestBow:
|
||||
ld a, [$DB45]
|
||||
cp $20
|
||||
jp nc, ChestWithItem
|
||||
ld a, $20
|
||||
ld [$DB45], a
|
||||
jp ChestWithItem
|
||||
|
||||
ChestMagicPowder:
|
||||
; Reset the toadstool state
|
||||
ld a, $0B
|
||||
ldh [$A5], a
|
||||
xor a
|
||||
ld [$DB4B], a ; has toadstool
|
||||
|
||||
ld a, [$DB4C] ; powder count
|
||||
add a, $10
|
||||
daa
|
||||
ld hl, $DB76 ; max powder
|
||||
cp [hl]
|
||||
jr c, .magicPowderNotFull
|
||||
ld a, [hl]
|
||||
.magicPowderNotFull:
|
||||
ld [$DB4C], a
|
||||
jp ChestWithItem
|
||||
|
||||
|
||||
Flippers:
|
||||
ld a, $01
|
||||
ld [wHasFlippers], a
|
||||
ret
|
||||
|
||||
Medicine:
|
||||
ld a, $01
|
||||
ld [wHasMedicine], a
|
||||
ret
|
||||
|
||||
TailKey:
|
||||
ld a, $01
|
||||
ld [$DB11], a
|
||||
ret
|
||||
|
||||
AnglerKey:
|
||||
ld a, $01
|
||||
ld [$DB12], a
|
||||
ret
|
||||
|
||||
FaceKey:
|
||||
ld a, $01
|
||||
ld [$DB13], a
|
||||
ret
|
||||
|
||||
BirdKey:
|
||||
ld a, $01
|
||||
ld [$DB14], a
|
||||
ret
|
||||
|
||||
SlimeKey:
|
||||
ld a, $01
|
||||
ld [$DB15], a
|
||||
ret
|
||||
|
||||
GoldenLeaf:
|
||||
ld hl, wGoldenLeaves
|
||||
inc [hl]
|
||||
ret
|
||||
|
||||
AddSeaShell:
|
||||
ld a, [wSeashellsCount]
|
||||
inc a
|
||||
daa
|
||||
ld [wSeashellsCount], a
|
||||
ret
|
||||
|
||||
PieceOfHeart:
|
||||
#IF HARD_MODE
|
||||
ld a, $FF
|
||||
ld [$DB93], a
|
||||
#ENDIF
|
||||
|
||||
ld a, [$DB5C]
|
||||
inc a
|
||||
cp $04
|
||||
jr z, .FullHeart
|
||||
ld [$DB5C], a
|
||||
ret
|
||||
.FullHeart:
|
||||
xor a
|
||||
ld [$DB5C], a
|
||||
jp GiveExtraHeart
|
||||
|
||||
GiveBowwow:
|
||||
ld a, $01
|
||||
ld [$DB56], a
|
||||
ret
|
||||
|
||||
ChestInventoryTable:
|
||||
db $03 ; CHEST_POWER_BRACELET
|
||||
db $04 ; CHEST_SHIELD
|
||||
db $05 ; CHEST_BOW
|
||||
db $06 ; CHEST_HOOKSHOT
|
||||
db $07 ; CHEST_MAGIC_ROD
|
||||
db $08 ; CHEST_PEGASUS_BOOTS
|
||||
db $09 ; CHEST_OCARINA
|
||||
db $0A ; CHEST_FEATHER
|
||||
db $0B ; CHEST_SHOVEL
|
||||
db $0C ; CHEST_MAGIC_POWDER_BAG
|
||||
db $02 ; CHEST_BOMB
|
||||
db $01 ; CHEST_SWORD
|
||||
db $00 ; - (flippers slot)
|
||||
db $00 ; - (magnifier lens slot)
|
||||
db $0D ; Boomerang
|
||||
|
||||
ChestWithItem:
|
||||
ldh a, [$F1] ; Load active sprite variant
|
||||
ld d, $00
|
||||
ld e, a
|
||||
ld hl, ChestInventoryTable
|
||||
add hl, de
|
||||
ld d, [hl]
|
||||
call $3E6B ; Give Inventory
|
||||
ret
|
||||
|
||||
ChestWithCurrentDungeonItem:
|
||||
sub $16 ; a -= CHEST_MAP
|
||||
ld e, a
|
||||
ld d, $00
|
||||
ld hl, $DBCC ; hasDungeonMap
|
||||
add hl, de
|
||||
inc [hl]
|
||||
call $2802 ; Sync current dungeon items with dungeon specific table
|
||||
ret
|
||||
|
||||
AddToadstool:
|
||||
ld d, $0E
|
||||
call $3E6B ; Give Inventory
|
||||
ret
|
||||
|
||||
AddKey:
|
||||
sub $23 ; Make 'A' target dungeon index
|
||||
ld de, $0004
|
||||
jr AddDungeonItem
|
||||
|
||||
AddMap:
|
||||
sub $2C ; Make 'A' target dungeon index
|
||||
ld de, $0000
|
||||
jr AddDungeonItem
|
||||
|
||||
AddCompass:
|
||||
sub $35 ; Make 'A' target dungeon index
|
||||
ld de, $0001
|
||||
jr AddDungeonItem
|
||||
|
||||
AddStoneBeak:
|
||||
sub $3E ; Make 'A' target dungeon index
|
||||
ld de, $0002
|
||||
jr AddDungeonItem
|
||||
|
||||
AddNightmareKey:
|
||||
sub $47 ; Make 'A' target dungeon index
|
||||
ld de, $0003
|
||||
jr AddDungeonItem
|
||||
|
||||
AddDungeonItem:
|
||||
cp $08
|
||||
jr z, .colorDungeon
|
||||
; hl = dungeonitems + type_type + dungeon * 8
|
||||
ld hl, $DB16
|
||||
add hl, de
|
||||
push de
|
||||
ld e, a
|
||||
add hl, de
|
||||
add hl, de
|
||||
add hl, de
|
||||
add hl, de
|
||||
add hl, de
|
||||
pop de
|
||||
inc [hl]
|
||||
; Check if we are in this specific dungeon, and then increase the copied counters as well.
|
||||
ld hl, $FFF7 ; is current map == target map
|
||||
cp [hl]
|
||||
ret nz
|
||||
ld a, [$DBA5] ; is indoor
|
||||
and a
|
||||
ret z
|
||||
|
||||
ld hl, $DBCC
|
||||
add hl, de
|
||||
inc [hl]
|
||||
ret
|
||||
.colorDungeon:
|
||||
; Special case for the color dungeon, which is in a different location in memory.
|
||||
ld hl, $DDDA
|
||||
add hl, de
|
||||
inc [hl]
|
||||
ldh a, [$F7] ; is current map == color dungeon
|
||||
cp $ff
|
||||
ret nz
|
||||
ld hl, $DBCC
|
||||
add hl, de
|
||||
inc [hl]
|
||||
ret
|
||||
|
||||
AddRupees20:
|
||||
xor a
|
||||
ld h, $14
|
||||
jr AddRupees
|
||||
|
||||
AddRupees50:
|
||||
xor a
|
||||
ld h, $32
|
||||
jr AddRupees
|
||||
|
||||
AddRupees100:
|
||||
xor a
|
||||
ld h, $64
|
||||
jr AddRupees
|
||||
|
||||
AddRupees200:
|
||||
xor a
|
||||
ld h, $C8
|
||||
jr AddRupees
|
||||
|
||||
AddRupees500:
|
||||
ld a, $01
|
||||
ld h, $F4
|
||||
jr AddRupees
|
||||
|
||||
AddRupees:
|
||||
ld [$DB8F], a
|
||||
ld a, h
|
||||
ld [$DB90], a
|
||||
ld a, $18
|
||||
ld [$C3CE], a
|
||||
ret
|
||||
|
||||
Give1Arrow:
|
||||
ld a, [$DB45]
|
||||
inc a
|
||||
jp FinishGivingArrows
|
||||
|
||||
Give10Arrows:
|
||||
ld a, [$DB45]
|
||||
add a, $0A
|
||||
FinishGivingArrows:
|
||||
daa
|
||||
ld [$DB45], a
|
||||
ld hl, $DB78
|
||||
cp [hl]
|
||||
ret c
|
||||
ld a, [hl]
|
||||
ld [$DB45], a
|
||||
ret
|
||||
|
||||
UpgradeMaxPowder:
|
||||
ld a, $40
|
||||
ld [$DB76], a
|
||||
; If we have no powder, we should not increase the current amount, as that would prevent
|
||||
; The toadstool from showing up.
|
||||
ld a, [$DB4C]
|
||||
and a
|
||||
ret z
|
||||
ld a, $40
|
||||
ld [$DB4C], a
|
||||
ret
|
||||
|
||||
UpgradeMaxBombs:
|
||||
ld a, $60
|
||||
ld [$DB77], a
|
||||
ld [$DB4D], a
|
||||
ret
|
||||
|
||||
UpgradeMaxArrows:
|
||||
ld a, $60
|
||||
ld [$DB78], a
|
||||
ld [$DB45], a
|
||||
ret
|
||||
|
||||
GiveRedTunic:
|
||||
ld a, $01
|
||||
ld [$DC0F], a
|
||||
; We use DB6D to store which tunics we have available.
|
||||
ld a, [wCollectedTunics]
|
||||
or $01
|
||||
ld [wCollectedTunics], a
|
||||
ret
|
||||
|
||||
GiveBlueTunic:
|
||||
ld a, $02
|
||||
ld [$DC0F], a
|
||||
; We use DB6D to store which tunics we have available.
|
||||
ld a, [wCollectedTunics]
|
||||
or $02
|
||||
ld [wCollectedTunics], a
|
||||
ret
|
||||
|
||||
GiveExtraHeart:
|
||||
; Regen all health
|
||||
ld hl, $DB93
|
||||
ld [hl], $FF
|
||||
; Increase max health if health is lower then 14 hearts
|
||||
ld hl, $DB5B
|
||||
ld a, $0E
|
||||
cp [hl]
|
||||
ret z
|
||||
inc [hl]
|
||||
ret
|
||||
|
||||
TakeHeart:
|
||||
; First, reduce the max HP
|
||||
ld hl, $DB5B
|
||||
ld a, [hl]
|
||||
cp $01
|
||||
ret z
|
||||
dec a
|
||||
ld [$DB5B], a
|
||||
|
||||
; Next, check if we need to reduce our actual HP to keep it below the maximum.
|
||||
rlca
|
||||
rlca
|
||||
rlca
|
||||
sub $01
|
||||
ld hl, $DB5A
|
||||
cp [hl]
|
||||
jr nc, .noNeedToReduceHp
|
||||
ld [hl], a
|
||||
.noNeedToReduceHp:
|
||||
; Finally, give all health back.
|
||||
ld hl, $DB93
|
||||
ld [hl], $FF
|
||||
ret
|
||||
|
||||
GiveSong1:
|
||||
ld hl, $DB49
|
||||
set 2, [hl]
|
||||
ld a, $00
|
||||
ld [$DB4A], a
|
||||
ret
|
||||
|
||||
GiveSong2:
|
||||
ld hl, $DB49
|
||||
set 1, [hl]
|
||||
ld a, $01
|
||||
ld [$DB4A], a
|
||||
ret
|
||||
|
||||
GiveSong3:
|
||||
ld hl, $DB49
|
||||
set 0, [hl]
|
||||
ld a, $02
|
||||
ld [$DB4A], a
|
||||
ret
|
||||
|
||||
GiveInstrument:
|
||||
ldh a, [$F1] ; Load active sprite variant
|
||||
sub $8E
|
||||
ld d, $00
|
||||
ld e, a
|
||||
ld hl, $db65 ; has instrument table
|
||||
add hl, de
|
||||
set 1, [hl]
|
||||
ret
|
||||
|
||||
GiveRooster:
|
||||
ld d, $0F
|
||||
call $3E6B ; Give Inventory (rooster item)
|
||||
|
||||
;ld a, $01
|
||||
;ld [$DB7B], a ; has rooster
|
||||
ldh a, [$F9] ; do not spawn rooster in sidescroller
|
||||
and a
|
||||
ret z
|
||||
|
||||
ld a, $D5 ; ENTITY_ROOSTER
|
||||
call $3B86 ; SpawnNewEntity_trampoline
|
||||
ldh a, [$98] ; LinkX
|
||||
ld hl, $C200 ; wEntitiesPosXTable
|
||||
add hl, de
|
||||
ld [hl], a
|
||||
ldh a, [$99] ; LinkY
|
||||
ld hl, $C210 ; wEntitiesPosYTable
|
||||
add hl, de
|
||||
ld [hl], a
|
||||
|
||||
ret
|
||||
|
||||
GiveTradeItem1:
|
||||
ld hl, wTradeSequenceItem
|
||||
set 0, [hl]
|
||||
ret
|
||||
GiveTradeItem2:
|
||||
ld hl, wTradeSequenceItem
|
||||
set 1, [hl]
|
||||
ret
|
||||
GiveTradeItem3:
|
||||
ld hl, wTradeSequenceItem
|
||||
set 2, [hl]
|
||||
ret
|
||||
GiveTradeItem4:
|
||||
ld hl, wTradeSequenceItem
|
||||
set 3, [hl]
|
||||
ret
|
||||
GiveTradeItem5:
|
||||
ld hl, wTradeSequenceItem
|
||||
set 4, [hl]
|
||||
ret
|
||||
GiveTradeItem6:
|
||||
ld hl, wTradeSequenceItem
|
||||
set 5, [hl]
|
||||
ret
|
||||
GiveTradeItem7:
|
||||
ld hl, wTradeSequenceItem
|
||||
set 6, [hl]
|
||||
ret
|
||||
GiveTradeItem8:
|
||||
ld hl, wTradeSequenceItem
|
||||
set 7, [hl]
|
||||
ret
|
||||
GiveTradeItem9:
|
||||
ld hl, wTradeSequenceItem2
|
||||
set 0, [hl]
|
||||
ret
|
||||
GiveTradeItem10:
|
||||
ld hl, wTradeSequenceItem2
|
||||
set 1, [hl]
|
||||
ret
|
||||
GiveTradeItem11:
|
||||
ld hl, wTradeSequenceItem2
|
||||
set 2, [hl]
|
||||
ret
|
||||
GiveTradeItem12:
|
||||
ld hl, wTradeSequenceItem2
|
||||
set 3, [hl]
|
||||
ret
|
||||
GiveTradeItem13:
|
||||
ld hl, wTradeSequenceItem2
|
||||
set 4, [hl]
|
||||
ret
|
||||
GiveTradeItem14:
|
||||
ld hl, wTradeSequenceItem2
|
||||
set 5, [hl]
|
||||
ret
|
||||
|
||||
ItemMessageMultiworld:
|
||||
; Check our "item is for other player" flag
|
||||
ld hl, $7300
|
||||
call OffsetPointerByRoomNumber
|
||||
ld a, [hl]
|
||||
ld hl, $0055
|
||||
cp [hl]
|
||||
jr nz, ItemMessageForOtherPlayer
|
||||
|
||||
ItemMessage:
|
||||
; Fill the custom message slot with this item message.
|
||||
call BuildItemMessage
|
||||
ldh a, [$F1]
|
||||
ld d, $00
|
||||
ld e, a
|
||||
ld hl, ItemMessageTable
|
||||
add hl, de
|
||||
ld a, [hl]
|
||||
cp $90
|
||||
jr z, .powerBracelet
|
||||
cp $3D
|
||||
jr z, .shield
|
||||
jp $2385 ; Opendialog in $000-$0FF range
|
||||
|
||||
.powerBracelet:
|
||||
; Check the power bracelet level, and give a different message when we get the lv2 bracelet
|
||||
ld hl, $DB43 ; power bracelet level
|
||||
bit 1, [hl]
|
||||
jp z, $2385 ; Opendialog in $000-$0FF range
|
||||
ld a, $EE
|
||||
jp $2385 ; Opendialog in $000-$0FF range
|
||||
|
||||
.shield:
|
||||
; Check the shield level, and give a different message when we get the lv2 shield
|
||||
ld hl, $DB44 ; shield level
|
||||
bit 1, [hl]
|
||||
jp z, $2385 ; Opendialog in $000-$0FF range
|
||||
ld a, $ED
|
||||
jp $2385 ; Opendialog in $000-$0FF range
|
||||
|
||||
ItemMessageForOtherPlayer:
|
||||
push bc
|
||||
push hl
|
||||
push af
|
||||
call BuildRemoteItemMessage
|
||||
ld hl, SpaceFor
|
||||
call MessageCopyString
|
||||
pop af
|
||||
call MessageAddPlayerName
|
||||
pop hl
|
||||
pop bc
|
||||
;dec de
|
||||
ld a, $C9
|
||||
jp $2385 ; Opendialog in $000-$0FF range
|
||||
|
||||
ItemSpriteTable:
|
||||
db $82, $15 ; CHEST_POWER_BRACELET
|
||||
db $86, $15 ; CHEST_SHIELD
|
||||
db $88, $14 ; CHEST_BOW
|
||||
db $8A, $14 ; CHEST_HOOKSHOT
|
||||
db $8C, $14 ; CHEST_MAGIC_ROD
|
||||
db $98, $16 ; CHEST_PEGASUS_BOOTS
|
||||
db $10, $1F ; CHEST_OCARINA
|
||||
db $12, $1D ; CHEST_FEATHER
|
||||
db $96, $17 ; CHEST_SHOVEL
|
||||
db $0E, $1C ; CHEST_MAGIC_POWDER_BAG
|
||||
db $80, $15 ; CHEST_BOMB
|
||||
db $84, $15 ; CHEST_SWORD
|
||||
db $94, $15 ; CHEST_FLIPPERS
|
||||
db $9A, $10 ; CHEST_MAGNIFYING_LENS
|
||||
db $24, $1C ; Boomerang
|
||||
db $4E, $1C ; Slime key
|
||||
db $A0, $14 ; CHEST_MEDICINE
|
||||
db $30, $1C ; CHEST_TAIL_KEY
|
||||
db $32, $1C ; CHEST_ANGLER_KEY
|
||||
db $34, $1C ; CHEST_FACE_KEY
|
||||
db $36, $1C ; CHEST_BIRD_KEY
|
||||
db $3A, $1C ; CHEST_GOLD_LEAF
|
||||
db $40, $1C ; CHEST_MAP
|
||||
db $42, $1D ; CHEST_COMPASS
|
||||
db $44, $1C ; CHEST_STONE_BEAK
|
||||
db $46, $1C ; CHEST_NIGHTMARE_KEY
|
||||
db $4A, $1F ; CHEST_SMALL_KEY
|
||||
db $A6, $15 ; CHEST_RUPEES_50 (normal blue)
|
||||
db $38, $19 ; CHEST_RUPEES_20 (red)
|
||||
db $38, $18 ; CHEST_RUPEES_100 (green)
|
||||
db $38, $1A ; CHEST_RUPEES_200 (yellow)
|
||||
db $38, $1A ; CHEST_RUPEES_500 (yellow)
|
||||
db $9E, $14 ; CHEST_SEASHELL
|
||||
db $8A, $14 ; CHEST_MESSAGE
|
||||
db $A0, $14 ; CHEST_GEL
|
||||
db $4A, $1D ; KEY1
|
||||
db $4A, $1D ; KEY2
|
||||
db $4A, $1D ; KEY3
|
||||
db $4A, $1D ; KEY4
|
||||
db $4A, $1D ; KEY5
|
||||
db $4A, $1D ; KEY6
|
||||
db $4A, $1D ; KEY7
|
||||
db $4A, $1D ; KEY8
|
||||
db $4A, $1D ; KEY9
|
||||
db $40, $1C ; MAP1
|
||||
db $40, $1C ; MAP2
|
||||
db $40, $1C ; MAP3
|
||||
db $40, $1C ; MAP4
|
||||
db $40, $1C ; MAP5
|
||||
db $40, $1C ; MAP6
|
||||
db $40, $1C ; MAP7
|
||||
db $40, $1C ; MAP8
|
||||
db $40, $1C ; MAP9
|
||||
db $42, $1D ; COMPASS1
|
||||
db $42, $1D ; COMPASS2
|
||||
db $42, $1D ; COMPASS3
|
||||
db $42, $1D ; COMPASS4
|
||||
db $42, $1D ; COMPASS5
|
||||
db $42, $1D ; COMPASS6
|
||||
db $42, $1D ; COMPASS7
|
||||
db $42, $1D ; COMPASS8
|
||||
db $42, $1D ; COMPASS9
|
||||
db $44, $1C ; STONE_BEAK1
|
||||
db $44, $1C ; STONE_BEAK2
|
||||
db $44, $1C ; STONE_BEAK3
|
||||
db $44, $1C ; STONE_BEAK4
|
||||
db $44, $1C ; STONE_BEAK5
|
||||
db $44, $1C ; STONE_BEAK6
|
||||
db $44, $1C ; STONE_BEAK7
|
||||
db $44, $1C ; STONE_BEAK8
|
||||
db $44, $1C ; STONE_BEAK9
|
||||
db $46, $1C ; NIGHTMARE_KEY1
|
||||
db $46, $1C ; NIGHTMARE_KEY2
|
||||
db $46, $1C ; NIGHTMARE_KEY3
|
||||
db $46, $1C ; NIGHTMARE_KEY4
|
||||
db $46, $1C ; NIGHTMARE_KEY5
|
||||
db $46, $1C ; NIGHTMARE_KEY6
|
||||
db $46, $1C ; NIGHTMARE_KEY7
|
||||
db $46, $1C ; NIGHTMARE_KEY8
|
||||
db $46, $1C ; NIGHTMARE_KEY9
|
||||
db $4C, $1C ; Toadstool
|
||||
|
||||
LargeItemSpriteTable:
|
||||
db $AC, $02, $AC, $22 ; heart piece
|
||||
db $54, $0A, $56, $0A ; bowwow
|
||||
db $2A, $41, $2A, $61 ; 10 arrows
|
||||
db $2A, $41, $2A, $61 ; single arrow
|
||||
db $0E, $1C, $22, $0C ; powder upgrade
|
||||
db $00, $0D, $22, $0C ; bomb upgrade
|
||||
db $08, $1C, $22, $0C ; arrow upgrade
|
||||
db $48, $0A, $48, $2A ; red tunic
|
||||
db $48, $0B, $48, $2B ; blue tunic
|
||||
db $2A, $0C, $2A, $2C ; heart container
|
||||
db $2A, $0F, $2A, $2F ; bad heart container
|
||||
db $70, $09, $70, $29 ; song 1
|
||||
db $72, $0B, $72, $2B ; song 2
|
||||
db $74, $08, $74, $28 ; song 3
|
||||
db $80, $0E, $82, $0E ; Instrument1
|
||||
db $84, $0E, $86, $0E ; Instrument2
|
||||
db $88, $0E, $8A, $0E ; Instrument3
|
||||
db $8C, $0E, $8E, $0E ; Instrument4
|
||||
db $90, $0E, $92, $0E ; Instrument5
|
||||
db $94, $0E, $96, $0E ; Instrument6
|
||||
db $98, $0E, $9A, $0E ; Instrument7
|
||||
db $9C, $0E, $9E, $0E ; Instrument8
|
||||
db $A6, $2B, $A4, $2B ; Rooster
|
||||
db $1A, $0E, $1C, $0E ; TradeItem1
|
||||
db $B0, $0C, $B2, $0C ; TradeItem2
|
||||
db $B4, $0C, $B6, $0C ; TradeItem3
|
||||
db $B8, $0C, $BA, $0C ; TradeItem4
|
||||
db $BC, $0C, $BE, $0C ; TradeItem5
|
||||
db $C0, $0C, $C2, $0C ; TradeItem6
|
||||
db $C4, $0C, $C6, $0C ; TradeItem7
|
||||
db $C8, $0C, $CA, $0C ; TradeItem8
|
||||
db $CC, $0C, $CE, $0C ; TradeItem9
|
||||
db $D0, $0C, $D2, $0C ; TradeItem10
|
||||
db $D4, $0D, $D6, $0D ; TradeItem11
|
||||
db $D8, $0D, $DA, $0D ; TradeItem12
|
||||
db $DC, $0D, $DE, $0D ; TradeItem13
|
||||
db $E0, $0D, $E2, $0D ; TradeItem14
|
||||
|
||||
ItemMessageTable:
|
||||
db $90, $3D, $89, $93, $94, $95, $96, $97, $98, $99, $9A, $9B, $9C, $9D, $D9, $A2
|
||||
db $A0, $A1, $A3, $A4, $A5, $E8, $A6, $A7, $A8, $A9, $AA, $AC, $AB, $AD, $AE, $C9
|
||||
db $EF, $BE, $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9
|
||||
db $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9
|
||||
; $40
|
||||
db $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9
|
||||
db $0F, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
|
||||
db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
|
||||
db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
|
||||
; $80
|
||||
db $4F, $C8, $CA, $CB, $E2, $E3, $E4, $CC, $CD, $2A, $2B, $C9, $C9, $C9, $C9, $C9
|
||||
db $C9, $C9, $C9, $C9, $C9, $C9, $B8, $44, $C9, $C9, $C9, $C9, $C9, $C9, $C9, $C9
|
||||
db $C9, $C9, $C9, $C9, $9D
|
||||
|
||||
RenderDroppedKey:
|
||||
;TODO: See EntityInitKeyDropPoint for a few special cases to unload.
|
||||
|
||||
RenderHeartPiece:
|
||||
; Check if our chest type is already loaded
|
||||
ld hl, $C2C0
|
||||
add hl, bc
|
||||
ld a, [hl]
|
||||
and a
|
||||
jr nz, .droppedKeyTypeLoaded
|
||||
inc [hl]
|
||||
|
||||
;Load the chest type from the chest table.
|
||||
ld hl, $7800
|
||||
call OffsetPointerByRoomNumber
|
||||
|
||||
ld a, [hl]
|
||||
ldh [$F1], a ; set currentEntitySpriteVariant
|
||||
call $3B0C ; SetEntitySpriteVariant
|
||||
|
||||
and $80
|
||||
ld hl, $C340
|
||||
add hl, bc
|
||||
ld a, [hl]
|
||||
jr z, .singleSprite
|
||||
; We potentially need to fix the physics flags table to allocate 2 sprites for us
|
||||
and $F8
|
||||
or $02
|
||||
ld [hl], a
|
||||
jr .droppedKeyTypeLoaded
|
||||
.singleSprite:
|
||||
and $F8
|
||||
or $01
|
||||
ld [hl], a
|
||||
.droppedKeyTypeLoaded:
|
||||
jp RenderChestItem
|
||||
|
||||
|
||||
OffsetPointerByRoomNumber:
|
||||
ldh a, [$F6] ; map room
|
||||
ld e, a
|
||||
ld a, [$DBA5] ; is indoor
|
||||
ld d, a
|
||||
ldh a, [$F7] ; mapId
|
||||
cp $FF
|
||||
jr nz, .notColorDungeon
|
||||
|
||||
ld d, $03
|
||||
jr .notCavesA
|
||||
|
||||
.notColorDungeon:
|
||||
cp $1A
|
||||
jr nc, .notCavesA
|
||||
cp $06
|
||||
jr c, .notCavesA
|
||||
inc d
|
||||
.notCavesA:
|
||||
add hl, de
|
||||
ret
|
||||
|
||||
GiveItemAndMessageForRoom:
|
||||
;Load the chest type from the chest table.
|
||||
ld hl, $7800
|
||||
call OffsetPointerByRoomNumber
|
||||
ld a, [hl]
|
||||
ldh [$F1], a
|
||||
call GiveItemFromChest
|
||||
jp ItemMessage
|
||||
|
||||
GiveItemAndMessageForRoomMultiworld:
|
||||
;Load the chest type from the chest table.
|
||||
ld hl, $7800
|
||||
call OffsetPointerByRoomNumber
|
||||
ld a, [hl]
|
||||
ldh [$F1], a
|
||||
call GiveItemFromChestMultiworld
|
||||
jp ItemMessageMultiworld
|
||||
|
||||
RenderItemForRoom:
|
||||
;Load the chest type from the chest table.
|
||||
ld hl, $7800
|
||||
call OffsetPointerByRoomNumber
|
||||
ld a, [hl]
|
||||
ldh [$F1], a
|
||||
jp RenderChestItem
|
||||
|
||||
; Increase the amount of checks we completed, unless we are on the multichest room.
|
||||
IncreaseCheckCounter:
|
||||
ldh a, [$F6] ; map room
|
||||
cp $F2
|
||||
jr nz, .noMultiChest
|
||||
ld a, [$DBA5] ; is indoor
|
||||
and a
|
||||
jr z, .noMultiChest
|
||||
ldh a, [$F7] ; mapId
|
||||
cp $0A
|
||||
ret z
|
||||
|
||||
.noMultiChest:
|
||||
call $27D0 ; Enable SRAM
|
||||
ld hl, $B010
|
||||
.loop:
|
||||
ld a, [hl]
|
||||
and a ; clear carry flag
|
||||
inc a
|
||||
daa
|
||||
ldi [hl], a
|
||||
ret nc
|
||||
jr .loop
|
||||
494
worlds/ladx/LADXR/patches/bank3e.asm/itemnames.asm
Normal file
494
worlds/ladx/LADXR/patches/bank3e.asm/itemnames.asm
Normal file
@@ -0,0 +1,494 @@
|
||||
|
||||
BuildRemoteItemMessage:
|
||||
ld de, wCustomMessage
|
||||
call CustomItemMessageThreeFour
|
||||
ld a, $A0 ; low of wCustomMessage
|
||||
cp e
|
||||
ret nz
|
||||
|
||||
BuildItemMessage:
|
||||
ld hl, ItemNamePointers
|
||||
ldh a, [$F1]
|
||||
ld d, $00
|
||||
ld e, a
|
||||
add hl, de
|
||||
add hl, de
|
||||
ldi a, [hl]
|
||||
ld h, [hl]
|
||||
ld l, a
|
||||
ld de, wCustomMessage
|
||||
jp MessageCopyString
|
||||
|
||||
; And then see if the custom item message func wants to override
|
||||
|
||||
; add hl, de
|
||||
|
||||
|
||||
CustomItemMessageThreeFour:
|
||||
; the stack _should_ have the address to return to here, so we can just pop it when we're done
|
||||
ld a, $34 ; Set bank number
|
||||
ld hl, $4000 ; Set next address
|
||||
push hl
|
||||
jp $080C ; switch bank
|
||||
|
||||
FoundItemForOtherPlayerPostfix:
|
||||
db m" for player X", $ff
|
||||
GotItemFromOtherPlayerPostfix:
|
||||
db m" from player X", $ff
|
||||
SpaceFrom:
|
||||
db " from ", $ff, $ff
|
||||
SpaceFor:
|
||||
db " for ", $ff, $ff
|
||||
MessagePad:
|
||||
jr .start ; goto start
|
||||
.loop:
|
||||
ld a, $20 ; a = ' '
|
||||
ld [de], a ; *de = ' '
|
||||
inc de ; de++
|
||||
ld a, $ff ; a = 0xFF
|
||||
ld [de], a ; *de = 0xff
|
||||
.start:
|
||||
ld a, e ; a = de & 0xF
|
||||
and $0F ; a &= 0x0xF
|
||||
jr nz, .loop ; if a != 0, goto loop
|
||||
ret
|
||||
|
||||
MessageAddTargetPlayer:
|
||||
call MessagePad
|
||||
ld hl, FoundItemForOtherPlayerPostfix
|
||||
call MessageCopyString
|
||||
ret
|
||||
|
||||
MessageAddFromPlayerOld:
|
||||
call MessagePad
|
||||
ld hl, GotItemFromOtherPlayerPostfix
|
||||
call MessageCopyString
|
||||
ret
|
||||
|
||||
; hahaha none of this follows calling conventions
|
||||
MessageAddPlayerName:
|
||||
; call MessagePad
|
||||
ld h, 0 ; bc = a, hl = a
|
||||
ld l, a
|
||||
ld b, 0
|
||||
ld c, a
|
||||
add hl, hl ; 2
|
||||
add hl, hl ; 4
|
||||
add hl, hl ; 8
|
||||
add hl, hl ; 16
|
||||
add hl, bc ; 17
|
||||
ld bc, MultiNamePointers
|
||||
add hl, bc ; hl = MultiNamePointers + wLinkGiveItemFrom * 17
|
||||
call MessageCopyString
|
||||
ret
|
||||
|
||||
ItemNamePointers:
|
||||
dw ItemNamePowerBracelet
|
||||
dw ItemNameShield
|
||||
dw ItemNameBow
|
||||
dw ItemNameHookshot
|
||||
dw ItemNameMagicRod
|
||||
dw ItemNamePegasusBoots
|
||||
dw ItemNameOcarina
|
||||
dw ItemNameFeather
|
||||
dw ItemNameShovel
|
||||
dw ItemNameMagicPowder
|
||||
dw ItemNameBomb
|
||||
dw ItemNameSword
|
||||
dw ItemNameFlippers
|
||||
dw ItemNameNone
|
||||
dw ItemNameBoomerang
|
||||
dw ItemNameSlimeKey
|
||||
dw ItemNameMedicine
|
||||
dw ItemNameTailKey
|
||||
dw ItemNameAnglerKey
|
||||
dw ItemNameFaceKey
|
||||
dw ItemNameBirdKey
|
||||
dw ItemNameGoldLeaf
|
||||
dw ItemNameMap
|
||||
dw ItemNameCompass
|
||||
dw ItemNameStoneBeak
|
||||
dw ItemNameNightmareKey
|
||||
dw ItemNameSmallKey
|
||||
dw ItemNameRupees50
|
||||
dw ItemNameRupees20
|
||||
dw ItemNameRupees100
|
||||
dw ItemNameRupees200
|
||||
dw ItemNameRupees500
|
||||
dw ItemNameSeashell
|
||||
dw ItemNameMessage
|
||||
dw ItemNameGel
|
||||
dw ItemNameKey1
|
||||
dw ItemNameKey2
|
||||
dw ItemNameKey3
|
||||
dw ItemNameKey4
|
||||
dw ItemNameKey5
|
||||
dw ItemNameKey6
|
||||
dw ItemNameKey7
|
||||
dw ItemNameKey8
|
||||
dw ItemNameKey9
|
||||
dw ItemNameMap1
|
||||
dw ItemNameMap2
|
||||
dw ItemNameMap3
|
||||
dw ItemNameMap4
|
||||
dw ItemNameMap5
|
||||
dw ItemNameMap6
|
||||
dw ItemNameMap7
|
||||
dw ItemNameMap8
|
||||
dw ItemNameMap9
|
||||
dw ItemNameCompass1
|
||||
dw ItemNameCompass2
|
||||
dw ItemNameCompass3
|
||||
dw ItemNameCompass4
|
||||
dw ItemNameCompass5
|
||||
dw ItemNameCompass6
|
||||
dw ItemNameCompass7
|
||||
dw ItemNameCompass8
|
||||
dw ItemNameCompass9
|
||||
dw ItemNameStoneBeak1
|
||||
dw ItemNameStoneBeak2
|
||||
dw ItemNameStoneBeak3
|
||||
dw ItemNameStoneBeak4
|
||||
dw ItemNameStoneBeak5
|
||||
dw ItemNameStoneBeak6
|
||||
dw ItemNameStoneBeak7
|
||||
dw ItemNameStoneBeak8
|
||||
dw ItemNameStoneBeak9
|
||||
dw ItemNameNightmareKey1
|
||||
dw ItemNameNightmareKey2
|
||||
dw ItemNameNightmareKey3
|
||||
dw ItemNameNightmareKey4
|
||||
dw ItemNameNightmareKey5
|
||||
dw ItemNameNightmareKey6
|
||||
dw ItemNameNightmareKey7
|
||||
dw ItemNameNightmareKey8
|
||||
dw ItemNameNightmareKey9
|
||||
dw ItemNameToadstool
|
||||
dw ItemNameNone ; 0x51
|
||||
dw ItemNameNone ; 0x52
|
||||
dw ItemNameNone ; 0x53
|
||||
dw ItemNameNone ; 0x54
|
||||
dw ItemNameNone ; 0x55
|
||||
dw ItemNameNone ; 0x56
|
||||
dw ItemNameNone ; 0x57
|
||||
dw ItemNameNone ; 0x58
|
||||
dw ItemNameNone ; 0x59
|
||||
dw ItemNameNone ; 0x5a
|
||||
dw ItemNameNone ; 0x5b
|
||||
dw ItemNameNone ; 0x5c
|
||||
dw ItemNameNone ; 0x5d
|
||||
dw ItemNameNone ; 0x5e
|
||||
dw ItemNameNone ; 0x5f
|
||||
dw ItemNameNone ; 0x60
|
||||
dw ItemNameNone ; 0x61
|
||||
dw ItemNameNone ; 0x62
|
||||
dw ItemNameNone ; 0x63
|
||||
dw ItemNameNone ; 0x64
|
||||
dw ItemNameNone ; 0x65
|
||||
dw ItemNameNone ; 0x66
|
||||
dw ItemNameNone ; 0x67
|
||||
dw ItemNameNone ; 0x68
|
||||
dw ItemNameNone ; 0x69
|
||||
dw ItemNameNone ; 0x6a
|
||||
dw ItemNameNone ; 0x6b
|
||||
dw ItemNameNone ; 0x6c
|
||||
dw ItemNameNone ; 0x6d
|
||||
dw ItemNameNone ; 0x6e
|
||||
dw ItemNameNone ; 0x6f
|
||||
dw ItemNameNone ; 0x70
|
||||
dw ItemNameNone ; 0x71
|
||||
dw ItemNameNone ; 0x72
|
||||
dw ItemNameNone ; 0x73
|
||||
dw ItemNameNone ; 0x74
|
||||
dw ItemNameNone ; 0x75
|
||||
dw ItemNameNone ; 0x76
|
||||
dw ItemNameNone ; 0x77
|
||||
dw ItemNameNone ; 0x78
|
||||
dw ItemNameNone ; 0x79
|
||||
dw ItemNameNone ; 0x7a
|
||||
dw ItemNameNone ; 0x7b
|
||||
dw ItemNameNone ; 0x7c
|
||||
dw ItemNameNone ; 0x7d
|
||||
dw ItemNameNone ; 0x7e
|
||||
dw ItemNameNone ; 0x7f
|
||||
dw ItemNameHeartPiece ; 0x80
|
||||
dw ItemNameBowwow
|
||||
dw ItemName10Arrows
|
||||
dw ItemNameSingleArrow
|
||||
dw ItemNamePowderUpgrade
|
||||
dw ItemNameBombUpgrade
|
||||
dw ItemNameArrowUpgrade
|
||||
dw ItemNameRedTunic
|
||||
dw ItemNameBlueTunic
|
||||
dw ItemNameHeartContainer
|
||||
dw ItemNameBadHeartContainer
|
||||
dw ItemNameSong1
|
||||
dw ItemNameSong2
|
||||
dw ItemNameSong3
|
||||
dw ItemInstrument1
|
||||
dw ItemInstrument2
|
||||
dw ItemInstrument3
|
||||
dw ItemInstrument4
|
||||
dw ItemInstrument5
|
||||
dw ItemInstrument6
|
||||
dw ItemInstrument7
|
||||
dw ItemInstrument8
|
||||
dw ItemRooster
|
||||
dw ItemTradeQuest1
|
||||
dw ItemTradeQuest2
|
||||
dw ItemTradeQuest3
|
||||
dw ItemTradeQuest4
|
||||
dw ItemTradeQuest5
|
||||
dw ItemTradeQuest6
|
||||
dw ItemTradeQuest7
|
||||
dw ItemTradeQuest8
|
||||
dw ItemTradeQuest9
|
||||
dw ItemTradeQuest10
|
||||
dw ItemTradeQuest11
|
||||
dw ItemTradeQuest12
|
||||
dw ItemTradeQuest13
|
||||
dw ItemTradeQuest14
|
||||
|
||||
ItemNameNone:
|
||||
db m"NONE", $ff
|
||||
|
||||
ItemNamePowerBracelet:
|
||||
db m"Got the {POWER_BRACELET}", $ff
|
||||
ItemNameShield:
|
||||
db m"Got a {SHIELD}", $ff
|
||||
ItemNameBow:
|
||||
db m"Got the {BOW}", $ff
|
||||
ItemNameHookshot:
|
||||
db m"Got the {HOOKSHOT}", $ff
|
||||
ItemNameMagicRod:
|
||||
db m"Got the {MAGIC_ROD}", $ff
|
||||
ItemNamePegasusBoots:
|
||||
db m"Got the {PEGASUS_BOOTS}", $ff
|
||||
ItemNameOcarina:
|
||||
db m"Got the {OCARINA}", $ff
|
||||
ItemNameFeather:
|
||||
db m"Got the {FEATHER}", $ff
|
||||
ItemNameShovel:
|
||||
db m"Got the {SHOVEL}", $ff
|
||||
ItemNameMagicPowder:
|
||||
db m"Got {MAGIC_POWDER}", $ff
|
||||
ItemNameBomb:
|
||||
db m"Got {BOMB}", $ff
|
||||
ItemNameSword:
|
||||
db m"Got a {SWORD}", $ff
|
||||
ItemNameFlippers:
|
||||
db m"Got the {FLIPPERS}", $ff
|
||||
ItemNameBoomerang:
|
||||
db m"Got the {BOOMERANG}", $ff
|
||||
ItemNameSlimeKey:
|
||||
db m"Got the {SLIME_KEY}", $ff
|
||||
ItemNameMedicine:
|
||||
db m"Got some {MEDICINE}", $ff
|
||||
ItemNameTailKey:
|
||||
db m"Got the {TAIL_KEY}", $ff
|
||||
ItemNameAnglerKey:
|
||||
db m"Got the {ANGLER_KEY}", $ff
|
||||
ItemNameFaceKey:
|
||||
db m"Got the {FACE_KEY}", $ff
|
||||
ItemNameBirdKey:
|
||||
db m"Got the {BIRD_KEY}", $ff
|
||||
ItemNameGoldLeaf:
|
||||
db m"Got the {GOLD_LEAF}", $ff
|
||||
ItemNameMap:
|
||||
db m"Got the {MAP}", $ff
|
||||
ItemNameCompass:
|
||||
db m"Got the {COMPASS}", $ff
|
||||
ItemNameStoneBeak:
|
||||
db m"Got the {STONE_BEAK}", $ff
|
||||
ItemNameNightmareKey:
|
||||
db m"Got the {NIGHTMARE_KEY}", $ff
|
||||
ItemNameSmallKey:
|
||||
db m"Got a {KEY}", $ff
|
||||
ItemNameRupees50:
|
||||
db m"Got 50 {RUPEES}", $ff
|
||||
ItemNameRupees20:
|
||||
db m"Got 20 {RUPEES}", $ff
|
||||
ItemNameRupees100:
|
||||
db m"Got 100 {RUPEES}", $ff
|
||||
ItemNameRupees200:
|
||||
db m"Got 200 {RUPEES}", $ff
|
||||
ItemNameRupees500:
|
||||
db m"Got 500 {RUPEES}", $ff
|
||||
ItemNameSeashell:
|
||||
db m"Got a {SEASHELL}", $ff
|
||||
ItemNameGel:
|
||||
db m"Got a Zol Attack", $ff
|
||||
ItemNameMessage:
|
||||
db m"Got ... nothing?", $ff
|
||||
ItemNameKey1:
|
||||
db m"Got a {KEY1}", $ff
|
||||
ItemNameKey2:
|
||||
db m"Got a {KEY2}", $ff
|
||||
ItemNameKey3:
|
||||
db m"Got a {KEY3}", $ff
|
||||
ItemNameKey4:
|
||||
db m"Got a {KEY4}", $ff
|
||||
ItemNameKey5:
|
||||
db m"Got a {KEY5}", $ff
|
||||
ItemNameKey6:
|
||||
db m"Got a {KEY6}", $ff
|
||||
ItemNameKey7:
|
||||
db m"Got a {KEY7}", $ff
|
||||
ItemNameKey8:
|
||||
db m"Got a {KEY8}", $ff
|
||||
ItemNameKey9:
|
||||
db m"Got a {KEY9}", $ff
|
||||
ItemNameMap1:
|
||||
db m"Got the {MAP1}", $ff
|
||||
ItemNameMap2:
|
||||
db m"Got the {MAP2}", $ff
|
||||
ItemNameMap3:
|
||||
db m"Got the {MAP3}", $ff
|
||||
ItemNameMap4:
|
||||
db m"Got the {MAP4}", $ff
|
||||
ItemNameMap5:
|
||||
db m"Got the {MAP5}", $ff
|
||||
ItemNameMap6:
|
||||
db m"Got the {MAP6}", $ff
|
||||
ItemNameMap7:
|
||||
db m"Got the {MAP7}", $ff
|
||||
ItemNameMap8:
|
||||
db m"Got the {MAP8}", $ff
|
||||
ItemNameMap9:
|
||||
db m"Got the {MAP9}", $ff
|
||||
ItemNameCompass1:
|
||||
db m"Got the {COMPASS1}", $ff
|
||||
ItemNameCompass2:
|
||||
db m"Got the {COMPASS2}", $ff
|
||||
ItemNameCompass3:
|
||||
db m"Got the {COMPASS3}", $ff
|
||||
ItemNameCompass4:
|
||||
db m"Got the {COMPASS4}", $ff
|
||||
ItemNameCompass5:
|
||||
db m"Got the {COMPASS5}", $ff
|
||||
ItemNameCompass6:
|
||||
db m"Got the {COMPASS6}", $ff
|
||||
ItemNameCompass7:
|
||||
db m"Got the {COMPASS7}", $ff
|
||||
ItemNameCompass8:
|
||||
db m"Got the {COMPASS8}", $ff
|
||||
ItemNameCompass9:
|
||||
db m"Got the {COMPASS9}", $ff
|
||||
ItemNameStoneBeak1:
|
||||
db m"Got the {STONE_BEAK1}", $ff
|
||||
ItemNameStoneBeak2:
|
||||
db m"Got the {STONE_BEAK2}", $ff
|
||||
ItemNameStoneBeak3:
|
||||
db m"Got the {STONE_BEAK3}", $ff
|
||||
ItemNameStoneBeak4:
|
||||
db m"Got the {STONE_BEAK4}", $ff
|
||||
ItemNameStoneBeak5:
|
||||
db m"Got the {STONE_BEAK5}", $ff
|
||||
ItemNameStoneBeak6:
|
||||
db m"Got the {STONE_BEAK6}", $ff
|
||||
ItemNameStoneBeak7:
|
||||
db m"Got the {STONE_BEAK7}", $ff
|
||||
ItemNameStoneBeak8:
|
||||
db m"Got the {STONE_BEAK8}", $ff
|
||||
ItemNameStoneBeak9:
|
||||
db m"Got the {STONE_BEAK9}", $ff
|
||||
ItemNameNightmareKey1:
|
||||
db m"Got the {NIGHTMARE_KEY1}", $ff
|
||||
ItemNameNightmareKey2:
|
||||
db m"Got the {NIGHTMARE_KEY2}", $ff
|
||||
ItemNameNightmareKey3:
|
||||
db m"Got the {NIGHTMARE_KEY3}", $ff
|
||||
ItemNameNightmareKey4:
|
||||
db m"Got the {NIGHTMARE_KEY4}", $ff
|
||||
ItemNameNightmareKey5:
|
||||
db m"Got the {NIGHTMARE_KEY5}", $ff
|
||||
ItemNameNightmareKey6:
|
||||
db m"Got the {NIGHTMARE_KEY6}", $ff
|
||||
ItemNameNightmareKey7:
|
||||
db m"Got the {NIGHTMARE_KEY7}", $ff
|
||||
ItemNameNightmareKey8:
|
||||
db m"Got the {NIGHTMARE_KEY8}", $ff
|
||||
ItemNameNightmareKey9:
|
||||
db m"Got the {NIGHTMARE_KEY9}", $ff
|
||||
ItemNameToadstool:
|
||||
db m"Got the {TOADSTOOL}", $ff
|
||||
|
||||
ItemNameHeartPiece:
|
||||
db m"Got the {HEART_PIECE}", $ff
|
||||
ItemNameBowwow:
|
||||
db m"Got the {BOWWOW}", $ff
|
||||
ItemName10Arrows:
|
||||
db m"Got {ARROWS_10}", $ff
|
||||
ItemNameSingleArrow:
|
||||
db m"Got the {SINGLE_ARROW}", $ff
|
||||
ItemNamePowderUpgrade:
|
||||
db m"Got the {MAX_POWDER_UPGRADE}", $ff
|
||||
ItemNameBombUpgrade:
|
||||
db m"Got the {MAX_BOMBS_UPGRADE}", $ff
|
||||
ItemNameArrowUpgrade:
|
||||
db m"Got the {MAX_ARROWS_UPGRADE}", $ff
|
||||
ItemNameRedTunic:
|
||||
db m"Got the {RED_TUNIC}", $ff
|
||||
ItemNameBlueTunic:
|
||||
db m"Got the {BLUE_TUNIC}", $ff
|
||||
ItemNameHeartContainer:
|
||||
db m"Got a {HEART_CONTAINER}", $ff
|
||||
ItemNameBadHeartContainer:
|
||||
db m"Got the {BAD_HEART_CONTAINER}", $ff
|
||||
ItemNameSong1:
|
||||
db m"Got the {SONG1}", $ff
|
||||
ItemNameSong2:
|
||||
db m"Got {SONG2}", $ff
|
||||
ItemNameSong3:
|
||||
db m"Got {SONG3}", $ff
|
||||
|
||||
ItemInstrument1:
|
||||
db m"You've got the {INSTRUMENT1}", $ff
|
||||
ItemInstrument2:
|
||||
db m"You've got the {INSTRUMENT2}", $ff
|
||||
ItemInstrument3:
|
||||
db m"You've got the {INSTRUMENT3}", $ff
|
||||
ItemInstrument4:
|
||||
db m"You've got the {INSTRUMENT4}", $ff
|
||||
ItemInstrument5:
|
||||
db m"You've got the {INSTRUMENT5}", $ff
|
||||
ItemInstrument6:
|
||||
db m"You've got the {INSTRUMENT6}", $ff
|
||||
ItemInstrument7:
|
||||
db m"You've got the {INSTRUMENT7}", $ff
|
||||
ItemInstrument8:
|
||||
db m"You've got the {INSTRUMENT8}", $ff
|
||||
|
||||
ItemRooster:
|
||||
db m"You've got the {ROOSTER}", $ff
|
||||
|
||||
ItemTradeQuest1:
|
||||
db m"You've got the Yoshi Doll", $ff
|
||||
ItemTradeQuest2:
|
||||
db m"You've got the Ribbon", $ff
|
||||
ItemTradeQuest3:
|
||||
db m"You've got the Dog Food", $ff
|
||||
ItemTradeQuest4:
|
||||
db m"You've got the Bananas", $ff
|
||||
ItemTradeQuest5:
|
||||
db m"You've got the Stick", $ff
|
||||
ItemTradeQuest6:
|
||||
db m"You've got the Honeycomb", $ff
|
||||
ItemTradeQuest7:
|
||||
db m"You've got the Pineapple", $ff
|
||||
ItemTradeQuest8:
|
||||
db m"You've got the Hibiscus", $ff
|
||||
ItemTradeQuest9:
|
||||
db m"You've got the Letter", $ff
|
||||
ItemTradeQuest10:
|
||||
db m"You've got the Broom", $ff
|
||||
ItemTradeQuest11:
|
||||
db m"You've got the Fishing Hook", $ff
|
||||
ItemTradeQuest12:
|
||||
db m"You've got the Necklace", $ff
|
||||
ItemTradeQuest13:
|
||||
db m"You've got the Scale", $ff
|
||||
ItemTradeQuest14:
|
||||
db m"You've got the Magnifying Lens", $ff
|
||||
|
||||
MultiNamePointers:
|
||||
89
worlds/ladx/LADXR/patches/bank3e.asm/link.asm
Normal file
89
worlds/ladx/LADXR/patches/bank3e.asm/link.asm
Normal file
@@ -0,0 +1,89 @@
|
||||
; Handle the serial link cable
|
||||
#IF HARDWARE_LINK
|
||||
; FF> = Idle
|
||||
; D6> = Read: D0><[L] D1><[H] [HL]>
|
||||
; D9> = Write: D8><[L] D9><[H] DA><[^DATA] DB><[DATA]
|
||||
; DD> = OrW: D8><[L] D9><[H] DA><[^DATA] DB><[DATA] (used to set flags without requiring a slow read,modify,write race condition)
|
||||
|
||||
handleSerialLink:
|
||||
; Check if we got a byte from hardware
|
||||
ldh a, [$01]
|
||||
|
||||
cp $D6
|
||||
jr z, serialReadMem
|
||||
cp $D9
|
||||
jr z, serialWriteMem
|
||||
cp $DD
|
||||
jr z, serialOrMem
|
||||
|
||||
finishSerialLink:
|
||||
; Do a new idle transfer.
|
||||
ld a, $E4
|
||||
ldh [$01], a
|
||||
ld a, $81
|
||||
ldh [$02], a
|
||||
ret
|
||||
|
||||
serialReadMem:
|
||||
ld a, $D0
|
||||
call serialTransfer
|
||||
ld h, a
|
||||
ld a, $D1
|
||||
call serialTransfer
|
||||
ld l, a
|
||||
ld a, [hl]
|
||||
call serialTransfer
|
||||
jr finishSerialLink
|
||||
|
||||
serialWriteMem:
|
||||
ld a, $D8
|
||||
call serialTransfer
|
||||
ld h, a
|
||||
ld a, $D9
|
||||
call serialTransfer
|
||||
ld l, a
|
||||
ld a, $DA
|
||||
call serialTransfer
|
||||
cpl
|
||||
ld c, a
|
||||
ld a, $DB
|
||||
call serialTransfer
|
||||
cp c
|
||||
jr nz, finishSerialLink
|
||||
ld [hl], a
|
||||
jr finishSerialLink
|
||||
|
||||
serialOrMem:
|
||||
ld a, $D8
|
||||
call serialTransfer
|
||||
ld h, a
|
||||
ld a, $D9
|
||||
call serialTransfer
|
||||
ld l, a
|
||||
ld a, $DA
|
||||
call serialTransfer
|
||||
cpl
|
||||
ld c, a
|
||||
ld a, $DB
|
||||
call serialTransfer
|
||||
cp c
|
||||
jr nz, finishSerialLink
|
||||
ld c, a
|
||||
ld a, [hl]
|
||||
or c
|
||||
ld [hl], a
|
||||
jr finishSerialLink
|
||||
|
||||
; Transfer A to the serial link and wait for it to be done and return the result in A
|
||||
serialTransfer:
|
||||
ldh [$01], a
|
||||
ld a, $81
|
||||
ldh [$02], a
|
||||
.loop:
|
||||
ldh a, [$02]
|
||||
and $80
|
||||
jr nz, .loop
|
||||
ldh a, [$01]
|
||||
ret
|
||||
|
||||
#ENDIF
|
||||
16
worlds/ladx/LADXR/patches/bank3e.asm/message.asm
Normal file
16
worlds/ladx/LADXR/patches/bank3e.asm/message.asm
Normal file
@@ -0,0 +1,16 @@
|
||||
MessageCopyString:
|
||||
.loop:
|
||||
ldi a, [hl]
|
||||
ld [de], a
|
||||
cp $ff
|
||||
ret z
|
||||
inc de
|
||||
jr .loop
|
||||
|
||||
MessageAddSpace:
|
||||
ld a, $20
|
||||
ld [de], a
|
||||
inc de
|
||||
ld a, $ff
|
||||
ld [de], a
|
||||
ret
|
||||
355
worlds/ladx/LADXR/patches/bank3e.asm/multiworld.asm
Normal file
355
worlds/ladx/LADXR/patches/bank3e.asm/multiworld.asm
Normal file
@@ -0,0 +1,355 @@
|
||||
; Handle the multiworld link
|
||||
|
||||
MainLoop:
|
||||
#IF HARDWARE_LINK
|
||||
call handleSerialLink
|
||||
#ENDIF
|
||||
; Check if the gameplay is world
|
||||
ld a, [$DB95]
|
||||
cp $0B
|
||||
ret nz
|
||||
; Check if the world subtype is the normal one
|
||||
ld a, [$DB96]
|
||||
cp $07
|
||||
ret nz
|
||||
; Check if we are moving between rooms
|
||||
ld a, [$C124]
|
||||
and a
|
||||
ret nz
|
||||
; Check if link is in a normal walking/swimming state
|
||||
ld a, [$C11C]
|
||||
cp $02
|
||||
ret nc
|
||||
; Check if a dialog is open
|
||||
ld a, [$C19F]
|
||||
and a
|
||||
ret nz
|
||||
; Check if interaction is blocked
|
||||
ldh a, [$A1]
|
||||
and a
|
||||
ret nz
|
||||
|
||||
ld a, [wLinkSpawnDelay]
|
||||
and a
|
||||
jr z, .allowSpawn
|
||||
dec a
|
||||
ld [wLinkSpawnDelay], a
|
||||
jr .noSpawn
|
||||
|
||||
.allowSpawn:
|
||||
ld a, [wZolSpawnCount]
|
||||
and a
|
||||
call nz, LinkSpawnSlime
|
||||
ld a, [wCuccoSpawnCount]
|
||||
and a
|
||||
call nz, LinkSpawnCucco
|
||||
ld a, [wDropBombSpawnCount]
|
||||
and a
|
||||
call nz, LinkSpawnBomb
|
||||
.noSpawn:
|
||||
|
||||
; Have an item to give?
|
||||
ld hl, wLinkStatusBits
|
||||
bit 0, [hl]
|
||||
ret z
|
||||
|
||||
; Give an item to the player
|
||||
ld a, [wLinkGiveItem]
|
||||
; if zol:
|
||||
cp $22 ; zol item
|
||||
jr z, LinkGiveSlime
|
||||
; if special item
|
||||
cp $F0
|
||||
jr nc, HandleSpecialItem
|
||||
; tmpChestItem = a
|
||||
ldh [$F1], a
|
||||
; Give the item
|
||||
call GiveItemFromChest
|
||||
; Paste the item text
|
||||
call BuildItemMessage
|
||||
; Paste " from "
|
||||
ld hl, SpaceFrom
|
||||
call MessageCopyString
|
||||
; Paste the player name
|
||||
ld a, [wLinkGiveItemFrom]
|
||||
call MessageAddPlayerName
|
||||
ld a, $C9
|
||||
; hl = $wLinkStatusBits
|
||||
ld hl, wLinkStatusBits
|
||||
; clear the 0 bit of *hl
|
||||
res 0, [hl]
|
||||
; OpenDialog()
|
||||
jp $2385 ; Opendialog in $000-$0FF range
|
||||
|
||||
LinkGiveSlime:
|
||||
ld a, $05
|
||||
ld [wZolSpawnCount], a
|
||||
ld hl, wLinkStatusBits
|
||||
res 0, [hl]
|
||||
ret
|
||||
|
||||
HandleSpecialItem:
|
||||
ld hl, wLinkStatusBits
|
||||
res 0, [hl]
|
||||
|
||||
and $0F
|
||||
rst 0
|
||||
dw SpecialSlimeStorm
|
||||
dw SpecialCuccoParty
|
||||
dw SpecialPieceOfPower
|
||||
dw SpecialHealth
|
||||
dw SpecialRandomTeleport
|
||||
dw .ret
|
||||
dw .ret
|
||||
dw .ret
|
||||
dw .ret
|
||||
dw .ret
|
||||
dw .ret
|
||||
dw .ret
|
||||
dw .ret
|
||||
dw .ret
|
||||
dw .ret
|
||||
dw .ret
|
||||
.ret:
|
||||
ret
|
||||
|
||||
SpecialSlimeStorm:
|
||||
ld a, $20
|
||||
ld [wZolSpawnCount], a
|
||||
ret
|
||||
SpecialCuccoParty:
|
||||
ld a, $20
|
||||
ld [wCuccoSpawnCount], a
|
||||
ret
|
||||
SpecialPieceOfPower:
|
||||
; Give the piece of power and the music
|
||||
ld a, $01
|
||||
ld [$D47C], a
|
||||
ld a, $27
|
||||
ld [$D368], a
|
||||
ld a, $49
|
||||
ldh [$BD], a
|
||||
ldh [$BF], a
|
||||
ret
|
||||
SpecialHealth:
|
||||
; Regen all health
|
||||
ld hl, $DB93
|
||||
ld [hl], $FF
|
||||
ret
|
||||
|
||||
LinkSpawnSlime:
|
||||
ld a, $1B
|
||||
ld e, $08
|
||||
call $3B98 ; SpawnNewEntity in range
|
||||
ret c
|
||||
|
||||
; Place somewhere random
|
||||
call placeRandom
|
||||
|
||||
ld hl, $C310
|
||||
add hl, de
|
||||
ld [hl], $7F
|
||||
|
||||
ld hl, wZolSpawnCount
|
||||
dec [hl]
|
||||
|
||||
call $280D
|
||||
and $03
|
||||
ld [wLinkSpawnDelay], a
|
||||
ret
|
||||
|
||||
LinkSpawnCucco:
|
||||
ld a, $6C
|
||||
ld e, $04
|
||||
call $3B98 ; SpawnNewEntity in range
|
||||
ret c
|
||||
|
||||
; Place where link is at.
|
||||
ld hl, $C200
|
||||
add hl, de
|
||||
ldh a, [$98]
|
||||
ld [hl], a
|
||||
ld hl, $C210
|
||||
add hl, de
|
||||
ldh a, [$99]
|
||||
ld [hl], a
|
||||
|
||||
; Set the "hits till cucco killer attack" much lower
|
||||
ld hl, $C2B0
|
||||
add hl, de
|
||||
ld a, $21
|
||||
ld [hl], a
|
||||
|
||||
ld hl, wCuccoSpawnCount
|
||||
dec [hl]
|
||||
|
||||
call $280D
|
||||
and $07
|
||||
ld [wLinkSpawnDelay], a
|
||||
ret
|
||||
|
||||
LinkSpawnBomb:
|
||||
ld a, $02
|
||||
ld e, $08
|
||||
call $3B98 ; SpawnNewEntity in range
|
||||
ret c
|
||||
|
||||
call placeRandom
|
||||
|
||||
ld hl, $C310 ; z pos
|
||||
add hl, de
|
||||
ld [hl], $4F
|
||||
|
||||
ld hl, $C430 ; wEntitiesOptions1Table
|
||||
add hl, de
|
||||
res 0, [hl]
|
||||
ld hl, $C2E0 ; wEntitiesTransitionCountdownTable
|
||||
add hl, de
|
||||
ld [hl], $80
|
||||
ld hl, $C440 ; wEntitiesPrivateState4Table
|
||||
add hl, de
|
||||
ld [hl], $01
|
||||
|
||||
ld hl, wDropBombSpawnCount
|
||||
dec [hl]
|
||||
|
||||
call $280D
|
||||
and $1F
|
||||
ld [wLinkSpawnDelay], a
|
||||
ret
|
||||
|
||||
placeRandom:
|
||||
; Place somewhere random
|
||||
ld hl, $C200
|
||||
add hl, de
|
||||
call $280D ; random number
|
||||
and $7F
|
||||
add a, $08
|
||||
ld [hl], a
|
||||
ld hl, $C210
|
||||
add hl, de
|
||||
call $280D ; random number
|
||||
and $3F
|
||||
add a, $20
|
||||
ld [hl], a
|
||||
ret
|
||||
|
||||
SpecialRandomTeleport:
|
||||
xor a
|
||||
; Warp data
|
||||
ld [$D401], a
|
||||
ld [$D402], a
|
||||
call $280D ; random number
|
||||
ld [$D403], a
|
||||
ld hl, RandomTeleportPositions
|
||||
ld d, $00
|
||||
ld e, a
|
||||
add hl, de
|
||||
ld e, [hl]
|
||||
ld a, e
|
||||
and $0F
|
||||
swap a
|
||||
add a, $08
|
||||
ld [$D404], a
|
||||
ld a, e
|
||||
and $F0
|
||||
add a, $10
|
||||
ld [$D405], a
|
||||
|
||||
ldh a, [$98]
|
||||
swap a
|
||||
and $0F
|
||||
ld e, a
|
||||
ldh a, [$99]
|
||||
sub $08
|
||||
and $F0
|
||||
or e
|
||||
ld [$D416], a ; wWarp0PositionTileIndex
|
||||
|
||||
call $0C7D
|
||||
ld a, $07
|
||||
ld [$DB96], a ; wGameplaySubtype
|
||||
|
||||
ret
|
||||
|
||||
Data_004_7AE5: ; @TODO Palette data
|
||||
db $33, $62, $1A, $01, $FF, $0F, $FF, $7F
|
||||
|
||||
|
||||
Deathlink:
|
||||
; Spawn the entity
|
||||
ld a, $CA ; $7AF3: $3E $CA
|
||||
call $3B86 ; $7AF5: $CD $86 $3B ;SpawnEntityTrampoline
|
||||
ld a, $26 ; $7AF8: $3E $26 ;
|
||||
ldh [$F4], a ; $7AFA: $E0 $F4 ; set noise
|
||||
; Set posX = linkX
|
||||
ldh a, [$98] ; LinkX
|
||||
ld hl, $C200 ; wEntitiesPosXTable
|
||||
add hl, de
|
||||
ld [hl], a
|
||||
; set posY = linkY - 54
|
||||
ldh a, [$99] ; LinkY
|
||||
sub a, 54
|
||||
ld hl, $C210 ; wEntitiesPosYTable
|
||||
add hl, de
|
||||
ld [hl], a
|
||||
; wEntitiesPrivateState3Table
|
||||
ld hl, $C2D0 ; $7B0A: $21 $D0 $C2
|
||||
add hl, de ; $7B0D: $19
|
||||
ld [hl], $01 ; $7B0E: $36 $01
|
||||
; wEntitiesTransitionCountdownTable
|
||||
ld hl, $C2E0 ; $7B10: $21 $E0 $C2
|
||||
add hl, de ; $7B13: $19
|
||||
ld [hl], $C0 ; $7B14: $36 $C0
|
||||
; GetEntityTransitionCountdown
|
||||
call $0C05 ; $7B16: $CD $05 $0C
|
||||
ld [hl], $C0 ; $7B19: $36 $C0
|
||||
; IncrementEntityState
|
||||
call $3B12 ; $7B1B: $CD $12 $3B
|
||||
|
||||
; Remove medicine
|
||||
xor a ; $7B1E: $AF
|
||||
ld [$DB0D], a ; $7B1F: $EA $0D $DB ; ld [wHasMedicine], a
|
||||
; Reduce health by a lot
|
||||
ld a, $FF ; $7B22: $3E $FF
|
||||
ld [$DB94], a ; $7B24: $EA $94 $DB ; ld [wSubtractHealthBuffer], a
|
||||
|
||||
ld hl, $DC88 ; $7B2C: $21 $88 $DC
|
||||
; Set palette
|
||||
ld de, Data_004_7AE5 ; $7B2F: $11 $E5 $7A
|
||||
|
||||
loop_7B32:
|
||||
ld a, [de] ; $7B32: $1A
|
||||
; ld [hl+], a ; $7B33: $22
|
||||
db $22
|
||||
inc de ; $7B34: $13
|
||||
ld a, l ; $7B35: $7D
|
||||
and $07 ; $7B36: $E6 $07
|
||||
jr nz, loop_7B32 ; $7B38: $20 $F8
|
||||
|
||||
ld a, $02 ; $7B3A: $3E $02
|
||||
ld [$DDD1], a ; $7B3C: $EA $D1 $DD
|
||||
|
||||
ret
|
||||
|
||||
; probalby wants
|
||||
; ld a, $02 ; $7B40: $3E $02
|
||||
;ldh [hLinkInteractiveMotionBlocked], a
|
||||
|
||||
RandomTeleportPositions:
|
||||
db $55, $54, $54, $54, $55, $55, $55, $54, $65, $55, $54, $65, $56, $56, $55, $55
|
||||
db $55, $45, $65, $54, $55, $55, $55, $55, $55, $55, $55, $58, $43, $57, $55, $55
|
||||
db $55, $55, $55, $55, $55, $54, $55, $53, $54, $56, $65, $65, $56, $55, $57, $65
|
||||
db $45, $55, $55, $55, $55, $55, $55, $55, $48, $45, $43, $34, $35, $35, $36, $34
|
||||
db $65, $55, $55, $54, $54, $54, $55, $54, $56, $65, $55, $55, $55, $55, $54, $54
|
||||
db $55, $55, $55, $55, $56, $55, $55, $54, $55, $55, $55, $53, $45, $35, $53, $46
|
||||
db $56, $55, $55, $55, $53, $55, $54, $54, $55, $55, $55, $54, $44, $55, $55, $54
|
||||
db $55, $55, $45, $55, $55, $54, $45, $45, $63, $55, $65, $55, $45, $45, $44, $54
|
||||
db $56, $56, $54, $55, $54, $55, $55, $55, $55, $55, $55, $56, $54, $55, $65, $56
|
||||
db $54, $54, $55, $65, $56, $54, $55, $56, $55, $55, $55, $66, $65, $65, $55, $56
|
||||
db $65, $55, $55, $75, $55, $55, $55, $54, $55, $55, $65, $57, $55, $54, $53, $45
|
||||
db $55, $56, $55, $55, $55, $45, $54, $55, $54, $55, $56, $55, $55, $55, $55, $54
|
||||
db $55, $55, $65, $55, $55, $54, $53, $58, $55, $05, $58, $55, $55, $55, $74, $55
|
||||
db $55, $55, $55, $55, $46, $55, $55, $56, $55, $55, $55, $54, $55, $45, $55, $55
|
||||
db $55, $55, $54, $55, $55, $55, $65, $55, $55, $46, $55, $55, $56, $55, $55, $55
|
||||
db $55, $55, $54, $55, $55, $55, $45, $36, $53, $51, $57, $53, $56, $54, $45, $46
|
||||
63
worlds/ladx/LADXR/patches/bank3e.asm/owl.asm
Normal file
63
worlds/ladx/LADXR/patches/bank3e.asm/owl.asm
Normal file
@@ -0,0 +1,63 @@
|
||||
HandleOwlStatue:
|
||||
call GetRoomStatusAddressInHL
|
||||
ld a, [hl]
|
||||
and $20
|
||||
ret nz
|
||||
ld a, [hl]
|
||||
or $20
|
||||
ld [hl], a
|
||||
|
||||
ld hl, $7B16
|
||||
call OffsetPointerByRoomNumber
|
||||
ld a, [hl]
|
||||
ldh [$F1], a
|
||||
call ItemMessage
|
||||
call GiveItemFromChest
|
||||
ret
|
||||
|
||||
|
||||
|
||||
GetRoomStatusAddressInHL:
|
||||
ld a, [$DBA5] ; isIndoor
|
||||
ld d, a
|
||||
ld hl, $D800
|
||||
ldh a, [$F6] ; room nr
|
||||
ld e, a
|
||||
ldh a, [$F7] ; map nr
|
||||
cp $FF
|
||||
jr nz, .notColorDungeon
|
||||
|
||||
ld d, $00
|
||||
ld hl, $DDE0
|
||||
jr .notIndoorB
|
||||
|
||||
.notColorDungeon:
|
||||
cp $1A
|
||||
jr nc, .notIndoorB
|
||||
|
||||
cp $06
|
||||
jr c, .notIndoorB
|
||||
|
||||
inc d
|
||||
|
||||
.notIndoorB:
|
||||
add hl, de
|
||||
ret
|
||||
|
||||
|
||||
RenderOwlStatueItem:
|
||||
ldh a, [$F6] ; map room
|
||||
cp $B2
|
||||
jr nz, .NotYipYip
|
||||
; Add 2 to room to set room pointer to an empty room for trade items
|
||||
add a, 2
|
||||
ldh [$F6], a
|
||||
call RenderItemForRoom
|
||||
ldh a, [$F6] ; map room
|
||||
; ...and undo it
|
||||
sub a, 2
|
||||
ldh [$F6], a
|
||||
ret
|
||||
.NotYipYip:
|
||||
call RenderItemForRoom
|
||||
ret
|
||||
225
worlds/ladx/LADXR/patches/bank3e.py
Normal file
225
worlds/ladx/LADXR/patches/bank3e.py
Normal file
@@ -0,0 +1,225 @@
|
||||
import os
|
||||
import binascii
|
||||
from ..assembler import ASM
|
||||
from ..utils import formatText
|
||||
|
||||
|
||||
def hasBank3E(rom):
|
||||
return rom.banks[0x3E][0] != 0x00
|
||||
|
||||
def generate_name(l, i):
|
||||
if i < len(l):
|
||||
name = l[i]
|
||||
else:
|
||||
name = f"player {i}"
|
||||
name = name[:16]
|
||||
assert(len(name) <= 16)
|
||||
return 'db "' + name + '"' + ', $ff' * (17 - len(name)) + '\n'
|
||||
|
||||
|
||||
# Bank $3E is used for large chunks of custom code.
|
||||
# Mainly for new chest and dropped items handling.
|
||||
def addBank3E(rom, seed, player_id, player_name_list):
|
||||
# No default text for getting the bow, so use an unused slot.
|
||||
rom.texts[0x89] = formatText("Found the {BOW}!")
|
||||
rom.texts[0xD9] = formatText("Found the {BOOMERANG}!") # owl text slot reuse
|
||||
rom.texts[0xBE] = rom.texts[0x111] # owl text slot reuse to get the master skull message in the first dialog group
|
||||
rom.texts[0xC8] = formatText("Found {BOWWOW}! Which monster put him in a chest? He is a good boi, and waits for you at the Swamp.")
|
||||
rom.texts[0xC9] = 0xC0A0 # Custom message slot
|
||||
rom.texts[0xCA] = formatText("Found {ARROWS_10}!")
|
||||
rom.texts[0xCB] = formatText("Found a {SINGLE_ARROW}... joy?")
|
||||
|
||||
# Create a trampoline to bank 0x3E in bank 0x00.
|
||||
# There is very little room in bank 0, so we set this up as a single trampoline for multiple possible usages.
|
||||
# the A register is preserved and can directly be used as a jumptable in page 3E.
|
||||
# Trampoline at rst 8
|
||||
# the A register is preserved and can directly be used as a jumptable in page 3E.
|
||||
rom.patch(0, 0x0008, "0000000000000000000000000000", ASM("""
|
||||
ld h, a
|
||||
ld a, [$DBAF]
|
||||
push af
|
||||
ld a, $3E
|
||||
call $080C ; switch bank
|
||||
ld a, h
|
||||
jp $4000
|
||||
"""), fill_nop=True)
|
||||
|
||||
# Special trampoline to jump to the damage-entity code, we use this from bowwow to damage instead of eat.
|
||||
rom.patch(0x00, 0x0018, "000000000000000000000000000000", ASM("""
|
||||
ld a, $03
|
||||
ld [$2100], a
|
||||
call $71C0
|
||||
ld a, [$DBAF]
|
||||
ld [$2100], a
|
||||
ret
|
||||
"""))
|
||||
|
||||
my_path = os.path.dirname(__file__)
|
||||
rom.patch(0x3E, 0x0000, 0x2F00, ASM("""
|
||||
call MainJumpTable
|
||||
pop af
|
||||
jp $080C ; switch bank and return to normal code.
|
||||
|
||||
MainJumpTable:
|
||||
rst 0 ; JUMP TABLE
|
||||
dw MainLoop ; 0
|
||||
dw RenderChestItem ; 1
|
||||
dw GiveItemFromChest ; 2
|
||||
dw ItemMessage ; 3
|
||||
dw RenderDroppedKey ; 4
|
||||
dw RenderHeartPiece ; 5
|
||||
dw GiveItemFromChestMultiworld ; 6
|
||||
dw CheckIfLoadBowWow ; 7
|
||||
dw BowwowEat ; 8
|
||||
dw HandleOwlStatue ; 9
|
||||
dw ItemMessageMultiworld ; A
|
||||
dw GiveItemAndMessageForRoom ; B
|
||||
dw RenderItemForRoom ; C
|
||||
dw StartGameMarinMessage ; D
|
||||
dw GiveItemAndMessageForRoomMultiworld ; E
|
||||
dw RenderOwlStatueItem ; F
|
||||
dw UpdateInventoryMenu ; 10
|
||||
dw LocalOnlyItemAndMessage ; 11
|
||||
StartGameMarinMessage:
|
||||
; Injection to reset our frame counter
|
||||
call $27D0 ; Enable SRAM
|
||||
ld hl, $B000
|
||||
xor a
|
||||
ldi [hl], a ;subsecond counter
|
||||
ld a, $08 ;(We set the counter to 8 seconds, as it takes 8 seconds before link wakes up and marin talks to him)
|
||||
ldi [hl], a ;second counter
|
||||
xor a
|
||||
ldi [hl], a ;minute counter
|
||||
ldi [hl], a ;hour counter
|
||||
|
||||
ld hl, $B010
|
||||
ldi [hl], a ;check counter low
|
||||
ldi [hl], a ;check counter high
|
||||
|
||||
; Show the normal message
|
||||
ld a, $01
|
||||
jp $2385
|
||||
|
||||
TradeSequenceItemData:
|
||||
; tile attributes
|
||||
db $0D, $0A, $0D, $0D, $0E, $0E, $0D, $0D, $0D, $0E, $09, $0A, $0A, $0D
|
||||
; tile index
|
||||
db $1A, $B0, $B4, $B8, $BC, $C0, $C4, $C8, $CC, $D0, $D4, $D8, $DC, $E0
|
||||
|
||||
UpdateInventoryMenu:
|
||||
ld a, [wTradeSequenceItem]
|
||||
ld hl, wTradeSequenceItem2
|
||||
or [hl]
|
||||
ret z
|
||||
|
||||
ld hl, TradeSequenceItemData
|
||||
ld a, [$C109]
|
||||
ld e, a
|
||||
ld d, $00
|
||||
add hl, de
|
||||
|
||||
; Check if we need to increase the counter
|
||||
ldh a, [$E7] ; frame counter
|
||||
and $0F
|
||||
jr nz, .noInc
|
||||
ld a, e
|
||||
inc a
|
||||
cp 14
|
||||
jr nz, .noWrap
|
||||
xor a
|
||||
.noWrap:
|
||||
ld [$C109], a
|
||||
.noInc:
|
||||
|
||||
; Check if we have the item
|
||||
ld b, e
|
||||
inc b
|
||||
ld a, $01
|
||||
|
||||
ld de, wTradeSequenceItem
|
||||
.shiftLoop:
|
||||
dec b
|
||||
jr z, .shiftLoopDone
|
||||
sla a
|
||||
jr nz, .shiftLoop
|
||||
; switching to second byte
|
||||
ld de, wTradeSequenceItem2
|
||||
ld a, $01
|
||||
jr .shiftLoop
|
||||
.shiftLoopDone:
|
||||
ld b, a
|
||||
ld a, [de]
|
||||
and b
|
||||
ret z ; skip this item
|
||||
|
||||
ld b, [hl]
|
||||
push hl
|
||||
|
||||
; Write the tile attribute data
|
||||
ld a, $01
|
||||
ldh [$4F], a
|
||||
|
||||
ld hl, $9C6E
|
||||
call WriteToVRAM
|
||||
inc hl
|
||||
call WriteToVRAM
|
||||
ld de, $001F
|
||||
add hl, de
|
||||
call WriteToVRAM
|
||||
inc hl
|
||||
call WriteToVRAM
|
||||
|
||||
; Write the tile data
|
||||
xor a
|
||||
ldh [$4F], a
|
||||
|
||||
pop hl
|
||||
ld de, 14
|
||||
add hl, de
|
||||
ld b, [hl]
|
||||
|
||||
ld hl, $9C6E
|
||||
call WriteToVRAM
|
||||
inc b
|
||||
inc b
|
||||
inc hl
|
||||
call WriteToVRAM
|
||||
ld de, $001F
|
||||
add hl, de
|
||||
dec b
|
||||
call WriteToVRAM
|
||||
inc hl
|
||||
inc b
|
||||
inc b
|
||||
call WriteToVRAM
|
||||
ret
|
||||
|
||||
WriteToVRAM:
|
||||
ldh a, [$41]
|
||||
and $02
|
||||
jr nz, WriteToVRAM
|
||||
ld [hl], b
|
||||
ret
|
||||
LocalOnlyItemAndMessage:
|
||||
call GiveItemFromChest
|
||||
call ItemMessage
|
||||
ret
|
||||
""" + open(os.path.join(my_path, "bank3e.asm/multiworld.asm"), "rt").read()
|
||||
+ open(os.path.join(my_path, "bank3e.asm/link.asm"), "rt").read()
|
||||
+ open(os.path.join(my_path, "bank3e.asm/chest.asm"), "rt").read()
|
||||
+ open(os.path.join(my_path, "bank3e.asm/bowwow.asm"), "rt").read()
|
||||
+ open(os.path.join(my_path, "bank3e.asm/message.asm"), "rt").read()
|
||||
+ open(os.path.join(my_path, "bank3e.asm/itemnames.asm"), "rt").read()
|
||||
+ "".join(generate_name(["The Server"] + player_name_list, i ) for i in range(100)) # allocate
|
||||
+ 'db "another world", $ff\n'
|
||||
+ open(os.path.join(my_path, "bank3e.asm/owl.asm"), "rt").read(), 0x4000), fill_nop=True)
|
||||
# 3E:3300-3616: Multiworld flags per room (for both chests and dropped keys)
|
||||
# 3E:3800-3B16: DroppedKey item types
|
||||
# 3E:3B16-3E2C: Owl statue or trade quest items
|
||||
|
||||
# Put 20 rupees in all owls by default.
|
||||
rom.patch(0x3E, 0x3B16, "00" * 0x316, "1C" * 0x316)
|
||||
|
||||
|
||||
# Prevent the photo album from crashing due to serial interrupts
|
||||
rom.patch(0x28, 0x00D2, ASM("ld a, $09"), ASM("ld a, $01"))
|
||||
386
worlds/ladx/LADXR/patches/bank3f.py
Normal file
386
worlds/ladx/LADXR/patches/bank3f.py
Normal file
@@ -0,0 +1,386 @@
|
||||
from ..assembler import ASM
|
||||
from .. import utils
|
||||
|
||||
|
||||
def addBank3F(rom):
|
||||
# Bank3F is used to initialize the tile data in VRAM:1 at the start of the rom.
|
||||
# The normal rom does not use this tile data to maintain GB compatibility.
|
||||
rom.patch(0, 0x0150, ASM("""
|
||||
cp $11 ; is running on Game Boy Color?
|
||||
jr nz, notGBC
|
||||
ldh a, [$4d]
|
||||
and $80 ; do we need to switch the CPU speed?
|
||||
jr nz, speedSwitchDone
|
||||
; switch to GBC speed
|
||||
ld a, $30
|
||||
ldh [$00], a
|
||||
ld a, $01
|
||||
ldh [$4d], a
|
||||
xor a
|
||||
ldh [$ff], a
|
||||
stop
|
||||
db $00
|
||||
|
||||
speedSwitchDone:
|
||||
xor a
|
||||
ldh [$70], a
|
||||
ld a, $01 ; isGBC = true
|
||||
jr Init
|
||||
|
||||
notGBC:
|
||||
xor a ; isGBC = false
|
||||
Init:
|
||||
"""), ASM("""
|
||||
; Check if we are a color gameboy, we require a color version now.
|
||||
cp $11
|
||||
jr nz, notGBC
|
||||
|
||||
; Switch to bank $3F to run our custom initializer
|
||||
ld a, $3F
|
||||
ld [$2100], a
|
||||
call $4000
|
||||
; Switch back to bank 0 after loading our own initializer
|
||||
ld a, $01
|
||||
ld [$2100], a
|
||||
|
||||
; set a to 1 to indicate GBC
|
||||
ld a, $01
|
||||
jr Init
|
||||
notGBC:
|
||||
xor a
|
||||
Init:
|
||||
"""), fill_nop=True)
|
||||
|
||||
rom.patch(0x3F, 0x0000, None, ASM("""
|
||||
; switch speed
|
||||
ld a, $30
|
||||
ldh [$00], a
|
||||
ld a, $01
|
||||
ldh [$4d], a
|
||||
xor a
|
||||
ldh [$ff], a
|
||||
stop
|
||||
db $00
|
||||
|
||||
; Switch VRAM bank
|
||||
ld a, $01
|
||||
ldh [$4F], a
|
||||
|
||||
call $28CF ; display off
|
||||
|
||||
; Use the GBC DMA to transfer our tile data
|
||||
ld a, $68
|
||||
ldh [$51], a
|
||||
ld a, $00
|
||||
ldh [$52], a
|
||||
|
||||
ld a, $80
|
||||
ldh [$53], a
|
||||
ld a, $00
|
||||
ldh [$54], a
|
||||
|
||||
ld a, $7F
|
||||
ldh [$55], a
|
||||
|
||||
waitTillTransferDone:
|
||||
ldh a, [$55]
|
||||
and $80
|
||||
jr z, waitTillTransferDone
|
||||
|
||||
ld a, $70
|
||||
ldh [$51], a
|
||||
ld a, $00
|
||||
ldh [$52], a
|
||||
|
||||
ld a, $88
|
||||
ldh [$53], a
|
||||
ld a, $00
|
||||
ldh [$54], a
|
||||
|
||||
ld a, $7F
|
||||
ldh [$55], a
|
||||
|
||||
waitTillTransferDone2:
|
||||
ldh a, [$55]
|
||||
and $80
|
||||
jr z, waitTillTransferDone2
|
||||
|
||||
ld a, $68
|
||||
ldh [$51], a
|
||||
ld a, $00
|
||||
ldh [$52], a
|
||||
|
||||
ld a, $90
|
||||
ldh [$53], a
|
||||
ld a, $00
|
||||
ldh [$54], a
|
||||
|
||||
ld a, $7F
|
||||
ldh [$55], a
|
||||
|
||||
waitTillTransferDone3:
|
||||
ldh a, [$55]
|
||||
and $80
|
||||
jr z, waitTillTransferDone3
|
||||
|
||||
; Switch VRAM bank back
|
||||
ld a, $00
|
||||
ldh [$4F], a
|
||||
|
||||
; Switch the display back on, else the later code hangs
|
||||
ld a, $80
|
||||
ldh [$40], a
|
||||
|
||||
speedSwitchDone:
|
||||
xor a
|
||||
ldh [$70], a
|
||||
|
||||
; Check if we are running on a bad emulator
|
||||
ldh [$02], a
|
||||
ldh a, [$02]
|
||||
and $7c
|
||||
cp $7c
|
||||
jr nz, badEmu
|
||||
|
||||
; Enable the timer to run 32 times per second
|
||||
xor a
|
||||
ldh [$06], a
|
||||
ld a, $04
|
||||
ldh [$07], a
|
||||
|
||||
; Set SB to $FF to indicate we have no data from hardware
|
||||
ld a, $FF
|
||||
ldh [$01], a
|
||||
ret
|
||||
badEmu:
|
||||
xor a
|
||||
ldh [$40], a ; switch display off
|
||||
; Load some palette
|
||||
ld a, $80
|
||||
ldh [$68], a
|
||||
xor a
|
||||
ldh [$69], a
|
||||
ldh [$69], a
|
||||
ldh [$69], a
|
||||
ldh [$69], a
|
||||
|
||||
; Load a different gfx tile for the first gfx
|
||||
cpl
|
||||
ld hl, $8000
|
||||
ld c, $10
|
||||
.loop:
|
||||
ldi [hl], a
|
||||
dec c
|
||||
jr nz, .loop
|
||||
|
||||
ld a, $01
|
||||
ld [$9800], a
|
||||
ld [$9820], a
|
||||
ld [$9840], a
|
||||
ld [$9860], a
|
||||
ld [$9880], a
|
||||
|
||||
ld [$9801], a
|
||||
ld [$9841], a
|
||||
ld [$9881], a
|
||||
|
||||
ld [$9822], a
|
||||
ld [$9862], a
|
||||
|
||||
ld [$9824], a
|
||||
ld [$9844], a
|
||||
ld [$9864], a
|
||||
ld [$9884], a
|
||||
|
||||
ld [$9805], a
|
||||
ld [$9845], a
|
||||
|
||||
ld [$9826], a
|
||||
ld [$9846], a
|
||||
ld [$9866], a
|
||||
ld [$9886], a
|
||||
|
||||
ld [$9808], a
|
||||
ld [$9828], a
|
||||
ld [$9848], a
|
||||
ld [$9868], a
|
||||
ld [$9888], a
|
||||
|
||||
ld [$9809], a
|
||||
ld [$9889], a
|
||||
|
||||
ld [$982A], a
|
||||
ld [$984A], a
|
||||
ld [$986A], a
|
||||
|
||||
ld [$9900], a
|
||||
ld [$9920], a
|
||||
ld [$9940], a
|
||||
ld [$9960], a
|
||||
ld [$9980], a
|
||||
|
||||
ld [$9901], a
|
||||
ld [$9941], a
|
||||
ld [$9981], a
|
||||
|
||||
ld [$9903], a
|
||||
ld [$9923], a
|
||||
ld [$9943], a
|
||||
ld [$9963], a
|
||||
ld [$9983], a
|
||||
|
||||
ld [$9904], a
|
||||
ld [$9925], a
|
||||
ld [$9906], a
|
||||
|
||||
ld [$9907], a
|
||||
ld [$9927], a
|
||||
ld [$9947], a
|
||||
ld [$9967], a
|
||||
ld [$9987], a
|
||||
|
||||
ld [$9909], a
|
||||
ld [$9929], a
|
||||
ld [$9949], a
|
||||
ld [$9969], a
|
||||
ld [$9989], a
|
||||
|
||||
ld [$998A], a
|
||||
|
||||
ld [$990B], a
|
||||
ld [$992B], a
|
||||
ld [$994B], a
|
||||
ld [$996B], a
|
||||
ld [$998B], a
|
||||
|
||||
; lcd on
|
||||
ld a, $91
|
||||
ldh [$40], a
|
||||
blockBadEmu:
|
||||
di
|
||||
jr blockBadEmu
|
||||
|
||||
"""))
|
||||
|
||||
# Copy all normal item graphics
|
||||
rom.banks[0x3F][0x2800:0x2B00] = rom.banks[0x2C][0x0800:0x0B00] # main items
|
||||
rom.banks[0x3F][0x2B00:0x2C00] = rom.banks[0x2C][0x0C00:0x0D00] # overworld key items
|
||||
rom.banks[0x3F][0x2C00:0x2D00] = rom.banks[0x32][0x3D00:0x3E00] # dungeon key items
|
||||
# Create ruppee for palettes 0-3
|
||||
rom.banks[0x3F][0x2B80:0x2BA0] = rom.banks[0x3F][0x2A60:0x2A80]
|
||||
for n in range(0x2B80, 0x2BA0, 2):
|
||||
rom.banks[0x3F][n+1] ^= rom.banks[0x3F][n]
|
||||
|
||||
# Create capacity upgrade arrows
|
||||
rom.banks[0x3F][0x2A30:0x2A40] = utils.createTileData("""
|
||||
33
|
||||
3113
|
||||
311113
|
||||
33311333
|
||||
3113
|
||||
3333
|
||||
""")
|
||||
rom.banks[0x3F][0x2A20:0x2A30] = rom.banks[0x3F][0x2A30:0x2A40]
|
||||
for n in range(0x2A20, 0x2A40, 2):
|
||||
rom.banks[0x3F][n] |= rom.banks[0x3F][n + 1]
|
||||
|
||||
# Add the slime key and mushroom which are not in the above sets
|
||||
rom.banks[0x3F][0x2CC0:0x2D00] = rom.banks[0x2C][0x28C0:0x2900]
|
||||
# Add tunic sprites as well.
|
||||
rom.banks[0x3F][0x2C80:0x2CA0] = rom.banks[0x35][0x0F00:0x0F20]
|
||||
|
||||
# Add the bowwow sprites
|
||||
rom.banks[0x3F][0x2D00:0x2E00] = rom.banks[0x2E][0x2400:0x2500]
|
||||
|
||||
# Zol sprites, so we can have zol anywhere from a chest
|
||||
rom.banks[0x3F][0x2E00:0x2E60] = rom.banks[0x2E][0x1120:0x1180]
|
||||
# Patch gel(zol) entity to load sprites from the 2nd bank
|
||||
rom.patch(0x06, 0x3C09, "5202522254025422" "5200522054005420", "600A602A620A622A" "6008602862086228")
|
||||
rom.patch(0x07, 0x329B, "FFFFFFFF" "FFFFFFFF" "54005420" "52005220" "56005600",
|
||||
"FFFFFFFF" "FFFFFFFF" "62086228" "60086028" "64086408")
|
||||
rom.patch(0x06, 0x3BFA, "56025622", "640A642A");
|
||||
|
||||
|
||||
# Cucco
|
||||
rom.banks[0x3F][0x2E80:0x2F00] = rom.banks[0x32][0x2500:0x2580]
|
||||
# Patch the cucco graphics to load from 2nd vram bank
|
||||
rom.patch(0x05, 0x0514,
|
||||
"5001" "5201" "5401" "5601" "5221" "5021" "5621" "5421",
|
||||
"6809" "6A09" "6C09" "6E09" "6A29" "6829" "6E29" "6C29")
|
||||
# Song symbols
|
||||
rom.banks[0x3F][0x2F00:0x2F60] = utils.createTileData("""
|
||||
|
||||
|
||||
...
|
||||
. .222
|
||||
.2.2222
|
||||
.22.222.
|
||||
.22222.3
|
||||
.2..22.3
|
||||
.33...3
|
||||
.33.3.3
|
||||
..233.3
|
||||
.22.2333
|
||||
.222.233
|
||||
.222...
|
||||
...
|
||||
""" + """
|
||||
|
||||
|
||||
..
|
||||
.22
|
||||
.223
|
||||
..222
|
||||
.33.22
|
||||
.3..22
|
||||
.33.33
|
||||
..23.
|
||||
..233.
|
||||
.22.333
|
||||
.22..233
|
||||
.. .23
|
||||
..
|
||||
""" + """
|
||||
|
||||
|
||||
...
|
||||
.222.
|
||||
.2.332
|
||||
.23.32
|
||||
.233.2
|
||||
.222222
|
||||
.2222222
|
||||
.2..22.2
|
||||
.2.3.222
|
||||
.22...22
|
||||
.2333..
|
||||
.23333
|
||||
.....""", " .23")
|
||||
|
||||
# Ghost
|
||||
rom.banks[0x3F][0x2F60:0x2FE0] = rom.banks[0x32][0x1800:0x1880]
|
||||
|
||||
# Instruments
|
||||
rom.banks[0x3F][0x3000:0x3200] = rom.banks[0x31][0x1000:0x1200]
|
||||
# Patch the egg song event to use the 2nd vram sprites
|
||||
rom.patch(0x19, 0x0BAC,
|
||||
"5006520654065606"
|
||||
"58065A065C065E06"
|
||||
"6006620664066606"
|
||||
"68066A066C066E06",
|
||||
"800E820E840E860E"
|
||||
"880E8A0E8C0E8E0E"
|
||||
"900E920E940E960E"
|
||||
"980E9A0E9C0E9E0E"
|
||||
)
|
||||
|
||||
# Rooster
|
||||
rom.banks[0x3F][0x3200:0x3300] = rom.banks[0x32][0x1D00:0x1E00]
|
||||
rom.patch(0x19, 0x19BC,
|
||||
"42234023" "46234423" "40034203" "44034603" "4C034C23" "4E034E23" "48034823" "4A034A23",
|
||||
"A22BA02B" "A62BA42B" "A00BA20B" "A40BA60B" "AC0BAC2B" "AE0BAE2B" "A80BA82B" "AA0BAA2B")
|
||||
# Replace some main item graphics with the rooster
|
||||
rom.banks[0x2C][0x0900:0x0940] = utils.createTileData(utils.tileDataToString(rom.banks[0x32][0x1D00:0x1D40]), " 321")
|
||||
|
||||
# Trade sequence items
|
||||
rom.banks[0x3F][0x3300:0x3640] = rom.banks[0x2C][0x0400:0x0740]
|
||||
1036
worlds/ladx/LADXR/patches/bingo.py
Normal file
1036
worlds/ladx/LADXR/patches/bingo.py
Normal file
File diff suppressed because it is too large
Load Diff
20
worlds/ladx/LADXR/patches/bomb.py
Normal file
20
worlds/ladx/LADXR/patches/bomb.py
Normal file
@@ -0,0 +1,20 @@
|
||||
from ..assembler import ASM
|
||||
|
||||
|
||||
def onlyDropBombsWhenHaveBombs(rom):
|
||||
rom.patch(0x03, 0x1FC5, ASM("call $608C"), ASM("call $50B2"))
|
||||
# We use some of the unused chest code space here to remove the bomb if you do not have bombs in your inventory.
|
||||
rom.patch(0x03, 0x10B2, 0x112A, ASM("""
|
||||
ld e, INV_SIZE
|
||||
ld hl, $DB00
|
||||
ld a, $02
|
||||
loop:
|
||||
cp [hl]
|
||||
jr z, resume
|
||||
dec e
|
||||
inc hl
|
||||
jr nz, loop
|
||||
jp $3F8D ; unload entity
|
||||
resume:
|
||||
jp $608C
|
||||
"""), fill_nop=True)
|
||||
207
worlds/ladx/LADXR/patches/bowwow.py
Normal file
207
worlds/ladx/LADXR/patches/bowwow.py
Normal file
@@ -0,0 +1,207 @@
|
||||
from ..assembler import ASM
|
||||
from ..roomEditor import RoomEditor
|
||||
|
||||
|
||||
def fixBowwow(rom, everywhere=False):
|
||||
### BowWow patches
|
||||
rom.patch(0x03, 0x1E0E, ASM("ld [$DB56], a"), "", fill_nop=True) # Do not mark BowWow as kidnapped after we complete dungeon 1.
|
||||
rom.patch(0x15, 0x06B6, ASM("ld a, [$DB56]\ncp $80"), ASM("xor a"), fill_nop=True) # always load the moblin boss
|
||||
rom.patch(0x03, 0x182D, ASM("ld a, [$DB56]\ncp $80"), ASM("ld a, [$DAE2]\nand $10")) # load the cave moblins if the chest is not opened
|
||||
rom.patch(0x07, 0x3947, ASM("ld a, [$DB56]\ncp $80"), ASM("ld a, [$DAE2]\nand $10")) # load the cave moblin with sword if the chest is not opened
|
||||
|
||||
# Modify the moblin cave to contain a chest at the end, which contains bowwow
|
||||
re = RoomEditor(rom, 0x2E2)
|
||||
re.removeEntities(0x6D)
|
||||
re.changeObject(8, 3, 0xA0)
|
||||
re.store(rom)
|
||||
# Place bowwow in the chest table
|
||||
rom.banks[0x14][0x560 + 0x2E2] = 0x81
|
||||
|
||||
# Patch bowwow follower sprite to be used from 2nd vram bank
|
||||
rom.patch(0x05, 0x001C,
|
||||
b"40034023"
|
||||
b"42034223"
|
||||
b"44034603"
|
||||
b"48034A03"
|
||||
b"46234423"
|
||||
b"4A234823"
|
||||
b"4C034C23",
|
||||
b"500B502B"
|
||||
b"520B522B"
|
||||
b"540B560B"
|
||||
b"580B5A0B"
|
||||
b"562B542B"
|
||||
b"5A2B582B"
|
||||
b"5C0B5C2B")
|
||||
# Patch to use the chain sprite from second vram bank (however, the chain bugs out various things)
|
||||
rom.patch(0x05, 0x0282,
|
||||
ASM("ld a, $4E\njr nz, $02\nld a, $7E\nld [de], a\ninc de\nld a, $00"),
|
||||
ASM("ld a, $5E\nld [de], a\ninc de\nld a, $08"), fill_nop=True)
|
||||
# Never load the bowwow tiles in the first VRAM bank, as we do not need them.
|
||||
rom.patch(0x00, 0x2EB0, ASM("ld a, [$DB56]\ncp $01\nld a, $A4\njr z, $18"), "", fill_nop=True)
|
||||
|
||||
# Patch the location where bowwow stores chain X/Y positions so it does not conflict with a lot of other things
|
||||
rom.patch(0x05, 0x00BE, ASM("ld hl, $D100"), ASM("ld hl, $D180"))
|
||||
rom.patch(0x05, 0x0275, ASM("ld hl, $D100"), ASM("ld hl, $D180"))
|
||||
rom.patch(0x05, 0x03AD, ASM("ld [$D100], a"), ASM("ld [$D180], a"))
|
||||
rom.patch(0x05, 0x03BD, ASM("ld de, $D100"), ASM("ld de, $D180"))
|
||||
rom.patch(0x05, 0x049F, ASM("ld hl, $D100"), ASM("ld hl, $D180"))
|
||||
rom.patch(0x05, 0x04C2, ASM("ld a, [$D100]"), ASM("ld a, [$D180]"))
|
||||
rom.patch(0x05, 0x03C0, ASM("ld hl, $D101"), ASM("ld hl, $D181"))
|
||||
rom.patch(0x05, 0x0418, ASM("ld [$D106], a"), ASM("ld [$D186], a"))
|
||||
rom.patch(0x05, 0x0423, ASM("ld de, $D106"), ASM("ld de, $D186"))
|
||||
rom.patch(0x05, 0x0426, ASM("ld hl, $D105"), ASM("ld hl, $D185"))
|
||||
|
||||
rom.patch(0x19, 0x3A4E, ASM("ld hl, $D100"), ASM("ld hl, $D180"))
|
||||
rom.patch(0x19, 0x3A5A, ASM("ld hl, $D110"), ASM("ld hl, $D190"))
|
||||
|
||||
rom.patch(0x05, 0x00D9, ASM("ld hl, $D110"), ASM("ld hl, $D190"))
|
||||
rom.patch(0x05, 0x026E, ASM("ld hl, $D110"), ASM("ld hl, $D190"))
|
||||
rom.patch(0x05, 0x03BA, ASM("ld [$D110], a"), ASM("ld [$D190], a"))
|
||||
rom.patch(0x05, 0x03DD, ASM("ld de, $D110"), ASM("ld de, $D190"))
|
||||
rom.patch(0x05, 0x0480, ASM("ld hl, $D110"), ASM("ld hl, $D190"))
|
||||
rom.patch(0x05, 0x04B5, ASM("ld a, [$D110]"), ASM("ld a, [$D190]"))
|
||||
rom.patch(0x05, 0x03E0, ASM("ld hl, $D111"), ASM("ld hl, $D191"))
|
||||
rom.patch(0x05, 0x0420, ASM("ld [$D116], a"), ASM("ld [$D196], a"))
|
||||
rom.patch(0x05, 0x044d, ASM("ld de, $D116"), ASM("ld de, $D196"))
|
||||
rom.patch(0x05, 0x0450, ASM("ld hl, $D115"), ASM("ld hl, $D195"))
|
||||
|
||||
rom.patch(0x05, 0x0039, ASM("ld [$D154], a"), "", fill_nop=True) # normally this stores the index to bowwow, for the kiki fight
|
||||
rom.patch(0x05, 0x013C, ASM("ld [$D150], a"), ASM("ld [$D197], a"))
|
||||
rom.patch(0x05, 0x0144, ASM("ld [$D151], a"), ASM("ld [$D198], a"))
|
||||
rom.patch(0x05, 0x02F9, ASM("ld [$D152], a"), ASM("ld [$D199], a"))
|
||||
rom.patch(0x05, 0x0335, ASM("ld a, [$D152]"), ASM("ld a, [$D199]"))
|
||||
rom.patch(0x05, 0x0485, ASM("ld a, [$D151]"), ASM("ld a, [$D198]"))
|
||||
rom.patch(0x05, 0x04A4, ASM("ld a, [$D150]"), ASM("ld a, [$D197]"))
|
||||
|
||||
# Patch the bowwow create code to call our custom check of we are in swamp function.
|
||||
if everywhere:
|
||||
# Load followers in dungeons, caves, etc
|
||||
rom.patch(0x01, 0x1FC1, ASM("ret z"), "", fill_nop=True)
|
||||
rom.patch(0x01, 0x1FC4, ASM("ret z"), "", fill_nop=True)
|
||||
rom.patch(0x01, 0x1FC7, ASM("ret z"), "", fill_nop=True)
|
||||
rom.patch(0x01, 0x1FCA, ASM("ret c"), "", fill_nop=True) # dungeon
|
||||
# rom.patch(0x01, 0x1FBC, ASM("ret nz"), "", fill_nop=True) # sidescroller: TOFIX this breaks fishing minigame reward
|
||||
else:
|
||||
# Patch the bowwow create code to call our custom check of we are in swamp function.
|
||||
rom.patch(0x01, 0x211F, ASM("ldh a, [$F6]\ncp $A7\nret z\nld a, [$DB56]\ncp $01\njr nz, $36"), ASM("""
|
||||
ld a, $07
|
||||
rst 8
|
||||
ld a, e
|
||||
and a
|
||||
ret z
|
||||
"""), fill_nop=True)
|
||||
# Patch bowwow to not stay around when we move from map to map
|
||||
rom.patch(0x05, 0x0049, 0x0054, ASM("""
|
||||
cp [hl]
|
||||
jr z, Continue
|
||||
ld hl, $C280
|
||||
add hl, bc
|
||||
ld [hl], b
|
||||
ret
|
||||
Continue:
|
||||
"""), fill_nop=True)
|
||||
|
||||
# Patch madam meow meow to not take bowwow
|
||||
rom.patch(0x06, 0x1BD7, ASM("ld a, [$DB66]\nand $02"), ASM("ld a, $00\nand $02"), fill_nop=True)
|
||||
|
||||
# Patch kiki not to react to bowwow, as bowwow is not with link at this map
|
||||
rom.patch(0x07, 0x18A8, ASM("ld a, [$DB56]\ncp $01"), ASM("ld a, $00\ncp $01"), fill_nop=True)
|
||||
|
||||
# Patch the color dungeon entrance not to check for bowwow
|
||||
rom.patch(0x02, 0x340D, ASM("ld hl, $DB56\nor [hl]"), "", fill_nop=True)
|
||||
|
||||
# Patch richard to ignore bowwow
|
||||
rom.patch(0x06, 0x006C, ASM("ld a, [$DB56]"), ASM("xor a"), fill_nop=True)
|
||||
|
||||
# Patch to modify how bowwow eats enemies, normally it just unloads them, but we call our handler in bank 3E
|
||||
rom.patch(0x05, 0x03A0, 0x03A8, ASM("""
|
||||
push bc
|
||||
ld b, d
|
||||
ld c, e
|
||||
ld a, $08
|
||||
rst 8
|
||||
pop bc
|
||||
ret
|
||||
"""), fill_nop=True)
|
||||
rom.patch(0x05, 0x0387, ASM("ld a, $03\nldh [$F2], a"), "", fill_nop=True) # remove the default chomp sfx
|
||||
|
||||
# Various enemies
|
||||
rom.banks[0x14][0x1218 + 0xC5] = 0x01 # Urchin
|
||||
rom.banks[0x14][0x1218 + 0x93] = 0x01 # MadBomber
|
||||
rom.banks[0x14][0x1218 + 0x51] = 0x01 # Swinging ball&chain golden leaf enemy
|
||||
rom.banks[0x14][0x1218 + 0xF2] = 0x01 # Color dungeon flying hopper
|
||||
rom.banks[0x14][0x1218 + 0xF3] = 0x01 # Color dungeon hopper
|
||||
rom.banks[0x14][0x1218 + 0xE9] = 0x01 # Color dungeon shell
|
||||
rom.banks[0x14][0x1218 + 0xEA] = 0x01 # Color dungeon shell
|
||||
rom.banks[0x14][0x1218 + 0xEB] = 0x01 # Color dungeon shell
|
||||
rom.banks[0x14][0x1218 + 0xEC] = 0x01 # Color dungeon thing
|
||||
rom.banks[0x14][0x1218 + 0xED] = 0x01 # Color dungeon thing
|
||||
rom.banks[0x14][0x1218 + 0xEE] = 0x01 # Color dungeon thing
|
||||
rom.banks[0x14][0x1218 + 0x87] = 0x01 # Lanmola (for D4 key)
|
||||
rom.banks[0x14][0x1218 + 0x88] = 0x01 # Armos knight (for D6 key)
|
||||
rom.banks[0x14][0x1218 + 0x16] = 0x01 # Spark
|
||||
rom.banks[0x14][0x1218 + 0x17] = 0x01 # Spark
|
||||
rom.banks[0x14][0x1218 + 0x2C] = 0x01 # Spiked beetle
|
||||
rom.banks[0x14][0x1218 + 0x90] = 0x01 # Three of a kind (screw these guys)
|
||||
rom.banks[0x14][0x1218 + 0x18] = 0x01 # Pols voice
|
||||
rom.banks[0x14][0x1218 + 0x50] = 0x01 # Boo buddy
|
||||
rom.banks[0x14][0x1218 + 0xA2] = 0x01 # Pirana plant
|
||||
rom.banks[0x14][0x1218 + 0x52] = 0x01 # Tractor device
|
||||
rom.banks[0x14][0x1218 + 0x53] = 0x01 # Tractor device (D3)
|
||||
rom.banks[0x14][0x1218 + 0x55] = 0x01 # Bounding bombite
|
||||
rom.banks[0x14][0x1218 + 0x56] = 0x01 # Timer bombite
|
||||
rom.banks[0x14][0x1218 + 0x57] = 0x01 # Pairod
|
||||
rom.banks[0x14][0x1218 + 0x15] = 0x01 # Antifairy
|
||||
rom.banks[0x14][0x1218 + 0xA0] = 0x01 # Peahat
|
||||
rom.banks[0x14][0x1218 + 0x9C] = 0x01 # Star
|
||||
rom.banks[0x14][0x1218 + 0xA1] = 0x01 # Snake
|
||||
rom.banks[0x14][0x1218 + 0xBD] = 0x01 # Vire
|
||||
rom.banks[0x14][0x1218 + 0xE4] = 0x01 # Moblin boss
|
||||
|
||||
# Bosses
|
||||
rom.banks[0x14][0x1218 + 0x59] = 0x01 # Moldorm
|
||||
rom.banks[0x14][0x1218 + 0x5C] = 0x01 # Genie
|
||||
rom.banks[0x14][0x1218 + 0x5B] = 0x01 # Slime Eye
|
||||
rom.patch(0x04, 0x0AC4, ASM("ld [hl], $28"), ASM("ld [hl], $FF")) # give more time before slimeeye unsplits
|
||||
rom.patch(0x04, 0x0B05, ASM("ld [hl], $50"), ASM("ld [hl], $FF")) # give more time before slimeeye unsplits
|
||||
rom.banks[0x14][0x1218 + 0x65] = 0x01 # Angler fish
|
||||
rom.banks[0x14][0x1218 + 0x5D] = 0x01 # Slime eel
|
||||
rom.banks[0x14][0x1218 + 0x5A] = 0x01 # Facade
|
||||
rom.banks[0x14][0x1218 + 0x63] = 0x01 # Eagle
|
||||
rom.banks[0x14][0x1218 + 0x62] = 0x01 # Hot head
|
||||
rom.banks[0x14][0x1218 + 0xF9] = 0x01 # Hardhit beetle
|
||||
rom.banks[0x14][0x1218 + 0xE6] = 0x01 # Nightmare
|
||||
|
||||
# Minibosses
|
||||
rom.banks[0x14][0x1218 + 0x81] = 0x01 # Rolling bones
|
||||
rom.banks[0x14][0x1218 + 0x89] = 0x01 # Hinox
|
||||
rom.banks[0x14][0x1218 + 0x8E] = 0x01 # Cue ball
|
||||
rom.banks[0x14][0x1218 + 0x5E] = 0x01 # Gnoma
|
||||
rom.banks[0x14][0x1218 + 0x5F] = 0x01 # Master stalfos
|
||||
rom.banks[0x14][0x1218 + 0x92] = 0x01 # Smasher
|
||||
rom.banks[0x14][0x1218 + 0xBC] = 0x01 # Grim creeper
|
||||
rom.banks[0x14][0x1218 + 0xBE] = 0x01 # Blaino
|
||||
rom.banks[0x14][0x1218 + 0xF8] = 0x01 # Giant buzz blob
|
||||
rom.banks[0x14][0x1218 + 0xF4] = 0x01 # Avalaunch
|
||||
|
||||
# NPCs
|
||||
rom.banks[0x14][0x1218 + 0x6F] = 0x01 # Dog
|
||||
rom.banks[0x14][0x1218 + 0x6E] = 0x01 # Butterfly
|
||||
rom.banks[0x14][0x1218 + 0x6C] = 0x01 # Cucco
|
||||
rom.banks[0x14][0x1218 + 0x70] = 0x01 # Kid
|
||||
rom.banks[0x14][0x1218 + 0x71] = 0x01 # Kid
|
||||
rom.banks[0x14][0x1218 + 0x72] = 0x01 # Kid
|
||||
rom.banks[0x14][0x1218 + 0x73] = 0x01 # Kid
|
||||
rom.banks[0x14][0x1218 + 0xD0] = 0x01 # Animal
|
||||
rom.banks[0x14][0x1218 + 0xD1] = 0x01 # Animal
|
||||
rom.banks[0x14][0x1218 + 0xD2] = 0x01 # Animal
|
||||
rom.banks[0x14][0x1218 + 0xD3] = 0x01 # Animal
|
||||
|
||||
|
||||
def bowwowMapPatches(rom):
|
||||
# Remove all the cystal things that can only be destroyed with a sword.
|
||||
for n in range(0x100, 0x2FF):
|
||||
re = RoomEditor(rom, n)
|
||||
re.objects = list(filter(lambda obj: obj.type_id != 0xDD, re.objects))
|
||||
re.store(rom)
|
||||
59
worlds/ladx/LADXR/patches/chest.py
Normal file
59
worlds/ladx/LADXR/patches/chest.py
Normal file
@@ -0,0 +1,59 @@
|
||||
from ..assembler import ASM
|
||||
from ..utils import formatText
|
||||
from ..locations.constants import CHEST_ITEMS
|
||||
|
||||
|
||||
def fixChests(rom):
|
||||
# Patch the chest code, so it can give a lvl1 sword.
|
||||
# Normally, there is some code related to the owl event when getting the tail key,
|
||||
# as we patched out the owl. We use it to jump to our custom code in bank $3E to handle getting the item
|
||||
rom.patch(0x03, 0x109C, ASM("""
|
||||
cp $11 ; if not tail key, skip
|
||||
jr nz, end
|
||||
push af
|
||||
ld a, [$C501]
|
||||
ld e, a
|
||||
ld hl, $C2F0
|
||||
add hl, de
|
||||
ld [hl], $38
|
||||
pop af
|
||||
end:
|
||||
ld e, a
|
||||
cp $21 ; if is message chest or higher number, next instruction is to skip giving things.
|
||||
"""), ASM("""
|
||||
ld a, $06 ; GiveItemMultiworld
|
||||
rst 8
|
||||
|
||||
and a ; clear the carry flag to always skip giving stuff.
|
||||
"""), fill_nop=True)
|
||||
|
||||
# Instead of the normal logic to on which sprite data to show, we jump to our custom code in bank 3E.
|
||||
rom.patch(0x07, 0x3C36, None, ASM("""
|
||||
ld a, $01
|
||||
rst 8
|
||||
jp $7C5E
|
||||
"""), fill_nop=True)
|
||||
|
||||
# Instead of the normal logic of showing the proper dialog, we jump to our custom code in bank 3E.
|
||||
rom.patch(0x07, 0x3C9C, None, ASM("""
|
||||
ld a, $0A ; showItemMessageMultiworld
|
||||
rst 8
|
||||
jp $7CE9
|
||||
"""))
|
||||
|
||||
# Sound to play is normally loaded from a table, which is no longer big enough. So always use the same sound.
|
||||
rom.patch(0x07, 0x3C81, ASM("""
|
||||
add hl, de
|
||||
ld a, [hl]
|
||||
"""), ASM("ld a, $01"), fill_nop=True)
|
||||
|
||||
# Always spawn seashells even if you have the L2 sword
|
||||
rom.patch(0x14, 0x192F, ASM("ld a, $1C"), ASM("ld a, $20"))
|
||||
|
||||
rom.texts[0x9A] = formatText("You found 10 {BOMB}!")
|
||||
|
||||
|
||||
def setMultiChest(rom, option):
|
||||
room = 0x2F2
|
||||
addr = room + 0x560
|
||||
rom.banks[0x14][addr] = CHEST_ITEMS[option]
|
||||
539
worlds/ladx/LADXR/patches/core.py
Normal file
539
worlds/ladx/LADXR/patches/core.py
Normal file
@@ -0,0 +1,539 @@
|
||||
from ..assembler import ASM
|
||||
from ..entranceInfo import ENTRANCE_INFO
|
||||
from ..roomEditor import RoomEditor, ObjectWarp, ObjectHorizontal
|
||||
from ..backgroundEditor import BackgroundEditor
|
||||
from .. import utils
|
||||
|
||||
|
||||
def bugfixWrittingWrongRoomStatus(rom):
|
||||
# The normal rom contains a pretty nasty bug where door closing triggers in D7/D8 can effect doors in
|
||||
# dungeons D1-D6. This fix should prevent this.
|
||||
rom.patch(0x02, 0x1D21, 0x1D3C, ASM("call $5B9F"), fill_nop=True)
|
||||
|
||||
def fixEggDeathClearingItems(rom):
|
||||
rom.patch(0x01, 0x1E79, ASM("cp $0A"), ASM("cp $08"))
|
||||
|
||||
def fixWrongWarp(rom):
|
||||
rom.patch(0x00, 0x18CE, ASM("cp $04"), ASM("cp $03"))
|
||||
re = RoomEditor(rom, 0x2b)
|
||||
for x in range(10):
|
||||
re.removeObject(x, 7)
|
||||
re.objects.append(ObjectHorizontal(0, 7, 0x2C, 10))
|
||||
while len(re.getWarps()) < 4:
|
||||
re.objects.append(ObjectWarp(1, 3, 0x7a, 80, 124))
|
||||
re.store(rom)
|
||||
|
||||
def bugfixBossroomTopPush(rom):
|
||||
rom.patch(0x14, 0x14D9, ASM("""
|
||||
ldh a, [$99]
|
||||
dec a
|
||||
ldh [$99], a
|
||||
"""), ASM("""
|
||||
jp $7F80
|
||||
"""), fill_nop=True)
|
||||
rom.patch(0x14, 0x3F80, "00" * 0x80, ASM("""
|
||||
ldh a, [$99]
|
||||
cp $50
|
||||
jr nc, up
|
||||
down:
|
||||
inc a
|
||||
ldh [$99], a
|
||||
jp $54DE
|
||||
up:
|
||||
dec a
|
||||
ldh [$99], a
|
||||
jp $54DE
|
||||
"""), fill_nop=True)
|
||||
|
||||
def bugfixPowderBagSprite(rom):
|
||||
rom.patch(0x03, 0x2055, "8E16", "0E1E")
|
||||
|
||||
def easyColorDungeonAccess(rom):
|
||||
re = RoomEditor(rom, 0x312)
|
||||
re.entities = [(3, 1, 246), (6, 1, 247)]
|
||||
re.store(rom)
|
||||
|
||||
def removeGhost(rom):
|
||||
## Ghost patch
|
||||
# Do not have the ghost follow you after dungeon 4
|
||||
rom.patch(0x03, 0x1E1B, ASM("LD [$DB79], A"), "", fill_nop=True)
|
||||
|
||||
def alwaysAllowSecretBook(rom):
|
||||
rom.patch(0x15, 0x3F23, ASM("ld a, [$DB0E]\ncp $0E"), ASM("xor a\ncp $00"), fill_nop=True)
|
||||
rom.patch(0x15, 0x3F2A, 0x3F30, "", fill_nop=True)
|
||||
|
||||
def cleanup(rom):
|
||||
# Remove unused rooms to make some space in the rom
|
||||
re = RoomEditor(rom, 0x2C4)
|
||||
re.objects = []
|
||||
re.entities = []
|
||||
re.store(rom, 0x2C4)
|
||||
re.store(rom, 0x2D4)
|
||||
re.store(rom, 0x277)
|
||||
re.store(rom, 0x278)
|
||||
re.store(rom, 0x279)
|
||||
re.store(rom, 0x1ED)
|
||||
re.store(rom, 0x1FC) # Beta room
|
||||
|
||||
rom.texts[0x02B] = b'' # unused text
|
||||
|
||||
|
||||
def disablePhotoPrint(rom):
|
||||
rom.patch(0x28, 0x07CC, ASM("ldh [$01], a\nldh [$02], a"), "", fill_nop=True) # do not reset the serial link
|
||||
rom.patch(0x28, 0x0483, ASM("ld a, $13"), ASM("jr $EA", 0x4483)) # Do not print on A press, but jump to cancel
|
||||
rom.patch(0x28, 0x0492, ASM("ld hl, $4439"), ASM("ret"), fill_nop=True) # Do not show the print/cancel overlay
|
||||
|
||||
def fixMarinFollower(rom):
|
||||
# Allow opening of D0 with marin
|
||||
rom.patch(0x02, 0x3402, ASM("ld a, [$DB73]"), ASM("xor a"), fill_nop=True)
|
||||
# Instead of uselessly checking for sidescroller rooms for follower spawns, check for color dungeon instead
|
||||
rom.patch(0x01, 0x1FCB, 0x1FD3, ASM("cp $FF\nret z"), fill_nop=True)
|
||||
# Do not load marin graphics in color dungeon
|
||||
rom.patch(0x00, 0x2EA6, 0x2EB0, ASM("cp $FF\njp $2ED3"), fill_nop=True)
|
||||
# Fix marin on taltal bridge causing a lockup if you have marin with you
|
||||
# This changes the location where the index to the marin entity is stored from it's normal location
|
||||
# To the memory normal reserved for progress on the egg maze (which is reset to 0 on a warp)
|
||||
rom.patch(0x18, 0x1EF7, ASM("ld [$C50F], a"), ASM("ld [$C5AA], a"))
|
||||
rom.patch(0x18, 0x2126, ASM("ld a, [$C50F]"), ASM("ld a, [$C5AA]"))
|
||||
rom.patch(0x18, 0x2139, ASM("ld a, [$C50F]"), ASM("ld a, [$C5AA]"))
|
||||
rom.patch(0x18, 0x214F, ASM("ld a, [$C50F]"), ASM("ld a, [$C5AA]"))
|
||||
rom.patch(0x18, 0x2166, ASM("ld a, [$C50F]"), ASM("ld a, [$C5AA]"))
|
||||
|
||||
def quickswap(rom, button):
|
||||
rom.patch(0x00, 0x1094, ASM("jr c, $49"), ASM("jr nz, $49")) # prevent agressive key repeat
|
||||
rom.patch(0x00, 0x10BC, # Patch the open minimap code to swap the your items instead
|
||||
ASM("xor a\nld [$C16B], a\nld [$C16C], a\nld [$DB96], a\nld a, $07\nld [$DB95], a"), ASM("""
|
||||
ld a, [$DB%02X]
|
||||
ld e, a
|
||||
ld a, [$DB%02X]
|
||||
ld [$DB%02X], a
|
||||
ld a, e
|
||||
ld [$DB%02X], a
|
||||
ret
|
||||
""" % (button, button + 2, button, button + 2)))
|
||||
|
||||
def injectMainLoop(rom):
|
||||
rom.patch(0x00, 0x0346, ASM("""
|
||||
ldh a, [$FE]
|
||||
and a
|
||||
jr z, $08
|
||||
"""), ASM("""
|
||||
; Call the mainloop handler
|
||||
xor a
|
||||
rst 8
|
||||
"""), fill_nop=True)
|
||||
|
||||
def warpHome(rom):
|
||||
# Patch the S&Q menu to allow 3 options
|
||||
rom.patch(0x01, 0x012A, 0x0150, ASM("""
|
||||
ld hl, $C13F
|
||||
call $6BA8 ; make sound on keypress
|
||||
ldh a, [$CC] ; load joystick status
|
||||
and $04 ; if up
|
||||
jr z, noUp
|
||||
dec [hl]
|
||||
noUp:
|
||||
ldh a, [$CC] ; load joystick status
|
||||
and $08 ; if down
|
||||
jr z, noDown
|
||||
inc [hl]
|
||||
noDown:
|
||||
|
||||
ld a, [hl]
|
||||
cp $ff
|
||||
jr nz, noWrapUp
|
||||
ld a, $02
|
||||
noWrapUp:
|
||||
cp $03
|
||||
jr nz, noWrapDown
|
||||
xor a
|
||||
noWrapDown:
|
||||
ld [hl], a
|
||||
jp $7E02
|
||||
"""), fill_nop=True)
|
||||
rom.patch(0x01, 0x3E02, 0x3E20, ASM("""
|
||||
swap a
|
||||
add a, $48
|
||||
ld hl, $C018
|
||||
ldi [hl], a
|
||||
ld a, $24
|
||||
ldi [hl], a
|
||||
ld a, $BE
|
||||
ldi [hl], a
|
||||
ld [hl], $00
|
||||
ret
|
||||
"""), fill_nop=True)
|
||||
|
||||
rom.patch(0x01, 0x00B7, ASM("""
|
||||
ld a, [$C13F]
|
||||
cp $01
|
||||
jr z, $3B
|
||||
"""), ASM("""
|
||||
ld a, [$C13F]
|
||||
jp $7E20
|
||||
"""), fill_nop=True)
|
||||
|
||||
re = RoomEditor(rom, 0x2a3)
|
||||
warp = re.getWarps()[0]
|
||||
|
||||
type = 0x00
|
||||
map = 0x00
|
||||
room = warp.room
|
||||
x = warp.target_x
|
||||
y = warp.target_y
|
||||
|
||||
one_way = [
|
||||
'd0',
|
||||
'd1',
|
||||
'd3',
|
||||
'd4',
|
||||
'd6',
|
||||
'd8',
|
||||
'animal_cave',
|
||||
'right_fairy',
|
||||
'rooster_grave',
|
||||
'prairie_left_cave2',
|
||||
'prairie_left_fairy',
|
||||
'armos_fairy',
|
||||
'boomerang_cave',
|
||||
'madbatter_taltal',
|
||||
'forest_madbatter',
|
||||
]
|
||||
|
||||
one_way = {ENTRANCE_INFO[x].room for x in one_way}
|
||||
|
||||
if warp.room in one_way:
|
||||
# we're starting at a one way exit room
|
||||
# warp indoors to avoid soft locks
|
||||
type = 0x01
|
||||
map = 0x10
|
||||
room = 0xa3
|
||||
x = 0x50
|
||||
y = 0x7f
|
||||
|
||||
rom.patch(0x01, 0x3E20, 0x3E6B, ASM("""
|
||||
; First, handle save & quit
|
||||
cp $01
|
||||
jp z, $40F9
|
||||
and a
|
||||
jp z, $40BE ; return to normal "return to game" handling
|
||||
|
||||
ld a, [$C509] ; Check if we have an item in the shop
|
||||
and a
|
||||
jp nz, $40BE ; return to normal "return to game" handling
|
||||
|
||||
ld a, $0B
|
||||
ld [$DB95], a
|
||||
call $0C7D
|
||||
|
||||
; Replace warp0 tile data, and put link on that tile.
|
||||
ld a, $%02x ; Type
|
||||
ld [$D401], a
|
||||
ld a, $%02x ; Map
|
||||
ld [$D402], a
|
||||
ld a, $%02x ; Room
|
||||
ld [$D403], a
|
||||
ld a, $%02x ; X
|
||||
ld [$D404], a
|
||||
ld a, $%02x ; Y
|
||||
ld [$D405], a
|
||||
|
||||
ldh a, [$98]
|
||||
swap a
|
||||
and $0F
|
||||
ld e, a
|
||||
ldh a, [$99]
|
||||
sub $08
|
||||
and $F0
|
||||
or e
|
||||
ld [$D416], a
|
||||
|
||||
ld a, $07
|
||||
ld [$DB96], a
|
||||
ret
|
||||
jp $40BE ; return to normal "return to game" handling
|
||||
""" % (type, map, room, x, y)), fill_nop=True)
|
||||
|
||||
# Patch the RAM clear not to delete our custom dialog when we screen transition
|
||||
rom.patch(0x01, 0x042C, "C629", "6B7E")
|
||||
rom.patch(0x01, 0x3E6B, 0x3FFF, ASM("""
|
||||
ld bc, $A0
|
||||
call $29DC
|
||||
ld bc, $1200
|
||||
ld hl, $C100
|
||||
call $29DF
|
||||
ret
|
||||
"""), fill_nop=True)
|
||||
# Patch the S&Q screen to have 3 options.
|
||||
be = BackgroundEditor(rom, 0x0D)
|
||||
for n in range(2, 18):
|
||||
be.tiles[0x99C0 + n] = be.tiles[0x9980 + n]
|
||||
be.tiles[0x99A0 + n] = be.tiles[0x9960 + n]
|
||||
be.tiles[0x9980 + n] = be.tiles[0x9940 + n]
|
||||
be.tiles[0x9960 + n] = be.tiles[0x98e0 + n]
|
||||
be.tiles[0x9960 + 10] = 0xCE
|
||||
be.tiles[0x9960 + 11] = 0xCF
|
||||
be.tiles[0x9960 + 12] = 0xC4
|
||||
be.tiles[0x9960 + 13] = 0x7F
|
||||
be.tiles[0x9960 + 14] = 0x7F
|
||||
be.store(rom)
|
||||
|
||||
sprite_data = [
|
||||
0b00000000,
|
||||
0b01000100,
|
||||
0b01000101,
|
||||
0b01000101,
|
||||
0b01111101,
|
||||
0b01000101,
|
||||
0b01000101,
|
||||
0b01000100,
|
||||
|
||||
0b00000000,
|
||||
0b11100100,
|
||||
0b00010110,
|
||||
0b00010101,
|
||||
0b00010100,
|
||||
0b00010100,
|
||||
0b00010100,
|
||||
0b11100100,
|
||||
]
|
||||
for n in range(32):
|
||||
rom.banks[0x0F][0x08E0 + n] = sprite_data[n // 2]
|
||||
|
||||
|
||||
def addFrameCounter(rom, check_count):
|
||||
# Patch marin giving the start the game to jump to a custom handler
|
||||
rom.patch(0x05, 0x1299, ASM("ld a, $01\ncall $2385"), ASM("push hl\nld a, $0D\nrst 8\npop hl"), fill_nop=True)
|
||||
|
||||
# Add code that needs to be called every frame to tick our ingame time counter.
|
||||
rom.patch(0x00, 0x0091, "00" * (0x100 - 0x91), ASM("""
|
||||
ld a, [$DB95] ;Get the gameplay type
|
||||
dec a ; and if it was 1
|
||||
ret z ; we are at the credits and the counter should stop.
|
||||
|
||||
; Check if the timer expired
|
||||
ld hl, $FF0F
|
||||
bit 2, [hl]
|
||||
ret z
|
||||
res 2, [hl]
|
||||
|
||||
; Increase the "subsecond" counter, and continue if it "overflows"
|
||||
call $27D0 ; Enable SRAM
|
||||
ld hl, $B000
|
||||
ld a, [hl]
|
||||
inc a
|
||||
cp $20
|
||||
ld [hl], a
|
||||
ret nz
|
||||
xor a
|
||||
ldi [hl], a
|
||||
|
||||
; Increase the seconds counter/minutes/hours counter
|
||||
increaseSecMinHours:
|
||||
ld a, [hl]
|
||||
inc a
|
||||
daa
|
||||
ld [hl], a
|
||||
cp $60
|
||||
ret nz
|
||||
xor a
|
||||
ldi [hl], a
|
||||
jr increaseSecMinHours
|
||||
"""), fill_nop=True)
|
||||
# Replace a cgb check with the call to our counter code.
|
||||
rom.patch(0x00, 0x0367, ASM("ld a, $0C\ncall $0B0B"), ASM("call $0091\nld a, $2C"))
|
||||
|
||||
# Do not switch to 8x8 sprite mode
|
||||
rom.patch(0x17, 0x2E9E, ASM("res 2, [hl]"), "", fill_nop=True)
|
||||
# We need to completely reorder link sitting on the raft to work with 16x8 sprites.
|
||||
sprites = rom.banks[0x38][0x1600:0x1800]
|
||||
sprites[0x1F0:0x200] = b'\x00' * 16
|
||||
for index, position in enumerate(
|
||||
(0, 0x1F,
|
||||
1, 0x1F, 2, 0x1F,
|
||||
7, 8,
|
||||
3, 9, 4, 10, 5, 11, 6, 12,
|
||||
3, 13, 4, 14, 5, 15, 6, 16,
|
||||
3, 17, 4, 18, 5, 19, 6, 20,
|
||||
)):
|
||||
rom.banks[0x38][0x1600+index*0x10:0x1610+index*0x10] = sprites[position*0x10:0x10+position*0x10]
|
||||
rom.patch(0x27, 0x376E, 0x3776, "00046601", fill_nop=True)
|
||||
rom.patch(0x27, 0x384E, ASM("ld c, $08"), ASM("ld c, $04"))
|
||||
rom.patch(0x27, 0x3776, 0x3826,
|
||||
"FA046002"
|
||||
"0208640402006204"
|
||||
"0A106E030A086C030A006A030AF86803"
|
||||
|
||||
"FA046002"
|
||||
"0208640402006204"
|
||||
"0A1076030A0874030A0072030AF87003"
|
||||
|
||||
"FA046002"
|
||||
"0208640402006204"
|
||||
"0A107E030A087C030A007A030AF87803"
|
||||
, fill_nop=True)
|
||||
rom.patch(0x27, 0x382E, ASM("ld a, $6C"), ASM("ld a, $80")) # OAM start position
|
||||
rom.patch(0x27, 0x384E, ASM("ld c, $08"), ASM("ld c, $04")) # Amount of overlay OAM data
|
||||
rom.patch(0x27, 0x3826, 0x382E, ASM("dw $7776, $7792, $77AE, $7792")) # pointers to animation
|
||||
rom.patch(0x27, 0x3846, ASM("ld c, $2C"), ASM("ld c, $1C")) # Amount of OAM data
|
||||
|
||||
# TODO: fix flying windfish
|
||||
# Upper line of credits roll into "TIME"
|
||||
rom.patch(0x17, 0x069D, 0x0713, ASM("""
|
||||
ld hl, OAMData
|
||||
ld de, $C000 ; OAM Buffer
|
||||
ld bc, $0048
|
||||
call $2914
|
||||
ret
|
||||
OAMData:
|
||||
db $20, $18, $34, $00 ;T
|
||||
db $20, $20, $20, $00 ;I
|
||||
db $20, $28, $28, $00 ;M
|
||||
db $20, $30, $18, $00 ;E
|
||||
|
||||
db $20, $70, $16, $00 ;D
|
||||
db $20, $78, $18, $00 ;E
|
||||
db $20, $80, $10, $00 ;A
|
||||
db $20, $88, $34, $00 ;T
|
||||
db $20, $90, $1E, $00 ;H
|
||||
|
||||
db $50, $18, $14, $00 ;C
|
||||
db $50, $20, $1E, $00 ;H
|
||||
db $50, $28, $18, $00 ;E
|
||||
db $50, $30, $14, $00 ;C
|
||||
db $50, $38, $24, $00 ;K
|
||||
db $50, $40, $32, $00 ;S
|
||||
|
||||
db $68, $38, $%02x, $00 ;0
|
||||
db $68, $40, $%02x, $00 ;0
|
||||
db $68, $48, $%02x, $00 ;0
|
||||
|
||||
""" % ((((check_count // 100) % 10) * 2) | 0x40, (((check_count // 10) % 10) * 2) | 0x40, ((check_count % 10) * 2) | 0x40), 0x469D), fill_nop=True)
|
||||
# Lower line of credits roll into XX XX XX
|
||||
rom.patch(0x17, 0x0784, 0x082D, ASM("""
|
||||
ld hl, OAMData
|
||||
ld de, $C048 ; OAM Buffer
|
||||
ld bc, $0038
|
||||
call $2914
|
||||
|
||||
call $27D0 ; Enable SRAM
|
||||
ld hl, $C04A
|
||||
ld a, [$B003] ; hours
|
||||
call updateOAM
|
||||
ld a, [$B002] ; minutes
|
||||
call updateOAM
|
||||
ld a, [$B001] ; seconds
|
||||
call updateOAM
|
||||
|
||||
ld a, [$DB58] ; death count high
|
||||
call updateOAM
|
||||
ld a, [$DB57] ; death count low
|
||||
call updateOAM
|
||||
|
||||
ld a, [$B011] ; check count high
|
||||
call updateOAM
|
||||
ld a, [$B010] ; check count low
|
||||
call updateOAM
|
||||
ret
|
||||
|
||||
updateOAM:
|
||||
ld de, $0004
|
||||
ld b, a
|
||||
swap a
|
||||
and $0F
|
||||
add a, a
|
||||
or $40
|
||||
ld [hl], a
|
||||
add hl, de
|
||||
|
||||
ld a, b
|
||||
and $0F
|
||||
add a, a
|
||||
or $40
|
||||
ld [hl], a
|
||||
add hl, de
|
||||
ret
|
||||
OAMData:
|
||||
db $38, $18, $40, $00 ;0 (10 hours)
|
||||
db $38, $20, $40, $00 ;0 (1 hours)
|
||||
db $38, $30, $40, $00 ;0 (10 minutes)
|
||||
db $38, $38, $40, $00 ;0 (1 minutes)
|
||||
db $38, $48, $40, $00 ;0 (10 seconds)
|
||||
db $38, $50, $40, $00 ;0 (1 seconds)
|
||||
|
||||
db $00, $00, $40, $00 ;0 (1000 death)
|
||||
db $38, $80, $40, $00 ;0 (100 death)
|
||||
|
||||
db $38, $88, $40, $00 ;0 (10 death)
|
||||
db $38, $90, $40, $00 ;0 (1 death)
|
||||
|
||||
; checks
|
||||
db $00, $00, $40, $00 ;0
|
||||
db $68, $18, $40, $00 ;0
|
||||
db $68, $20, $40, $00 ;0
|
||||
db $68, $28, $40, $00 ;0
|
||||
|
||||
""", 0x4784), fill_nop=True)
|
||||
|
||||
# Grab the "mostly" complete A-Z font
|
||||
sprites = rom.banks[0x38][0x1100:0x1400]
|
||||
for index, position in enumerate((
|
||||
0x10, 0x20, # A
|
||||
0x11, 0x21, # B
|
||||
0x12, 0x12 | 0x100, # C
|
||||
0x13, 0x23, # D
|
||||
0x14, 0x24, # E
|
||||
0x14, 0x25, # F
|
||||
0x12, 0x22, # G
|
||||
0x20 | 0x100, 0x26, # H
|
||||
0x17, 0x17 | 0x100, # I
|
||||
0x28, 0x28, # J
|
||||
0x19, 0x29, # K
|
||||
0x06, 0x07, # L
|
||||
0x1A, 0x2A, # M
|
||||
0x1B, 0x2B, # N
|
||||
0x00, 0x00, # O?
|
||||
0x00, 0x00, # P?
|
||||
#0x00, 0x00, # Q?
|
||||
0x11, 0x18, # R
|
||||
0x1C, 0x2C, # S
|
||||
0x1D, 0x2D, # T
|
||||
0x26, 0x10, # U
|
||||
0x00, 0x00, # V?
|
||||
0x1E, 0x2E, # W
|
||||
#0x00, 0x00, # X?
|
||||
#0x00, 0x00, # Y?
|
||||
0x27, 0x27, # Z
|
||||
)):
|
||||
sprite = sprites[(position&0xFF)*0x10:0x10+(position&0xFF)*0x10]
|
||||
if position & 0x100:
|
||||
for n in range(4):
|
||||
sprite[n * 2], sprite[14 - n * 2] = sprite[14 - n * 2], sprite[n * 2]
|
||||
sprite[n * 2 + 1], sprite[15 - n * 2] = sprite[15 - n * 2], sprite[n * 2 + 1]
|
||||
rom.banks[0x38][0x1100+index*0x10:0x1110+index*0x10] = sprite
|
||||
|
||||
|
||||
# Number graphics change for the end
|
||||
tile_graphics = """
|
||||
........ ........ ........ ........ ........ ........ ........ ........ ........ ........
|
||||
.111111. ..1111.. .111111. .111111. ..11111. 11111111 .111111. 11111111 .111111. .111111.
|
||||
11333311 .11331.. 11333311 11333311 .113331. 13333331 11333311 13333331 11333311 11333311
|
||||
13311331 113331.. 13311331 13311331 1133331. 13311111 13311331 11111331 13311331 13311331
|
||||
13311331 133331.. 13311331 11111331 1331331. 1331.... 13311331 ...11331 13311331 13311331
|
||||
13311331 133331.. 11111331 ....1331 1331331. 1331.... 13311111 ...13311 13311331 13311331
|
||||
13311331 111331.. ...13311 .1111331 1331331. 1331111. 1331.... ..11331. 13311331 13311331
|
||||
13311331 ..1331.. ..11331. .1333331 13313311 13333311 1331111. ..13311. 11333311 11333331
|
||||
13311331 ..1331.. ..13311. .1111331 13333331 13311331 13333311 .11331.. 13311331 .1111331
|
||||
13311331 ..1331.. .11331.. ....1331 11113311 11111331 13311331 .13311.. 13311331 ....1331
|
||||
13311331 ..1331.. .13311.. ....1331 ...1331. ....1331 13311331 11331... 13311331 ....1331
|
||||
13311331 ..1331.. 11331... 11111331 ...1331. 11111331 13311331 13311... 13311331 11111331
|
||||
13311331 ..1331.. 13311111 13311331 ...1331. 13311331 13311331 1331.... 13311331 13311331
|
||||
11333311 ..1331.. 13333331 11333311 ...1331. 11333311 11333311 1331.... 11333311 11333311
|
||||
.111111. ..1111.. 11111111 .111111. ...1111. .111111. .111111. 1111.... .111111. .111111.
|
||||
........ ........ ........ ........ ........ ........ ........ ........ ........ ........
|
||||
""".strip()
|
||||
for n in range(10):
|
||||
gfx_high = "\n".join([line.split(" ")[n] for line in tile_graphics.split("\n")[:8]])
|
||||
gfx_low = "\n".join([line.split(" ")[n] for line in tile_graphics.split("\n")[8:]])
|
||||
rom.banks[0x38][0x1400+n*0x20:0x1410+n*0x20] = utils.createTileData(gfx_high)
|
||||
rom.banks[0x38][0x1410+n*0x20:0x1420+n*0x20] = utils.createTileData(gfx_low)
|
||||
7
worlds/ladx/LADXR/patches/desert.py
Normal file
7
worlds/ladx/LADXR/patches/desert.py
Normal file
@@ -0,0 +1,7 @@
|
||||
from ..roomEditor import RoomEditor
|
||||
|
||||
|
||||
def desertAccess(rom):
|
||||
re = RoomEditor(rom, 0x0FD)
|
||||
re.entities = [(6, 2, 0xC4)]
|
||||
re.store(rom)
|
||||
134
worlds/ladx/LADXR/patches/droppedKey.py
Normal file
134
worlds/ladx/LADXR/patches/droppedKey.py
Normal file
@@ -0,0 +1,134 @@
|
||||
from ..assembler import ASM
|
||||
|
||||
|
||||
def fixDroppedKey(rom):
|
||||
# Patch the rendering code to use the dropped key rendering code.
|
||||
rom.patch(0x03, 0x1C99, None, ASM("""
|
||||
ld a, $04
|
||||
rst 8
|
||||
jp $5CA6
|
||||
"""))
|
||||
|
||||
# Patch the key pickup code to use the chest pickup code.
|
||||
rom.patch(0x03, 0x248F, None, ASM("""
|
||||
ldh a, [$F6] ; load room nr
|
||||
cp $7C ; L4 Side-view room where the key drops
|
||||
jr nz, notSpecialSideView
|
||||
|
||||
ld hl, $D969 ; status of the room above the side-view where the key drops in dungeon 4
|
||||
set 4, [hl]
|
||||
notSpecialSideView:
|
||||
call $512A ; mark room as done
|
||||
|
||||
; Handle item effect
|
||||
ld a, $06 ; giveItemMultiworld
|
||||
rst 8
|
||||
|
||||
ldh a, [$F1] ; Load active sprite variant to see if this is just a normal small key
|
||||
cp $1A
|
||||
jr z, isAKey
|
||||
|
||||
;Show message (if not a key)
|
||||
ld a, $0A ; showMessageMultiworld
|
||||
rst 8
|
||||
isAKey:
|
||||
ret
|
||||
"""))
|
||||
rom.patch(0x03, 0x24B7, "3E", "3E") # sanity check
|
||||
|
||||
# Mark all dropped keys as keys by default.
|
||||
for n in range(0x316):
|
||||
rom.banks[0x3E][0x3800 + n] = 0x1A
|
||||
# Set the proper angler key by default
|
||||
rom.banks[0x3E][0x3800 + 0x0CE] = 0x12
|
||||
rom.banks[0x3E][0x3800 + 0x1F8] = 0x12
|
||||
# Set the proper bird key by default
|
||||
rom.banks[0x3E][0x3800 + 0x27A] = 0x14
|
||||
# Set the proper face key by default
|
||||
rom.banks[0x3E][0x3800 + 0x27F] = 0x13
|
||||
|
||||
# Set the proper hookshot key by default
|
||||
rom.banks[0x3E][0x3800 + 0x180] = 0x03
|
||||
|
||||
# Set the proper golden leaves
|
||||
rom.banks[0x3E][0x3800 + 0x058] = 0x15
|
||||
rom.banks[0x3E][0x3800 + 0x05a] = 0x15
|
||||
rom.banks[0x3E][0x3800 + 0x2d2] = 0x15
|
||||
rom.banks[0x3E][0x3800 + 0x2c5] = 0x15
|
||||
rom.banks[0x3E][0x3800 + 0x2c6] = 0x15
|
||||
|
||||
# Set the slime key drop.
|
||||
rom.banks[0x3E][0x3800 + 0x0C6] = 0x0F
|
||||
|
||||
# Set the heart pieces
|
||||
rom.banks[0x3E][0x3800 + 0x000] = 0x80
|
||||
rom.banks[0x3E][0x3800 + 0x2A4] = 0x80
|
||||
rom.banks[0x3E][0x3800 + 0x2B1] = 0x80 # fishing game, unused
|
||||
rom.banks[0x3E][0x3800 + 0x044] = 0x80
|
||||
rom.banks[0x3E][0x3800 + 0x2AB] = 0x80
|
||||
rom.banks[0x3E][0x3800 + 0x2DF] = 0x80
|
||||
rom.banks[0x3E][0x3800 + 0x2E5] = 0x80
|
||||
rom.banks[0x3E][0x3800 + 0x078] = 0x80
|
||||
rom.banks[0x3E][0x3800 + 0x2E6] = 0x80
|
||||
rom.banks[0x3E][0x3800 + 0x1E8] = 0x80
|
||||
rom.banks[0x3E][0x3800 + 0x1F2] = 0x80
|
||||
rom.banks[0x3E][0x3800 + 0x2BA] = 0x80
|
||||
|
||||
# Set the seashells
|
||||
rom.banks[0x3E][0x3800 + 0x0A3] = 0x20
|
||||
rom.banks[0x3E][0x3800 + 0x2B2] = 0x20
|
||||
rom.banks[0x3E][0x3800 + 0x0A5] = 0x20
|
||||
rom.banks[0x3E][0x3800 + 0x0A6] = 0x20
|
||||
rom.banks[0x3E][0x3800 + 0x08B] = 0x20
|
||||
rom.banks[0x3E][0x3800 + 0x074] = 0x20
|
||||
rom.banks[0x3E][0x3800 + 0x0A4] = 0x20
|
||||
rom.banks[0x3E][0x3800 + 0x0D2] = 0x20
|
||||
rom.banks[0x3E][0x3800 + 0x0E9] = 0x20
|
||||
rom.banks[0x3E][0x3800 + 0x0B9] = 0x20
|
||||
rom.banks[0x3E][0x3800 + 0x0F8] = 0x20
|
||||
rom.banks[0x3E][0x3800 + 0x0A8] = 0x20
|
||||
rom.banks[0x3E][0x3800 + 0x0FF] = 0x20
|
||||
rom.banks[0x3E][0x3800 + 0x1E3] = 0x20
|
||||
rom.banks[0x3E][0x3800 + 0x0DA] = 0x20
|
||||
rom.banks[0x3E][0x3800 + 0x00C] = 0x20
|
||||
|
||||
# Set heart containers
|
||||
rom.banks[0x3E][0x3800 + 0x106] = 0x89
|
||||
rom.banks[0x3E][0x3800 + 0x12B] = 0x89
|
||||
rom.banks[0x3E][0x3800 + 0x15A] = 0x89
|
||||
rom.banks[0x3E][0x3800 + 0x1FF] = 0x89
|
||||
rom.banks[0x3E][0x3800 + 0x185] = 0x89
|
||||
rom.banks[0x3E][0x3800 + 0x1BC] = 0x89
|
||||
rom.banks[0x3E][0x3800 + 0x2E8] = 0x89
|
||||
rom.banks[0x3E][0x3800 + 0x234] = 0x89
|
||||
|
||||
# Toadstool
|
||||
rom.banks[0x3E][0x3800 + 0x050] = 0x50
|
||||
# Sword on beach
|
||||
rom.banks[0x3E][0x3800 + 0x0F2] = 0x0B
|
||||
# Sword upgrade
|
||||
rom.banks[0x3E][0x3800 + 0x2E9] = 0x0B
|
||||
|
||||
# Songs
|
||||
rom.banks[0x3E][0x3800 + 0x092] = 0x8B # song 1
|
||||
rom.banks[0x3E][0x3800 + 0x0DC] = 0x8B # song 1
|
||||
rom.banks[0x3E][0x3800 + 0x2FD] = 0x8C # song 2
|
||||
rom.banks[0x3E][0x3800 + 0x2FB] = 0x8D # song 3
|
||||
|
||||
# Instruments
|
||||
rom.banks[0x3E][0x3800 + 0x102] = 0x8E
|
||||
rom.banks[0x3E][0x3800 + 0x12a] = 0x8F
|
||||
rom.banks[0x3E][0x3800 + 0x159] = 0x90
|
||||
rom.banks[0x3E][0x3800 + 0x162] = 0x91
|
||||
rom.banks[0x3E][0x3800 + 0x182] = 0x92
|
||||
rom.banks[0x3E][0x3800 + 0x1b5] = 0x93
|
||||
rom.banks[0x3E][0x3800 + 0x22c] = 0x94
|
||||
rom.banks[0x3E][0x3800 + 0x230] = 0x95
|
||||
|
||||
# Start item
|
||||
rom.banks[0x3E][0x3800 + 0x2a3] = 0x01
|
||||
|
||||
# Master stalfos overkill drops
|
||||
rom.banks[0x3E][0x3800 + 0x195] = 0x1A
|
||||
rom.banks[0x3E][0x3800 + 0x192] = 0x1A
|
||||
rom.banks[0x3E][0x3800 + 0x184] = 0x1A
|
||||
129
worlds/ladx/LADXR/patches/dungeon.py
Normal file
129
worlds/ladx/LADXR/patches/dungeon.py
Normal file
@@ -0,0 +1,129 @@
|
||||
from ..roomEditor import RoomEditor, Object, ObjectHorizontal
|
||||
|
||||
|
||||
KEY_DOORS = {
|
||||
0xEC: 0xF4,
|
||||
0xED: 0xF5,
|
||||
0xEE: 0xF6,
|
||||
0xEF: 0xF7,
|
||||
0xF8: 0xF4,
|
||||
}
|
||||
|
||||
def removeKeyDoors(rom):
|
||||
for n in range(0x100, 0x316):
|
||||
if n == 0x2FF:
|
||||
continue
|
||||
update = False
|
||||
re = RoomEditor(rom, n)
|
||||
for obj in re.objects:
|
||||
if obj.type_id in KEY_DOORS:
|
||||
obj.type_id = KEY_DOORS[obj.type_id]
|
||||
update = True
|
||||
if obj.type_id == 0xDE: # Keyblocks
|
||||
obj.type_id = re.floor_object & 0x0F
|
||||
update = True
|
||||
if update:
|
||||
re.store(rom)
|
||||
|
||||
|
||||
def patchNoDungeons(rom):
|
||||
def setMinimap(dungeon_nr, x, y, room):
|
||||
for n in range(64):
|
||||
if rom.banks[0x14][0x0220 + 64 * dungeon_nr + n] == room:
|
||||
rom.banks[0x14][0x0220 + 64 * dungeon_nr + n] = 0xFF
|
||||
rom.banks[0x14][0x0220 + 64 * dungeon_nr + x + y * 8] = room
|
||||
#D1
|
||||
setMinimap(0, 3, 6, 0x06)
|
||||
setMinimap(0, 3, 5, 0x02)
|
||||
re = RoomEditor(rom, 0x117)
|
||||
for n in range(1, 7):
|
||||
re.removeObject(n, 0)
|
||||
re.removeObject(0, n)
|
||||
re.removeObject(9, n)
|
||||
re.objects += [Object(4, 0, 0xf0)]
|
||||
re.store(rom)
|
||||
re = RoomEditor(rom, 0x11A)
|
||||
re.getWarps()[0].room = 0x117
|
||||
re.store(rom)
|
||||
re = RoomEditor(rom, 0x11B)
|
||||
re.getWarps()[0].room = 0x117
|
||||
re.store(rom)
|
||||
|
||||
#D2
|
||||
setMinimap(1, 2, 6, 0x2B)
|
||||
setMinimap(1, 1, 6, 0x2A)
|
||||
re = RoomEditor(rom, 0x136)
|
||||
for n in range(1, 7):
|
||||
re.removeObject(n, 0)
|
||||
re.objects += [Object(4, 0, 0xf0)]
|
||||
re.store(rom)
|
||||
|
||||
#D3
|
||||
setMinimap(2, 1, 6, 0x5A)
|
||||
setMinimap(2, 1, 5, 0x59)
|
||||
re = RoomEditor(rom, 0x152)
|
||||
for n in range(2, 7):
|
||||
re.removeObject(9, n)
|
||||
re.store(rom)
|
||||
|
||||
#D4
|
||||
setMinimap(3, 3, 6, 0x66)
|
||||
setMinimap(3, 3, 5, 0x62)
|
||||
re = RoomEditor(rom, 0x17A)
|
||||
for n in range(3, 7):
|
||||
re.removeObject(n, 0)
|
||||
re.objects += [Object(4, 0, 0xf0)]
|
||||
re.store(rom)
|
||||
|
||||
#D5
|
||||
setMinimap(4, 7, 6, 0x85)
|
||||
setMinimap(4, 7, 5, 0x82)
|
||||
re = RoomEditor(rom, 0x1A1)
|
||||
for n in range(3, 8):
|
||||
re.removeObject(n, 0)
|
||||
re.removeObject(0, n)
|
||||
for n in range(4, 6):
|
||||
re.removeObject(n, 1)
|
||||
re.removeObject(n, 2)
|
||||
re.objects += [Object(4, 0, 0xf0)]
|
||||
re.store(rom)
|
||||
|
||||
#D6
|
||||
setMinimap(5, 3, 6, 0xBC)
|
||||
setMinimap(5, 3, 5, 0xB5)
|
||||
re = RoomEditor(rom, 0x1D4)
|
||||
for n in range(2, 8):
|
||||
re.removeObject(0, n)
|
||||
re.removeObject(9, n)
|
||||
re.objects += [Object(4, 0, 0xf0)]
|
||||
re.store(rom)
|
||||
|
||||
#D7
|
||||
setMinimap(6, 1, 6, 0x2E)
|
||||
setMinimap(6, 1, 5, 0x2C)
|
||||
re = RoomEditor(rom, 0x20E)
|
||||
for n in range(1, 8):
|
||||
re.removeObject(0, n)
|
||||
re.removeObject(9, n)
|
||||
re.objects += [Object(3, 0, 0x29), ObjectHorizontal(4, 0, 0x0D, 2), Object(6, 0, 0x2A)]
|
||||
re.store(rom)
|
||||
re = RoomEditor(rom, 0x22E)
|
||||
re.objects = [Object(4, 0, 0xf0), Object(3, 7, 0x2B), ObjectHorizontal(4, 7, 0x0D, 2), Object(6, 7, 0x2C), Object(1, 0, 0xA8)] + re.getWarps()
|
||||
re.floor_object = 13
|
||||
re.store(rom)
|
||||
re = RoomEditor(rom, 0x22C)
|
||||
re.removeObject(0, 7)
|
||||
re.removeObject(2, 7)
|
||||
re.objects.append(ObjectHorizontal(0, 7, 0x03, 3))
|
||||
re.store(rom)
|
||||
|
||||
#D8
|
||||
setMinimap(7, 3, 6, 0x34)
|
||||
setMinimap(7, 3, 5, 0x30)
|
||||
re = RoomEditor(rom, 0x25D)
|
||||
re.objects += [Object(3, 0, 0x25), Object(4, 0, 0xf0), Object(6, 0, 0x26)]
|
||||
re.store(rom)
|
||||
|
||||
#D0
|
||||
setMinimap(11, 2, 6, 0x00)
|
||||
setMinimap(11, 3, 6, 0x01)
|
||||
139
worlds/ladx/LADXR/patches/endscreen.py
Normal file
139
worlds/ladx/LADXR/patches/endscreen.py
Normal file
@@ -0,0 +1,139 @@
|
||||
from ..assembler import ASM
|
||||
import os
|
||||
|
||||
|
||||
def updateEndScreen(rom):
|
||||
# Call our custom data loader in bank 3F
|
||||
rom.patch(0x00, 0x391D, ASM("""
|
||||
ld a, $20
|
||||
ld [$2100], a
|
||||
jp $7de6
|
||||
"""), ASM("""
|
||||
ld a, $3F
|
||||
ld [$2100], a
|
||||
jp $4200
|
||||
"""))
|
||||
rom.patch(0x17, 0x2FCE, "B170", "D070") # Ignore the final tile data load
|
||||
|
||||
rom.patch(0x3F, 0x0200, None, ASM("""
|
||||
; Disable LCD
|
||||
xor a
|
||||
ldh [$40], a
|
||||
|
||||
ld hl, $8000
|
||||
ld de, $5000
|
||||
copyLoop:
|
||||
ld a, [de]
|
||||
inc de
|
||||
ldi [hl], a
|
||||
bit 4, h
|
||||
jr z, copyLoop
|
||||
|
||||
ld a, $01
|
||||
ldh [$4F], a
|
||||
|
||||
ld hl, $8000
|
||||
ld de, $6000
|
||||
copyLoop2:
|
||||
ld a, [de]
|
||||
inc de
|
||||
ldi [hl], a
|
||||
bit 4, h
|
||||
jr z, copyLoop2
|
||||
|
||||
ld hl, $9800
|
||||
ld de, $0190
|
||||
clearLoop1:
|
||||
xor a
|
||||
ldi [hl], a
|
||||
dec de
|
||||
ld a, d
|
||||
or e
|
||||
jr nz, clearLoop1
|
||||
|
||||
ld de, $0190
|
||||
clearLoop2:
|
||||
ld a, $08
|
||||
ldi [hl], a
|
||||
dec de
|
||||
ld a, d
|
||||
or e
|
||||
jr nz, clearLoop2
|
||||
|
||||
xor a
|
||||
ldh [$4F], a
|
||||
|
||||
|
||||
ld hl, $9800
|
||||
ld de, $000C
|
||||
xor a
|
||||
loadLoop1:
|
||||
ldi [hl], a
|
||||
ld b, a
|
||||
ld a, l
|
||||
and $1F
|
||||
cp $14
|
||||
jr c, .noLineSkip
|
||||
add hl, de
|
||||
.noLineSkip:
|
||||
ld a, b
|
||||
inc a
|
||||
jr nz, loadLoop1
|
||||
|
||||
loadLoop2:
|
||||
ldi [hl], a
|
||||
ld b, a
|
||||
ld a, l
|
||||
and $1F
|
||||
cp $14
|
||||
jr c, .noLineSkip
|
||||
add hl, de
|
||||
.noLineSkip:
|
||||
ld a, b
|
||||
inc a
|
||||
jr nz, loadLoop2
|
||||
|
||||
; Load palette
|
||||
ld hl, $DC10
|
||||
ld a, $00
|
||||
ldi [hl], a
|
||||
ld a, $00
|
||||
ldi [hl], a
|
||||
|
||||
ld a, $ad
|
||||
ldi [hl], a
|
||||
ld a, $35
|
||||
ldi [hl], a
|
||||
|
||||
ld a, $94
|
||||
ldi [hl], a
|
||||
ld a, $52
|
||||
ldi [hl], a
|
||||
|
||||
ld a, $FF
|
||||
ldi [hl], a
|
||||
ld a, $7F
|
||||
ldi [hl], a
|
||||
|
||||
ld a, $00
|
||||
ld [$DDD3], a
|
||||
ld a, $04
|
||||
ld [$DDD4], a
|
||||
ld a, $81
|
||||
ld [$DDD1], a
|
||||
|
||||
; Enable LCD
|
||||
ld a, $91
|
||||
ldh [$40], a
|
||||
ld [$d6fd], a
|
||||
|
||||
xor a
|
||||
ldh [$96], a
|
||||
ldh [$97], a
|
||||
ret
|
||||
"""))
|
||||
|
||||
addr = 0x1000
|
||||
for c in open(os.path.join(os.path.dirname(__file__), "nyan.bin"), "rb").read():
|
||||
rom.banks[0x3F][addr] = c
|
||||
addr += 1
|
||||
462
worlds/ladx/LADXR/patches/enemies.py
Normal file
462
worlds/ladx/LADXR/patches/enemies.py
Normal file
@@ -0,0 +1,462 @@
|
||||
from ..roomEditor import RoomEditor, Object, ObjectWarp, ObjectHorizontal
|
||||
from ..assembler import ASM
|
||||
from ..locations import constants
|
||||
from typing import List
|
||||
|
||||
|
||||
# Room containing the boss
|
||||
BOSS_ROOMS = [
|
||||
0x106,
|
||||
0x12b,
|
||||
0x15a,
|
||||
0x166,
|
||||
0x185,
|
||||
0x1bc,
|
||||
0x223, # Note: unused room normally
|
||||
0x234,
|
||||
0x300,
|
||||
]
|
||||
BOSS_ENTITIES = [
|
||||
(3, 2, 0x59),
|
||||
(4, 2, 0x5C),
|
||||
(4, 3, 0x5B),
|
||||
None,
|
||||
(4, 3, 0x5D),
|
||||
(4, 3, 0x5A),
|
||||
None,
|
||||
(4, 3, 0x62),
|
||||
(5, 2, 0xF9),
|
||||
]
|
||||
MINIBOSS_ENTITIES = {
|
||||
"ROLLING_BONES": [(8, 3, 0x81), (6, 3, 0x82)],
|
||||
"HINOX": [(5, 2, 0x89)],
|
||||
"DODONGO": [(3, 2, 0x60), (5, 2, 0x60)],
|
||||
"CUE_BALL": [(1, 1, 0x8e)],
|
||||
"GHOMA": [(2, 1, 0x5e), (2, 4, 0x5e)],
|
||||
"SMASHER": [(5, 2, 0x92)],
|
||||
"GRIM_CREEPER": [(4, 0, 0xbc)],
|
||||
"BLAINO": [(5, 3, 0xbe)],
|
||||
"AVALAUNCH": [(5, 1, 0xf4)],
|
||||
"GIANT_BUZZ_BLOB": [(4, 2, 0xf8)],
|
||||
"MOBLIN_KING": [(5, 5, 0xe4)],
|
||||
"ARMOS_KNIGHT": [(4, 3, 0x88)],
|
||||
}
|
||||
MINIBOSS_ROOMS = {
|
||||
0: 0x111, 1: 0x128, 2: 0x145, 3: 0x164, 4: 0x193, 5: 0x1C5, 6: 0x228, 7: 0x23F,
|
||||
"c1": 0x30C, "c2": 0x303,
|
||||
"moblin_cave": 0x2E1,
|
||||
"armos_temple": 0x27F,
|
||||
}
|
||||
|
||||
|
||||
def fixArmosKnightAsMiniboss(rom):
|
||||
# Make the armos temple room with armos knight drop a ceiling key on kill.
|
||||
# This makes the door always open, but that's fine.
|
||||
rom.patch(0x14, 0x017F, "21", "81")
|
||||
|
||||
# Do not change the drop from Armos knight into a ceiling key.
|
||||
rom.patch(0x06, 0x12E8, ASM("ld [hl], $30"), "", fill_nop=True)
|
||||
|
||||
|
||||
def getBossRoomStatusFlagLocation(dungeon_nr):
|
||||
if BOSS_ROOMS[dungeon_nr] >= 0x300:
|
||||
return 0xDDE0 - 0x300 + BOSS_ROOMS[dungeon_nr]
|
||||
return 0xD800 + BOSS_ROOMS[dungeon_nr]
|
||||
|
||||
|
||||
def fixDungeonItem(item_chest_id, dungeon_nr):
|
||||
if item_chest_id == constants.CHEST_ITEMS[constants.MAP]:
|
||||
return constants.CHEST_ITEMS["MAP%d" % (dungeon_nr + 1)]
|
||||
if item_chest_id == constants.CHEST_ITEMS[constants.COMPASS]:
|
||||
return constants.CHEST_ITEMS["COMPASS%d" % (dungeon_nr + 1)]
|
||||
if item_chest_id == constants.CHEST_ITEMS[constants.KEY]:
|
||||
return constants.CHEST_ITEMS["KEY%d" % (dungeon_nr + 1)]
|
||||
if item_chest_id == constants.CHEST_ITEMS[constants.NIGHTMARE_KEY]:
|
||||
return constants.CHEST_ITEMS["NIGHTMARE_KEY%d" % (dungeon_nr + 1)]
|
||||
if item_chest_id == constants.CHEST_ITEMS[constants.STONE_BEAK]:
|
||||
return constants.CHEST_ITEMS["STONE_BEAK%d" % (dungeon_nr + 1)]
|
||||
return item_chest_id
|
||||
|
||||
|
||||
def getCleanBossRoom(rom, dungeon_nr):
|
||||
re = RoomEditor(rom, BOSS_ROOMS[dungeon_nr])
|
||||
new_objects = []
|
||||
for obj in re.objects:
|
||||
if isinstance(obj, ObjectWarp):
|
||||
continue
|
||||
if obj.type_id == 0xBE: # Remove staircases
|
||||
continue
|
||||
if obj.type_id == 0x06: # Remove lava
|
||||
continue
|
||||
if obj.type_id == 0x1c: # Change D1 pits into normal pits
|
||||
obj.type_id = 0x01
|
||||
if obj.type_id == 0x1e: # Change D1 pits into normal pits
|
||||
obj.type_id = 0xaf
|
||||
if obj.type_id == 0x1f: # Change D1 pits into normal pits
|
||||
obj.type_id = 0xb0
|
||||
if obj.type_id == 0xF5: # Change open doors into closing doors.
|
||||
obj.type_id = 0xF1
|
||||
new_objects.append(obj)
|
||||
|
||||
|
||||
# Make D4 room a valid fighting room by removing most content.
|
||||
if dungeon_nr == 3:
|
||||
new_objects = new_objects[:2] + [Object(1, 1, 0xAC), Object(8, 1, 0xAC), Object(1, 6, 0xAC), Object(8, 6, 0xAC)]
|
||||
|
||||
# D7 has an empty room we use for most bosses, but it needs some adjustments.
|
||||
if dungeon_nr == 6:
|
||||
# Move around the unused and instrument room.
|
||||
rom.banks[0x14][0x03a0 + 6 + 1 * 8] = 0x00
|
||||
rom.banks[0x14][0x03a0 + 7 + 2 * 8] = 0x2C
|
||||
rom.banks[0x14][0x03a0 + 7 + 3 * 8] = 0x23
|
||||
rom.banks[0x14][0x03a0 + 6 + 5 * 8] = 0x00
|
||||
|
||||
rom.banks[0x14][0x0520 + 7 + 2 * 8] = 0x2C
|
||||
rom.banks[0x14][0x0520 + 7 + 3 * 8] = 0x23
|
||||
rom.banks[0x14][0x0520 + 6 + 5 * 8] = 0x00
|
||||
|
||||
re.floor_object &= 0x0F
|
||||
new_objects += [
|
||||
Object(4, 0, 0xF0),
|
||||
Object(1, 6, 0xBE),
|
||||
ObjectWarp(1, dungeon_nr, 0x22E, 24, 16)
|
||||
]
|
||||
|
||||
# Set the stairs towards the eagle tower top to our new room.
|
||||
r = RoomEditor(rom, 0x22E)
|
||||
r.objects[-1] = ObjectWarp(1, dungeon_nr, re.room, 24, 112)
|
||||
r.store(rom)
|
||||
|
||||
# Remove the normal door to the instrument room
|
||||
r = RoomEditor(rom, 0x22e)
|
||||
r.removeObject(4, 0)
|
||||
r.store(rom)
|
||||
rom.banks[0x14][0x22e - 0x100] = 0x00
|
||||
|
||||
r = RoomEditor(rom, 0x22c)
|
||||
r.changeObject(0, 7, 0x03)
|
||||
r.changeObject(2, 7, 0x03)
|
||||
r.store(rom)
|
||||
|
||||
re.objects = new_objects
|
||||
re.entities = []
|
||||
return re
|
||||
|
||||
|
||||
def changeBosses(rom, mapping: List[int]):
|
||||
# Fix the color dungeon not properly warping to room 0 with the boss.
|
||||
for addr in range(0x04E0, 0x04E0 + 64):
|
||||
if rom.banks[0x14][addr] == 0x00 and addr not in {0x04E0 + 1 + 3 * 8, 0x04E0 + 2 + 6 * 8}:
|
||||
rom.banks[0x14][addr] = 0xFF
|
||||
# Fix the genie death not really liking pits/water.
|
||||
rom.patch(0x04, 0x0521, ASM("ld [hl], $81"), ASM("ld [hl], $91"))
|
||||
|
||||
# For the sidescroll bosses, we need to update this check to be the evil eagle dungeon.
|
||||
# But if evil eagle is not there we still need to remove this check to make angler fish work in D7
|
||||
dungeon_nr = mapping.index(6) if 6 in mapping else 0xFE
|
||||
rom.patch(0x02, 0x1FC8, ASM("cp $06"), ASM("cp $%02x" % (dungeon_nr if dungeon_nr < 8 else 0xff)))
|
||||
|
||||
for dungeon_nr in range(9):
|
||||
target = mapping[dungeon_nr]
|
||||
if target == dungeon_nr:
|
||||
continue
|
||||
|
||||
if target == 3: # D4 fish boss
|
||||
# If dungeon_nr == 6: use normal eagle door towards fish.
|
||||
if dungeon_nr == 6:
|
||||
# Add the staircase to the boss, and fix the warp back.
|
||||
re = RoomEditor(rom, 0x22E)
|
||||
for obj in re.objects:
|
||||
if isinstance(obj, ObjectWarp):
|
||||
obj.type_id = 2
|
||||
obj.map_nr = 3
|
||||
obj.room = 0x1EF
|
||||
obj.target_x = 24
|
||||
obj.target_y = 16
|
||||
re.store(rom)
|
||||
re = RoomEditor(rom, 0x1EF)
|
||||
re.objects[-1] = ObjectWarp(1, dungeon_nr if dungeon_nr < 8 else 0xff, 0x22E, 24, 16)
|
||||
re.store(rom)
|
||||
else:
|
||||
# Set the proper room event flags
|
||||
rom.banks[0x14][BOSS_ROOMS[dungeon_nr] - 0x100] = 0x2A
|
||||
|
||||
# Add the staircase to the boss, and fix the warp back.
|
||||
re = getCleanBossRoom(rom, dungeon_nr)
|
||||
re.objects += [Object(4, 4, 0xBE), ObjectWarp(2, 3, 0x1EF, 24, 16)]
|
||||
re.store(rom)
|
||||
re = RoomEditor(rom, 0x1EF)
|
||||
re.objects[-1] = ObjectWarp(1, dungeon_nr if dungeon_nr < 8 else 0xff, BOSS_ROOMS[dungeon_nr], 72, 80)
|
||||
re.store(rom)
|
||||
|
||||
# Patch the fish heart container to open up the right room.
|
||||
if dungeon_nr == 6:
|
||||
rom.patch(0x03, 0x1A0F, ASM("ld hl, $D966"), ASM("ld hl, $%04x" % (0xD800 + 0x22E)))
|
||||
else:
|
||||
rom.patch(0x03, 0x1A0F, ASM("ld hl, $D966"), ASM("ld hl, $%04x" % (getBossRoomStatusFlagLocation(dungeon_nr))))
|
||||
|
||||
# Patch the proper item towards the D4 boss
|
||||
rom.banks[0x3E][0x3800 + 0x01ff] = fixDungeonItem(rom.banks[0x3E][0x3800 + BOSS_ROOMS[dungeon_nr]], dungeon_nr)
|
||||
rom.banks[0x3E][0x3300 + 0x01ff] = fixDungeonItem(rom.banks[0x3E][0x3300 + BOSS_ROOMS[dungeon_nr]], dungeon_nr)
|
||||
elif target == 6: # Evil eagle
|
||||
rom.banks[0x14][BOSS_ROOMS[dungeon_nr] - 0x100] = 0x2A
|
||||
|
||||
# Patch the eagle heart container to open up the right room.
|
||||
rom.patch(0x03, 0x1A04, ASM("ld hl, $DA2E"), ASM("ld hl, $%04x" % (getBossRoomStatusFlagLocation(dungeon_nr))))
|
||||
|
||||
# Add the staircase to the boss, and fix the warp back.
|
||||
re = getCleanBossRoom(rom, dungeon_nr)
|
||||
re.objects += [Object(4, 4, 0xBE), ObjectWarp(2, 6, 0x2F8, 72, 80)]
|
||||
re.store(rom)
|
||||
re = RoomEditor(rom, 0x2F8)
|
||||
re.objects[-1] = ObjectWarp(1, dungeon_nr if dungeon_nr < 8 else 0xff, BOSS_ROOMS[dungeon_nr], 72, 80)
|
||||
re.store(rom)
|
||||
|
||||
# Patch the proper item towards the D7 boss
|
||||
rom.banks[0x3E][0x3800 + 0x02E8] = fixDungeonItem(rom.banks[0x3E][0x3800 + BOSS_ROOMS[dungeon_nr]], dungeon_nr)
|
||||
rom.banks[0x3E][0x3300 + 0x02E8] = fixDungeonItem(rom.banks[0x3E][0x3300 + BOSS_ROOMS[dungeon_nr]], dungeon_nr)
|
||||
else:
|
||||
rom.banks[0x14][BOSS_ROOMS[dungeon_nr] - 0x100] = 0x21
|
||||
re = getCleanBossRoom(rom, dungeon_nr)
|
||||
re.entities = [BOSS_ENTITIES[target]]
|
||||
|
||||
if target == 4:
|
||||
# For slime eel, we need to setup the right wall tiles.
|
||||
rom.banks[0x20][0x2EB3 + BOSS_ROOMS[dungeon_nr] - 0x100] = 0x06
|
||||
if target == 5:
|
||||
# Patch facade so he doesn't use the spinning tiles, which is a problem for the sprites.
|
||||
rom.patch(0x04, 0x121D, ASM("cp $14"), ASM("cp $00"))
|
||||
rom.patch(0x04, 0x1226, ASM("cp $04"), ASM("cp $00"))
|
||||
rom.patch(0x04, 0x127F, ASM("cp $14"), ASM("cp $00"))
|
||||
if target == 7:
|
||||
pass
|
||||
# For hot head, add some lava (causes graphical glitches)
|
||||
# re.animation_id = 0x06
|
||||
# re.objects += [
|
||||
# ObjectHorizontal(3, 2, 0x06, 4),
|
||||
# ObjectHorizontal(2, 3, 0x06, 6),
|
||||
# ObjectHorizontal(2, 4, 0x06, 6),
|
||||
# ObjectHorizontal(3, 5, 0x06, 4),
|
||||
# ]
|
||||
|
||||
re.store(rom)
|
||||
|
||||
|
||||
def readBossMapping(rom):
|
||||
mapping = []
|
||||
for dungeon_nr in range(9):
|
||||
r = RoomEditor(rom, BOSS_ROOMS[dungeon_nr])
|
||||
if r.entities:
|
||||
mapping.append(BOSS_ENTITIES.index(r.entities[0]))
|
||||
elif isinstance(r.objects[-1], ObjectWarp) and r.objects[-1].room == 0x1ef:
|
||||
mapping.append(3)
|
||||
elif isinstance(r.objects[-1], ObjectWarp) and r.objects[-1].room == 0x2f8:
|
||||
mapping.append(6)
|
||||
else:
|
||||
mapping.append(dungeon_nr)
|
||||
return mapping
|
||||
|
||||
|
||||
def changeMiniBosses(rom, mapping):
|
||||
# Fix avalaunch not working when entering a room from the left or right
|
||||
rom.patch(0x03, 0x0BE0, ASM("""
|
||||
ld [hl], $50
|
||||
ld hl, $C2D0
|
||||
add hl, bc
|
||||
ld [hl], $00
|
||||
jp $4B56
|
||||
"""), ASM("""
|
||||
ld a, [hl]
|
||||
sub $08
|
||||
ld [hl], a
|
||||
ld hl, $C2D0
|
||||
add hl, bc
|
||||
ld [hl], b ; b is always zero here
|
||||
ret
|
||||
"""), fill_nop=True)
|
||||
# Fix avalaunch waiting until the room event is done (and not all rooms have a room event on enter)
|
||||
rom.patch(0x36, 0x1C14, ASM("ret z"), "", fill_nop=True)
|
||||
# Fix giant buzz blob waiting until the room event is done (and not all rooms have a room event on enter)
|
||||
rom.patch(0x36, 0x153B, ASM("ret z"), "", fill_nop=True)
|
||||
|
||||
# Remove the powder fairy from giant buzz blob
|
||||
rom.patch(0x36, 0x14F7, ASM("jr nz, $05"), ASM("jr $05"))
|
||||
|
||||
# Do not allow the force barrier in D3 dodongo room
|
||||
rom.patch(0x14, 0x14AC, 0x14B5, ASM("jp $7FE0"), fill_nop=True)
|
||||
rom.patch(0x14, 0x3FE0, "00" * 0x20, ASM("""
|
||||
ld a, [$C124] ; room transition
|
||||
ld hl, $C17B
|
||||
or [hl]
|
||||
ret nz
|
||||
ldh a, [$F6] ; room
|
||||
cp $45 ; check for D3 dodogo room
|
||||
ret z
|
||||
cp $7F ; check for armos temple room
|
||||
ret z
|
||||
jp $54B5
|
||||
"""), fill_nop=True)
|
||||
|
||||
# Patch smasher to spawn the ball closer, so it doesn't spawn on the wall in the armos temple
|
||||
rom.patch(0x06, 0x0533, ASM("add a, $30"), ASM("add a, $20"))
|
||||
|
||||
for target, name in mapping.items():
|
||||
re = RoomEditor(rom, MINIBOSS_ROOMS[target])
|
||||
re.entities = [e for e in re.entities if e[2] == 0x61] # Only keep warp, if available
|
||||
re.entities += MINIBOSS_ENTITIES[name]
|
||||
|
||||
if re.room == 0x228 and name != "GRIM_CREEPER":
|
||||
for x in range(3, 7):
|
||||
for y in range(0, 3):
|
||||
re.removeObject(x, y)
|
||||
|
||||
if name == "CUE_BALL":
|
||||
re.objects += [
|
||||
Object(3, 3, 0x2c),
|
||||
ObjectHorizontal(4, 3, 0x22, 2),
|
||||
Object(6, 3, 0x2b),
|
||||
Object(3, 4, 0x2a),
|
||||
ObjectHorizontal(4, 4, 0x21, 2),
|
||||
Object(6, 4, 0x29),
|
||||
]
|
||||
if name == "BLAINO":
|
||||
# BLAINO needs a warp object to hit you to the entrance of the dungeon.
|
||||
if len(re.getWarps()) < 1:
|
||||
# Default to start house.
|
||||
target = (0x10, 0x2A3, 0x50, 0x7c)
|
||||
if 0x100 <= re.room < 0x11D: #D1
|
||||
target = (0, 0x117, 80, 80)
|
||||
elif 0x11D <= re.room < 0x140: #D2
|
||||
target = (1, 0x136, 80, 80)
|
||||
elif 0x140 <= re.room < 0x15D: #D3
|
||||
target = (2, 0x152, 80, 80)
|
||||
elif 0x15D <= re.room < 0x180: #D4
|
||||
target = (3, 0x174, 80, 80)
|
||||
elif 0x180 <= re.room < 0x1AC: #D5
|
||||
target = (4, 0x1A1, 80, 80)
|
||||
elif 0x1B0 <= re.room < 0x1DE: #D6
|
||||
target = (5, 0x1D4, 80, 80)
|
||||
elif 0x200 <= re.room < 0x22D: #D7
|
||||
target = (6, 0x20E, 80, 80)
|
||||
elif 0x22D <= re.room < 0x26C: #D8
|
||||
target = (7, 0x25D, 80, 80)
|
||||
elif re.room >= 0x300: #D0
|
||||
target = (0xFF, 0x312, 80, 80)
|
||||
elif re.room == 0x2E1: #Moblin cave
|
||||
target = (0x15, 0x2F0, 0x50, 0x7C)
|
||||
elif re.room == 0x27F: #Armos temple
|
||||
target = (0x16, 0x28F, 0x50, 0x7C)
|
||||
re.objects.append(ObjectWarp(1, *target))
|
||||
if name == "DODONGO":
|
||||
# Remove breaking floor tiles from the room.
|
||||
re.objects = [obj for obj in re.objects if obj.type_id != 0xDF]
|
||||
if name == "ROLLING_BONES" and target == 2:
|
||||
# Make rolling bones pass trough walls so it does not get stuck here.
|
||||
rom.patch(0x03, 0x02F1 + 0x81, "84", "95")
|
||||
re.store(rom)
|
||||
|
||||
|
||||
def readMiniBossMapping(rom):
|
||||
mapping = {}
|
||||
for key, room in MINIBOSS_ROOMS.items():
|
||||
r = RoomEditor(rom, room)
|
||||
for me_key, me_data in MINIBOSS_ENTITIES.items():
|
||||
if me_data[-1][2] == r.entities[-1][2]:
|
||||
mapping[key] = me_key
|
||||
return mapping
|
||||
|
||||
|
||||
def doubleTrouble(rom):
|
||||
for n in range(0x316):
|
||||
if n == 0x2FF:
|
||||
continue
|
||||
re = RoomEditor(rom, n)
|
||||
# Bosses
|
||||
if re.hasEntity(0x59): # Moldorm (TODO; double heart container drop)
|
||||
re.removeEntities(0x59)
|
||||
re.entities += [(3, 2, 0x59), (4, 2, 0x59)]
|
||||
re.store(rom)
|
||||
if re.hasEntity(0x5C): # Ghini
|
||||
re.removeEntities(0x5C)
|
||||
re.entities += [(3, 2, 0x5C), (4, 2, 0x5C)]
|
||||
re.store(rom)
|
||||
if re.hasEntity(0x5B): # slime eye
|
||||
re.removeEntities(0x5B)
|
||||
re.entities += [(3, 2, 0x5B), (6, 2, 0x5B)]
|
||||
re.store(rom)
|
||||
if re.hasEntity(0x65): # angler fish
|
||||
re.removeEntities(0x65)
|
||||
re.entities += [(6, 2, 0x65), (6, 5, 0x65)]
|
||||
re.store(rom)
|
||||
# Slime eel bugs out on death if duplicated.
|
||||
# if re.hasEntity(0x5D): # slime eel
|
||||
# re.removeEntities(0x5D)
|
||||
# re.entities += [(6, 2, 0x5D), (6, 5, 0x5D)]
|
||||
# re.store(rom)
|
||||
if re.hasEntity(0x5A): # facade (TODO: Drops two hearts, shared health?)
|
||||
re.removeEntities(0x5A)
|
||||
re.entities += [(2, 3, 0x5A), (6, 3, 0x5A)]
|
||||
re.store(rom)
|
||||
# Evil eagle causes a crash, and messes up the intro sequence and generally is just a mess if I spawn multiple
|
||||
# if re.hasEntity(0x63): # evil eagle
|
||||
# re.removeEntities(0x63)
|
||||
# re.entities += [(3, 4, 0x63), (2, 4, 0x63)]
|
||||
# re.store(rom)
|
||||
# # Remove that links movement is blocked
|
||||
# rom.patch(0x05, 0x2258, ASM("ldh [$A1], a"), "0000")
|
||||
# rom.patch(0x05, 0x1AE3, ASM("ldh [$A1], a"), "0000")
|
||||
# rom.patch(0x05, 0x1C5D, ASM("ldh [$A1], a"), "0000")
|
||||
# rom.patch(0x05, 0x1C8D, ASM("ldh [$A1], a"), "0000")
|
||||
# rom.patch(0x05, 0x1CAF, ASM("ldh [$A1], a"), "0000")
|
||||
if re.hasEntity(0x62): # hot head (TODO: Drops thwo hearts)
|
||||
re.removeEntities(0x62)
|
||||
re.entities += [(2, 2, 0x62), (4, 4, 0x62)]
|
||||
re.store(rom)
|
||||
if re.hasEntity(0xF9): # hardhit beetle
|
||||
re.removeEntities(0xF9)
|
||||
re.entities += [(2, 2, 0xF9), (5, 4, 0xF9)]
|
||||
re.store(rom)
|
||||
# Minibosses
|
||||
if re.hasEntity(0x89):
|
||||
re.removeEntities(0x89)
|
||||
re.entities += [(2, 3, 0x89), (6, 3, 0x89)]
|
||||
re.store(rom)
|
||||
if re.hasEntity(0x81):
|
||||
re.removeEntities(0x81)
|
||||
re.entities += [(2, 3, 0x81), (6, 3, 0x81)]
|
||||
re.store(rom)
|
||||
if re.hasEntity(0x60):
|
||||
dodongo = [e for e in re.entities if e[2] == 0x60]
|
||||
x = (dodongo[0][0] + dodongo[1][0]) // 2
|
||||
y = (dodongo[0][1] + dodongo[1][1]) // 2
|
||||
re.entities += [(x, y, 0x60)]
|
||||
re.store(rom)
|
||||
if re.hasEntity(0x8e):
|
||||
re.removeEntities(0x8e)
|
||||
re.entities += [(1, 1, 0x8e), (7, 1, 0x8e)]
|
||||
re.store(rom)
|
||||
if re.hasEntity(0x92):
|
||||
re.removeEntities(0x92)
|
||||
re.entities += [(2, 3, 0x92), (4, 3, 0x92)]
|
||||
re.store(rom)
|
||||
if re.hasEntity(0xf4):
|
||||
re.removeEntities(0xf4)
|
||||
re.entities += [(2, 1, 0xf4), (6, 1, 0xf4)]
|
||||
re.store(rom)
|
||||
if re.hasEntity(0xf8):
|
||||
re.removeEntities(0xf8)
|
||||
re.entities += [(2, 2, 0xf8), (6, 2, 0xf8)]
|
||||
re.store(rom)
|
||||
if re.hasEntity(0xe4):
|
||||
re.removeEntities(0xe4)
|
||||
re.entities += [(5, 2, 0xe4), (5, 5, 0xe4)]
|
||||
re.store(rom)
|
||||
|
||||
if re.hasEntity(0x88): # Armos knight (TODO: double item drop)
|
||||
re.removeEntities(0x88)
|
||||
re.entities += [(3, 3, 0x88), (6, 3, 0x88)]
|
||||
re.store(rom)
|
||||
if re.hasEntity(0x87): # Lanmola (TODO: killing one drops the item, and marks as done)
|
||||
re.removeEntities(0x87)
|
||||
re.entities += [(2, 2, 0x87), (1, 1, 0x87)]
|
||||
re.store(rom)
|
||||
58
worlds/ladx/LADXR/patches/entrances.py
Normal file
58
worlds/ladx/LADXR/patches/entrances.py
Normal file
@@ -0,0 +1,58 @@
|
||||
from ..roomEditor import RoomEditor, ObjectWarp
|
||||
from ..worldSetup import ENTRANCE_INFO
|
||||
|
||||
|
||||
def changeEntrances(rom, mapping):
|
||||
warp_to_indoor = {}
|
||||
warp_to_outdoor = {}
|
||||
for key in mapping.keys():
|
||||
info = ENTRANCE_INFO[key]
|
||||
re = RoomEditor(rom, info.alt_room if info.alt_room is not None else info.room)
|
||||
warp = re.getWarps()[info.index if info.index not in (None, "all") else 0]
|
||||
warp_to_indoor[key] = warp
|
||||
assert info.target == warp.room, "%s != %03x" % (key, warp.room)
|
||||
|
||||
re = RoomEditor(rom, warp.room)
|
||||
for warp in re.getWarps():
|
||||
if warp.room == info.room:
|
||||
warp_to_outdoor[key] = warp
|
||||
assert key in warp_to_outdoor, "Missing warp to outdoor on %s" % (key)
|
||||
|
||||
# First collect all the changes we need to do per room
|
||||
changes_per_room = {}
|
||||
def addChange(source_room, target_room, new_warp):
|
||||
if source_room not in changes_per_room:
|
||||
changes_per_room[source_room] = {}
|
||||
changes_per_room[source_room][target_room] = new_warp
|
||||
for key, target in mapping.items():
|
||||
if key == target:
|
||||
continue
|
||||
info = ENTRANCE_INFO[key]
|
||||
# Change the entrance to point to the new indoor room
|
||||
addChange(info.room, warp_to_indoor[key].room, warp_to_indoor[target])
|
||||
if info.alt_room:
|
||||
addChange(info.alt_room, warp_to_indoor[key].room, warp_to_indoor[target])
|
||||
|
||||
# Change the exit to point to the right outside
|
||||
addChange(warp_to_indoor[target].room, ENTRANCE_INFO[target].room, warp_to_outdoor[key])
|
||||
if ENTRANCE_INFO[target].instrument_room is not None:
|
||||
addChange(ENTRANCE_INFO[target].instrument_room, ENTRANCE_INFO[target].room, warp_to_outdoor[key])
|
||||
|
||||
# Finally apply the changes, we need to do this once per room to prevent A->B->C issues.
|
||||
for room, changes in changes_per_room.items():
|
||||
re = RoomEditor(rom, room)
|
||||
for idx, obj in enumerate(re.objects):
|
||||
if isinstance(obj, ObjectWarp) and obj.room in changes:
|
||||
re.objects[idx] = changes[obj.room].copy()
|
||||
re.store(rom)
|
||||
|
||||
|
||||
def readEntrances(rom):
|
||||
result = {}
|
||||
for key, info in ENTRANCE_INFO.items():
|
||||
re = RoomEditor(rom, info.alt_room if info.alt_room is not None else info.room)
|
||||
warp = re.getWarps()[info.index if info.index not in (None, "all") else 0]
|
||||
for other_key, other_info in ENTRANCE_INFO.items():
|
||||
if warp.room == other_info.target:
|
||||
result[key] = other_key
|
||||
return result
|
||||
19
worlds/ladx/LADXR/patches/fishingMinigame.py
Normal file
19
worlds/ladx/LADXR/patches/fishingMinigame.py
Normal file
@@ -0,0 +1,19 @@
|
||||
from ..assembler import ASM
|
||||
from ..roomEditor import RoomEditor
|
||||
|
||||
|
||||
def updateFinishingMinigame(rom):
|
||||
rom.patch(0x04, 0x26BE, 0x26DF, ASM("""
|
||||
ld a, $0E ; GiveItemAndMessageForRoomMultiworld
|
||||
rst 8
|
||||
|
||||
; Mark selection as stopping minigame, as we are not asking a question.
|
||||
ld a, $01
|
||||
ld [$C177], a
|
||||
|
||||
; Check if we got rupees from the item skip getting rupees from the fish.
|
||||
ld a, [$DB90]
|
||||
ld hl, $DB8F
|
||||
or [hl]
|
||||
jp nz, $66FE
|
||||
"""), fill_nop=True)
|
||||
317
worlds/ladx/LADXR/patches/goal.py
Normal file
317
worlds/ladx/LADXR/patches/goal.py
Normal file
@@ -0,0 +1,317 @@
|
||||
from ..assembler import ASM
|
||||
from ..roomEditor import RoomEditor, Object, ObjectVertical, ObjectHorizontal, ObjectWarp
|
||||
from ..utils import formatText
|
||||
|
||||
|
||||
def setRequiredInstrumentCount(rom, count):
|
||||
rom.texts[0x1A3] = formatText("You need %d instruments" % (count))
|
||||
if count >= 8:
|
||||
return
|
||||
if count < 0:
|
||||
rom.patch(0x00, 0x31f5, ASM("ld a, [$D806]\nand $10\njr z, $25"), ASM(""), fill_nop=True)
|
||||
rom.patch(0x20, 0x2dea, ASM("ld a, [$D806]\nand $10\njr z, $29"), ASM(""), fill_nop=True)
|
||||
count = 0
|
||||
|
||||
# TODO: Music bugs out at the end, unless you have all instruments.
|
||||
rom.patch(0x19, 0x0B79, None, "0000") # always spawn all instruments, we need the last one as that handles opening the egg.
|
||||
rom.patch(0x19, 0x0BF4, ASM("jp $3BC0"), ASM("jp $7FE0")) # instead of rendering the instrument, jump to the code below.
|
||||
rom.patch(0x19, 0x0BFE, ASM("""
|
||||
; Normal check fo all instruments
|
||||
ld e, $08
|
||||
ld hl, $DB65
|
||||
loop:
|
||||
ldi a, [hl]
|
||||
and $02
|
||||
jr z, $12
|
||||
dec e
|
||||
jr nz, loop
|
||||
"""), ASM("""
|
||||
jp $7F2B ; jump to the end of the bank, where there is some space for code.
|
||||
"""), fill_nop=True)
|
||||
# Add some code at the end of the bank, as we do not have enough space to do this "in place"
|
||||
rom.patch(0x19, 0x3F2B, "0000000000000000000000000000000000000000000000000000", ASM("""
|
||||
ld d, $00
|
||||
ld e, $08
|
||||
ld hl, $DB65 ; start of has instrument memory
|
||||
loop:
|
||||
ld a, [hl]
|
||||
and $02
|
||||
jr z, noinc
|
||||
inc d
|
||||
noinc:
|
||||
inc hl
|
||||
dec e
|
||||
jr nz, loop
|
||||
ld a, d
|
||||
cp $%02x ; check if we have a minimal of this amount of instruments.
|
||||
jp c, $4C1A ; not enough instruments
|
||||
jp $4C0B ; enough instruments
|
||||
""" % (count)), fill_nop=True)
|
||||
rom.patch(0x19, 0x3FE0, "0000000000000000000000000000000000000000000000000000", ASM("""
|
||||
; Entry point of render code
|
||||
ld hl, $DB65 ; table of having instruments
|
||||
push bc
|
||||
ldh a, [$F1]
|
||||
ld c, a
|
||||
add hl, bc
|
||||
pop bc
|
||||
ld a, [hl]
|
||||
and $02 ; check if we have this instrument
|
||||
ret z
|
||||
jp $3BC0 ; jump to render code
|
||||
"""), fill_nop=True)
|
||||
|
||||
|
||||
def setSeashellGoal(rom, count):
|
||||
rom.texts[0x1A3] = formatText("You need %d {SEASHELL}s" % (count))
|
||||
|
||||
# Remove the seashell mansion handler (as it will take your seashells) but put a heartpiece instead
|
||||
re = RoomEditor(rom, 0x2E9)
|
||||
re.entities = [(4, 4, 0x35)]
|
||||
re.store(rom)
|
||||
|
||||
rom.patch(0x19, 0x0ACB, 0x0C21, ASM("""
|
||||
ldh a, [$F8] ; room status
|
||||
and $10
|
||||
ret nz
|
||||
ldh a, [$F0] ; active entity state
|
||||
rst 0
|
||||
dw state0, state1, state2, state3, state4
|
||||
|
||||
state0:
|
||||
ld a, [$C124] ; room transition state
|
||||
and a
|
||||
ret nz
|
||||
ldh a, [$99] ; link position Y
|
||||
cp $70
|
||||
ret nc
|
||||
jp $3B12 ; increase entity state
|
||||
|
||||
state1:
|
||||
call $0C05 ; get entity transition countdown
|
||||
jr nz, renderShells
|
||||
ld [hl], $10
|
||||
call renderShells
|
||||
|
||||
ld hl, $C2B0 ; private state 1 table
|
||||
add hl, bc
|
||||
ld a, [wSeashellsCount]
|
||||
cp [hl]
|
||||
jp z, $3B12 ; increase entity state
|
||||
ld a, [hl] ; increase the amount of compared shells
|
||||
inc a
|
||||
daa
|
||||
ld [hl], a
|
||||
ld hl, $C2C0 ; private state 2 table
|
||||
add hl, bc
|
||||
inc [hl] ; increase amount of displayed shells
|
||||
ld a, $2B
|
||||
ldh [$F4], a ; SFX
|
||||
ret
|
||||
|
||||
state2:
|
||||
ld a, [wSeashellsCount]
|
||||
cp $%02d
|
||||
jr c, renderShells
|
||||
; got enough shells
|
||||
call $3B12 ; increase entity state
|
||||
call $0C05 ; get entity transition countdown
|
||||
ld [hl], $40
|
||||
jp renderShells
|
||||
|
||||
state3:
|
||||
ld a, $23
|
||||
ldh [$F2], a ; SFX: Dungeon opened
|
||||
ld hl, $D806 ; egg room status
|
||||
set 4, [hl]
|
||||
ld a, [hl]
|
||||
ldh [$F8], a ; current room status
|
||||
call $3B12 ; increase entity state
|
||||
|
||||
ld a, $00
|
||||
jp $4C2E
|
||||
|
||||
state4:
|
||||
ret
|
||||
|
||||
renderShells:
|
||||
ld hl, $C2C0 ; private state 2 table
|
||||
add hl, bc
|
||||
ld a, [hl]
|
||||
cp $14
|
||||
jr c, .noMax
|
||||
ld a, $14
|
||||
.noMax:
|
||||
and a
|
||||
ret z
|
||||
ld c, a
|
||||
ld hl, spriteRect
|
||||
call $3CE6 ; RenderActiveEntitySpritesRect
|
||||
ret
|
||||
|
||||
spriteRect:
|
||||
db $10, $1E, $1E, $0C
|
||||
db $10, $2A, $1E, $0C
|
||||
db $10, $36, $1E, $0C
|
||||
db $10, $42, $1E, $0C
|
||||
db $10, $4E, $1E, $0C
|
||||
|
||||
db $10, $5A, $1E, $0C
|
||||
db $10, $66, $1E, $0C
|
||||
db $10, $72, $1E, $0C
|
||||
db $10, $7E, $1E, $0C
|
||||
db $10, $8A, $1E, $0C
|
||||
|
||||
db $24, $1E, $1E, $0C
|
||||
db $24, $2A, $1E, $0C
|
||||
db $24, $36, $1E, $0C
|
||||
db $24, $42, $1E, $0C
|
||||
db $24, $4E, $1E, $0C
|
||||
|
||||
db $24, $5A, $1E, $0C
|
||||
db $24, $66, $1E, $0C
|
||||
db $24, $72, $1E, $0C
|
||||
db $24, $7E, $1E, $0C
|
||||
db $24, $8A, $1E, $0C
|
||||
""" % (count), 0x4ACB), fill_nop=True)
|
||||
|
||||
|
||||
def setRaftGoal(rom):
|
||||
rom.texts[0x1A3] = formatText("Just sail away.")
|
||||
|
||||
# Remove the egg and egg event handler.
|
||||
re = RoomEditor(rom, 0x006)
|
||||
for x in range(4, 7):
|
||||
for y in range(0, 4):
|
||||
re.removeObject(x, y)
|
||||
re.objects.append(ObjectHorizontal(4, 1, 0x4d, 3))
|
||||
re.objects.append(ObjectHorizontal(4, 2, 0x03, 3))
|
||||
re.objects.append(ObjectHorizontal(4, 3, 0x03, 3))
|
||||
re.entities = []
|
||||
re.updateOverlay()
|
||||
re.store(rom)
|
||||
|
||||
re = RoomEditor(rom, 0x08D)
|
||||
re.objects[6].count = 4
|
||||
re.objects[7].x += 2
|
||||
re.objects[7].type_id = 0x2B
|
||||
re.objects[8].x += 2
|
||||
re.objects[8].count = 2
|
||||
re.objects[9].x += 1
|
||||
re.objects[11] = ObjectVertical(7, 5, 0x37, 2)
|
||||
re.objects[12].x -= 1
|
||||
re.objects[13].x -= 1
|
||||
re.objects[14].x -= 1
|
||||
re.objects[14].type_id = 0x34
|
||||
re.objects[17].x += 3
|
||||
re.objects[17].count -= 3
|
||||
re.updateOverlay()
|
||||
re.overlay[7 + 60] = 0x33
|
||||
re.store(rom)
|
||||
|
||||
re = RoomEditor(rom, 0x0E9)
|
||||
re.objects[30].count = 1
|
||||
re.objects[30].x += 2
|
||||
re.overlay[7 + 70] = 0x0E
|
||||
re.overlay[8 + 70] = 0x0E
|
||||
re.store(rom)
|
||||
re = RoomEditor(rom, 0x0F9)
|
||||
re.objects = [
|
||||
ObjectHorizontal(4, 0, 0x0E, 6),
|
||||
ObjectVertical(9, 0, 0xCA, 8),
|
||||
ObjectVertical(8, 0, 0x0E, 8),
|
||||
|
||||
Object(3, 0, 0x38),
|
||||
Object(3, 1, 0x32),
|
||||
ObjectHorizontal(4, 1, 0x2C, 3),
|
||||
Object(7, 1, 0x2D),
|
||||
ObjectVertical(7, 2, 0x38, 5),
|
||||
Object(7, 7, 0x34),
|
||||
ObjectHorizontal(0, 7, 0x2F, 7),
|
||||
|
||||
ObjectVertical(2, 3, 0xE8, 4),
|
||||
ObjectVertical(3, 2, 0xE8, 5),
|
||||
ObjectVertical(4, 2, 0xE8, 2),
|
||||
|
||||
ObjectVertical(4, 4, 0x5C, 3),
|
||||
ObjectVertical(5, 2, 0x5C, 5),
|
||||
ObjectVertical(6, 2, 0x5C, 5),
|
||||
|
||||
Object(6, 4, 0xC6),
|
||||
ObjectWarp(1, 0x1F, 0xF6, 136, 112)
|
||||
]
|
||||
re.updateOverlay(True)
|
||||
re.entities.append((0, 0, 0x41))
|
||||
re.store(rom)
|
||||
re = RoomEditor(rom, 0x1F6)
|
||||
re.objects[-1].target_x -= 16
|
||||
re.store(rom)
|
||||
|
||||
# Fix the raft graphics (this overrides some unused graphic tiles)
|
||||
rom.banks[0x31][0x21C0:0x2200] = rom.banks[0x2E][0x07C0:0x0800]
|
||||
|
||||
# Patch the owl entity to run our custom end handling.
|
||||
rom.patch(0x06, 0x27F5, 0x2A77, ASM("""
|
||||
ld a, [$DB95]
|
||||
cp $0B
|
||||
ret nz
|
||||
; If map is not fully loaded, return
|
||||
ld a, [$C124]
|
||||
and a
|
||||
ret nz
|
||||
; Check if we are moving off the bottom of the map
|
||||
ldh a, [$99]
|
||||
cp $7D
|
||||
ret c
|
||||
; Move link back so it does not move off the map
|
||||
ld a, $7D
|
||||
ldh [$99], a
|
||||
|
||||
xor a
|
||||
ld e, a
|
||||
ld d, a
|
||||
|
||||
raftSearchLoop:
|
||||
ld hl, $C280
|
||||
add hl, de
|
||||
ld a, [hl]
|
||||
and a
|
||||
jr z, .skipEntity
|
||||
|
||||
ld hl, $C3A0
|
||||
add hl, de
|
||||
ld a, [hl]
|
||||
cp $6A
|
||||
jr nz, .skipEntity
|
||||
|
||||
; Raft found, check if near the bottom of the screen.
|
||||
ld hl, $C210
|
||||
add hl, de
|
||||
ld a, [hl]
|
||||
cp $70
|
||||
jr nc, raftOffWorld
|
||||
|
||||
.skipEntity:
|
||||
inc e
|
||||
ld a, e
|
||||
cp $10
|
||||
jr nz, raftSearchLoop
|
||||
ret
|
||||
|
||||
raftOffWorld:
|
||||
; Switch to the end credits
|
||||
ld a, $01
|
||||
ld [$DB95], a
|
||||
ld a, $00
|
||||
ld [$DB96], a
|
||||
ret
|
||||
"""), fill_nop=True)
|
||||
|
||||
# We need to run quickly trough part of the credits, or else it bugs out
|
||||
# Skip the whole windfish part.
|
||||
rom.patch(0x17, 0x0D39, None, ASM("ld a, $18\nld [$D00E], a\nret"))
|
||||
# And skip the zoomed out laying on the log
|
||||
rom.patch(0x17, 0x20ED, None, ASM("ld a, $00"))
|
||||
# Finally skip some waking up on the log.
|
||||
rom.patch(0x17, 0x23BC, None, ASM("jp $4CD9"))
|
||||
rom.patch(0x17, 0x2476, None, ASM("jp $4CD9"))
|
||||
34
worlds/ladx/LADXR/patches/goldenLeaf.py
Normal file
34
worlds/ladx/LADXR/patches/goldenLeaf.py
Normal file
@@ -0,0 +1,34 @@
|
||||
from ..assembler import ASM
|
||||
|
||||
|
||||
def fixGoldenLeaf(rom):
|
||||
# Patch the golden leaf code so it jumps to the dropped key handling in bank 3E
|
||||
rom.patch(3, 0x2007, ASM("""
|
||||
ld de, $5FFB
|
||||
call $3C77 ; RenderActiveEntitySprite
|
||||
"""), ASM("""
|
||||
ld a, $04
|
||||
rst 8
|
||||
"""), fill_nop=True)
|
||||
rom.patch(3, 0x2018, None, ASM("""
|
||||
ld a, $06 ; giveItemMultiworld
|
||||
rst 8
|
||||
jp $602F
|
||||
"""))
|
||||
rom.patch(3, 0x2037, None, ASM("""
|
||||
ld a, $0a ; showMessageMultiworld
|
||||
rst 8
|
||||
jp $604B
|
||||
"""))
|
||||
|
||||
# Patch all over the place to move the golden leafs to a different memory location.
|
||||
# We use $DB6D (dungeon 9 status), but we could also use $DB7A (which is only used by the ghost)
|
||||
rom.patch(0x00, 0x2D17, ASM("ld a, [$DB15]"), ASM("ld a, $06"), fill_nop=True) # Always load the slime tiles
|
||||
rom.patch(0x02, 0x3005, ASM("cp $06"), ASM("cp $01"), fill_nop=True) # Instead of checking for 6 leaves a the keyhole, just check for the key
|
||||
rom.patch(0x20, 0x1AD1, ASM("ld a, [$DB15]"), ASM("ld a, [wGoldenLeaves]")) # For the status screen, load the number of leafs from the proper memory
|
||||
rom.patch(0x03, 0x0980, ASM("ld a, [$DB15]"), ASM("ld a, [wGoldenLeaves]")) # If leaves >= 6 move richard
|
||||
rom.patch(0x06, 0x0059, ASM("ld a, [$DB15]"), ASM("ld a, [wGoldenLeaves]")) # If leaves >= 6 move richard
|
||||
rom.patch(0x06, 0x007D, ASM("ld a, [$DB15]"), ASM("ld a, [wGoldenLeaves]")) # Richard message if no leaves
|
||||
rom.patch(0x06, 0x00B8, ASM("ld [$DB15], a"), ASM("ld [wGoldenLeaves], a")) # Stores FF in the leaf counter if we opened the path
|
||||
# 6:40EE uses leaves == 6 to check if we have collected the key, but only to change the message.
|
||||
# rom.patch(0x06, 0x2AEF, ASM("ld a, [$DB15]"), ASM("ld a, [wGoldenLeaves]")) # Telephone message handler
|
||||
64
worlds/ladx/LADXR/patches/hardMode.py
Normal file
64
worlds/ladx/LADXR/patches/hardMode.py
Normal file
@@ -0,0 +1,64 @@
|
||||
from ..assembler import ASM
|
||||
|
||||
|
||||
def oracleMode(rom):
|
||||
# Reduce iframes
|
||||
rom.patch(0x03, 0x2DB2, ASM("ld a, $50"), ASM("ld a, $20"))
|
||||
|
||||
# Make bomb explosions damage you.
|
||||
rom.patch(0x03, 0x2618, ASM("""
|
||||
ld hl, $C440
|
||||
add hl, bc
|
||||
ld a, [hl]
|
||||
and a
|
||||
jr nz, $05
|
||||
"""), ASM("""
|
||||
call $6625
|
||||
"""), fill_nop=True)
|
||||
# Reduce bomb blast push back on link
|
||||
rom.patch(0x03, 0x2643, ASM("sla [hl]"), ASM("sra [hl]"), fill_nop=True)
|
||||
rom.patch(0x03, 0x2648, ASM("sla [hl]"), ASM("sra [hl]"), fill_nop=True)
|
||||
|
||||
# Never spawn a piece of power or acorn
|
||||
rom.patch(0x03, 0x1608, ASM("jr nz, $05"), ASM("jr $05"))
|
||||
rom.patch(0x03, 0x1642, ASM("jr nz, $04"), ASM("jr $04"))
|
||||
|
||||
# Let hearts only recover half a container instead of a full one.
|
||||
rom.patch(0x03, 0x24B7, ASM("ld a, $08"), ASM("ld a, $04"))
|
||||
# Don't randomly drop fairies from enemies, drop a rupee instead
|
||||
rom.patch(0x03, 0x15C7, "2E2D382F2E2D3837", "2E2D382E2E2D3837")
|
||||
|
||||
# Make dropping in water without flippers damage you.
|
||||
rom.patch(0x02, 0x3722, ASM("ldh a, [$AF]"), ASM("ld a, $06"))
|
||||
|
||||
|
||||
def heroMode(rom):
|
||||
# Don't randomly drop fairies and hearts from enemies, drop a rupee instead
|
||||
rom.patch(0x03, 0x159D,
|
||||
"2E2E2D2D372DFFFF2F37382E2F2F",
|
||||
"2E2EFFFF37FFFFFFFF37382EFFFF")
|
||||
rom.patch(0x03, 0x15C7,
|
||||
"2E2D382F2E2D3837",
|
||||
"2E2E382E2E2E3837")
|
||||
rom.patch(0x00, 0x168F, ASM("ld a, $2D"), "", fill_nop=True)
|
||||
rom.patch(0x02, 0x0CDB, ASM("ld a, $2D"), "", fill_nop=True)
|
||||
# Double damage
|
||||
rom.patch(0x03, 0x2DAB,
|
||||
ASM("ld a, [$DB94]\nadd a, e\nld [$DB94], a"),
|
||||
ASM("ld hl, $DB94\nld a, [hl]\nadd a, e\nadd a, e\nld [hl], a"))
|
||||
rom.patch(0x02, 0x11B2, ASM("add a, $04"), ASM("add a, $08"))
|
||||
rom.patch(0x02, 0x127E, ASM("add a, $04"), ASM("add a, $08"))
|
||||
rom.patch(0x02, 0x291C, ASM("add a, $04"), ASM("add a, $08"))
|
||||
rom.patch(0x02, 0x362B, ASM("add a, $04"), ASM("add a, $08"))
|
||||
rom.patch(0x06, 0x041C, ASM("ld a, $02"), ASM("ld a, $04"))
|
||||
rom.patch(0x15, 0x09B8, ASM("add a, $08"), ASM("add a, $10"))
|
||||
rom.patch(0x15, 0x32FD, ASM("ld a, $08"), ASM("ld a, $10"))
|
||||
rom.patch(0x18, 0x370E, ASM("ld a, $08"), ASM("ld a, $10"))
|
||||
rom.patch(0x07, 0x3103, ASM("ld a, $08"), ASM("ld a, $10"))
|
||||
rom.patch(0x06, 0x1166, ASM("ld a, $08"), ASM("ld a, $10"))
|
||||
|
||||
|
||||
|
||||
|
||||
def oneHitKO(rom):
|
||||
rom.patch(0x02, 0x238C, ASM("ld [$DB94], a"), "", fill_nop=True)
|
||||
33
worlds/ladx/LADXR/patches/health.py
Normal file
33
worlds/ladx/LADXR/patches/health.py
Normal file
@@ -0,0 +1,33 @@
|
||||
from ..assembler import ASM
|
||||
from ..utils import formatText
|
||||
|
||||
|
||||
def setStartHealth(rom, amount):
|
||||
rom.patch(0x01, 0x0B1C, ASM("ld [hl], $03"), ASM("ld [hl], $%02X" % (amount))) # max health of new save
|
||||
rom.patch(0x01, 0x0B14, ASM("ld [hl], $18"), ASM("ld [hl], $%02X" % (amount * 8))) # current health of new save
|
||||
|
||||
|
||||
def upgradeHealthContainers(rom):
|
||||
# Reuse 2 unused shop messages for the heart containers.
|
||||
rom.texts[0x2A] = formatText("You found a {HEART_CONTAINER}!")
|
||||
rom.texts[0x2B] = formatText("You lost a heart!")
|
||||
|
||||
rom.patch(0x03, 0x19DC, ASM("""
|
||||
ld de, $59D8
|
||||
call $3BC0
|
||||
"""), ASM("""
|
||||
ld a, $05 ; renderHeartPiece
|
||||
rst 8
|
||||
"""), fill_nop=True)
|
||||
rom.patch(0x03, 0x19F0, ASM("""
|
||||
ld hl, $DB5B
|
||||
inc [hl]
|
||||
ld hl, $DB93
|
||||
ld [hl], $FF
|
||||
"""), ASM("""
|
||||
ld a, $06 ; giveItemMultiworld
|
||||
rst 8
|
||||
ld a, $0A ; messageForItemMultiworld
|
||||
rst 8
|
||||
skip:
|
||||
"""), fill_nop=True) # add heart->remove heart on heart container
|
||||
42
worlds/ladx/LADXR/patches/heartPiece.py
Normal file
42
worlds/ladx/LADXR/patches/heartPiece.py
Normal file
@@ -0,0 +1,42 @@
|
||||
from ..assembler import ASM
|
||||
|
||||
|
||||
def fixHeartPiece(rom):
|
||||
# Patch all locations where the piece of heart is rendered.
|
||||
rom.patch(0x03, 0x1b52, ASM("ld de, $5A4D\ncall $3BC0"), ASM("ld a, $04\nrst 8"), fill_nop=True) # state 0
|
||||
|
||||
# Write custom code in the first state handler, this overwrites all state handlers
|
||||
# Till state 5.
|
||||
rom.patch(0x03, 0x1A74, 0x1A98, ASM("""
|
||||
; Render sprite
|
||||
ld a, $05
|
||||
rst 8
|
||||
|
||||
; Handle item effect
|
||||
ld a, $06 ; giveItemMultiworld
|
||||
rst 8
|
||||
|
||||
;Show message
|
||||
ld a, $0A ; showMessageMultiworld
|
||||
rst 8
|
||||
|
||||
; Switch to state 5
|
||||
ld hl, $C290; stateTable
|
||||
add hl, bc
|
||||
ld [hl], $05
|
||||
ret
|
||||
"""), fill_nop=True)
|
||||
# Insert a state 5 handler
|
||||
rom.patch(0x03, 0x1A98, 0x1B17, ASM("""
|
||||
; Render sprite
|
||||
ld a, $05
|
||||
rst 8
|
||||
|
||||
ld a, [$C19F] ; dialog state
|
||||
and a
|
||||
ret nz
|
||||
|
||||
call $512A ; mark room as done
|
||||
call $3F8D ; unload entity
|
||||
ret
|
||||
"""), fill_nop=True)
|
||||
24
worlds/ladx/LADXR/patches/instrument.py
Normal file
24
worlds/ladx/LADXR/patches/instrument.py
Normal file
@@ -0,0 +1,24 @@
|
||||
from ..assembler import ASM
|
||||
|
||||
|
||||
def fixInstruments(rom):
|
||||
rom.patch(0x03, 0x1EA9, 0x1EAE, "", fill_nop=True)
|
||||
rom.patch(0x03, 0x1EB9, 0x1EC8, ASM("""
|
||||
; Render sprite
|
||||
ld a, $05
|
||||
rst 8
|
||||
"""), fill_nop=True)
|
||||
|
||||
# Patch the message and instrument giving code
|
||||
rom.patch(0x03, 0x1EE3, 0x1EF6, ASM("""
|
||||
; Handle item effect
|
||||
ld a, $06 ; giveItemMultiworld
|
||||
rst 8
|
||||
|
||||
;Show message
|
||||
ld a, $0A ; showMessageMultiworld
|
||||
rst 8
|
||||
"""), fill_nop=True)
|
||||
|
||||
# Color cycle palette 7 instead of 1
|
||||
rom.patch(0x36, 0x30F0, ASM("ld de, $DC5C"), ASM("ld de, $DC84"))
|
||||
421
worlds/ladx/LADXR/patches/inventory.py
Normal file
421
worlds/ladx/LADXR/patches/inventory.py
Normal file
@@ -0,0 +1,421 @@
|
||||
from ..assembler import ASM
|
||||
from ..backgroundEditor import BackgroundEditor
|
||||
|
||||
|
||||
def selectToSwitchSongs(rom):
|
||||
# Do not ignore left/right keys when ocarina is selected
|
||||
rom.patch(0x20, 0x1F18, ASM("and a"), ASM("xor a"))
|
||||
# Change the keys which switch the ocarina song to select and no key.
|
||||
rom.patch(0x20, 0x21A9, ASM("and $01"), ASM("and $40"))
|
||||
rom.patch(0x20, 0x21C7, ASM("and $02"), ASM("and $00"))
|
||||
|
||||
def songSelectAfterOcarinaSelect(rom):
|
||||
rom.patch(0x20, 0x2002, ASM("ld [$DB00], a"), ASM("call $5F96"))
|
||||
rom.patch(0x20, 0x1FE0, ASM("ld [$DB01], a"), ASM("call $5F9B"))
|
||||
# Remove the code that opens the ocerina on cursor movement, but use it to insert code
|
||||
# for opening the menu on item select
|
||||
rom.patch(0x20, 0x1F93, 0x1FB2, ASM("""
|
||||
jp $5FB2
|
||||
itemToB:
|
||||
ld [$DB00], a
|
||||
jr checkForOcarina
|
||||
itemToA:
|
||||
ld [$DB01], a
|
||||
checkForOcarina:
|
||||
cp $09
|
||||
jp nz, $6010
|
||||
ld a, [$DB49]
|
||||
and a
|
||||
ret z
|
||||
ld a, $08
|
||||
ldh [$90], a ; load ocarina song select graphics
|
||||
;ld a, $10
|
||||
;ld [$C1B8], a ; shows the opening animation
|
||||
ld a, $01
|
||||
ld [$C1B5], a
|
||||
ret
|
||||
"""), fill_nop=True)
|
||||
# More code that opens the menu, use this to close the menu
|
||||
rom.patch(0x20, 0x200D, 0x2027, ASM("""
|
||||
jp $6027
|
||||
closeOcarinaMenu:
|
||||
ld a, [$C1B5]
|
||||
and a
|
||||
ret z
|
||||
xor a
|
||||
ld [$C1B5], a
|
||||
ld a, $10
|
||||
ld [$C1B9], a ; shows the closing animation
|
||||
ret
|
||||
"""), fill_nop=True)
|
||||
rom.patch(0x20, 0x2027, 0x2036, "", fill_nop=True) # Code that closes the ocarina menu on item select
|
||||
|
||||
rom.patch(0x20, 0x22A2, ASM("""
|
||||
ld a, [$C159]
|
||||
inc a
|
||||
ld [$C159], a
|
||||
and $10
|
||||
jr nz, $30
|
||||
"""), ASM("""
|
||||
ld a, [$C1B5]
|
||||
and a
|
||||
ret nz
|
||||
ldh a, [$E7] ; frame counter
|
||||
and $10
|
||||
ret nz
|
||||
"""), fill_nop=True)
|
||||
|
||||
def moreSlots(rom):
|
||||
#Move flippers, medicine, trade item and seashells to DB3E+
|
||||
rom.patch(0x02, 0x292B, ASM("ld a, [$DB0C]"), ASM("ld a, [$DB3E]"))
|
||||
#rom.patch(0x02, 0x2E8F, ASM("ld a, [$DB0C]"), ASM("ld a, [$DB3E]"))
|
||||
rom.patch(0x02, 0x3713, ASM("ld a, [$DB0C]"), ASM("ld a, [$DB3E]"))
|
||||
rom.patch(0x20, 0x1A23, ASM("ld de, $DB0C"), ASM("ld de, $DB3E"))
|
||||
rom.patch(0x02, 0x23a3, ASM("ld a, [$DB0D]"), ASM("ld a, [$DB3F]"))
|
||||
rom.patch(0x02, 0x23d7, ASM("ld a, [$DB0D]"), ASM("ld a, [$DB3F]"))
|
||||
rom.patch(0x02, 0x23aa, ASM("ld [$DB0D], a"), ASM("ld [$DB3F], a"))
|
||||
rom.patch(0x04, 0x3b1f, ASM("ld [$DB0D], a"), ASM("ld [$DB3F], a"))
|
||||
rom.patch(0x06, 0x1f58, ASM("ld a, [$DB0D]"), ASM("ld a, [$DB3F]"))
|
||||
rom.patch(0x06, 0x1ff5, ASM("ld hl, $DB0D"), ASM("ld hl, $DB3F"))
|
||||
rom.patch(0x07, 0x3c33, ASM("ld [$DB0D], a"), ASM("ld [$DB3F], a"))
|
||||
rom.patch(0x00, 0x1e01, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x00, 0x2d21, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x00, 0x3199, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x03, 0x0ae6, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x03, 0x0b6d, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x03, 0x0f68, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x04, 0x2faa, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x04, 0x3502, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x04, 0x3624, ASM("ld [$DB0E], a"), ASM("ld [$DB40], a"))
|
||||
rom.patch(0x05, 0x0bff, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x05, 0x0d20, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x05, 0x0db1, ASM("ld [$DB0E], a"), ASM("ld [$DB40], a"))
|
||||
rom.patch(0x05, 0x0dd5, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x05, 0x0e8e, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x05, 0x11ce, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x06, 0x1a2c, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x06, 0x1a7c, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x06, 0x1ab1, ASM("ld [$DB0E], a"), ASM("ld [$DB40], a"))
|
||||
rom.patch(0x06, 0x2214, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x06, 0x223e, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x07, 0x02f8, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x07, 0x04bf, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x07, 0x057f, ASM("ld [$DB0E], a"), ASM("ld [$DB40], a"))
|
||||
rom.patch(0x07, 0x0797, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x07, 0x0856, ASM("ld [$DB0E], a"), ASM("ld [$DB40], a"))
|
||||
rom.patch(0x07, 0x0a21, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x07, 0x0a33, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x07, 0x0a58, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x07, 0x0a81, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x07, 0x0acf, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x07, 0x0af9, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x07, 0x0b31, ASM("ld [$DB0E], a"), ASM("ld [$DB40], a"))
|
||||
rom.patch(0x07, 0x0bcc, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x07, 0x0c23, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x07, 0x0c3c, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x07, 0x0c60, ASM("ld [$DB0E], a"), ASM("ld [$DB40], a"))
|
||||
rom.patch(0x07, 0x0d73, ASM("ld [$DB0E], a"), ASM("ld [$DB40], a"))
|
||||
rom.patch(0x07, 0x1549, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x07, 0x155d, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x07, 0x159f, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x07, 0x18e6, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x07, 0x19ce, ASM("ld [$DB0E], a"), ASM("ld [$DB40], a"))
|
||||
#rom.patch(0x15, 0x3F23, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x18, 0x0966, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x18, 0x0972, ASM("ld [$DB0E], a"), ASM("ld [$DB40], a"))
|
||||
rom.patch(0x18, 0x09f3, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x18, 0x0bf1, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x18, 0x0c2c, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x18, 0x0c6d, ASM("ld [$DB0E], a"), ASM("ld [$DB40], a"))
|
||||
rom.patch(0x18, 0x0c8b, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x18, 0x0ce4, ASM("ld [$DB0E], a"), ASM("ld [$DB40], a"))
|
||||
rom.patch(0x18, 0x0d3c, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x18, 0x0d4a, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x18, 0x0d95, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x18, 0x0da3, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x18, 0x0de4, ASM("ld [$DB0E], a"), ASM("ld [$DB40], a"))
|
||||
rom.patch(0x18, 0x0e7a, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x18, 0x0e91, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x18, 0x0eb6, ASM("ld [$DB0E], a"), ASM("ld [$DB40], a"))
|
||||
rom.patch(0x18, 0x219e, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x19, 0x05ec, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x19, 0x2d54, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x19, 0x2df2, ASM("ld [$DB0E], a"), ASM("ld [$DB40], a"))
|
||||
rom.patch(0x19, 0x2ef1, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x19, 0x2f95, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x20, 0x1b04, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x20, 0x1e42, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x36, 0x0948, ASM("ld a, [$DB0E]"), ASM("ld a, [$DB40]"))
|
||||
rom.patch(0x19, 0x31Ca, ASM("ld a, [$DB0F]"), ASM("ld a, [$DB41]"))
|
||||
rom.patch(0x19, 0x3215, ASM("ld a, [$DB0F]"), ASM("ld a, [$DB41]"))
|
||||
rom.patch(0x19, 0x32a2, ASM("ld a, [$DB0F]"), ASM("ld a, [$DB41]"))
|
||||
rom.patch(0x19, 0x3700, ASM("ld [$DB0F], a"), ASM("ld [$DB41], a"))
|
||||
rom.patch(0x19, 0x38b3, ASM("ld a, [$DB0F]"), ASM("ld a, [$DB41]"))
|
||||
rom.patch(0x19, 0x38c3, ASM("ld [$DB0F], a"), ASM("ld [$DB41], a"))
|
||||
rom.patch(0x20, 0x1a83, ASM("ld a, [$DB0F]"), ASM("ld a, [$DB41]"))
|
||||
|
||||
# Fix the whole inventory rendering, this needs to extend a few tables with more entries so it moves tables
|
||||
# to the end of the bank as well.
|
||||
rom.patch(0x20, 0x3E53, "00" * 32,
|
||||
"9C019C06"
|
||||
"9C619C65"
|
||||
"9CA19CA5"
|
||||
"9CE19CE5"
|
||||
"9D219D25"
|
||||
"9D619D65"
|
||||
"9DA19DA5"
|
||||
"9DE19DE5") # New table with tile addresses for all slots
|
||||
rom.patch(0x20, 0x1CC7, ASM("ld hl, $5C84"), ASM("ld hl, $7E53")) # use the new table
|
||||
rom.patch(0x20, 0x1BCC, ASM("ld hl, $5C84"), ASM("ld hl, $7E53")) # use the new table
|
||||
rom.patch(0x20, 0x1CF0, ASM("ld hl, $5C84"), ASM("ld hl, $7E53")) # use the new table
|
||||
|
||||
# sprite positions for inventory cursor, new table, placed at the end of the bank
|
||||
rom.patch(0x20, 0x3E90, "00" * 16, "28283838484858586868787888889898")
|
||||
rom.patch(0x20, 0x22b3, ASM("ld hl, $6298"), ASM("ld hl, $7E90"))
|
||||
rom.patch(0x20, 0x2298, "28284040", "08280828") # Extend the sprite X positions for the inventory table
|
||||
|
||||
# Piece of power overlay positions
|
||||
rom.patch(0x20, 0x233A,
|
||||
"1038103010301030103010300E0E2626",
|
||||
"10381030103010301030103010301030")
|
||||
rom.patch(0x20, 0x3E73, "00" * 16,
|
||||
"0E0E2626363646465656666676768686")
|
||||
rom.patch(0x20, 0x2377, ASM("ld hl, $6346"), ASM("ld hl, $7E73"))
|
||||
|
||||
# Allow selecting the 4 extra slots.
|
||||
rom.patch(0x20, 0x1F33, ASM("ld a, $09"), ASM("ld a, $0D"))
|
||||
rom.patch(0x20, 0x1F54, ASM("ld a, $09"), ASM("ld a, $0D"))
|
||||
rom.patch(0x20, 0x1F2A, ASM("cp $0A"), ASM("cp $0E"))
|
||||
rom.patch(0x20, 0x1F4B, ASM("cp $0A"), ASM("cp $0E"))
|
||||
rom.patch(0x02, 0x217E, ASM("ld a, $0B"), ASM("ld a, $0F"))
|
||||
|
||||
# Patch all the locations that iterate over inventory to check the extra slots
|
||||
rom.patch(0x02, 0x33FC, ASM("cp $0C"), ASM("cp $10"))
|
||||
rom.patch(0x03, 0x2475, ASM("ld e, $0C"), ASM("ld e, $10"))
|
||||
rom.patch(0x03, 0x248a, ASM("cp $0C"), ASM("cp $10"))
|
||||
rom.patch(0x04, 0x3849, ASM("ld c, $0B"), ASM("ld c, $0F"))
|
||||
rom.patch(0x04, 0x3862, ASM("ld c, $0B"), ASM("ld c, $0F"))
|
||||
rom.patch(0x04, 0x39C2, ASM("ld d, $0C"), ASM("ld d, $10"))
|
||||
rom.patch(0x04, 0x39E0, ASM("ld d, $0C"), ASM("ld d, $10"))
|
||||
rom.patch(0x04, 0x39FE, ASM("ld d, $0C"), ASM("ld d, $10"))
|
||||
rom.patch(0x05, 0x0F95, ASM("ld e, $0B"), ASM("ld e, $0F"))
|
||||
rom.patch(0x05, 0x0FD1, ASM("ld c, $0B"), ASM("ld c, $0F"))
|
||||
rom.patch(0x05, 0x1324, ASM("ld e, $0C"), ASM("ld e, $10"))
|
||||
rom.patch(0x05, 0x1339, ASM("cp $0C"), ASM("cp $10"))
|
||||
rom.patch(0x18, 0x005A, ASM("ld e, $0B"), ASM("ld e, $0F"))
|
||||
rom.patch(0x18, 0x0571, ASM("ld e, $0B"), ASM("ld e, $0F"))
|
||||
rom.patch(0x19, 0x0703, ASM("cp $0C"), ASM("cp $10"))
|
||||
rom.patch(0x20, 0x235C, ASM("ld d, $0C"), ASM("ld d, $10"))
|
||||
rom.patch(0x36, 0x31B8, ASM("ld e, $0C"), ASM("ld e, $10"))
|
||||
|
||||
## Patch the toadstool as a different item
|
||||
rom.patch(0x20, 0x1C84, "9C019C" "069C61", "4C7F7F" "4D7F7F") # Which tiles are used for the toadstool
|
||||
rom.patch(0x20, 0x1C8A, "9C659C" "C19CC5", "90927F" "91937F") # Which tiles are used for the rooster
|
||||
rom.patch(0x20, 0x1C6C, "927F7F" "937F7F", "127F7F" "137F7F") # Which tiles are used for the feather (to make space for rooster)
|
||||
rom.patch(0x20, 0x1C66, "907F7F" "917F7F", "107F7F" "117F7F") # Which tiles are used for the ocarina (to make space for rooster)
|
||||
|
||||
# Move the inventory tile numbers to a higher address, so there is space for the table above it.
|
||||
rom.banks[0x20][0x1C34:0x1C94] = rom.banks[0x20][0x1C30:0x1C90]
|
||||
rom.patch(0x20, 0x1CDB, ASM("ld hl, $5C30"), ASM("ld hl, $5C34"))
|
||||
rom.patch(0x20, 0x1D0D, ASM("ld hl, $5C33"), ASM("ld hl, $5C37"))
|
||||
rom.patch(0x20, 0x1C30, "7F7F", "0A0B") # Toadstool tile attributes
|
||||
rom.patch(0x20, 0x1C32, "7F7F", "0101") # Rooster tile attributes
|
||||
rom.patch(0x20, 0x1C28, "0303", "0B0B") # Feather tile attributes (due to rooster)
|
||||
rom.patch(0x20, 0x1C26, "0202", "0A0A") # Ocarina tile attributes (due to rooster)
|
||||
|
||||
# Allow usage of the toadstool (replace the whole manual jump table with an rst 0 jumptable
|
||||
rom.patch(0x00, 0x129D, 0x12D8, ASM("""
|
||||
rst 0 ; jump table
|
||||
dw $12ED ; no item
|
||||
dw $1528 ; Sword
|
||||
dw $135A ; Bomb
|
||||
dw $1382 ; Bracelet
|
||||
dw $12EE ; Shield
|
||||
dw $13BD ; Bow
|
||||
dw $1319 ; Hookshot
|
||||
dw $12D8 ; Magic rod
|
||||
dw $12ED ; Boots (no action)
|
||||
dw $41FC ; Ocarina
|
||||
dw $14CB ; Feather
|
||||
dw $12F8 ; Shovel
|
||||
dw $148D ; Magic powder
|
||||
dw $1383 ; Boomerang
|
||||
dw $1498 ; Toadstool
|
||||
dw RoosterUse ; Rooster
|
||||
RoosterUse:
|
||||
ld a, $01
|
||||
ld [$DB7B], a ; has rooster
|
||||
call $3958 ; spawn followers
|
||||
xor a
|
||||
ld [$DB7B], a ; has rooster
|
||||
ret
|
||||
""", 0x129D), fill_nop=True)
|
||||
# Fix the graphics of the toadstool hold over your head
|
||||
rom.patch(0x02, 0x121E, ASM("ld e, $8E"), ASM("ld e, $4C"))
|
||||
rom.patch(0x02, 0x1241, ASM("ld a, $14"), ASM("ld a, $1C"))
|
||||
|
||||
# Do not remove powder when it is used up.
|
||||
rom.patch(0x20, 0x0C59, ASM("jr nz, $12"), ASM("jr $12"))
|
||||
|
||||
# Patch the toadstool entity code to give the proper item, and not set the has-toadstool flag.
|
||||
rom.patch(0x03, 0x1D6F, ASM("""
|
||||
ld a, $0A
|
||||
ldh [$A5], a
|
||||
ld d, $0C
|
||||
call $6472
|
||||
ld a, $01
|
||||
ld [$DB4B], a
|
||||
"""), ASM("""
|
||||
ld d, $0E
|
||||
call $6472
|
||||
"""), fill_nop=True)
|
||||
|
||||
# Patch the debug save game so it does not give a bunch of swords
|
||||
rom.patch(0x01, 0x0673, "01010100", "0D0E0F00")
|
||||
|
||||
# Patch the witch to use the new toadstool instead of the old flag
|
||||
rom.patch(0x05, 0x081A, ASM("ld a, [$DB4B]"), ASM("ld a, $01"), fill_nop=True)
|
||||
rom.patch(0x05, 0x082A, ASM("cp $0C"), ASM("cp $0E"))
|
||||
rom.patch(0x05, 0x083E, ASM("cp $0C"), ASM("cp $0E"))
|
||||
|
||||
|
||||
def advancedInventorySubscreen(rom):
|
||||
# Instrument positions
|
||||
rom.patch(0x01, 0x2BCF,
|
||||
"0F51B1EFECAA4A0C",
|
||||
"090C0F12494C4F52")
|
||||
|
||||
be = BackgroundEditor(rom, 2)
|
||||
be.tiles[0x9DA9] = 0x4A
|
||||
be.tiles[0x9DC9] = 0x4B
|
||||
for x in range(1, 10):
|
||||
be.tiles[0x9DE9 + x] = 0xB0 + (x % 9)
|
||||
be.tiles[0x9DE9] = 0xBA
|
||||
be.store(rom)
|
||||
be = BackgroundEditor(rom, 2, attributes=True)
|
||||
|
||||
# Remove all attributes out of range.
|
||||
for y in range(0x9C00, 0x9E40, 0x20):
|
||||
for x in range(0x14, 0x20):
|
||||
del be.tiles[x + y]
|
||||
for n in range(0x9E40, 0xA020):
|
||||
del be.tiles[n]
|
||||
|
||||
# Remove palette of instruments
|
||||
for y in range(0x9D00, 0x9E20, 0x20):
|
||||
for x in range(0x00, 0x14):
|
||||
be.tiles[x + y] = 0x01
|
||||
# And place it at the proper location
|
||||
for y in range(0x9D00, 0x9D80, 0x20):
|
||||
for x in range(0x09, 0x14):
|
||||
be.tiles[x + y] = 0x07
|
||||
|
||||
# Key from 2nd vram bank
|
||||
be.tiles[0x9DA9] = 0x09
|
||||
be.tiles[0x9DC9] = 0x09
|
||||
# Nightmare heads from 2nd vram bank with proper palette
|
||||
for n in range(1, 10):
|
||||
be.tiles[0x9DA9 + n] = 0x0E
|
||||
|
||||
be.store(rom)
|
||||
|
||||
rom.patch(0x20, 0x19D3, ASM("ld bc, $5994\nld e, $33"), ASM("ld bc, $7E08\nld e, $%02x" % (0x33 + 24)))
|
||||
rom.banks[0x20][0x3E08:0x3E08+0x33] = rom.banks[0x20][0x1994:0x1994+0x33]
|
||||
rom.patch(0x20, 0x3E08+0x32, "00" * 25, "9DAA08464646464646464646" "9DCA08B0B0B0B0B0B0B0B0B0" "00")
|
||||
|
||||
# instead of doing an GBC specific check, jump to our custom handling
|
||||
rom.patch(0x20, 0x19DE, ASM("ldh a, [$FE]\nand a\njr z, $40"), ASM("call $7F00"), fill_nop=True)
|
||||
|
||||
rom.patch(0x20, 0x3F00, "00" * 0x100, ASM("""
|
||||
ld a, [$DBA5] ; isIndoor
|
||||
and a
|
||||
jr z, RenderKeysCounts
|
||||
ldh a, [$F7] ; mapNr
|
||||
cp $FF
|
||||
jr z, RenderDungeonFix
|
||||
cp $06
|
||||
jr z, D7RenderDungeonFix
|
||||
cp $08
|
||||
jr c, RenderDungeonFix
|
||||
|
||||
RenderKeysCounts:
|
||||
; Check if we have each nightmare key, and else null out the rendered tile
|
||||
ld hl, $D636
|
||||
ld de, $DB19
|
||||
ld c, $08
|
||||
NKeyLoop:
|
||||
ld a, [de]
|
||||
and a
|
||||
jr nz, .hasNKey
|
||||
ld a, $7F
|
||||
ld [hl], a
|
||||
.hasNKey:
|
||||
inc hl
|
||||
inc de
|
||||
inc de
|
||||
inc de
|
||||
inc de
|
||||
inc de
|
||||
dec c
|
||||
jr nz, NKeyLoop
|
||||
|
||||
ld a, [$DDDD]
|
||||
and a
|
||||
jr nz, .hasCNKey
|
||||
ld a, $7F
|
||||
ld [hl], a
|
||||
.hasCNKey:
|
||||
|
||||
; Check the small key count for each dungeon and increase the tile to match the number
|
||||
ld hl, $D642
|
||||
ld de, $DB1A
|
||||
ld c, $08
|
||||
KeyLoop:
|
||||
ld a, [de]
|
||||
add a, $B0
|
||||
ld [hl], a
|
||||
inc hl
|
||||
inc de
|
||||
inc de
|
||||
inc de
|
||||
inc de
|
||||
inc de
|
||||
dec c
|
||||
jr nz, KeyLoop
|
||||
|
||||
ld a, [$DDDE]
|
||||
add a, $B0
|
||||
ld [hl], a
|
||||
ret
|
||||
|
||||
D7RenderDungeonFix:
|
||||
ld de, D7DungeonFix
|
||||
ld c, $11
|
||||
jr RenderDungeonFixGo
|
||||
|
||||
RenderDungeonFix:
|
||||
ld de, DungeonFix
|
||||
ld c, $0D
|
||||
RenderDungeonFixGo:
|
||||
ld hl, $D633
|
||||
.copyLoop:
|
||||
ld a, [de]
|
||||
inc de
|
||||
ldi [hl], a
|
||||
dec c
|
||||
jr nz, .copyLoop
|
||||
ret
|
||||
|
||||
DungeonFix:
|
||||
db $9D, $09, $C7, $7F
|
||||
db $9D, $0A, $C7, $7F
|
||||
db $9D, $13, $C3, $7F
|
||||
db $00
|
||||
D7DungeonFix:
|
||||
db $9D, $09, $C7, $7F
|
||||
db $9D, $0A, $C7, $7F
|
||||
db $9D, $6B, $48, $7F
|
||||
db $9D, $0F, $C7, $7F
|
||||
db $00
|
||||
|
||||
""", 0x7F00), fill_nop=True)
|
||||
42
worlds/ladx/LADXR/patches/madBatter.py
Normal file
42
worlds/ladx/LADXR/patches/madBatter.py
Normal file
@@ -0,0 +1,42 @@
|
||||
from ..assembler import ASM
|
||||
from ..utils import formatText
|
||||
|
||||
|
||||
def upgradeMadBatter(rom):
|
||||
# Normally the madbatter won't do anything if you have full capacity. Remove that check.
|
||||
rom.patch(0x18, 0x0F05, 0x0F1D, "", fill_nop=True)
|
||||
# Remove the code that finds which upgrade to apply,
|
||||
rom.patch(0x18, 0x0F9E, 0x0FC4, "", fill_nop=True)
|
||||
rom.patch(0x18, 0x0FD2, 0x0FD8, "", fill_nop=True)
|
||||
|
||||
# Finally, at the last step, give the item and the item message.
|
||||
rom.patch(0x18, 0x1016, 0x101B, "", fill_nop=True)
|
||||
rom.patch(0x18, 0x101E, 0x1051, ASM("""
|
||||
; Mad batter rooms are E0,E1 and E2, load the item type from a table in the rom
|
||||
; which only has 3 entries, and store it where bank 3E wants it.
|
||||
ldh a, [$F6] ; current room
|
||||
and $0F
|
||||
ld d, $00
|
||||
ld e, a
|
||||
ld hl, $4F90
|
||||
add hl, de
|
||||
ld a, [hl]
|
||||
ldh [$F1], a
|
||||
|
||||
; Give item
|
||||
ld a, $06 ; giveItemMultiworld
|
||||
rst 8
|
||||
; Message
|
||||
ld a, $0A ; showMessageMultiworld
|
||||
rst 8
|
||||
; Force the dialog at the bottom
|
||||
ld a, [$C19F]
|
||||
or $80
|
||||
ld [$C19F], a
|
||||
"""), fill_nop=True)
|
||||
# Setup the default items
|
||||
rom.patch(0x18, 0x0F90, "406060", "848586")
|
||||
|
||||
rom.texts[0xE2] = formatText("You can now carry more Magic Powder!")
|
||||
rom.texts[0xE3] = formatText("You can now carry more Bombs!")
|
||||
rom.texts[0xE4] = formatText("You can now carry more Arrows!")
|
||||
27
worlds/ladx/LADXR/patches/maptweaks.py
Normal file
27
worlds/ladx/LADXR/patches/maptweaks.py
Normal file
@@ -0,0 +1,27 @@
|
||||
from ..roomEditor import RoomEditor, ObjectWarp, ObjectVertical
|
||||
|
||||
|
||||
def tweakMap(rom):
|
||||
# 5 holes at the castle, reduces to 3
|
||||
re = RoomEditor(rom, 0x078)
|
||||
re.objects[-1].count = 3
|
||||
re.overlay[7 + 6 * 10] = re.overlay[9 + 6 * 10]
|
||||
re.overlay[8 + 6 * 10] = re.overlay[9 + 6 * 10]
|
||||
re.store(rom)
|
||||
|
||||
|
||||
def addBetaRoom(rom):
|
||||
re = RoomEditor(rom, 0x1FC)
|
||||
re.objects[-1].target_y -= 0x10
|
||||
re.store(rom)
|
||||
re = RoomEditor(rom, 0x038)
|
||||
re.changeObject(5, 1, 0xE1)
|
||||
re.removeObject(0, 0)
|
||||
re.removeObject(0, 1)
|
||||
re.removeObject(0, 2)
|
||||
re.removeObject(6, 1)
|
||||
re.objects.append(ObjectVertical(0, 0, 0x38, 3))
|
||||
re.objects.append(ObjectWarp(1, 0x1F, 0x1FC, 0x50, 0x7C))
|
||||
re.store(rom)
|
||||
|
||||
rom.room_sprite_data_indoor[0x0FC] = rom.room_sprite_data_indoor[0x1A1]
|
||||
308
worlds/ladx/LADXR/patches/multiworld.py
Normal file
308
worlds/ladx/LADXR/patches/multiworld.py
Normal file
@@ -0,0 +1,308 @@
|
||||
from ..assembler import ASM
|
||||
from ..roomEditor import RoomEditor, ObjectHorizontal, ObjectVertical, Object
|
||||
from .. import entityData
|
||||
|
||||
|
||||
def addMultiworldShop(rom, this_player, player_count):
|
||||
# Make a copy of the shop into GrandpaUlrira house
|
||||
re = RoomEditor(rom, 0x2A9)
|
||||
re.objects = [
|
||||
ObjectHorizontal(1,1, 0x00, 8),
|
||||
ObjectHorizontal(1,2, 0x00, 8),
|
||||
ObjectHorizontal(1,3, 0xCD, 8),
|
||||
Object(2, 0, 0xC7),
|
||||
Object(7, 0, 0xC7),
|
||||
Object(7, 7, 0xFD),
|
||||
] + re.getWarps()
|
||||
re.entities = [(0, 6, 0xD4)]
|
||||
for n in range(player_count):
|
||||
if n != this_player:
|
||||
re.entities.append((n + 1, 6, 0xD4))
|
||||
re.animation_id = 0x04
|
||||
re.floor_object = 0x0D
|
||||
re.store(rom)
|
||||
# Fix the tileset
|
||||
rom.banks[0x20][0x2EB3 + 0x2A9 - 0x100] = rom.banks[0x20][0x2EB3 + 0x2A1 - 0x100]
|
||||
|
||||
re = RoomEditor(rom, 0x0B1)
|
||||
re.getWarps()[0].target_x = 128
|
||||
re.store(rom)
|
||||
|
||||
# Load the shopkeeper sprites
|
||||
entityData.SPRITE_DATA[0xD4] = entityData.SPRITE_DATA[0x4D]
|
||||
rom.patch(0x03, 0x01CF, "00", "98") # Fix the hitbox of the ghost to be 16x16
|
||||
|
||||
# Patch Ghost to work as a multiworld shop
|
||||
rom.patch(0x19, 0x1E18, 0x20B0, ASM("""
|
||||
ld a, $01
|
||||
ld [$C50A], a ; this stops link from using items
|
||||
|
||||
ldh a, [$EE] ; X
|
||||
cp $08
|
||||
; Jump to other code which is placed on the old owl code. As we do not have enough space here.
|
||||
jp z, shopItemsHandler
|
||||
|
||||
;Draw shopkeeper
|
||||
ld de, OwnerSpriteData
|
||||
call $3BC0 ; render sprite pair
|
||||
ldh a, [$E7] ; frame counter
|
||||
swap a
|
||||
and $01
|
||||
call $3B0C ; set sprite variant
|
||||
|
||||
ldh a, [$F0]
|
||||
and a
|
||||
jr nz, checkTalkingResult
|
||||
|
||||
call $7CA2 ; prevent link from moving into the sprite
|
||||
call $7CF0 ; check if talking to NPC
|
||||
call c, talkHandler ; talk handling
|
||||
ret
|
||||
|
||||
checkTalkingResult:
|
||||
ld a, [$C19F]
|
||||
and a
|
||||
ret nz ; still taking
|
||||
call $3B12 ; increase entity state
|
||||
ld [hl], $00
|
||||
ld a, [$C177] ; dialog selection
|
||||
and a
|
||||
ret nz
|
||||
jp TalkResultHandler
|
||||
|
||||
OwnerSpriteData:
|
||||
;db $60, $03, $62, $03, $62, $23, $60, $23 ; down
|
||||
db $64, $03, $66, $03, $66, $23, $64, $23 ; up
|
||||
;db $68, $03, $6A, $03, $6C, $03, $6E, $03 ; left
|
||||
;db $6A, $23, $68, $23, $6E, $23, $6C, $23 ; right
|
||||
|
||||
shopItemsHandler:
|
||||
; Render the shop items
|
||||
ld h, $00
|
||||
loop:
|
||||
; First load links position to render the item at
|
||||
ldh a, [$98] ; LinkX
|
||||
ldh [$EE], a ; X
|
||||
ldh a, [$99] ; LinkY
|
||||
sub $0E
|
||||
ldh [$EC], a ; Y
|
||||
; Check if this is the item we have picked up
|
||||
ld a, [$C509] ; picked up item in shop
|
||||
dec a
|
||||
cp h
|
||||
jr z, .renderCarry
|
||||
|
||||
ld a, h
|
||||
swap a
|
||||
add a, $20
|
||||
ldh [$EE], a ; X
|
||||
ld a, $30
|
||||
ldh [$EC], a ; Y
|
||||
.renderCarry:
|
||||
ld a, h
|
||||
push hl
|
||||
ldh [$F1], a ; variant
|
||||
cp $03
|
||||
jr nc, .singleSprite
|
||||
ld de, ItemsDualSpriteData
|
||||
call $3BC0 ; render sprite pair
|
||||
jr .renderDone
|
||||
.singleSprite:
|
||||
ld de, ItemsSingleSpriteData
|
||||
call $3C77 ; render sprite
|
||||
.renderDone:
|
||||
|
||||
pop hl
|
||||
.skipItem:
|
||||
inc h
|
||||
ld a, $07
|
||||
cp h
|
||||
jr nz, loop
|
||||
|
||||
; check if we want to pickup or drop an item
|
||||
ldh a, [$CC]
|
||||
and $30 ; A or B button
|
||||
call nz, checkForPickup
|
||||
|
||||
; check if we have an item
|
||||
ld a, [$C509] ; carry item
|
||||
and a
|
||||
ret z
|
||||
|
||||
; Set that link has picked something up
|
||||
ld a, $01
|
||||
ld [$C15C], a
|
||||
call $0CAF ; reset spin attack...
|
||||
|
||||
; Check if we are trying to exit the shop and so drop our item.
|
||||
ldh a, [$99]
|
||||
cp $78
|
||||
ret c
|
||||
xor a
|
||||
ld [$C509], a
|
||||
|
||||
ret
|
||||
|
||||
checkForPickup:
|
||||
ldh a, [$9E] ; direction
|
||||
cp $02
|
||||
ret nz
|
||||
ldh a, [$99] ; LinkY
|
||||
cp $48
|
||||
ret nc
|
||||
|
||||
ld a, $13
|
||||
ldh [$F2], a ; play SFX
|
||||
|
||||
ld a, [$C509] ; picked up shop item
|
||||
and a
|
||||
jr nz, .drop
|
||||
|
||||
ldh a, [$98] ; LinkX
|
||||
sub $08
|
||||
swap a
|
||||
and $07
|
||||
ld [$C509], a ; picked up shop item
|
||||
ret
|
||||
.drop:
|
||||
xor a
|
||||
ld [$C509], a
|
||||
ret
|
||||
|
||||
ItemsDualSpriteData:
|
||||
db $60, $08, $60, $28 ; zol
|
||||
db $68, $09 ; chicken (left)
|
||||
ItemsSingleSpriteData: ; (first 3 entries are still dual sprites)
|
||||
db $6A, $09 ; chicken (right)
|
||||
db $14, $02, $14, $22 ; piece of power
|
||||
;Real single sprite data starts here
|
||||
db $00, $0F ; bomb
|
||||
db $38, $0A ; rupees
|
||||
db $20, $0C ; medicine
|
||||
db $28, $0C ; heart
|
||||
|
||||
;------------------------------------trying to buy something starts here
|
||||
talkHandler:
|
||||
ld a, [$C509] ; carry item
|
||||
add a, a
|
||||
ret z ; check if we have something to buy
|
||||
sub $02
|
||||
|
||||
ld hl, itemNames
|
||||
ld e, a
|
||||
ld d, b ; b=0
|
||||
add hl, de
|
||||
ld e, [hl]
|
||||
inc hl
|
||||
ld d, [hl]
|
||||
|
||||
ld hl, wCustomMessage
|
||||
call appendString
|
||||
dec hl
|
||||
call padString
|
||||
ld de, postMessage
|
||||
call appendString
|
||||
dec hl
|
||||
ld a, $fe
|
||||
ld [hl], a
|
||||
ld de, $FFEF
|
||||
add hl, de
|
||||
ldh a, [$EE]
|
||||
swap a
|
||||
and $0F
|
||||
add a, $30
|
||||
ld [hl], a
|
||||
ld a, $C9
|
||||
call $2385 ; open dialog
|
||||
call $3B12 ; increase entity state
|
||||
ret
|
||||
|
||||
appendString:
|
||||
ld a, [de]
|
||||
inc de
|
||||
and a
|
||||
ret z
|
||||
ldi [hl], a
|
||||
jr appendString
|
||||
|
||||
padString:
|
||||
ld a, l
|
||||
and $0F
|
||||
ret z
|
||||
ld a, $20
|
||||
ldi [hl], a
|
||||
jr padString
|
||||
|
||||
itemNames:
|
||||
dw itemZol
|
||||
dw itemChicken
|
||||
dw itemPieceOfPower
|
||||
dw itemBombs
|
||||
dw itemRupees
|
||||
dw itemMedicine
|
||||
dw itemHealth
|
||||
|
||||
postMessage:
|
||||
db "For player X? Yes No ", $00
|
||||
|
||||
itemZol:
|
||||
db m"Slime storm|100 {RUPEES}", $00
|
||||
itemChicken:
|
||||
db m"Coccu party|50 {RUPEES}", $00
|
||||
itemPieceOfPower:
|
||||
db m"Piece of Power|50 {RUPEES}", $00
|
||||
itemBombs:
|
||||
db m"10 Bombs|50 {RUPEES}", $00
|
||||
itemRupees:
|
||||
db m"100 {RUPEES}|200 {RUPEES}", $00
|
||||
itemMedicine:
|
||||
db m"Medicine|100 {RUPEES}", $00
|
||||
itemHealth:
|
||||
db m"Health refill|10 {RUPEES}", $00
|
||||
|
||||
TalkResultHandler:
|
||||
ld hl, ItemPriceTableBCD
|
||||
ld a, [$C509]
|
||||
dec a
|
||||
add a, a
|
||||
ld c, a ; b=0
|
||||
add hl, bc
|
||||
ldi a, [hl]
|
||||
ld d, [hl]
|
||||
ld e, a
|
||||
ld a, [$DB5D]
|
||||
cp d
|
||||
ret c
|
||||
jr nz, .highEnough
|
||||
ld a, [$DB5E]
|
||||
cp e
|
||||
ret c
|
||||
.highEnough:
|
||||
; Got enough money, take it.
|
||||
ld hl, ItemPriceTableDEC
|
||||
ld a, [$C509]
|
||||
dec a
|
||||
ld c, a ; b=0
|
||||
add hl, bc
|
||||
ld a, [hl]
|
||||
ld [$DB92], a ; set substract buffer
|
||||
|
||||
; Set the item to send
|
||||
ld hl, $DDFE
|
||||
ld a, [$C509] ; currently picked up item
|
||||
ldi [hl], a
|
||||
ldh a, [$EE] ; X position of NPC
|
||||
ldi [hl], a
|
||||
ld hl, $DDF7
|
||||
set 2, [hl]
|
||||
|
||||
; No longer picked up item
|
||||
xor a
|
||||
ld [$C509], a
|
||||
ret
|
||||
|
||||
ItemPriceTableBCD:
|
||||
dw $0100, $0050, $0050, $0050, $0200, $0100, $0010
|
||||
ItemPriceTableDEC:
|
||||
db $64, $32, $32, $32, $C8, $64, $0A
|
||||
""", 0x5E18), fill_nop=True)
|
||||
27
worlds/ladx/LADXR/patches/music.py
Normal file
27
worlds/ladx/LADXR/patches/music.py
Normal file
@@ -0,0 +1,27 @@
|
||||
from ..assembler import ASM
|
||||
|
||||
|
||||
_LOOPING_MUSIC = (1, 2, 3, 4, 5, 6, 7, 8, 9, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1C, 0x1D, 0x1F, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x2F, 0x31, 0x32, 0x33, 0x37,
|
||||
0x39, 0x3A, 0x3C, 0x3E, 0x40, 0x48, 0x49, 0x4A, 0x4B, 0x4E, 0x50, 0x53, 0x54, 0x55, 0x57, 0x58, 0x59,
|
||||
0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61)
|
||||
|
||||
|
||||
def randomizeMusic(rom, rnd):
|
||||
# Randomize overworld
|
||||
for x in range(0, 16, 2):
|
||||
for y in range(0, 16, 2):
|
||||
idx = x + y * 16
|
||||
result = rnd.choice(_LOOPING_MUSIC)
|
||||
rom.banks[0x02][idx] = result
|
||||
rom.banks[0x02][idx+1] = result
|
||||
rom.banks[0x02][idx+16] = result
|
||||
rom.banks[0x02][idx+17] = result
|
||||
# Random music in dungeons/caves
|
||||
for n in range(0x20):
|
||||
rom.banks[0x02][0x100 + n] = rnd.choice(_LOOPING_MUSIC)
|
||||
|
||||
|
||||
def noMusic(rom):
|
||||
rom.patch(0x1B, 0x001E, ASM("ld hl, $D368\nldi a, [hl]"), ASM("xor a"), fill_nop=True)
|
||||
rom.patch(0x1E, 0x001E, ASM("ld hl, $D368\nldi a, [hl]"), ASM("xor a"), fill_nop=True)
|
||||
BIN
worlds/ladx/LADXR/patches/nyan.bin
Normal file
BIN
worlds/ladx/LADXR/patches/nyan.bin
Normal file
Binary file not shown.
224
worlds/ladx/LADXR/patches/overworld.py
Normal file
224
worlds/ladx/LADXR/patches/overworld.py
Normal file
@@ -0,0 +1,224 @@
|
||||
from ..assembler import ASM
|
||||
from ..roomEditor import RoomEditor, ObjectWarp, Object, WARP_TYPE_IDS
|
||||
from .. import entityData
|
||||
import os
|
||||
import json
|
||||
|
||||
|
||||
def patchOverworldTilesets(rom):
|
||||
rom.patch(0x00, 0x0D5B, 0x0D79, ASM("""
|
||||
; Instead of loading tileset info from a small 8x8 table, load it from a 16x16 table to give
|
||||
; full control.
|
||||
; A=MapRoom
|
||||
ld hl, $2100
|
||||
ld [hl], $3F
|
||||
ld d, $00
|
||||
ld e, a
|
||||
ld hl, $7F00
|
||||
add hl, de
|
||||
ldh a, [$94] ; We need to load the currently loaded tileset in E to compare it
|
||||
ld e, a
|
||||
ld a, [hl]
|
||||
ld hl, $2100
|
||||
ld [hl], $20
|
||||
"""), fill_nop=True)
|
||||
# Remove the camera shop exception
|
||||
rom.patch(0x00, 0x0D80, 0x0D8B, "", fill_nop=True)
|
||||
|
||||
for x in range(16):
|
||||
for y in range(16):
|
||||
rom.banks[0x3F][0x3F00+x+y*16] = rom.banks[0x20][0x2E73 + (x // 2) + (y // 2) * 8]
|
||||
rom.banks[0x3F][0x3F07] = rom.banks[0x3F][0x3F08] # Fix the room next to the egg
|
||||
rom.banks[0x3F][0x3F17] = rom.banks[0x3F][0x3F08] # Fix the room next to the egg
|
||||
rom.banks[0x3F][0x3F3A] = 0x0F # room below mambo cave
|
||||
rom.banks[0x3F][0x3F3B] = 0x0F # room below D4
|
||||
rom.banks[0x3F][0x3F4B] = 0x0F # room next to castle
|
||||
rom.banks[0x3F][0x3F5B] = 0x0F # room next to castle
|
||||
# Fix the rooms around the camera shop
|
||||
rom.banks[0x3F][0x3F26] = 0x0F
|
||||
rom.banks[0x3F][0x3F27] = 0x0F
|
||||
rom.banks[0x3F][0x3F36] = 0x0F
|
||||
|
||||
|
||||
def createDungeonOnlyOverworld(rom):
|
||||
# Skip the whole egg maze.
|
||||
rom.patch(0x14, 0x0453, "75", "73")
|
||||
|
||||
instrument_rooms = [0x102, 0x12A, 0x159, 0x162, 0x182, 0x1B5, 0x22C, 0x230, 0x301]
|
||||
path = os.path.dirname(__file__)
|
||||
|
||||
# Start with clearing all the maps, because this just generates a bunch of room in the rom.
|
||||
for n in range(0x100):
|
||||
re = RoomEditor(rom, n)
|
||||
re.entities = []
|
||||
re.objects = []
|
||||
if os.path.exists("%s/overworld/dive/%02X.json" % (path, n)):
|
||||
re.loadFromJson("%s/overworld/dive/%02X.json" % (path, n))
|
||||
entrances = list(filter(lambda obj: obj.type_id in WARP_TYPE_IDS, re.objects))
|
||||
for obj in re.objects:
|
||||
if isinstance(obj, ObjectWarp) and entrances:
|
||||
e = entrances.pop(0)
|
||||
|
||||
other = RoomEditor(rom, obj.room)
|
||||
for o in other.objects:
|
||||
if isinstance(o, ObjectWarp) and o.warp_type == 0:
|
||||
o.room = n
|
||||
o.target_x = e.x * 16 + 8
|
||||
o.target_y = e.y * 16 + 16
|
||||
other.store(rom)
|
||||
|
||||
if obj.room == 0x1F5:
|
||||
# Patch the boomang guy exit
|
||||
other = RoomEditor(rom, "Alt1F5")
|
||||
other.getWarps()[0].room = n
|
||||
other.getWarps()[0].target_x = e.x * 16 + 8
|
||||
other.getWarps()[0].target_y = e.y * 16 + 16
|
||||
other.store(rom)
|
||||
|
||||
if obj.warp_type == 1 and (obj.map_nr < 8 or obj.map_nr == 0xFF) and obj.room not in (0x1B0, 0x23A, 0x23D):
|
||||
other = RoomEditor(rom, instrument_rooms[min(8, obj.map_nr)])
|
||||
for o in other.objects:
|
||||
if isinstance(o, ObjectWarp) and o.warp_type == 0:
|
||||
o.room = n
|
||||
o.target_x = e.x * 16 + 8
|
||||
o.target_y = e.y * 16 + 16
|
||||
other.store(rom)
|
||||
re.store(rom)
|
||||
|
||||
|
||||
def exportOverworld(rom):
|
||||
import PIL.Image
|
||||
|
||||
path = os.path.dirname(__file__)
|
||||
for room_index in list(range(0x100)) + ["Alt06", "Alt0E", "Alt1B", "Alt2B", "Alt79", "Alt8C"]:
|
||||
room = RoomEditor(rom, room_index)
|
||||
if isinstance(room_index, int):
|
||||
room_nr = room_index
|
||||
else:
|
||||
room_nr = int(room_index[3:], 16)
|
||||
tileset_index = rom.banks[0x3F][0x3F00 + room_nr]
|
||||
attributedata_bank = rom.banks[0x1A][0x2476 + room_nr]
|
||||
attributedata_addr = rom.banks[0x1A][0x1E76 + room_nr * 2]
|
||||
attributedata_addr |= rom.banks[0x1A][0x1E76 + room_nr * 2 + 1] << 8
|
||||
attributedata_addr -= 0x4000
|
||||
|
||||
metatile_info = rom.banks[0x1A][0x2B1D:0x2B1D + 0x400]
|
||||
attrtile_info = rom.banks[attributedata_bank][attributedata_addr:attributedata_addr+0x400]
|
||||
|
||||
palette_index = rom.banks[0x21][0x02EF + room_nr]
|
||||
palette_addr = rom.banks[0x21][0x02B1 + palette_index * 2]
|
||||
palette_addr |= rom.banks[0x21][0x02B1 + palette_index * 2 + 1] << 8
|
||||
palette_addr -= 0x4000
|
||||
|
||||
hidden_warp_tiles = []
|
||||
for obj in room.objects:
|
||||
if obj.type_id in WARP_TYPE_IDS and room.overlay[obj.x + obj.y * 10] != obj.type_id:
|
||||
if obj.type_id != 0xE1 or room.overlay[obj.x + obj.y * 10] != 0x53: # Ignore the waterfall 'caves'
|
||||
hidden_warp_tiles.append(obj)
|
||||
if obj.type_id == 0xC5 and room_nr < 0x100 and room.overlay[obj.x + obj.y * 10] == 0xC4:
|
||||
# Pushable gravestones have the wrong overlay by default
|
||||
room.overlay[obj.x + obj.y * 10] = 0xC5
|
||||
if obj.type_id == 0xDC and room_nr < 0x100:
|
||||
# Flowers above the rooster windmill need a different tile
|
||||
hidden_warp_tiles.append(obj)
|
||||
|
||||
image_filename = "tiles_%02x_%02x_%02x_%02x_%04x.png" % (tileset_index, room.animation_id, palette_index, attributedata_bank, attributedata_addr)
|
||||
data = {
|
||||
"width": 10, "height": 8,
|
||||
"type": "map", "renderorder": "right-down", "tiledversion": "1.4.3", "version": 1.4,
|
||||
"tilewidth": 16, "tileheight": 16, "orientation": "orthogonal",
|
||||
"tilesets": [
|
||||
{
|
||||
"columns": 16, "firstgid": 1,
|
||||
"image": image_filename, "imageheight": 256, "imagewidth": 256,
|
||||
"margin": 0, "name": "main", "spacing": 0,
|
||||
"tilecount": 256, "tileheight": 16, "tilewidth": 16
|
||||
}
|
||||
],
|
||||
"layers": [{
|
||||
"data": [n+1 for n in room.overlay],
|
||||
"width": 10, "height": 8,
|
||||
"id": 1, "name": "Tiles", "type": "tilelayer", "visible": True, "opacity": 1, "x": 0, "y": 0,
|
||||
}, {
|
||||
"id": 2, "name": "EntityLayer", "type": "objectgroup", "visible": True, "opacity": 1, "x": 0, "y": 0,
|
||||
"objects": [
|
||||
{"width": 16, "height": 16, "x": entity[0] * 16, "y": entity[1] * 16, "name": entityData.NAME[entity[2]], "type": "entity"} for entity in room.entities
|
||||
] + [
|
||||
{"width": 8, "height": 8, "x": 0, "y": idx * 8, "name": "%x:%02x:%03x:%02x:%02x" % (obj.warp_type, obj.map_nr, obj.room, obj.target_x, obj.target_y), "type": "warp"} for idx, obj in enumerate(room.getWarps()) if isinstance(obj, ObjectWarp)
|
||||
] + [
|
||||
{"width": 16, "height": 16, "x": obj.x * 16, "y": obj.y * 16, "name": "%02X" % (obj.type_id), "type": "hidden_tile"} for obj in hidden_warp_tiles
|
||||
],
|
||||
}],
|
||||
"properties": [
|
||||
{"name": "tileset", "type": "string", "value": "%02X" % (tileset_index)},
|
||||
{"name": "animationset", "type": "string", "value": "%02X" % (room.animation_id)},
|
||||
{"name": "attribset", "type": "string", "value": "%02X:%04X" % (attributedata_bank, attributedata_addr)},
|
||||
{"name": "palette", "type": "string", "value": "%02X" % (palette_index)},
|
||||
]
|
||||
}
|
||||
if isinstance(room_index, str):
|
||||
json.dump(data, open("%s/overworld/export/%s.json" % (path, room_index), "wt"))
|
||||
else:
|
||||
json.dump(data, open("%s/overworld/export/%02X.json" % (path, room_index), "wt"))
|
||||
|
||||
if not os.path.exists("%s/overworld/export/%s" % (path, image_filename)):
|
||||
tilemap = rom.banks[0x2F][tileset_index*0x100:tileset_index*0x100+0x200]
|
||||
tilemap += rom.banks[0x2C][0x1200:0x1800]
|
||||
tilemap += rom.banks[0x2C][0x0800:0x1000]
|
||||
anim_addr = {2: 0x2B00, 3: 0x2C00, 4: 0x2D00, 5: 0x2E00, 6: 0x2F00, 7: 0x2D00, 8: 0x3000, 9: 0x3100, 10: 0x3200, 11: 0x2A00, 12: 0x3300, 13: 0x3500, 14: 0x3600, 15: 0x3400, 16: 0x3700}.get(room.animation_id, 0x0000)
|
||||
tilemap[0x6C0:0x700] = rom.banks[0x2C][anim_addr:anim_addr + 0x40]
|
||||
|
||||
palette = []
|
||||
for n in range(8*4):
|
||||
p0 = rom.banks[0x21][palette_addr]
|
||||
p1 = rom.banks[0x21][palette_addr + 1]
|
||||
pal = p0 | p1 << 8
|
||||
palette_addr += 2
|
||||
r = (pal & 0x1F) << 3
|
||||
g = ((pal >> 5) & 0x1F) << 3
|
||||
b = ((pal >> 10) & 0x1F) << 3
|
||||
palette += [r, g, b]
|
||||
|
||||
img = PIL.Image.new("P", (16*16, 16*16))
|
||||
img.putpalette(palette)
|
||||
def drawTile(x, y, index, attr):
|
||||
for py in range(8):
|
||||
a = tilemap[index * 16 + py * 2]
|
||||
b = tilemap[index * 16 + py * 2 + 1]
|
||||
if attr & 0x40:
|
||||
a = tilemap[index * 16 + 14 - py * 2]
|
||||
b = tilemap[index * 16 + 15 - py * 2]
|
||||
for px in range(8):
|
||||
bit = 0x80 >> px
|
||||
if attr & 0x20:
|
||||
bit = 0x01 << px
|
||||
c = (attr & 7) << 2
|
||||
if a & bit:
|
||||
c |= 1
|
||||
if b & bit:
|
||||
c |= 2
|
||||
img.putpixel((x+px, y+py), c)
|
||||
for x in range(16):
|
||||
for y in range(16):
|
||||
idx = x+y*16
|
||||
metatiles = metatile_info[idx*4:idx*4+4]
|
||||
attrtiles = attrtile_info[idx*4:idx*4+4]
|
||||
drawTile(x * 16 + 0, y * 16 + 0, metatiles[0], attrtiles[0])
|
||||
drawTile(x * 16 + 8, y * 16 + 0, metatiles[1], attrtiles[1])
|
||||
drawTile(x * 16 + 0, y * 16 + 8, metatiles[2], attrtiles[2])
|
||||
drawTile(x * 16 + 8, y * 16 + 8, metatiles[3], attrtiles[3])
|
||||
img.save("%s/overworld/export/%s" % (path, image_filename))
|
||||
|
||||
world = {
|
||||
"maps": [
|
||||
{"fileName": "%02X.json" % (n), "height": 128, "width": 160, "x": (n & 0x0F) * 160, "y": (n >> 4) * 128}
|
||||
for n in range(0x100)
|
||||
],
|
||||
"onlyShowAdjacentMaps": False,
|
||||
"type": "world"
|
||||
}
|
||||
json.dump(world, open("%s/overworld/export/world.world" % (path), "wt"))
|
||||
|
||||
|
||||
def isNormalOverworld(rom):
|
||||
return len(RoomEditor(rom, 0x010).getWarps()) > 0
|
||||
124
worlds/ladx/LADXR/patches/overworld/dive/00.json
Normal file
124
worlds/ladx/LADXR/patches/overworld/dive/00.json
Normal file
@@ -0,0 +1,124 @@
|
||||
{ "compressionlevel":-1,
|
||||
"editorsettings":
|
||||
{
|
||||
"export":
|
||||
{
|
||||
"target":"."
|
||||
}
|
||||
},
|
||||
"height":8,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 125, 126, 1, 129, 78, 78, 78, 130, 1, 125, 240, 240, 240, 56, 11, 11, 11, 57, 240, 240, 2, 2, 30, 47, 73, 225, 74, 79, 94, 2, 2, 2, 56, 58, 226, 225, 59, 60, 57, 2, 2, 2, 56, 10, 10, 10, 10, 10, 123, 123, 2, 2, 56, 10, 10, 10, 10, 10, 57, 2, 2, 2, 47, 48, 48, 48, 48, 48, 79, 2],
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"Tiles",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":2,
|
||||
"name":"EntityLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":16,
|
||||
"id":1,
|
||||
"name":"HEART_PIECE",
|
||||
"rotation":0,
|
||||
"type":"entity",
|
||||
"visible":true,
|
||||
"width":16,
|
||||
"x":64,
|
||||
"y":32
|
||||
},
|
||||
{
|
||||
"height":16,
|
||||
"id":2,
|
||||
"name":"CROW",
|
||||
"rotation":0,
|
||||
"type":"entity",
|
||||
"visible":true,
|
||||
"width":16,
|
||||
"x":96,
|
||||
"y":32
|
||||
},
|
||||
{
|
||||
"height":16,
|
||||
"id":3,
|
||||
"name":"MINI_MOLDORM",
|
||||
"rotation":0,
|
||||
"type":"entity",
|
||||
"visible":true,
|
||||
"width":16,
|
||||
"x":112,
|
||||
"y":96
|
||||
},
|
||||
{
|
||||
"height":8,
|
||||
"id":4,
|
||||
"name":"1:07:23a:58:10",
|
||||
"rotation":0,
|
||||
"type":"warp",
|
||||
"visible":true,
|
||||
"width":8,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":1,
|
||||
"nextobjectid":5,
|
||||
"orientation":"orthogonal",
|
||||
"properties":[
|
||||
{
|
||||
"name":"animationset",
|
||||
"type":"string",
|
||||
"value":"0B"
|
||||
},
|
||||
{
|
||||
"name":"attribset",
|
||||
"type":"string",
|
||||
"value":"25:3400"
|
||||
},
|
||||
{
|
||||
"name":"palette",
|
||||
"type":"string",
|
||||
"value":"0F"
|
||||
},
|
||||
{
|
||||
"name":"tileset",
|
||||
"type":"string",
|
||||
"value":"1C"
|
||||
}],
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"1.4.3",
|
||||
"tileheight":16,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":16,
|
||||
"firstgid":1,
|
||||
"image":"tiles_1c_0b_0f_25_3400.png",
|
||||
"imageheight":256,
|
||||
"imagewidth":256,
|
||||
"margin":0,
|
||||
"name":"main",
|
||||
"spacing":0,
|
||||
"tilecount":256,
|
||||
"tileheight":16,
|
||||
"tilewidth":16
|
||||
}],
|
||||
"tilewidth":16,
|
||||
"type":"map",
|
||||
"version":1.4,
|
||||
"width":10
|
||||
}
|
||||
102
worlds/ladx/LADXR/patches/overworld/dive/01.json
Normal file
102
worlds/ladx/LADXR/patches/overworld/dive/01.json
Normal file
@@ -0,0 +1,102 @@
|
||||
{ "compressionlevel":-1,
|
||||
"editorsettings":
|
||||
{
|
||||
"export":
|
||||
{
|
||||
"target":"."
|
||||
}
|
||||
},
|
||||
"height":8,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[125, 126, 1, 1, 1, 1, 1, 1, 1, 125, 29, 29, 126, 1, 1, 129, 78, 130, 125, 29, 240, 240, 240, 240, 240, 56, 4, 57, 240, 240, 2, 2, 30, 81, 81, 47, 48, 79, 94, 2, 2, 2, 56, 4, 4, 206, 226, 216, 57, 2, 123, 123, 123, 11, 4, 4, 4, 4, 57, 2, 2, 2, 56, 11, 11, 11, 11, 11, 57, 2, 2, 2, 47, 48, 48, 48, 48, 48, 79, 2],
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"Tiles",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":2,
|
||||
"name":"EntityLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":16,
|
||||
"id":1,
|
||||
"name":"CROW",
|
||||
"rotation":0,
|
||||
"type":"entity",
|
||||
"visible":true,
|
||||
"width":16,
|
||||
"x":32,
|
||||
"y":80
|
||||
},
|
||||
{
|
||||
"height":8,
|
||||
"id":2,
|
||||
"name":"1:07:23d:58:10",
|
||||
"rotation":0,
|
||||
"type":"warp",
|
||||
"visible":true,
|
||||
"width":8,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":1,
|
||||
"nextobjectid":3,
|
||||
"orientation":"orthogonal",
|
||||
"properties":[
|
||||
{
|
||||
"name":"animationset",
|
||||
"type":"string",
|
||||
"value":"0B"
|
||||
},
|
||||
{
|
||||
"name":"attribset",
|
||||
"type":"string",
|
||||
"value":"25:3400"
|
||||
},
|
||||
{
|
||||
"name":"palette",
|
||||
"type":"string",
|
||||
"value":"0F"
|
||||
},
|
||||
{
|
||||
"name":"tileset",
|
||||
"type":"string",
|
||||
"value":"1C"
|
||||
}],
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"1.4.3",
|
||||
"tileheight":16,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":16,
|
||||
"firstgid":1,
|
||||
"image":"tiles_1c_0b_0f_25_3400.png",
|
||||
"imageheight":256,
|
||||
"imagewidth":256,
|
||||
"margin":0,
|
||||
"name":"main",
|
||||
"spacing":0,
|
||||
"tilecount":256,
|
||||
"tileheight":16,
|
||||
"tilewidth":16
|
||||
}],
|
||||
"tilewidth":16,
|
||||
"type":"map",
|
||||
"version":1.4,
|
||||
"width":10
|
||||
}
|
||||
113
worlds/ladx/LADXR/patches/overworld/dive/06.json
Normal file
113
worlds/ladx/LADXR/patches/overworld/dive/06.json
Normal file
@@ -0,0 +1,113 @@
|
||||
{ "compressionlevel":-1,
|
||||
"editorsettings":
|
||||
{
|
||||
"export":
|
||||
{
|
||||
"target":"."
|
||||
}
|
||||
},
|
||||
"height":8,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[1, 1, 1, 1, 6, 7, 8, 1, 1, 1, 125, 126, 1, 129, 100, 101, 102, 130, 125, 126, 240, 240, 240, 56, 114, 29, 128, 57, 240, 240, 230, 230, 30, 56, 170, 171, 192, 57, 94, 230, 230, 230, 56, 47, 73, 225, 74, 79, 57, 230, 230, 230, 56, 63, 59, 225, 59, 64, 57, 230, 230, 30, 47, 48, 73, 225, 74, 48, 79, 94, 230, 56, 63, 59, 59, 225, 59, 59, 64, 57],
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"Tiles",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":2,
|
||||
"name":"EntityLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":16,
|
||||
"id":1,
|
||||
"name":"EGG_SONG_EVENT",
|
||||
"rotation":0,
|
||||
"type":"entity",
|
||||
"visible":true,
|
||||
"width":16,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"height":8,
|
||||
"id":2,
|
||||
"name":"1:08:270:50:7c",
|
||||
"rotation":0,
|
||||
"type":"warp",
|
||||
"visible":true,
|
||||
"width":8,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"height":16,
|
||||
"id":3,
|
||||
"name":"E1",
|
||||
"rotation":0,
|
||||
"type":"hidden_tile",
|
||||
"visible":true,
|
||||
"width":16,
|
||||
"x":80,
|
||||
"y":48
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":1,
|
||||
"nextobjectid":4,
|
||||
"orientation":"orthogonal",
|
||||
"properties":[
|
||||
{
|
||||
"name":"animationset",
|
||||
"type":"string",
|
||||
"value":"0B"
|
||||
},
|
||||
{
|
||||
"name":"attribset",
|
||||
"type":"string",
|
||||
"value":"27:1620"
|
||||
},
|
||||
{
|
||||
"name":"palette",
|
||||
"type":"string",
|
||||
"value":"13"
|
||||
},
|
||||
{
|
||||
"name":"tileset",
|
||||
"type":"string",
|
||||
"value":"3C"
|
||||
}],
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"1.4.3",
|
||||
"tileheight":16,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":16,
|
||||
"firstgid":1,
|
||||
"image":"tiles_3c_0b_13_27_1620.png",
|
||||
"imageheight":256,
|
||||
"imagewidth":256,
|
||||
"margin":0,
|
||||
"name":"main",
|
||||
"spacing":0,
|
||||
"tilecount":256,
|
||||
"tileheight":16,
|
||||
"tilewidth":16
|
||||
}],
|
||||
"tilewidth":16,
|
||||
"type":"map",
|
||||
"version":1.4,
|
||||
"width":10
|
||||
}
|
||||
91
worlds/ladx/LADXR/patches/overworld/dive/16.json
Normal file
91
worlds/ladx/LADXR/patches/overworld/dive/16.json
Normal file
@@ -0,0 +1,91 @@
|
||||
{ "compressionlevel":-1,
|
||||
"editorsettings":
|
||||
{
|
||||
"export":
|
||||
{
|
||||
"target":"."
|
||||
}
|
||||
},
|
||||
"height":8,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[30, 47, 48, 48, 73, 225, 48, 48, 48, 79, 56, 63, 59, 59, 59, 225, 59, 59, 59, 64, 56, 58, 59, 59, 59, 225, 59, 59, 59, 60, 47, 48, 48, 48, 73, 225, 74, 48, 48, 48, 58, 59, 226, 59, 59, 225, 59, 59, 59, 59, 201, 213, 4, 4, 4, 4, 4, 4, 4, 201, 201, 4, 4, 4, 4, 4, 4, 4, 4, 201, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48],
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"Tiles",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":2,
|
||||
"name":"EntityLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"0:00:082:48:30",
|
||||
"rotation":0,
|
||||
"type":"warp",
|
||||
"visible":true,
|
||||
"width":8,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":1,
|
||||
"nextobjectid":2,
|
||||
"orientation":"orthogonal",
|
||||
"properties":[
|
||||
{
|
||||
"name":"animationset",
|
||||
"type":"string",
|
||||
"value":"0B"
|
||||
},
|
||||
{
|
||||
"name":"attribset",
|
||||
"type":"string",
|
||||
"value":"27:1620"
|
||||
},
|
||||
{
|
||||
"name":"palette",
|
||||
"type":"string",
|
||||
"value":"13"
|
||||
},
|
||||
{
|
||||
"name":"tileset",
|
||||
"type":"string",
|
||||
"value":"3C"
|
||||
}],
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"1.4.3",
|
||||
"tileheight":16,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":16,
|
||||
"firstgid":1,
|
||||
"image":"tiles_3c_0b_13_27_1620.png",
|
||||
"imageheight":256,
|
||||
"imagewidth":256,
|
||||
"margin":0,
|
||||
"name":"main",
|
||||
"spacing":0,
|
||||
"tilecount":256,
|
||||
"tileheight":16,
|
||||
"tilewidth":16
|
||||
}],
|
||||
"tilewidth":16,
|
||||
"type":"map",
|
||||
"version":1.4,
|
||||
"width":10
|
||||
}
|
||||
91
worlds/ladx/LADXR/patches/overworld/dive/62.json
Normal file
91
worlds/ladx/LADXR/patches/overworld/dive/62.json
Normal file
@@ -0,0 +1,91 @@
|
||||
{ "compressionlevel":-1,
|
||||
"editorsettings":
|
||||
{
|
||||
"export":
|
||||
{
|
||||
"target":"."
|
||||
}
|
||||
},
|
||||
"height":8,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[2, 2, 2, 115, 117, 117, 117, 116, 2, 2, 2, 2, 2, 115, 118, 215, 119, 116, 2, 2, 2, 2, 30, 115, 117, 226, 117, 116, 94, 2, 2, 2, 56, 183, 117, 120, 117, 184, 57, 2, 2, 2, 56, 4, 4, 4, 4, 4, 57, 2, 2, 2, 56, 4, 4, 4, 4, 4, 57, 2, 2, 2, 47, 48, 73, 225, 74, 48, 79, 2, 2, 2, 63, 59, 59, 225, 59, 59, 64, 2],
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"Tiles",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":2,
|
||||
"name":"EntityLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"1:06:20e:50:7c",
|
||||
"rotation":0,
|
||||
"type":"warp",
|
||||
"visible":true,
|
||||
"width":8,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":1,
|
||||
"nextobjectid":2,
|
||||
"orientation":"orthogonal",
|
||||
"properties":[
|
||||
{
|
||||
"name":"animationset",
|
||||
"type":"string",
|
||||
"value":"00"
|
||||
},
|
||||
{
|
||||
"name":"attribset",
|
||||
"type":"string",
|
||||
"value":"27:1E40"
|
||||
},
|
||||
{
|
||||
"name":"palette",
|
||||
"type":"string",
|
||||
"value":"16"
|
||||
},
|
||||
{
|
||||
"name":"tileset",
|
||||
"type":"string",
|
||||
"value":"30"
|
||||
}],
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"1.4.3",
|
||||
"tileheight":16,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":16,
|
||||
"firstgid":1,
|
||||
"image":"tiles_30_00_16_27_1e40.png",
|
||||
"imageheight":256,
|
||||
"imagewidth":256,
|
||||
"margin":0,
|
||||
"name":"main",
|
||||
"spacing":0,
|
||||
"tilecount":256,
|
||||
"tileheight":16,
|
||||
"tilewidth":16
|
||||
}],
|
||||
"tilewidth":16,
|
||||
"type":"map",
|
||||
"version":1.4,
|
||||
"width":10
|
||||
}
|
||||
91
worlds/ladx/LADXR/patches/overworld/dive/6C.json
Normal file
91
worlds/ladx/LADXR/patches/overworld/dive/6C.json
Normal file
@@ -0,0 +1,91 @@
|
||||
{ "compressionlevel":-1,
|
||||
"editorsettings":
|
||||
{
|
||||
"export":
|
||||
{
|
||||
"target":"."
|
||||
}
|
||||
},
|
||||
"height":8,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 44, 45, 45, 46, 15, 15, 15, 15, 15, 15, 56, 161, 199, 57, 15, 15, 15, 15, 15, 15, 56, 5, 5, 57, 15, 15, 15, 15, 15, 15, 52, 48, 48, 53, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15],
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"Tiles",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":2,
|
||||
"name":"EntityLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"1:05:1b0:78:10",
|
||||
"rotation":0,
|
||||
"type":"warp",
|
||||
"visible":true,
|
||||
"width":8,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":1,
|
||||
"nextobjectid":2,
|
||||
"orientation":"orthogonal",
|
||||
"properties":[
|
||||
{
|
||||
"name":"animationset",
|
||||
"type":"string",
|
||||
"value":"03"
|
||||
},
|
||||
{
|
||||
"name":"attribset",
|
||||
"type":"string",
|
||||
"value":"22:0000"
|
||||
},
|
||||
{
|
||||
"name":"palette",
|
||||
"type":"string",
|
||||
"value":"16"
|
||||
},
|
||||
{
|
||||
"name":"tileset",
|
||||
"type":"string",
|
||||
"value":"0F"
|
||||
}],
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"1.4.3",
|
||||
"tileheight":16,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":16,
|
||||
"firstgid":1,
|
||||
"image":"tiles_0f_03_16_22_0000.png",
|
||||
"imageheight":256,
|
||||
"imagewidth":256,
|
||||
"margin":0,
|
||||
"name":"main",
|
||||
"spacing":0,
|
||||
"tilecount":256,
|
||||
"tileheight":16,
|
||||
"tilewidth":16
|
||||
}],
|
||||
"tilewidth":16,
|
||||
"type":"map",
|
||||
"version":1.4,
|
||||
"width":10
|
||||
}
|
||||
91
worlds/ladx/LADXR/patches/overworld/dive/71.json
Normal file
91
worlds/ladx/LADXR/patches/overworld/dive/71.json
Normal file
@@ -0,0 +1,91 @@
|
||||
{ "compressionlevel":-1,
|
||||
"editorsettings":
|
||||
{
|
||||
"export":
|
||||
{
|
||||
"target":"."
|
||||
}
|
||||
},
|
||||
"height":8,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[3, 56, 63, 59, 59, 59, 59, 59, 64, 48, 3, 56, 58, 183, 59, 226, 59, 183, 60, 10, 3, 56, 33, 184, 10, 10, 10, 184, 10, 10, 3, 56, 33, 10, 10, 10, 10, 10, 10, 4, 3, 56, 201, 10, 10, 10, 10, 10, 4, 4, 3, 56, 201, 201, 10, 10, 10, 10, 10, 4, 3, 47, 48, 48, 48, 48, 48, 48, 48, 48, 3, 63, 59, 59, 59, 59, 59, 59, 59, 59],
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"Tiles",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":2,
|
||||
"name":"EntityLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"1:07:25d:50:7c",
|
||||
"rotation":0,
|
||||
"type":"warp",
|
||||
"visible":true,
|
||||
"width":8,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":1,
|
||||
"nextobjectid":2,
|
||||
"orientation":"orthogonal",
|
||||
"properties":[
|
||||
{
|
||||
"name":"animationset",
|
||||
"type":"string",
|
||||
"value":"00"
|
||||
},
|
||||
{
|
||||
"name":"attribset",
|
||||
"type":"string",
|
||||
"value":"25:3400"
|
||||
},
|
||||
{
|
||||
"name":"palette",
|
||||
"type":"string",
|
||||
"value":"19"
|
||||
},
|
||||
{
|
||||
"name":"tileset",
|
||||
"type":"string",
|
||||
"value":"1C"
|
||||
}],
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"1.4.3",
|
||||
"tileheight":16,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":16,
|
||||
"firstgid":1,
|
||||
"image":"tiles_1c_00_19_25_3400.png",
|
||||
"imageheight":256,
|
||||
"imagewidth":256,
|
||||
"margin":0,
|
||||
"name":"main",
|
||||
"spacing":0,
|
||||
"tilecount":256,
|
||||
"tileheight":16,
|
||||
"tilewidth":16
|
||||
}],
|
||||
"tilewidth":16,
|
||||
"type":"map",
|
||||
"version":1.4,
|
||||
"width":10
|
||||
}
|
||||
80
worlds/ladx/LADXR/patches/overworld/dive/72.json
Normal file
80
worlds/ladx/LADXR/patches/overworld/dive/72.json
Normal file
@@ -0,0 +1,80 @@
|
||||
{ "compressionlevel":-1,
|
||||
"editorsettings":
|
||||
{
|
||||
"export":
|
||||
{
|
||||
"target":"."
|
||||
}
|
||||
},
|
||||
"height":8,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[48, 54, 58, 59, 59, 225, 59, 59, 60, 46, 4, 4, 4, 4, 4, 4, 4, 4, 4, 57, 4, 4, 4, 4, 4, 93, 93, 93, 4, 77, 4, 4, 12, 12, 4, 93, 93, 93, 93, 4, 4, 4, 12, 4, 4, 4, 93, 93, 4, 4, 4, 4, 12, 4, 4, 4, 4, 4, 4, 4, 48, 73, 225, 74, 48, 73, 75, 74, 48, 48, 59, 59, 225, 59, 59, 59, 59, 59, 59, 59],
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"Tiles",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":2,
|
||||
"name":"EntityLayer",
|
||||
"objects":[],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":1,
|
||||
"nextobjectid":1,
|
||||
"orientation":"orthogonal",
|
||||
"properties":[
|
||||
{
|
||||
"name":"animationset",
|
||||
"type":"string",
|
||||
"value":"00"
|
||||
},
|
||||
{
|
||||
"name":"attribset",
|
||||
"type":"string",
|
||||
"value":"22:0000"
|
||||
},
|
||||
{
|
||||
"name":"palette",
|
||||
"type":"string",
|
||||
"value":"16"
|
||||
},
|
||||
{
|
||||
"name":"tileset",
|
||||
"type":"string",
|
||||
"value":"0F"
|
||||
}],
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"1.4.3",
|
||||
"tileheight":16,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":16,
|
||||
"firstgid":1,
|
||||
"image":"tiles_0f_00_16_22_0000.png",
|
||||
"imageheight":256,
|
||||
"imagewidth":256,
|
||||
"margin":0,
|
||||
"name":"main",
|
||||
"spacing":0,
|
||||
"tilecount":256,
|
||||
"tileheight":16,
|
||||
"tilewidth":16
|
||||
}],
|
||||
"tilewidth":16,
|
||||
"type":"map",
|
||||
"version":1.4,
|
||||
"width":10
|
||||
}
|
||||
113
worlds/ladx/LADXR/patches/overworld/dive/73.json
Normal file
113
worlds/ladx/LADXR/patches/overworld/dive/73.json
Normal file
@@ -0,0 +1,113 @@
|
||||
{ "compressionlevel":-1,
|
||||
"editorsettings":
|
||||
{
|
||||
"export":
|
||||
{
|
||||
"target":"."
|
||||
}
|
||||
},
|
||||
"height":8,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[2, 2, 2, 180, 180, 180, 180, 180, 2, 2, 2, 2, 44, 180, 180, 180, 180, 180, 46, 2, 81, 81, 76, 174, 178, 232, 174, 178, 57, 2, 4, 4, 4, 175, 179, 228, 175, 179, 57, 2, 4, 4, 4, 4, 4, 4, 4, 4, 57, 2, 4, 4, 4, 4, 4, 4, 4, 4, 57, 2, 48, 48, 48, 48, 48, 48, 48, 48, 53, 2, 59, 59, 59, 59, 59, 59, 59, 59, 64, 2],
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"Tiles",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":2,
|
||||
"name":"EntityLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":16,
|
||||
"id":1,
|
||||
"name":"ARMOS_STATUE",
|
||||
"rotation":0,
|
||||
"type":"entity",
|
||||
"visible":true,
|
||||
"width":16,
|
||||
"x":64,
|
||||
"y":64
|
||||
},
|
||||
{
|
||||
"height":16,
|
||||
"id":2,
|
||||
"name":"ARMOS_STATUE",
|
||||
"rotation":0,
|
||||
"type":"entity",
|
||||
"visible":true,
|
||||
"width":16,
|
||||
"x":96,
|
||||
"y":64
|
||||
},
|
||||
{
|
||||
"height":8,
|
||||
"id":3,
|
||||
"name":"1:05:1d4:50:7c",
|
||||
"rotation":0,
|
||||
"type":"warp",
|
||||
"visible":true,
|
||||
"width":8,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":1,
|
||||
"nextobjectid":4,
|
||||
"orientation":"orthogonal",
|
||||
"properties":[
|
||||
{
|
||||
"name":"animationset",
|
||||
"type":"string",
|
||||
"value":"00"
|
||||
},
|
||||
{
|
||||
"name":"attribset",
|
||||
"type":"string",
|
||||
"value":"25:3C00"
|
||||
},
|
||||
{
|
||||
"name":"palette",
|
||||
"type":"string",
|
||||
"value":"1C"
|
||||
},
|
||||
{
|
||||
"name":"tileset",
|
||||
"type":"string",
|
||||
"value":"2A"
|
||||
}],
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"1.4.3",
|
||||
"tileheight":16,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":16,
|
||||
"firstgid":1,
|
||||
"image":"tiles_2a_00_1c_25_3c00.png",
|
||||
"imageheight":256,
|
||||
"imagewidth":256,
|
||||
"margin":0,
|
||||
"name":"main",
|
||||
"spacing":0,
|
||||
"tilecount":256,
|
||||
"tileheight":16,
|
||||
"tilewidth":16
|
||||
}],
|
||||
"tilewidth":16,
|
||||
"type":"map",
|
||||
"version":1.4,
|
||||
"width":10
|
||||
}
|
||||
91
worlds/ladx/LADXR/patches/overworld/dive/81.json
Normal file
91
worlds/ladx/LADXR/patches/overworld/dive/81.json
Normal file
@@ -0,0 +1,91 @@
|
||||
{ "compressionlevel":-1,
|
||||
"editorsettings":
|
||||
{
|
||||
"export":
|
||||
{
|
||||
"target":"."
|
||||
}
|
||||
},
|
||||
"height":8,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[11, 57, 63, 59, 214, 215, 216, 59, 64, 63, 11, 57, 58, 59, 206, 226, 207, 59, 60, 63, 11, 57, 15, 15, 15, 12, 15, 15, 15, 58, 11, 57, 15, 15, 15, 12, 15, 15, 15, 5, 11, 57, 15, 15, 15, 12, 15, 15, 5, 5, 55, 53, 15, 15, 15, 12, 12, 12, 5, 5, 38, 39, 10, 15, 15, 15, 15, 15, 15, 38, 40, 42, 39, 38, 39, 38, 39, 38, 39, 40],
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"Tiles",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":2,
|
||||
"name":"EntityLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"1:03:17a:50:7c",
|
||||
"rotation":0,
|
||||
"type":"warp",
|
||||
"visible":true,
|
||||
"width":8,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":1,
|
||||
"nextobjectid":2,
|
||||
"orientation":"orthogonal",
|
||||
"properties":[
|
||||
{
|
||||
"name":"animationset",
|
||||
"type":"string",
|
||||
"value":"03"
|
||||
},
|
||||
{
|
||||
"name":"attribset",
|
||||
"type":"string",
|
||||
"value":"27:2640"
|
||||
},
|
||||
{
|
||||
"name":"palette",
|
||||
"type":"string",
|
||||
"value":"01"
|
||||
},
|
||||
{
|
||||
"name":"tileset",
|
||||
"type":"string",
|
||||
"value":"34"
|
||||
}],
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"1.4.3",
|
||||
"tileheight":16,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":16,
|
||||
"firstgid":1,
|
||||
"image":"tiles_34_03_01_27_2640.png",
|
||||
"imageheight":256,
|
||||
"imagewidth":256,
|
||||
"margin":0,
|
||||
"name":"main",
|
||||
"spacing":0,
|
||||
"tilecount":256,
|
||||
"tileheight":16,
|
||||
"tilewidth":16
|
||||
}],
|
||||
"tilewidth":16,
|
||||
"type":"map",
|
||||
"version":1.4,
|
||||
"width":10
|
||||
}
|
||||
91
worlds/ladx/LADXR/patches/overworld/dive/82.json
Normal file
91
worlds/ladx/LADXR/patches/overworld/dive/82.json
Normal file
@@ -0,0 +1,91 @@
|
||||
{ "compressionlevel":-1,
|
||||
"editorsettings":
|
||||
{
|
||||
"export":
|
||||
{
|
||||
"target":"."
|
||||
}
|
||||
},
|
||||
"height":8,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[59, 59, 225, 59, 59, 59, 59, 59, 59, 59, 59, 59, 225, 59, 59, 59, 59, 59, 59, 59, 59, 59, 225, 59, 187, 59, 59, 59, 59, 59, 5, 5, 12, 10, 93, 10, 5, 5, 5, 5, 5, 5, 12, 5, 10, 5, 11, 11, 11, 5, 5, 5, 12, 5, 5, 11, 93, 93, 93, 11, 39, 5, 5, 5, 5, 11, 93, 93, 93, 11, 41, 5, 5, 5, 5, 5, 11, 11, 11, 62],
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"Tiles",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":2,
|
||||
"name":"EntityLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"0:00:016:28:50",
|
||||
"rotation":0,
|
||||
"type":"warp",
|
||||
"visible":true,
|
||||
"width":8,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":1,
|
||||
"nextobjectid":2,
|
||||
"orientation":"orthogonal",
|
||||
"properties":[
|
||||
{
|
||||
"name":"animationset",
|
||||
"type":"string",
|
||||
"value":"00"
|
||||
},
|
||||
{
|
||||
"name":"attribset",
|
||||
"type":"string",
|
||||
"value":"25:0C00"
|
||||
},
|
||||
{
|
||||
"name":"palette",
|
||||
"type":"string",
|
||||
"value":"01"
|
||||
},
|
||||
{
|
||||
"name":"tileset",
|
||||
"type":"string",
|
||||
"value":"0F"
|
||||
}],
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"1.4.3",
|
||||
"tileheight":16,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":16,
|
||||
"firstgid":1,
|
||||
"image":"tiles_0f_00_01_25_0c00.png",
|
||||
"imageheight":256,
|
||||
"imagewidth":256,
|
||||
"margin":0,
|
||||
"name":"main",
|
||||
"spacing":0,
|
||||
"tilecount":256,
|
||||
"tileheight":16,
|
||||
"tilewidth":16
|
||||
}],
|
||||
"tilewidth":16,
|
||||
"type":"map",
|
||||
"version":1.4,
|
||||
"width":10
|
||||
}
|
||||
91
worlds/ladx/LADXR/patches/overworld/dive/83.json
Normal file
91
worlds/ladx/LADXR/patches/overworld/dive/83.json
Normal file
@@ -0,0 +1,91 @@
|
||||
{ "compressionlevel":-1,
|
||||
"editorsettings":
|
||||
{
|
||||
"export":
|
||||
{
|
||||
"target":"."
|
||||
}
|
||||
},
|
||||
"height":8,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[59, 64, 38, 39, 72, 59, 59, 59, 59, 60, 59, 64, 40, 41, 57, 183, 184, 103, 82, 82, 59, 60, 212, 212, 57, 104, 228, 105, 82, 203, 5, 5, 5, 5, 57, 15, 15, 15, 15, 203, 5, 5, 62, 225, 53, 15, 15, 15, 15, 203, 5, 5, 57, 15, 15, 15, 15, 15, 82, 203, 5, 33, 57, 15, 15, 15, 15, 82, 82, 203, 48, 61, 51, 45, 45, 45, 45, 45, 45, 45],
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"Tiles",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":2,
|
||||
"name":"EntityLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"1:04:1a1:50:7c",
|
||||
"rotation":0,
|
||||
"type":"warp",
|
||||
"visible":true,
|
||||
"width":8,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":1,
|
||||
"nextobjectid":2,
|
||||
"orientation":"orthogonal",
|
||||
"properties":[
|
||||
{
|
||||
"name":"animationset",
|
||||
"type":"string",
|
||||
"value":"03"
|
||||
},
|
||||
{
|
||||
"name":"attribset",
|
||||
"type":"string",
|
||||
"value":"22:2400"
|
||||
},
|
||||
{
|
||||
"name":"palette",
|
||||
"type":"string",
|
||||
"value":"09"
|
||||
},
|
||||
{
|
||||
"name":"tileset",
|
||||
"type":"string",
|
||||
"value":"3A"
|
||||
}],
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"1.4.3",
|
||||
"tileheight":16,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":16,
|
||||
"firstgid":1,
|
||||
"image":"tiles_3a_03_09_22_2400.png",
|
||||
"imageheight":256,
|
||||
"imagewidth":256,
|
||||
"margin":0,
|
||||
"name":"main",
|
||||
"spacing":0,
|
||||
"tilecount":256,
|
||||
"tileheight":16,
|
||||
"tilewidth":16
|
||||
}],
|
||||
"tilewidth":16,
|
||||
"type":"map",
|
||||
"version":1.4,
|
||||
"width":10
|
||||
}
|
||||
91
worlds/ladx/LADXR/patches/overworld/dive/91.json
Normal file
91
worlds/ladx/LADXR/patches/overworld/dive/91.json
Normal file
@@ -0,0 +1,91 @@
|
||||
{ "compressionlevel":-1,
|
||||
"editorsettings":
|
||||
{
|
||||
"export":
|
||||
{
|
||||
"target":"."
|
||||
}
|
||||
},
|
||||
"height":8,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[43, 42, 63, 59, 59, 59, 59, 59, 64, 42, 42, 43, 63, 59, 183, 216, 183, 59, 64, 40, 43, 41, 58, 183, 184, 226, 184, 183, 60, 11, 41, 82, 82, 28, 28, 28, 28, 82, 19, 5, 82, 28, 28, 28, 28, 28, 28, 27, 23, 5, 82, 82, 28, 28, 82, 82, 28, 19, 33, 5, 82, 82, 82, 28, 28, 28, 28, 19, 33, 5, 38, 39, 38, 39, 38, 39, 38, 39, 38, 39],
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"Tiles",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":2,
|
||||
"name":"EntityLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"1:01:136:50:7c",
|
||||
"rotation":0,
|
||||
"type":"warp",
|
||||
"visible":true,
|
||||
"width":8,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":1,
|
||||
"nextobjectid":2,
|
||||
"orientation":"orthogonal",
|
||||
"properties":[
|
||||
{
|
||||
"name":"animationset",
|
||||
"type":"string",
|
||||
"value":"03"
|
||||
},
|
||||
{
|
||||
"name":"attribset",
|
||||
"type":"string",
|
||||
"value":"22:3400"
|
||||
},
|
||||
{
|
||||
"name":"palette",
|
||||
"type":"string",
|
||||
"value":"0E"
|
||||
},
|
||||
{
|
||||
"name":"tileset",
|
||||
"type":"string",
|
||||
"value":"36"
|
||||
}],
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"1.4.3",
|
||||
"tileheight":16,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":16,
|
||||
"firstgid":1,
|
||||
"image":"tiles_36_03_0e_22_3400.png",
|
||||
"imageheight":256,
|
||||
"imagewidth":256,
|
||||
"margin":0,
|
||||
"name":"main",
|
||||
"spacing":0,
|
||||
"tilecount":256,
|
||||
"tileheight":16,
|
||||
"tilewidth":16
|
||||
}],
|
||||
"tilewidth":16,
|
||||
"type":"map",
|
||||
"version":1.4,
|
||||
"width":10
|
||||
}
|
||||
102
worlds/ladx/LADXR/patches/overworld/dive/92.json
Normal file
102
worlds/ladx/LADXR/patches/overworld/dive/92.json
Normal file
@@ -0,0 +1,102 @@
|
||||
{ "compressionlevel":-1,
|
||||
"editorsettings":
|
||||
{
|
||||
"export":
|
||||
{
|
||||
"target":"."
|
||||
}
|
||||
},
|
||||
"height":8,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[39, 5, 5, 5, 5, 5, 5, 5, 5, 51, 41, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 11, 11, 11, 5, 38, 70, 39, 5, 5, 5, 83, 83, 83, 11, 40, 226, 41, 5, 5, 5, 92, 227, 92, 11, 11, 93, 11, 5, 5, 5, 5, 5, 5, 11, 11, 11, 5, 10, 5, 5, 5, 5, 5, 5, 5, 5, 10, 10, 38, 39, 5, 5, 5, 5, 5, 5, 10, 111],
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"Tiles",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":2,
|
||||
"name":"EntityLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"1:10:2cb:50:7c",
|
||||
"rotation":0,
|
||||
"type":"warp",
|
||||
"visible":true,
|
||||
"width":8,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"height":8,
|
||||
"id":2,
|
||||
"name":"1:0e:2a1:50:7c",
|
||||
"rotation":0,
|
||||
"type":"warp",
|
||||
"visible":true,
|
||||
"width":8,
|
||||
"x":0,
|
||||
"y":8
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":1,
|
||||
"nextobjectid":3,
|
||||
"orientation":"orthogonal",
|
||||
"properties":[
|
||||
{
|
||||
"name":"animationset",
|
||||
"type":"string",
|
||||
"value":"03"
|
||||
},
|
||||
{
|
||||
"name":"attribset",
|
||||
"type":"string",
|
||||
"value":"22:0000"
|
||||
},
|
||||
{
|
||||
"name":"palette",
|
||||
"type":"string",
|
||||
"value":"0E"
|
||||
},
|
||||
{
|
||||
"name":"tileset",
|
||||
"type":"string",
|
||||
"value":"0F"
|
||||
}],
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"1.4.3",
|
||||
"tileheight":16,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":16,
|
||||
"firstgid":1,
|
||||
"image":"tiles_0f_03_0e_22_0000.png",
|
||||
"imageheight":256,
|
||||
"imagewidth":256,
|
||||
"margin":0,
|
||||
"name":"main",
|
||||
"spacing":0,
|
||||
"tilecount":256,
|
||||
"tileheight":16,
|
||||
"tilewidth":16
|
||||
}],
|
||||
"tilewidth":16,
|
||||
"type":"map",
|
||||
"version":1.4,
|
||||
"width":10
|
||||
}
|
||||
91
worlds/ladx/LADXR/patches/overworld/dive/93.json
Normal file
91
worlds/ladx/LADXR/patches/overworld/dive/93.json
Normal file
@@ -0,0 +1,91 @@
|
||||
{ "compressionlevel":-1,
|
||||
"editorsettings":
|
||||
{
|
||||
"export":
|
||||
{
|
||||
"target":"."
|
||||
}
|
||||
},
|
||||
"height":8,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[45, 50, 63, 59, 59, 59, 59, 59, 64, 63, 5, 5, 58, 107, 109, 109, 109, 107, 60, 63, 5, 5, 183, 108, 99, 228, 99, 108, 183, 63, 5, 5, 184, 18, 28, 28, 28, 19, 184, 63, 5, 5, 5, 22, 17, 17, 17, 23, 5, 63, 10, 5, 10, 183, 5, 5, 5, 183, 5, 58, 10, 10, 10, 184, 5, 5, 5, 184, 5, 38, 111, 38, 39, 38, 39, 38, 39, 38, 39, 40],
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"Tiles",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":2,
|
||||
"name":"EntityLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"1:02:152:50:7c",
|
||||
"rotation":0,
|
||||
"type":"warp",
|
||||
"visible":true,
|
||||
"width":8,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":1,
|
||||
"nextobjectid":2,
|
||||
"orientation":"orthogonal",
|
||||
"properties":[
|
||||
{
|
||||
"name":"animationset",
|
||||
"type":"string",
|
||||
"value":"03"
|
||||
},
|
||||
{
|
||||
"name":"attribset",
|
||||
"type":"string",
|
||||
"value":"22:1800"
|
||||
},
|
||||
{
|
||||
"name":"palette",
|
||||
"type":"string",
|
||||
"value":"01"
|
||||
},
|
||||
{
|
||||
"name":"tileset",
|
||||
"type":"string",
|
||||
"value":"2E"
|
||||
}],
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"1.4.3",
|
||||
"tileheight":16,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":16,
|
||||
"firstgid":1,
|
||||
"image":"tiles_2e_03_01_22_1800.png",
|
||||
"imageheight":256,
|
||||
"imagewidth":256,
|
||||
"margin":0,
|
||||
"name":"main",
|
||||
"spacing":0,
|
||||
"tilecount":256,
|
||||
"tileheight":16,
|
||||
"tilewidth":16
|
||||
}],
|
||||
"tilewidth":16,
|
||||
"type":"map",
|
||||
"version":1.4,
|
||||
"width":10
|
||||
}
|
||||
91
worlds/ladx/LADXR/patches/overworld/dive/A1.json
Normal file
91
worlds/ladx/LADXR/patches/overworld/dive/A1.json
Normal file
@@ -0,0 +1,91 @@
|
||||
{ "compressionlevel":-1,
|
||||
"editorsettings":
|
||||
{
|
||||
"export":
|
||||
{
|
||||
"target":"."
|
||||
}
|
||||
},
|
||||
"height":8,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[43, 42, 44, 45, 45, 45, 46, 42, 43, 42, 42, 43, 47, 48, 48, 48, 79, 40, 41, 40, 43, 41, 58, 99, 228, 99, 60, 11, 11, 5, 41, 11, 11, 10, 10, 10, 10, 10, 10, 10, 111, 11, 183, 10, 10, 10, 183, 10, 10, 10, 111, 5, 184, 10, 10, 10, 184, 10, 5, 5, 111, 5, 5, 10, 10, 10, 10, 5, 5, 5, 48, 48, 73, 75, 74, 48, 48, 48, 48, 48],
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"Tiles",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":2,
|
||||
"name":"EntityLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"1:00:117:50:7c",
|
||||
"rotation":0,
|
||||
"type":"warp",
|
||||
"visible":true,
|
||||
"width":8,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":1,
|
||||
"nextobjectid":2,
|
||||
"orientation":"orthogonal",
|
||||
"properties":[
|
||||
{
|
||||
"name":"animationset",
|
||||
"type":"string",
|
||||
"value":"00"
|
||||
},
|
||||
{
|
||||
"name":"attribset",
|
||||
"type":"string",
|
||||
"value":"22:0C00"
|
||||
},
|
||||
{
|
||||
"name":"palette",
|
||||
"type":"string",
|
||||
"value":"01"
|
||||
},
|
||||
{
|
||||
"name":"tileset",
|
||||
"type":"string",
|
||||
"value":"24"
|
||||
}],
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"1.4.3",
|
||||
"tileheight":16,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":16,
|
||||
"firstgid":1,
|
||||
"image":"tiles_24_00_01_22_0c00.png",
|
||||
"imageheight":256,
|
||||
"imagewidth":256,
|
||||
"margin":0,
|
||||
"name":"main",
|
||||
"spacing":0,
|
||||
"tilecount":256,
|
||||
"tileheight":16,
|
||||
"tilewidth":16
|
||||
}],
|
||||
"tilewidth":16,
|
||||
"type":"map",
|
||||
"version":1.4,
|
||||
"width":10
|
||||
}
|
||||
113
worlds/ladx/LADXR/patches/overworld/dive/A2.json
Normal file
113
worlds/ladx/LADXR/patches/overworld/dive/A2.json
Normal file
@@ -0,0 +1,113 @@
|
||||
{ "compressionlevel":-1,
|
||||
"editorsettings":
|
||||
{
|
||||
"export":
|
||||
{
|
||||
"target":"."
|
||||
}
|
||||
},
|
||||
"height":8,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[43, 41, 5, 5, 5, 5, 5, 10, 10, 111, 41, 5, 5, 5, 5, 5, 5, 5, 5, 10, 5, 5, 38, 39, 93, 93, 93, 38, 39, 11, 10, 5, 40, 41, 83, 83, 83, 40, 41, 11, 10, 5, 11, 11, 92, 227, 92, 11, 11, 11, 5, 5, 11, 11, 11, 12, 11, 11, 11, 11, 5, 5, 5, 11, 12, 12, 5, 5, 5, 11, 61, 4, 4, 4, 12, 4, 4, 4, 4, 62],
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"Tiles",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":2,
|
||||
"name":"EntityLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":16,
|
||||
"id":1,
|
||||
"name":"BUTTERFLY",
|
||||
"rotation":0,
|
||||
"type":"entity",
|
||||
"visible":true,
|
||||
"width":16,
|
||||
"x":32,
|
||||
"y":48
|
||||
},
|
||||
{
|
||||
"height":16,
|
||||
"id":2,
|
||||
"name":"BUTTERFLY",
|
||||
"rotation":0,
|
||||
"type":"entity",
|
||||
"visible":true,
|
||||
"width":16,
|
||||
"x":112,
|
||||
"y":80
|
||||
},
|
||||
{
|
||||
"height":8,
|
||||
"id":3,
|
||||
"name":"1:10:2a3:50:7c",
|
||||
"rotation":0,
|
||||
"type":"warp",
|
||||
"visible":true,
|
||||
"width":8,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":1,
|
||||
"nextobjectid":4,
|
||||
"orientation":"orthogonal",
|
||||
"properties":[
|
||||
{
|
||||
"name":"animationset",
|
||||
"type":"string",
|
||||
"value":"00"
|
||||
},
|
||||
{
|
||||
"name":"attribset",
|
||||
"type":"string",
|
||||
"value":"22:0000"
|
||||
},
|
||||
{
|
||||
"name":"palette",
|
||||
"type":"string",
|
||||
"value":"01"
|
||||
},
|
||||
{
|
||||
"name":"tileset",
|
||||
"type":"string",
|
||||
"value":"0F"
|
||||
}],
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"1.4.3",
|
||||
"tileheight":16,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":16,
|
||||
"firstgid":1,
|
||||
"image":"tiles_0f_00_01_22_0000.png",
|
||||
"imageheight":256,
|
||||
"imagewidth":256,
|
||||
"margin":0,
|
||||
"name":"main",
|
||||
"spacing":0,
|
||||
"tilecount":256,
|
||||
"tileheight":16,
|
||||
"tilewidth":16
|
||||
}],
|
||||
"tilewidth":16,
|
||||
"type":"map",
|
||||
"version":1.4,
|
||||
"width":10
|
||||
}
|
||||
91
worlds/ladx/LADXR/patches/overworld/dive/A3.json
Normal file
91
worlds/ladx/LADXR/patches/overworld/dive/A3.json
Normal file
@@ -0,0 +1,91 @@
|
||||
{ "compressionlevel":-1,
|
||||
"editorsettings":
|
||||
{
|
||||
"export":
|
||||
{
|
||||
"target":"."
|
||||
}
|
||||
},
|
||||
"height":8,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[111, 82, 82, 82, 82, 82, 82, 82, 82, 82, 11, 11, 11, 5, 5, 5, 5, 11, 11, 82, 11, 183, 184, 10, 183, 201, 184, 5, 11, 82, 11, 206, 207, 10, 206, 226, 207, 5, 11, 82, 11, 5, 5, 11, 11, 11, 11, 11, 11, 82, 11, 11, 11, 5, 197, 10, 197, 11, 11, 82, 11, 5, 11, 11, 11, 11, 5, 5, 11, 82, 48, 48, 48, 48, 48, 48, 48, 48, 48, 61],
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"Tiles",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":2,
|
||||
"name":"EntityLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"1:ff:312:50:5c",
|
||||
"rotation":0,
|
||||
"type":"warp",
|
||||
"visible":true,
|
||||
"width":8,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":1,
|
||||
"nextobjectid":2,
|
||||
"orientation":"orthogonal",
|
||||
"properties":[
|
||||
{
|
||||
"name":"animationset",
|
||||
"type":"string",
|
||||
"value":"00"
|
||||
},
|
||||
{
|
||||
"name":"attribset",
|
||||
"type":"string",
|
||||
"value":"25:2800"
|
||||
},
|
||||
{
|
||||
"name":"palette",
|
||||
"type":"string",
|
||||
"value":"01"
|
||||
},
|
||||
{
|
||||
"name":"tileset",
|
||||
"type":"string",
|
||||
"value":"38"
|
||||
}],
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"1.4.3",
|
||||
"tileheight":16,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":16,
|
||||
"firstgid":1,
|
||||
"image":"tiles_38_00_01_25_2800.png",
|
||||
"imageheight":256,
|
||||
"imagewidth":256,
|
||||
"margin":0,
|
||||
"name":"main",
|
||||
"spacing":0,
|
||||
"tilecount":256,
|
||||
"tileheight":16,
|
||||
"tilewidth":16
|
||||
}],
|
||||
"tilewidth":16,
|
||||
"type":"map",
|
||||
"version":1.4,
|
||||
"width":10
|
||||
}
|
||||
80
worlds/ladx/LADXR/patches/overworld/dive/B0.json
Normal file
80
worlds/ladx/LADXR/patches/overworld/dive/B0.json
Normal file
@@ -0,0 +1,80 @@
|
||||
{ "compressionlevel":-1,
|
||||
"editorsettings":
|
||||
{
|
||||
"export":
|
||||
{
|
||||
"target":"."
|
||||
}
|
||||
},
|
||||
"height":8,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[56, 4, 4, 4, 4, 4, 4, 4, 4, 57, 56, 183, 184, 4, 4, 4, 4, 62, 48, 53, 56, 206, 207, 4, 4, 4, 4, 57, 183, 184, 56, 161, 93, 4, 4, 4, 4, 57, 206, 207, 56, 93, 93, 62, 73, 75, 74, 79, 183, 184, 56, 93, 4, 57, 59, 59, 59, 60, 206, 207, 47, 48, 48, 79, 31, 31, 31, 31, 31, 31, 58, 59, 59, 60, 32, 32, 32, 32, 32, 32],
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"Tiles",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":2,
|
||||
"name":"EntityLayer",
|
||||
"objects":[],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":1,
|
||||
"nextobjectid":1,
|
||||
"orientation":"orthogonal",
|
||||
"properties":[
|
||||
{
|
||||
"name":"animationset",
|
||||
"type":"string",
|
||||
"value":"02"
|
||||
},
|
||||
{
|
||||
"name":"attribset",
|
||||
"type":"string",
|
||||
"value":"22:1000"
|
||||
},
|
||||
{
|
||||
"name":"palette",
|
||||
"type":"string",
|
||||
"value":"01"
|
||||
},
|
||||
{
|
||||
"name":"tileset",
|
||||
"type":"string",
|
||||
"value":"22"
|
||||
}],
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"1.4.3",
|
||||
"tileheight":16,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":16,
|
||||
"firstgid":1,
|
||||
"image":"tiles_22_02_01_22_1000.png",
|
||||
"imageheight":256,
|
||||
"imagewidth":256,
|
||||
"margin":0,
|
||||
"name":"main",
|
||||
"spacing":0,
|
||||
"tilecount":256,
|
||||
"tileheight":16,
|
||||
"tilewidth":16
|
||||
}],
|
||||
"tilewidth":16,
|
||||
"type":"map",
|
||||
"version":1.4,
|
||||
"width":10
|
||||
}
|
||||
102
worlds/ladx/LADXR/patches/overworld/dive/B1.json
Normal file
102
worlds/ladx/LADXR/patches/overworld/dive/B1.json
Normal file
@@ -0,0 +1,102 @@
|
||||
{ "compressionlevel":-1,
|
||||
"editorsettings":
|
||||
{
|
||||
"export":
|
||||
{
|
||||
"target":"."
|
||||
}
|
||||
},
|
||||
"height":8,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[44, 46, 44, 45, 45, 45, 45, 46, 44, 46, 52, 53, 52, 48, 227, 48, 48, 53, 52, 53, 183, 184, 9, 9, 9, 9, 201, 183, 184, 9, 206, 207, 9, 9, 9, 9, 9, 206, 207, 9, 183, 184, 201, 9, 9, 9, 9, 183, 184, 9, 206, 207, 9, 9, 9, 9, 9, 206, 207, 9, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32],
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"Tiles",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":2,
|
||||
"name":"EntityLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":16,
|
||||
"id":1,
|
||||
"name":"MARIN",
|
||||
"rotation":0,
|
||||
"type":"entity",
|
||||
"visible":true,
|
||||
"width":16,
|
||||
"x":48,
|
||||
"y":48
|
||||
},
|
||||
{
|
||||
"height":8,
|
||||
"id":2,
|
||||
"name":"1:1f:1e1:88:50",
|
||||
"rotation":0,
|
||||
"type":"warp",
|
||||
"visible":true,
|
||||
"width":8,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":1,
|
||||
"nextobjectid":3,
|
||||
"orientation":"orthogonal",
|
||||
"properties":[
|
||||
{
|
||||
"name":"animationset",
|
||||
"type":"string",
|
||||
"value":"02"
|
||||
},
|
||||
{
|
||||
"name":"attribset",
|
||||
"type":"string",
|
||||
"value":"22:1000"
|
||||
},
|
||||
{
|
||||
"name":"palette",
|
||||
"type":"string",
|
||||
"value":"01"
|
||||
},
|
||||
{
|
||||
"name":"tileset",
|
||||
"type":"string",
|
||||
"value":"22"
|
||||
}],
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"1.4.3",
|
||||
"tileheight":16,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":16,
|
||||
"firstgid":1,
|
||||
"image":"tiles_22_02_01_22_1000.png",
|
||||
"imageheight":256,
|
||||
"imagewidth":256,
|
||||
"margin":0,
|
||||
"name":"main",
|
||||
"spacing":0,
|
||||
"tilecount":256,
|
||||
"tileheight":16,
|
||||
"tilewidth":16
|
||||
}],
|
||||
"tilewidth":16,
|
||||
"type":"map",
|
||||
"version":1.4,
|
||||
"width":10
|
||||
}
|
||||
91
worlds/ladx/LADXR/patches/overworld/dive/B2.json
Normal file
91
worlds/ladx/LADXR/patches/overworld/dive/B2.json
Normal file
@@ -0,0 +1,91 @@
|
||||
{ "compressionlevel":-1,
|
||||
"editorsettings":
|
||||
{
|
||||
"export":
|
||||
{
|
||||
"target":"."
|
||||
}
|
||||
},
|
||||
"height":8,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[56, 4, 4, 4, 12, 4, 4, 4, 4, 57, 52, 54, 4, 4, 4, 9, 9, 9, 55, 53, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 183, 184, 9, 9, 9, 9, 9, 37, 9, 9, 206, 207, 36, 9, 9, 9, 9, 9, 9, 9, 9, 36, 9, 9, 9, 9, 9, 9, 9, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32],
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"Tiles",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":2,
|
||||
"name":"EntityLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":16,
|
||||
"id":1,
|
||||
"name":"HEART_PIECE",
|
||||
"rotation":0,
|
||||
"type":"entity",
|
||||
"visible":true,
|
||||
"width":16,
|
||||
"x":80,
|
||||
"y":80
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":1,
|
||||
"nextobjectid":2,
|
||||
"orientation":"orthogonal",
|
||||
"properties":[
|
||||
{
|
||||
"name":"animationset",
|
||||
"type":"string",
|
||||
"value":"02"
|
||||
},
|
||||
{
|
||||
"name":"attribset",
|
||||
"type":"string",
|
||||
"value":"22:1000"
|
||||
},
|
||||
{
|
||||
"name":"palette",
|
||||
"type":"string",
|
||||
"value":"01"
|
||||
},
|
||||
{
|
||||
"name":"tileset",
|
||||
"type":"string",
|
||||
"value":"22"
|
||||
}],
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"1.4.3",
|
||||
"tileheight":16,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":16,
|
||||
"firstgid":1,
|
||||
"image":"tiles_22_02_01_22_1000.png",
|
||||
"imageheight":256,
|
||||
"imagewidth":256,
|
||||
"margin":0,
|
||||
"name":"main",
|
||||
"spacing":0,
|
||||
"tilecount":256,
|
||||
"tileheight":16,
|
||||
"tilewidth":16
|
||||
}],
|
||||
"tilewidth":16,
|
||||
"type":"map",
|
||||
"version":1.4,
|
||||
"width":10
|
||||
}
|
||||
91
worlds/ladx/LADXR/patches/overworld/dive/B3.json
Normal file
91
worlds/ladx/LADXR/patches/overworld/dive/B3.json
Normal file
@@ -0,0 +1,91 @@
|
||||
{ "compressionlevel":-1,
|
||||
"editorsettings":
|
||||
{
|
||||
"export":
|
||||
{
|
||||
"target":"."
|
||||
}
|
||||
},
|
||||
"height":8,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[63, 59, 59, 63, 59, 59, 59, 64, 59, 56, 58, 59, 59, 63, 59, 59, 59, 64, 59, 56, 9, 9, 9, 58, 59, 187, 59, 60, 9, 56, 9, 9, 36, 9, 9, 36, 9, 9, 9, 56, 9, 9, 9, 9, 9, 9, 9, 9, 9, 56, 9, 9, 9, 9, 36, 9, 9, 9, 37, 56, 31, 31, 31, 31, 31, 31, 31, 31, 31, 52, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32],
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"Tiles",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":2,
|
||||
"name":"EntityLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":8,
|
||||
"id":1,
|
||||
"name":"1:1f:1f5:48:7c",
|
||||
"rotation":0,
|
||||
"type":"warp",
|
||||
"visible":true,
|
||||
"width":8,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":1,
|
||||
"nextobjectid":2,
|
||||
"orientation":"orthogonal",
|
||||
"properties":[
|
||||
{
|
||||
"name":"animationset",
|
||||
"type":"string",
|
||||
"value":"02"
|
||||
},
|
||||
{
|
||||
"name":"attribset",
|
||||
"type":"string",
|
||||
"value":"22:1000"
|
||||
},
|
||||
{
|
||||
"name":"palette",
|
||||
"type":"string",
|
||||
"value":"01"
|
||||
},
|
||||
{
|
||||
"name":"tileset",
|
||||
"type":"string",
|
||||
"value":"22"
|
||||
}],
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"1.4.3",
|
||||
"tileheight":16,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":16,
|
||||
"firstgid":1,
|
||||
"image":"tiles_22_02_01_22_1000.png",
|
||||
"imageheight":256,
|
||||
"imagewidth":256,
|
||||
"margin":0,
|
||||
"name":"main",
|
||||
"spacing":0,
|
||||
"tilecount":256,
|
||||
"tileheight":16,
|
||||
"tilewidth":16
|
||||
}],
|
||||
"tilewidth":16,
|
||||
"type":"map",
|
||||
"version":1.4,
|
||||
"width":10
|
||||
}
|
||||
144
worlds/ladx/LADXR/patches/owl.py
Normal file
144
worlds/ladx/LADXR/patches/owl.py
Normal file
@@ -0,0 +1,144 @@
|
||||
from ..roomEditor import RoomEditor
|
||||
from ..assembler import ASM
|
||||
from ..utils import formatText
|
||||
|
||||
|
||||
def removeOwlEvents(rom):
|
||||
# Remove all the owl events from the entity tables.
|
||||
for room in range(0x100):
|
||||
re = RoomEditor(rom, room)
|
||||
if re.hasEntity(0x41):
|
||||
re.removeEntities(0x41)
|
||||
re.store(rom)
|
||||
# Clear texts used by the owl. Potentially reused somewhere o else.
|
||||
rom.texts[0x0D9] = b'\xff' # used by boomerang
|
||||
# 1 Used by empty chest (master stalfos message)
|
||||
# 8 unused (0x0C0-0x0C7)
|
||||
# 1 used by bowwow in chest
|
||||
# 1 used by item for other player message
|
||||
# 2 used by arrow chest messages
|
||||
# 2 used by tunics
|
||||
for idx in range(0x0BE, 0x0CE):
|
||||
rom.texts[idx] = b'\xff'
|
||||
|
||||
|
||||
# Patch the owl entity into a ghost to allow refill of powder/bombs/arrows
|
||||
rom.texts[0xC0] = formatText("Everybody hates me, so I give away free things in the hope people will love me. Want something?", ask="Okay No")
|
||||
rom.texts[0xC1] = formatText("Good for you.")
|
||||
rom.patch(0x06, 0x27F5, 0x2A77, ASM("""
|
||||
; Check if we have powder or bombs.
|
||||
ld e, INV_SIZE
|
||||
ld hl, $DB00
|
||||
loop:
|
||||
ldi a, [hl]
|
||||
cp $02 ; bombs
|
||||
jr z, hasProperItem
|
||||
cp $0C ; powder
|
||||
jr z, hasProperItem
|
||||
cp $05 ; bow
|
||||
jr z, hasProperItem
|
||||
dec e
|
||||
jr nz, loop
|
||||
ret
|
||||
hasProperItem:
|
||||
|
||||
; Render ghost
|
||||
ld de, sprite
|
||||
call $3BC0
|
||||
|
||||
call $64C6 ; check if game is busy (pops this stack frame if busy)
|
||||
|
||||
ldh a, [$E7] ; frame counter
|
||||
swap a
|
||||
and $01
|
||||
call $3B0C ; set entity sprite variant
|
||||
call $641A ; check collision
|
||||
ldh a, [$F0] ;entity state
|
||||
rst 0
|
||||
dw waitForTalk
|
||||
dw talking
|
||||
|
||||
waitForTalk:
|
||||
call $645D ; check if talked to
|
||||
ret nc
|
||||
ld a, $C0
|
||||
call $2385 ; open dialog
|
||||
call $3B12 ; increase entity state
|
||||
ret
|
||||
|
||||
talking:
|
||||
; Check if we are still talking
|
||||
ld a, [$C19F]
|
||||
and a
|
||||
ret nz
|
||||
call $3B12 ; increase entity state
|
||||
ld [hl], $00 ; set to state 0
|
||||
ld a, [$C177] ; get which option we selected
|
||||
and a
|
||||
ret nz
|
||||
|
||||
; Give powder
|
||||
ld a, [$DB4C]
|
||||
cp $10
|
||||
jr nc, doNotGivePowder
|
||||
ld a, $10
|
||||
ld [$DB4C], a
|
||||
doNotGivePowder:
|
||||
|
||||
ld a, [$DB4D]
|
||||
cp $10
|
||||
jr nc, doNotGiveBombs
|
||||
ld a, $10
|
||||
ld [$DB4D], a
|
||||
doNotGiveBombs:
|
||||
|
||||
ld a, [$DB45]
|
||||
cp $10
|
||||
jr nc, doNotGiveArrows
|
||||
ld a, $10
|
||||
ld [$DB45], a
|
||||
doNotGiveArrows:
|
||||
|
||||
ld a, $C1
|
||||
call $2385 ; open dialog
|
||||
ret
|
||||
|
||||
sprite:
|
||||
db $76, $09, $78, $09, $7A, $09, $7C, $09
|
||||
""", 0x67F5), fill_nop=True)
|
||||
rom.patch(0x20, 0x0322 + 0x41 * 2, "734A", "564B") # Remove the owl init handler
|
||||
|
||||
re = RoomEditor(rom, 0x2A3)
|
||||
re.entities.append((7, 6, 0x41))
|
||||
re.store(rom)
|
||||
|
||||
|
||||
def upgradeDungeonOwlStatues(rom):
|
||||
# Call our custom handler after the check for the stone beak
|
||||
rom.patch(0x18, 0x1EA2, ASM("ldh a, [$F7]\ncp $FF\njr nz, $05"), ASM("ld a, $09\nrst 8\nret"), fill_nop=True)
|
||||
|
||||
def upgradeOverworldOwlStatues(rom):
|
||||
# Replace the code that handles signs/owl statues on the overworld
|
||||
# This removes a "have marin with you" special case to make some room for our custom owl handling.
|
||||
rom.patch(0x00, 0x201A, ASM("""
|
||||
cp $6F
|
||||
jr z, $2B
|
||||
cp $D4
|
||||
jr z, $27
|
||||
ld a, [$DB73]
|
||||
and a
|
||||
jr z, $08
|
||||
ld a, $78
|
||||
call $237C
|
||||
jp $20CF
|
||||
"""), ASM("""
|
||||
cp $D4
|
||||
jr z, $2B
|
||||
cp $6F
|
||||
jr nz, skip
|
||||
|
||||
ld a, $09
|
||||
rst 8
|
||||
jp $20CF
|
||||
skip:
|
||||
"""), fill_nop=True)
|
||||
60
worlds/ladx/LADXR/patches/phone.py
Normal file
60
worlds/ladx/LADXR/patches/phone.py
Normal file
@@ -0,0 +1,60 @@
|
||||
from ..assembler import ASM
|
||||
|
||||
|
||||
def patchPhone(rom):
|
||||
rom.texts[0x141] = b""
|
||||
rom.texts[0x142] = b""
|
||||
rom.texts[0x143] = b""
|
||||
rom.texts[0x144] = b""
|
||||
rom.texts[0x145] = b""
|
||||
rom.texts[0x146] = b""
|
||||
rom.texts[0x147] = b""
|
||||
rom.texts[0x148] = b""
|
||||
rom.texts[0x149] = b""
|
||||
rom.texts[0x14A] = b""
|
||||
rom.texts[0x14B] = b""
|
||||
rom.texts[0x14C] = b""
|
||||
rom.texts[0x14D] = b""
|
||||
rom.texts[0x14E] = b""
|
||||
rom.texts[0x14F] = b""
|
||||
rom.texts[0x16E] = b""
|
||||
rom.texts[0x1FD] = b""
|
||||
rom.texts[0x228] = b""
|
||||
rom.texts[0x229] = b""
|
||||
rom.texts[0x22A] = b""
|
||||
rom.texts[0x240] = b""
|
||||
rom.texts[0x241] = b""
|
||||
rom.texts[0x242] = b""
|
||||
rom.texts[0x243] = b""
|
||||
rom.texts[0x244] = b""
|
||||
rom.texts[0x245] = b""
|
||||
rom.texts[0x247] = b""
|
||||
rom.texts[0x248] = b""
|
||||
rom.patch(0x06, 0x2A8F, 0x2BBC, ASM("""
|
||||
; We use $DB6D to store which tunics we have. This is normally the Dungeon9 instrument, which does not exist.
|
||||
ld a, [$DC0F]
|
||||
ld hl, wCollectedTunics
|
||||
inc a
|
||||
|
||||
cp $01
|
||||
jr nz, notTunic1
|
||||
bit 0, [HL]
|
||||
jr nz, notTunic1
|
||||
inc a
|
||||
notTunic1:
|
||||
|
||||
cp $02
|
||||
jr nz, notTunic2
|
||||
bit 1, [HL]
|
||||
jr nz, notTunic2
|
||||
inc a
|
||||
notTunic2:
|
||||
|
||||
cp $03
|
||||
jr nz, noWrap
|
||||
xor a
|
||||
noWrap:
|
||||
|
||||
ld [$DC0F], a
|
||||
ret
|
||||
"""), fill_nop=True)
|
||||
19
worlds/ladx/LADXR/patches/photographer.py
Normal file
19
worlds/ladx/LADXR/patches/photographer.py
Normal file
@@ -0,0 +1,19 @@
|
||||
from ..assembler import ASM
|
||||
|
||||
|
||||
def fixPhotographer(rom):
|
||||
# Allow richard photo without slime key
|
||||
rom.patch(0x36, 0x3234, ASM("jr nz, $52"), "", fill_nop=True)
|
||||
rom.patch(0x36, 0x3240, ASM("jr z, $46"), "", fill_nop=True)
|
||||
# Allow richard photo when castle is opened
|
||||
rom.patch(0x36, 0x31FF, ASM("jp nz, $7288"), "", fill_nop=True)
|
||||
# Allow photographer with bowwow saved
|
||||
rom.patch(0x36, 0x0398, ASM("or [hl]"), "", fill_nop=True)
|
||||
rom.patch(0x36, 0x3183, ASM("ret nz"), "", fill_nop=True)
|
||||
rom.patch(0x36, 0x31CB, ASM("jp nz, $7288"), "", fill_nop=True)
|
||||
rom.patch(0x36, 0x03DC, ASM("and $7F"), ASM("and $00"))
|
||||
# Allow bowwow photo with follower
|
||||
rom.patch(0x36, 0x31DA, ASM("jp nz, $7288"), "", fill_nop=True)
|
||||
# Allow bridge photo with follower
|
||||
rom.patch(0x36, 0x004D, ASM("call nz, $3F8D"), "", fill_nop=True)
|
||||
rom.patch(0x36, 0x006D, ASM("ret nz"), "", fill_nop=True) # Checks if any entity is alive
|
||||
9
worlds/ladx/LADXR/patches/reduceRNG.py
Normal file
9
worlds/ladx/LADXR/patches/reduceRNG.py
Normal file
@@ -0,0 +1,9 @@
|
||||
from ..assembler import ASM
|
||||
|
||||
|
||||
def slowdownThreeOfAKind(rom):
|
||||
rom.patch(0x06, 0x096B, ASM("ldh a, [$E7]\nand $0F"), ASM("ldh a, [$E7]\nand $3F"))
|
||||
|
||||
|
||||
def fixHorseHeads(rom):
|
||||
rom.patch(0x07, 0x3653, "00010400", "00010000")
|
||||
40
worlds/ladx/LADXR/patches/rooster.py
Normal file
40
worlds/ladx/LADXR/patches/rooster.py
Normal file
@@ -0,0 +1,40 @@
|
||||
from ..assembler import ASM
|
||||
from ..utils import formatText
|
||||
|
||||
|
||||
def patchRooster(rom):
|
||||
# Do not give the rooster
|
||||
rom.patch(0x19, 0x0E9D, ASM("ld [$DB7B], a"), "", fill_nop=True)
|
||||
|
||||
# Do not load the rooster sprites
|
||||
rom.patch(0x00, 0x2EC7, ASM("jr nz, $08"), "", fill_nop=True)
|
||||
|
||||
# Draw the found item
|
||||
rom.patch(0x19, 0x0E4A, ASM("ld hl, $4E37\nld c, $03\ncall $3CE6"), ASM("ld a, $0C\nrst $08"), fill_nop=True)
|
||||
rom.patch(0x19, 0x0E7B, ASM("ld hl, $4E37\nld c, $03\ncall $3CE6"), ASM("ld a, $0C\nrst $08"), fill_nop=True)
|
||||
# Give the item and message
|
||||
rom.patch(0x19, 0x0E69, ASM("ld a, $6D\ncall $2373"), ASM("ld a, $0E\nrst $08"), fill_nop=True)
|
||||
|
||||
# Reuse unused evil eagle text slot for rooster message
|
||||
rom.texts[0x0B8] = formatText("Got the {ROOSTER}!")
|
||||
|
||||
# Allow rooster pickup with special rooster item
|
||||
rom.patch(0x19, 0x1ABC, ASM("cp $03"), ASM("cp $0F"))
|
||||
rom.patch(0x19, 0x1AAE, ASM("cp $03"), ASM("cp $0F"))
|
||||
|
||||
# Ignore the has-rooster flag in the rooster entity (do not despawn)
|
||||
rom.patch(0x19, 0x19E0, ASM("jp z, $7E61"), "", fill_nop=True)
|
||||
|
||||
# If we are spawning the rooster, and the rooster is already existing, do not do anything, instead of despawning the rooster.
|
||||
rom.patch(0x01, 0x1FEF, ASM("ld [hl], d"), ASM("ret"))
|
||||
# Allow rooster to unload when changing rooms
|
||||
rom.patch(0x19, 0x19E9, ASM("ld [hl], a"), "", fill_nop=True)
|
||||
|
||||
# Do not take away the rooster after D7
|
||||
rom.patch(0x03, 0x1E25, ASM("ld [$DB7B], a"), "", fill_nop=True)
|
||||
|
||||
# Patch the color dungeon entrance not to check for rooster
|
||||
rom.patch(0x02, 0x3409, ASM("ld hl, $DB7B\nor [hl]"), "", fill_nop=True)
|
||||
|
||||
# Spawn marin at taltal even with rooster
|
||||
rom.patch(0x18, 0x1EE3, ASM("jp nz, $7F08"), "", fill_nop=True)
|
||||
54
worlds/ladx/LADXR/patches/save.py
Normal file
54
worlds/ladx/LADXR/patches/save.py
Normal file
@@ -0,0 +1,54 @@
|
||||
from ..assembler import ASM
|
||||
from ..backgroundEditor import BackgroundEditor
|
||||
|
||||
|
||||
def singleSaveSlot(rom):
|
||||
# Do not validate/erase slots 2 and 3 at rom start
|
||||
rom.patch(0x01, 0x06B3, ASM("call $4794"), "", fill_nop=True)
|
||||
rom.patch(0x01, 0x06B9, ASM("call $4794"), "", fill_nop=True)
|
||||
|
||||
# Patch the code that checks if files have proper filenames to skip file 2/3
|
||||
rom.patch(0x01, 0x1DD9, ASM("ld b, $02"), ASM("ret"), fill_nop=True)
|
||||
|
||||
# Remove the part that writes death counters for save2/3 on the file select screen
|
||||
rom.patch(0x01, 0x0821, 0x084B, "", fill_nop=True)
|
||||
# Remove the call that updates the hearts for save2
|
||||
rom.patch(0x01, 0x0800, ASM("call $4DBE"), "", fill_nop=True)
|
||||
# Remove the call that updates the hearts for save3
|
||||
rom.patch(0x01, 0x0806, ASM("call $4DD6"), "", fill_nop=True)
|
||||
|
||||
# Remove the call that updates the names for save2 and save3
|
||||
rom.patch(0x01, 0x0D70, ASM("call $4D94\ncall $4D9D"), "", fill_nop=True)
|
||||
|
||||
# Remove the 2/3 slots from the screen and remove the copy text
|
||||
be = BackgroundEditor(rom, 0x03)
|
||||
del be.tiles[0x9924]
|
||||
del be.tiles[0x9984]
|
||||
be.store(rom)
|
||||
be = BackgroundEditor(rom, 0x04)
|
||||
del be.tiles[0x9924]
|
||||
del be.tiles[0x9984]
|
||||
for n in range(0x99ED, 0x99F1):
|
||||
del be.tiles[n]
|
||||
be.store(rom)
|
||||
|
||||
# Do not do left/right for erase/copy selection.
|
||||
rom.patch(0x01, 0x092B, ASM("jr z, $0B"), ASM("jr $0B"))
|
||||
# Only switch between players
|
||||
rom.patch(0x01, 0x08FA, 0x091D, ASM("""
|
||||
ld a, [$DBA7]
|
||||
and a
|
||||
ld a, [$DBA6]
|
||||
jr z, skip
|
||||
xor $03
|
||||
skip:
|
||||
"""), fill_nop=True)
|
||||
|
||||
# On the erase screen, only switch between save 1 and return
|
||||
rom.patch(0x01, 0x0E12, ASM("inc a\nand $03"), ASM("xor $03"), fill_nop=True)
|
||||
rom.patch(0x01, 0x0E21, ASM("dec a\ncp $ff\njr nz, $02\nld a,$03"), ASM("xor $03"), fill_nop=True)
|
||||
|
||||
be = BackgroundEditor(rom, 0x06)
|
||||
del be.tiles[0x9924]
|
||||
del be.tiles[0x9984]
|
||||
be.store(rom)
|
||||
64
worlds/ladx/LADXR/patches/seashell.py
Normal file
64
worlds/ladx/LADXR/patches/seashell.py
Normal file
@@ -0,0 +1,64 @@
|
||||
from ..assembler import ASM
|
||||
|
||||
|
||||
def fixSeashell(rom):
|
||||
# Do not unload if we have the lvl2 sword.
|
||||
rom.patch(0x03, 0x1FD3, ASM("ld a, [$DB4E]\ncp $02\njp nc, $3F8D"), "", fill_nop=True)
|
||||
# Do not unload in the ghost house
|
||||
rom.patch(0x03, 0x1FE8, ASM("ldh a, [$F8]\nand $40\njp z, $3F8D"), "", fill_nop=True)
|
||||
|
||||
# Call our special rendering code
|
||||
rom.patch(0x03, 0x1FF2, ASM("ld de, $5FD1\ncall $3C77"), ASM("ld a, $05\nrst 8"), fill_nop=True)
|
||||
|
||||
# Call our special handlers for messages and pickup
|
||||
rom.patch(0x03, 0x2368, 0x237C, ASM("""
|
||||
ld a, $0A ; showMessageMultiworld
|
||||
rst 8
|
||||
ld a, $06 ; giveItemMultiworld
|
||||
rst 8
|
||||
call $512A
|
||||
ret
|
||||
"""), fill_nop=True)
|
||||
|
||||
|
||||
def upgradeMansion(rom):
|
||||
rom.patch(0x19, 0x38EC, ASM("""
|
||||
ld hl, $78DC
|
||||
jr $03
|
||||
"""), "", fill_nop=True)
|
||||
rom.patch(0x19, 0x38F1, ASM("""
|
||||
ld hl, $78CC
|
||||
ld c, $04
|
||||
call $3CE6
|
||||
"""), ASM("""
|
||||
ld a, $0C
|
||||
rst 8
|
||||
"""), fill_nop=True)
|
||||
rom.patch(0x19, 0x3718, ASM("sub $13"), ASM("sub $0D"))
|
||||
rom.patch(0x19, 0x3697, ASM("""
|
||||
cp $70
|
||||
jr c, $15
|
||||
ld [hl], $70
|
||||
"""), ASM("""
|
||||
cp $73
|
||||
jr c, $15
|
||||
ld [hl], $73
|
||||
"""))
|
||||
rom.patch(0x19, 0x36F5, ASM("""
|
||||
ld a, $02
|
||||
ld [$DB4E], a
|
||||
"""), ASM("""
|
||||
ld a, $0E ; give item and message for current room multiworld
|
||||
rst 8
|
||||
"""), fill_nop=True)
|
||||
rom.patch(0x19, 0x36E6, ASM("""
|
||||
ld a, $9F
|
||||
call $2385
|
||||
"""), "", fill_nop=True)
|
||||
rom.patch(0x19, 0x31E8, ASM("""
|
||||
ld a, [$DB4E]
|
||||
and $02
|
||||
"""), ASM("""
|
||||
ld a, [$DAE9]
|
||||
and $10
|
||||
"""))
|
||||
152
worlds/ladx/LADXR/patches/shop.py
Normal file
152
worlds/ladx/LADXR/patches/shop.py
Normal file
@@ -0,0 +1,152 @@
|
||||
from ..assembler import ASM
|
||||
|
||||
|
||||
def fixShop(rom):
|
||||
# Move shield visuals to the 2nd slot, and arrow to 3th slot
|
||||
rom.patch(0x04, 0x3732 + 22, "986A027FB2B098AC01BAB1", "9867027FB2B098A801BAB1")
|
||||
rom.patch(0x04, 0x3732 + 55, "986302B1B07F98A4010A09", "986B02B1B07F98AC010A09")
|
||||
|
||||
# Just use a fixed location in memory to store which inventory we give.
|
||||
rom.patch(0x04, 0x37C5, "0708", "0802")
|
||||
|
||||
# Patch the code that decides which shop to show.
|
||||
rom.patch(0x04, 0x3839, 0x388E, ASM("""
|
||||
push bc
|
||||
jr skipSubRoutine
|
||||
|
||||
checkInventory:
|
||||
ld hl, $DB00 ; inventory
|
||||
ld c, INV_SIZE
|
||||
loop:
|
||||
cp [hl]
|
||||
ret z
|
||||
inc hl
|
||||
dec c
|
||||
jr nz, loop
|
||||
and a
|
||||
ret
|
||||
|
||||
skipSubRoutine:
|
||||
; Set the shop table to all nothing.
|
||||
ld hl, $C505
|
||||
xor a
|
||||
ldi [hl], a
|
||||
ldi [hl], a
|
||||
ldi [hl], a
|
||||
ldi [hl], a
|
||||
ld de, $C505
|
||||
|
||||
; Check if we want to load a key item into the shop.
|
||||
ldh a, [$F8]
|
||||
bit 4, a
|
||||
jr nz, checkForSecondKeyItem
|
||||
ld a, $01
|
||||
ld [de], a
|
||||
jr checkForShield
|
||||
checkForSecondKeyItem:
|
||||
bit 5, a
|
||||
jr nz, checkForShield
|
||||
ld a, $05
|
||||
ld [de], a
|
||||
|
||||
checkForShield:
|
||||
inc de
|
||||
; Check if we have the shield or the bow to see if we need to remove certain entries from the shop
|
||||
ld a, [$DB44]
|
||||
and a
|
||||
jr z, hasNoShieldLevel
|
||||
ld a, $03
|
||||
ld [de], a ; Add shield buy option
|
||||
hasNoShieldLevel:
|
||||
|
||||
inc de
|
||||
ld a, $05
|
||||
call checkInventory
|
||||
jr nz, hasNoBow
|
||||
ld a, $06
|
||||
ld [de], a ; Add arrow buy option
|
||||
hasNoBow:
|
||||
|
||||
inc de
|
||||
ld a, $02
|
||||
call checkInventory
|
||||
jr nz, hasNoBombs
|
||||
ld a, $04
|
||||
ld [de], a ; Add bomb buy option
|
||||
hasNoBombs:
|
||||
|
||||
pop bc
|
||||
call $3B12 ; increase entity state
|
||||
""", 0x7839), fill_nop=True)
|
||||
|
||||
# We do not have enough room at the shovel/bow buy entry to handle this
|
||||
# So jump to a bit where we have some more space to work, as there is some dead code in the shop.
|
||||
rom.patch(0x04, 0x3AA9, 0x3AAE, ASM("jp $7AC3"), fill_nop=True)
|
||||
|
||||
# Patch over the "you stole it" dialog
|
||||
rom.patch(0x00, 0x1A1C, 0x1A21, ASM("""ld a, $C9
|
||||
call $2385"""), fill_nop=True)
|
||||
rom.patch(0x04, 0x3AC3, 0x3AD8, ASM("""
|
||||
; No room override needed, we're in the proper room
|
||||
; Call our chest item giving code.
|
||||
ld a, $0E
|
||||
rst 8
|
||||
; Update the room status to mark first item as bought
|
||||
ld hl, $DAA1
|
||||
ld a, [hl]
|
||||
or $10
|
||||
ld [hl], a
|
||||
ret
|
||||
"""), fill_nop=True)
|
||||
rom.patch(0x04, 0x3A73, 0x3A7E, ASM("jp $7A91"), fill_nop=True)
|
||||
rom.patch(0x04, 0x3A91, 0x3AA9, ASM("""
|
||||
; Override the room - luckily nothing will go wrong here if we leave it as is
|
||||
ld a, $A7
|
||||
ldh [$F6], a
|
||||
; Call our chest item giving code.
|
||||
ld a, $0E
|
||||
rst 8
|
||||
; Update the room status to mark second item as bought
|
||||
ld hl, $DAA1
|
||||
ld a, [hl]
|
||||
or $20
|
||||
ld [hl], a
|
||||
ret
|
||||
"""), fill_nop=True)
|
||||
|
||||
# Patch shop item graphics rendering to use some new code at the end of the bank.
|
||||
rom.patch(0x04, 0x3B91, 0x3BAC, ASM("""
|
||||
call $7FD0
|
||||
"""), fill_nop=True)
|
||||
rom.patch(0x04, 0x3BD3, 0x3BE3, ASM("""
|
||||
jp $7FD0
|
||||
"""), fill_nop=True)
|
||||
rom.patch(0x04, 0x3FD0, "00" * 42, ASM("""
|
||||
; Check if first key item
|
||||
and a
|
||||
jr nz, notShovel
|
||||
ld a, [$77C5]
|
||||
ldh [$F1], a
|
||||
ld a, $01
|
||||
rst 8
|
||||
ret
|
||||
notShovel:
|
||||
cp $04
|
||||
jr nz, notBow
|
||||
ld a, [$77C6]
|
||||
ldh [$F1], a
|
||||
ld a, $01
|
||||
rst 8
|
||||
ret
|
||||
notBow:
|
||||
cp $05
|
||||
jr nz, notArrows
|
||||
; Load arrow graphics and render then as a dual sprite
|
||||
ld de, $7B58
|
||||
call $3BC0
|
||||
ret
|
||||
notArrows:
|
||||
; Load the normal graphics
|
||||
ld de, $7B5A
|
||||
jp $3C77
|
||||
"""), fill_nop=True)
|
||||
93
worlds/ladx/LADXR/patches/softlock.py
Normal file
93
worlds/ladx/LADXR/patches/softlock.py
Normal file
@@ -0,0 +1,93 @@
|
||||
from ..roomEditor import RoomEditor, Object
|
||||
from ..assembler import ASM
|
||||
|
||||
|
||||
def fixAll(rom):
|
||||
# Prevent soft locking in the first mountain cave if we do not have a feather
|
||||
re = RoomEditor(rom, 0x2B7)
|
||||
re.removeObject(3, 3)
|
||||
re.store(rom)
|
||||
|
||||
# Prevent getting stuck in the sidescroll room in the beginning of dungeon 5
|
||||
re = RoomEditor(rom, 0x1A9)
|
||||
re.objects[6].count = 7
|
||||
re.store(rom)
|
||||
|
||||
# Cave that allows you to escape from D4 without flippers, make it no longer require a feather
|
||||
re = RoomEditor(rom, 0x1EA)
|
||||
re.objects[9].count = 8
|
||||
re.removeObject(5, 4)
|
||||
re.moveObject(4, 4, 7, 5)
|
||||
re.store(rom)
|
||||
|
||||
# D3 west side room requires feather to get the key. But feather is not required to unlock the door, potentially softlocking you.
|
||||
re = RoomEditor(rom, 0x155)
|
||||
re.changeObject(4, 1, 0xcf)
|
||||
re.changeObject(4, 6, 0xd0)
|
||||
re.store(rom)
|
||||
|
||||
# D3 boots room requires boots to escape
|
||||
re = RoomEditor(rom, 0x146)
|
||||
re.removeObject(5, 6)
|
||||
re.store(rom)
|
||||
|
||||
allowRaftGameWithoutFlippers(rom)
|
||||
# We cannot access thes holes in logic:
|
||||
# removeBirdKeyHoleDrop(rom)
|
||||
fixDoghouse(rom)
|
||||
flameThrowerShieldRequirement(rom)
|
||||
fixLessThen3MaxHealth(rom)
|
||||
|
||||
def fixDoghouse(rom):
|
||||
# Fix entering the dog house from the back, and ending up out of bounds.
|
||||
re = RoomEditor(rom, 0x0A1)
|
||||
re.objects.append(Object(6, 2, 0x0E2))
|
||||
re.objects.append(re.objects[20]) # Move the flower patch after the warp entry definition so it overrules the tile
|
||||
re.objects.append(re.objects[3])
|
||||
|
||||
re.objects.pop(22)
|
||||
re.objects.pop(21)
|
||||
re.objects.pop(20) # Remove the flower patch at the normal entry index
|
||||
re.objects.pop(11) # Duplicate object, we can just remove it, gives room for our custom entry door
|
||||
re.store(rom)
|
||||
|
||||
def allowRaftGameWithoutFlippers(rom):
|
||||
# Allow jumping down the waterfall in the raft game without the flippers.
|
||||
rom.patch(0x02, 0x2E8F, ASM("ld a, [$DB0C]"), ASM("ld a, $01"), fill_nop=True)
|
||||
# Change the room that goes back up to the raft game from the bottom, so we no longer need flippers
|
||||
re = RoomEditor(rom, 0x1F7)
|
||||
re.changeObject(3, 2, 0x1B)
|
||||
re.changeObject(2, 3, 0x1B)
|
||||
re.changeObject(3, 4, 0x1B)
|
||||
re.changeObject(4, 5, 0x1B)
|
||||
re.changeObject(6, 6, 0x1B)
|
||||
re.store(rom)
|
||||
|
||||
def removeBirdKeyHoleDrop(rom):
|
||||
# Prevent the cave with the bird key from dropping you in the water
|
||||
# (if you do not have flippers this would softlock you)
|
||||
rom.patch(0x02, 0x1176, ASM("""
|
||||
ldh a, [$F7]
|
||||
cp $0A
|
||||
jr nz, $30
|
||||
"""), ASM("""
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
jr $30
|
||||
"""))
|
||||
# Remove the hole that drops you all the way from dungeon7 entrance to the water in the cave
|
||||
re = RoomEditor(rom, 0x01E)
|
||||
re.removeObject(5, 4)
|
||||
re.store(rom)
|
||||
|
||||
def flameThrowerShieldRequirement(rom):
|
||||
# if you somehow get a lvl3 shield or higher, it no longer works against the flamethrower, easy fix.
|
||||
rom.patch(0x03, 0x2EBA,
|
||||
ASM("ld a, [$DB44]\ncp $02\nret nz"), # if not shield level 2
|
||||
ASM("ld a, [$DB44]\ncp $02\nret c")) # if not shield level 2 or higher
|
||||
|
||||
def fixLessThen3MaxHealth(rom):
|
||||
# The table that starts your start HP when you die is not working for less then 3 HP, and locks the game.
|
||||
rom.patch(0x01, 0x1295, "18181818", "08081018")
|
||||
159
worlds/ladx/LADXR/patches/songs.py
Normal file
159
worlds/ladx/LADXR/patches/songs.py
Normal file
@@ -0,0 +1,159 @@
|
||||
from ..assembler import ASM
|
||||
|
||||
|
||||
def upgradeMarin(rom):
|
||||
# Show marin outside, even without a sword.
|
||||
rom.patch(0x05, 0x0E78, ASM("ld a, [$DB4E]"), ASM("ld a, $01"), fill_nop=True)
|
||||
# Make marin ignore the fact that you did not save the tarin yet, and allowing getting her song
|
||||
rom.patch(0x05, 0x0E87, ASM("ld a, [$D808]"), ASM("ld a, $10"), fill_nop=True)
|
||||
rom.patch(0x05, 0x0F73, ASM("ld a, [$D808]"), ASM("ld a, $10"), fill_nop=True)
|
||||
rom.patch(0x05, 0x0FB0, ASM("ld a, [$DB48]"), ASM("ld a, $01"), fill_nop=True)
|
||||
# Show marin in the animal village
|
||||
rom.patch(0x03, 0x0A86, ASM("ld a, [$DB74]"), ASM("ld a, $01"), fill_nop=True)
|
||||
rom.patch(0x05, 0x3F2E, ASM("ld a, [$DB74]"), ASM("ld a, $01"), fill_nop=True) # animal d0
|
||||
rom.patch(0x15, 0x3F96, ASM("ld a, [$DB74]"), ASM("ld a, $01"), fill_nop=True) # animal d1
|
||||
rom.patch(0x18, 0x11B0, ASM("ld a, [$DB74]"), ASM("ld a, $01"), fill_nop=True) # animal d2
|
||||
|
||||
# Instead of checking if we have the ballad, check if we have a specific room flag set
|
||||
rom.patch(0x05, 0x0F89, ASM("""
|
||||
ld a, [$DB49]
|
||||
and $04
|
||||
"""), ASM("""
|
||||
ld a, [$D892]
|
||||
and $10
|
||||
"""), fill_nop=True)
|
||||
rom.patch(0x05, 0x0FDF, ASM("""
|
||||
ld a, [$DB49]
|
||||
and $04
|
||||
"""), ASM("""
|
||||
ld a, [$D892]
|
||||
and $10
|
||||
"""), fill_nop=True)
|
||||
rom.patch(0x05, 0x1042, ASM("""
|
||||
ld a, [$DB49]
|
||||
and $04
|
||||
"""), ASM("""
|
||||
ld a, [$D892]
|
||||
and $10
|
||||
"""), fill_nop=True)
|
||||
|
||||
# Patch that we call our specific handler instead of giving the song
|
||||
rom.patch(0x05, 0x1170, ASM("""
|
||||
ld hl, $DB49
|
||||
set 2, [hl]
|
||||
xor a
|
||||
ld [$DB4A], a
|
||||
"""), ASM("""
|
||||
; Mark Marin as done.
|
||||
ld a, [$D892]
|
||||
or $10
|
||||
ld [$D892], a
|
||||
"""), fill_nop=True)
|
||||
|
||||
|
||||
# Show the right item instead of the ocerina
|
||||
rom.patch(0x05, 0x11B3, ASM("""
|
||||
ld de, $515F
|
||||
xor a
|
||||
ldh [$F1], a
|
||||
jp $3C77
|
||||
"""), ASM("""
|
||||
ld a, $0C
|
||||
rst 8
|
||||
ret
|
||||
"""), fill_nop=True)
|
||||
|
||||
# Patch the message that tells we got the song, to give the item and show the right message
|
||||
rom.patch(0x05, 0x119C, ASM("""
|
||||
ld a, $13
|
||||
call $2385
|
||||
"""), ASM("""
|
||||
ld a, $0E
|
||||
rst 8
|
||||
"""), fill_nop=True)
|
||||
|
||||
|
||||
def upgradeManbo(rom):
|
||||
# Instead of checking if we have the song, check if we have a specific room flag set
|
||||
rom.patch(0x18, 0x0536, ASM("""
|
||||
ld a, [$DB49]
|
||||
and $02
|
||||
"""), ASM("""
|
||||
ld a, [$DAFD]
|
||||
and $20
|
||||
"""), fill_nop=True)
|
||||
|
||||
# Show the right item instead of the ocerina
|
||||
rom.patch(0x18, 0x0786, ASM("""
|
||||
ld de, $474D
|
||||
xor a
|
||||
ldh [$F1], a
|
||||
jp $3C77
|
||||
"""), ASM("""
|
||||
ld a, $0C
|
||||
rst 8
|
||||
ret
|
||||
"""), fill_nop=True)
|
||||
|
||||
# Patch to replace song giving to give the right item
|
||||
rom.patch(0x18, 0x0757, ASM("""
|
||||
ld a, $01
|
||||
ld [$DB4A], a
|
||||
ld hl, $DB49
|
||||
set 1, [hl]
|
||||
"""), ASM("""
|
||||
; Mark Manbo as done.
|
||||
ld hl, $DAFD
|
||||
set 5, [hl]
|
||||
; Show item message and give item
|
||||
ld a, $0E
|
||||
rst 8
|
||||
"""), fill_nop=True)
|
||||
# Remove the normal "got song message")
|
||||
rom.patch(0x18, 0x076F, 0x0774, "", fill_nop=True)
|
||||
|
||||
def upgradeMamu(rom):
|
||||
# Always allow the sign maze instead of only allowing the sign maze if you do not have song3
|
||||
rom.patch(0x00, 0x2057, ASM("ld a, [$DB49]"), ASM("ld a, $00"), fill_nop=True)
|
||||
|
||||
# Patch the condition at which Mamu gives you the option to listen to him
|
||||
rom.patch(0x18, 0x0031, ASM("""
|
||||
ld a, [$DB49]
|
||||
and $01
|
||||
"""), ASM("""
|
||||
ld a, [$DAFB] ; load room flag of the Mamu room
|
||||
and $10
|
||||
"""), fill_nop=True)
|
||||
|
||||
# Show the right item instead of the ocerina
|
||||
rom.patch(0x18, 0x0299, ASM("""
|
||||
ld de, $474D
|
||||
xor a
|
||||
ldh [$F1], a
|
||||
call $3C77
|
||||
"""), ASM("""
|
||||
ld a, $0C
|
||||
rst 8
|
||||
"""), fill_nop=True)
|
||||
|
||||
# Patch given an item
|
||||
rom.patch(0x18, 0x0270, ASM("""
|
||||
ld a, $02
|
||||
ld [$DB4A], a
|
||||
ld hl, $DB49
|
||||
set 0, [hl]
|
||||
"""), ASM("""
|
||||
; Set the room complete flag.
|
||||
ld hl, $DAFB
|
||||
set 4, [hl]
|
||||
"""), fill_nop=True)
|
||||
|
||||
# Patch to show the right message for the item
|
||||
rom.patch(0x18, 0x0282, ASM("""
|
||||
ld a, $DF
|
||||
call $4087
|
||||
"""), ASM("""
|
||||
; Give item and message for room.
|
||||
ld a, $0E
|
||||
rst 8
|
||||
"""), fill_nop=True)
|
||||
51
worlds/ladx/LADXR/patches/tarin.py
Normal file
51
worlds/ladx/LADXR/patches/tarin.py
Normal file
@@ -0,0 +1,51 @@
|
||||
from ..assembler import ASM
|
||||
from ..utils import formatText
|
||||
|
||||
|
||||
def updateTarin(rom):
|
||||
# Do not give the shield.
|
||||
rom.patch(0x05, 0x0CD0, ASM("""
|
||||
ld d, $04
|
||||
call $5321
|
||||
ld a, $01
|
||||
ld [$DB44], a
|
||||
"""), "", fill_nop=True)
|
||||
|
||||
# Instead of showing the usual "your shield back" message, give the proper message and give the item.
|
||||
rom.patch(0x05, 0x0CDE, ASM("""
|
||||
ld a, $91
|
||||
call $2385
|
||||
"""), ASM("""
|
||||
ld a, $0B ; GiveItemAndMessageForRoom
|
||||
rst 8
|
||||
"""), fill_nop=True)
|
||||
|
||||
rom.patch(0x05, 0x0CF0, ASM("""
|
||||
xor a
|
||||
ldh [$F1], a
|
||||
ld de, $4CC6
|
||||
call $3C77
|
||||
"""), ASM("""
|
||||
ld a, $0C ; RenderItemForRoom
|
||||
rst 8
|
||||
xor a
|
||||
ldh [$F1], a
|
||||
"""), fill_nop=True)
|
||||
|
||||
# Set the room status to finished. (replaces a GBC check)
|
||||
rom.patch(0x05, 0x0CAB, 0x0CB0, ASM("""
|
||||
ld a, $20
|
||||
call $36C4
|
||||
"""), fill_nop=True)
|
||||
|
||||
# Instead of checking for the shield level to put you in the bed, check the room flag.
|
||||
rom.patch(0x05, 0x1202, ASM("ld a, [$DB44]\nand a"), ASM("ldh a, [$F8]\nand $20"))
|
||||
rom.patch(0x05, 0x0C6D, ASM("ld a, [$DB44]\nand a"), ASM("ldh a, [$F8]\nand $20"))
|
||||
|
||||
# If the starting item is picked up, load the right palette when entering the room
|
||||
rom.patch(0x21, 0x0176, ASM("ld a, [$DB48]\ncp $01"), ASM("ld a, [$DAA3]\ncp $A1"), fill_nop=True)
|
||||
rom.patch(0x05, 0x0C94, "FF473152C5280000", "FD2ED911CE100000")
|
||||
rom.patch(0x05, 0x0CB0, ASM("ld hl, $DC88"), ASM("ld hl, $DC80"))
|
||||
|
||||
# Patch the text that Tarin uses to give your shield back.
|
||||
rom.texts[0x54] = formatText("#####, it is dangerous to go alone!\nTake this!")
|
||||
89
worlds/ladx/LADXR/patches/titleScreen.py
Normal file
89
worlds/ladx/LADXR/patches/titleScreen.py
Normal file
@@ -0,0 +1,89 @@
|
||||
from ..backgroundEditor import BackgroundEditor
|
||||
import subprocess
|
||||
import binascii
|
||||
|
||||
|
||||
CHAR_MAP = {'z': 0x3E, '-': 0x3F, '.': 0x39, ':': 0x42, '?': 0x3C, '!': 0x3D}
|
||||
|
||||
|
||||
def _encode(s):
|
||||
result = bytearray()
|
||||
for char in s:
|
||||
if ord("A") <= ord(char) <= ord("Z"):
|
||||
result.append(ord(char) - ord("A"))
|
||||
elif ord("a") <= ord(char) <= ord("y"):
|
||||
result.append(ord(char) - ord("a") + 26)
|
||||
elif ord("0") <= ord(char) <= ord("9"):
|
||||
result.append(ord(char) - ord("0") + 0x70)
|
||||
else:
|
||||
result.append(CHAR_MAP.get(char, 0x7E))
|
||||
return result
|
||||
|
||||
|
||||
def setRomInfo(rom, seed, settings, player_name, player_id):
|
||||
#try:
|
||||
# version = subprocess.run(['git', 'describe', '--tags', '--dirty=-D'], stdout=subprocess.PIPE).stdout.strip().decode("ascii", "replace")
|
||||
#except:
|
||||
# version = ""
|
||||
|
||||
try:
|
||||
seednr = int(seed, 16)
|
||||
except:
|
||||
import hashlib
|
||||
seednr = int(hashlib.md5(seed.encode('ascii', 'replace')).hexdigest(), 16)
|
||||
|
||||
if settings.race:
|
||||
seed = "Race"
|
||||
if isinstance(settings.race, str):
|
||||
seed += " " + settings.race
|
||||
rom.patch(0x00, 0x07, "00", "01")
|
||||
else:
|
||||
rom.patch(0x00, 0x07, "00", "52")
|
||||
|
||||
line_1_hex = _encode(seed)
|
||||
#line_2_hex = _encode(seed[16:])
|
||||
BASE_DRAWING_AREA = 0x98a0
|
||||
LINE_WIDTH = 0x20
|
||||
player_id_text = f"Player {player_id}:"
|
||||
for n in (3, 4):
|
||||
be = BackgroundEditor(rom, n)
|
||||
ba = BackgroundEditor(rom, n, attributes=True)
|
||||
|
||||
for n, v in enumerate(_encode(player_id_text)):
|
||||
be.tiles[BASE_DRAWING_AREA + LINE_WIDTH * 5 + 2 + n] = v
|
||||
ba.tiles[BASE_DRAWING_AREA + LINE_WIDTH * 5 + 2 + n] = 0x00
|
||||
for n, v in enumerate(_encode(player_name)):
|
||||
be.tiles[BASE_DRAWING_AREA + LINE_WIDTH * 6 + 0x13 - len(player_name) + n] = v
|
||||
ba.tiles[BASE_DRAWING_AREA + LINE_WIDTH * 6 + 0x13 - len(player_name) + n] = 0x00
|
||||
for n, v in enumerate(line_1_hex):
|
||||
be.tiles[0x9a20 + n] = v
|
||||
ba.tiles[0x9a20 + n] = 0x00
|
||||
|
||||
for n in range(0x09, 0x14):
|
||||
be.tiles[0x9820 + n] = 0x7F
|
||||
be.tiles[0x9840 + n] = 0xA0 + (n % 2)
|
||||
be.tiles[0x9860 + n] = 0xA2
|
||||
sn = seednr
|
||||
for n in range(0x0A, 0x14):
|
||||
tilenr = sn % 30
|
||||
sn //= 30
|
||||
if tilenr > 12:
|
||||
tilenr += 2
|
||||
if tilenr > 16:
|
||||
tilenr += 1
|
||||
if tilenr > 19:
|
||||
tilenr += 3
|
||||
if tilenr > 27:
|
||||
tilenr += 1
|
||||
if tilenr > 29:
|
||||
tilenr += 2
|
||||
if tilenr > 35:
|
||||
tilenr += 1
|
||||
be.tiles[0x9800 + n] = tilenr * 2
|
||||
be.tiles[0x9820 + n] = tilenr * 2 + 1
|
||||
pal = sn % 8
|
||||
sn //= 8
|
||||
ba.tiles[0x9800 + n] = 0x08 | pal
|
||||
ba.tiles[0x9820 + n] = 0x08 | pal
|
||||
be.store(rom)
|
||||
ba.store(rom)
|
||||
355
worlds/ladx/LADXR/patches/tradeSequence.py
Normal file
355
worlds/ladx/LADXR/patches/tradeSequence.py
Normal file
@@ -0,0 +1,355 @@
|
||||
from ..assembler import ASM
|
||||
|
||||
|
||||
def patchTradeSequence(rom, boomerang_option):
|
||||
patchTrendy(rom)
|
||||
patchPapahlsWife(rom)
|
||||
patchYipYip(rom)
|
||||
patchBananasSchule(rom)
|
||||
patchKiki(rom)
|
||||
patchTarin(rom)
|
||||
patchBear(rom)
|
||||
patchPapahl(rom)
|
||||
patchGoatMrWrite(rom)
|
||||
patchGrandmaUlrira(rom)
|
||||
patchFisherman(rom)
|
||||
patchMermaid(rom)
|
||||
patchMermaidStatue(rom)
|
||||
patchSharedCode(rom)
|
||||
patchVarious(rom, boomerang_option)
|
||||
patchInventoryMenu(rom)
|
||||
|
||||
|
||||
def patchTrendy(rom):
|
||||
# Trendy game yoshi
|
||||
rom.patch(0x04, 0x3502, 0x350F, ASM("""
|
||||
ldh a, [$F8] ; room status
|
||||
and a, $20
|
||||
jp nz, $6D7A ; clear entity
|
||||
; Render sprite
|
||||
ld a, $0F
|
||||
rst 8
|
||||
; Reset the sprite variant, else the code gets confused
|
||||
xor a
|
||||
ldh [$F1], a ; sprite variant
|
||||
"""), fill_nop=True)
|
||||
rom.patch(0x04, 0x2E80, ASM("ldh a, [$F8]"), ASM("ld a, $10")) # Prevent marin cutscene from triggering, as that locks the game now.
|
||||
rom.patch(0x04, 0x3622, 0x3627, "", fill_nop=True) # Dont set the trade item
|
||||
|
||||
|
||||
def patchPapahlsWife(rom):
|
||||
# Rewrite how the first dialog is generated.
|
||||
rom.patch(0x18, 0x0E7A, 0x0EA8, ASM("""
|
||||
ldh a, [$F8] ; room status
|
||||
and a, $20
|
||||
jr nz, tradeDone
|
||||
|
||||
ld a, [wTradeSequenceItem]
|
||||
and $01
|
||||
jr nz, requestTrade
|
||||
|
||||
ld a, $2A ; Dialog about wanting a yoshi doll
|
||||
jp $2373 ; OpenDialogInTable1
|
||||
tradeDone:
|
||||
ld a, $2C ; Dialog about kids, after trade is done
|
||||
jp $2373 ; OpenDialogInTable1
|
||||
requestTrade:
|
||||
ld a, $2B ; Dialog about kids, after trade is done
|
||||
call $3B12; IncrementEntityState
|
||||
jp $2373 ; OpenDialogInTable1
|
||||
"""), fill_nop=True)
|
||||
rom.patch(0x18, 0x0EB4, 0x0EBD, ASM("ld hl, wTradeSequenceItem\nres 0, [hl]"), fill_nop=True) # Take the trade item
|
||||
|
||||
|
||||
def patchYipYip(rom):
|
||||
# Change how the decision is made to draw yipyip with a ribbon
|
||||
rom.patch(0x06, 0x1A2C, 0x1A36, ASM("""
|
||||
ldh a, [$F8] ; room status
|
||||
and $20
|
||||
jr z, tradeNotDone
|
||||
ld de, $59C8 ; yipyip with ribbon
|
||||
tradeNotDone:
|
||||
"""), fill_nop=True)
|
||||
# Check if we have the ribbon
|
||||
rom.patch(0x06, 0x1A7C, 0x1A83, ASM("""
|
||||
ld a, [wTradeSequenceItem]
|
||||
and $02
|
||||
jr z, $07
|
||||
"""), fill_nop=True)
|
||||
rom.patch(0x06, 0x1AAF, 0x1AB8, ASM("ld hl, wTradeSequenceItem\nres 1, [hl]"), fill_nop=True) # Take the trade item
|
||||
|
||||
|
||||
def patchBananasSchule(rom):
|
||||
# Change how to check if we have the right trade item
|
||||
rom.patch(0x19, 0x2D54, 0x2D5B, ASM("""
|
||||
ld a, [wTradeSequenceItem]
|
||||
and $04
|
||||
jr z, $08
|
||||
"""), fill_nop=True)
|
||||
rom.patch(0x19, 0x2DF0, 0x2DF9, ASM("ld hl, wTradeSequenceItem\nres 2, [hl]"), fill_nop=True) # Take the trade item
|
||||
# Change how the decision is made to render less bananas
|
||||
rom.patch(0x19, 0x2EF1, 0x2EFA, ASM("""
|
||||
ldh a, [$F8]
|
||||
and $20
|
||||
jr z, skip
|
||||
dec c
|
||||
dec c
|
||||
skip: """), fill_nop=True)
|
||||
|
||||
# Part of the same entity code, but this is the painter, which changes the dialog depending on mermaid scale or magnifier
|
||||
rom.patch(0x19, 0x2F95, 0x2F9C, ASM("""
|
||||
ld a, [wTradeSequenceItem2]
|
||||
and $10 ; Check for mermaid scale
|
||||
jr z, $04
|
||||
"""))
|
||||
rom.patch(0x19, 0x2FA0, 0x2FA4, ASM("""
|
||||
and $20 ; Check for magnifier
|
||||
jr z, $07
|
||||
"""))
|
||||
rom.patch(0x19, 0x2CE3, "9A159C15", "B41DB61D") # Properly draw the dog food
|
||||
|
||||
|
||||
def patchKiki(rom):
|
||||
rom.patch(0x07, 0x18E6, 0x18ED, ASM("""
|
||||
ld a, [wTradeSequenceItem]
|
||||
and $08 ; check for banana
|
||||
jr z, $08
|
||||
"""))
|
||||
rom.patch(0x07, 0x19AF, 0x19B4, "", fill_nop=True) # Do not change trading item memory
|
||||
rom.patch(0x07, 0x19CC, 0x19D5, ASM("ld hl, wTradeSequenceItem\nres 3, [hl]"), fill_nop=True) # Take the trade item
|
||||
rom.patch(0x07, 0x194D, "9A179C17", "B81FBA1F") # Properly draw the banana above kiki
|
||||
|
||||
|
||||
def patchTarin(rom):
|
||||
rom.patch(0x07, 0x0EC5, 0x0ECA, ASM("""
|
||||
ld a, [wTradeSequenceItem]
|
||||
and $10 ; check for stick
|
||||
"""))
|
||||
rom.patch(0x07, 0x0F30, 0x0F33, "", fill_nop=True) # Take the trade item
|
||||
# Honeycomb, change how we detect that it should fall on entering the room
|
||||
rom.patch(0x07, 0x0CCC, 0x0CD3, ASM("""
|
||||
ld a, [$D887]
|
||||
and $40
|
||||
jr z, $14
|
||||
"""))
|
||||
# Something about tarin changing messages or not showing up depending on the trade sequence
|
||||
rom.patch(0x05, 0x0BFF, 0x0C07, "", fill_nop=True) # Just ignore the trade sequence
|
||||
rom.patch(0x05, 0x0D20, 0x0D27, "", fill_nop=True) # Just ignore the trade sequence
|
||||
rom.patch(0x05, 0x0DAF, 0x0DB8, "", fill_nop=True) # Tarin giving bananas?
|
||||
|
||||
rom.patch(0x07, 0x0D6D, 0x0D7A, ASM("ld hl, wTradeSequenceItem\nres 4, [hl]"), fill_nop=True) # Take the trade item
|
||||
|
||||
|
||||
def patchBear(rom):
|
||||
# Change the trade item check
|
||||
rom.patch(0x07, 0x0BCC, 0x0BD3, ASM("""
|
||||
ld a, [wTradeSequenceItem]
|
||||
and $20 ; check for honeycomb
|
||||
jr z, $0E
|
||||
"""))
|
||||
rom.patch(0x07, 0x0C21, ASM("jr nz, $22"), "", fill_nop=True)
|
||||
rom.patch(0x07, 0x0C23, 0x0C2A, ASM("""
|
||||
ld a, [wTradeSequenceItem]
|
||||
and $20 ; check for honeycomb
|
||||
jr z, $08
|
||||
"""))
|
||||
|
||||
rom.patch(0x07, 0x0C3C, 0x0C43, ASM("""
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
jr $02
|
||||
"""))
|
||||
rom.patch(0x07, 0x0C5E, 0x0C67, ASM("ld hl, wTradeSequenceItem\nres 5, [hl]"), fill_nop=True) # Take the trade item
|
||||
|
||||
|
||||
def patchPapahl(rom):
|
||||
rom.patch(0x07, 0x0A21, 0x0A30, ASM("call $7EA4"), fill_nop=True) # Never show indoor papahl
|
||||
# Render the bag condition
|
||||
rom.patch(0x07, 0x0A81, 0x0A88, ASM("""
|
||||
ldh a, [$F8] ; current room status
|
||||
and $20
|
||||
nop
|
||||
jr nz, $18
|
||||
"""))
|
||||
# Check for the right item
|
||||
rom.patch(0x07, 0x0ACF, 0x0AD4, ASM("""
|
||||
ld a, [wTradeSequenceItem]
|
||||
and $40 ; pineapple
|
||||
"""))
|
||||
rom.patch(0x07, 0x0AD6, ASM("jr z, $02"), ASM("jr nz, $02"))
|
||||
|
||||
rom.patch(0x07, 0x0AF9, 0x0B00, ASM("""
|
||||
ld a, [wTradeSequenceItem]
|
||||
and $40 ; pineapple
|
||||
jr z, $0E
|
||||
"""))
|
||||
rom.patch(0x07, 0x0B2F, 0x0B38, ASM("ld hl, wTradeSequenceItem\nres 6, [hl]"), fill_nop=True) # Take the trade item
|
||||
|
||||
|
||||
def patchGoatMrWrite(rom): # The goat and mrwrite are the same entity
|
||||
rom.patch(0x18, 0x0BF1, 0x0BF8, ASM("""
|
||||
ldh a, [$F8]
|
||||
and $20
|
||||
nop
|
||||
jr nz, $03
|
||||
""")) # Check if we made the trade with the goat
|
||||
rom.patch(0x18, 0x0C2C, 0x0C33, ASM("""
|
||||
ld a, [wTradeSequenceItem]
|
||||
and $80 ; hibiscus
|
||||
jr z, $08
|
||||
""")) # Check if we have the hibiscus
|
||||
rom.patch(0x18, 0x0C3D, 0x0C41, "", fill_nop=True)
|
||||
rom.patch(0x18, 0x0C6B, 0x0C74, ASM("ld hl, wTradeSequenceItem\nres 7, [hl]"), fill_nop=True) # Take the trade item for the goat
|
||||
|
||||
rom.patch(0x18, 0x0C8B, 0x0C92, ASM("""
|
||||
ld a, [wTradeSequenceItem2]
|
||||
and $01 ; letter
|
||||
jr z, $08
|
||||
""")) # Check if we have the letter
|
||||
rom.patch(0x18, 0x0C9C, 0x0CA0, "", fill_nop=True)
|
||||
rom.patch(0x18, 0x0CE2, 0x0CEB, ASM("ld hl, wTradeSequenceItem2\nres 0, [hl]"), fill_nop=True) # Take the trade item for mrwrite
|
||||
|
||||
|
||||
def patchGrandmaUlrira(rom):
|
||||
rom.patch(0x18, 0x0D2C, ASM("jr z, $02"), "", fill_nop=True) # Always show up in animal village
|
||||
rom.patch(0x18, 0x0D3C, 0x0D51, ASM("""
|
||||
ldh a, [$F8]
|
||||
and $20
|
||||
jp nz, $4D58
|
||||
"""), fill_nop=True)
|
||||
rom.patch(0x18, 0x0D95, 0x0D9A, "", fill_nop=True)
|
||||
rom.patch(0x18, 0x0D9C, 0x0DA0, "", fill_nop=True)
|
||||
rom.patch(0x18, 0x0DA3, 0x0DAA, ASM("""
|
||||
ld a, [wTradeSequenceItem2]
|
||||
and $02 ; broom
|
||||
jr z, $0B
|
||||
"""))
|
||||
rom.patch(0x18, 0x0DC4, 0x0DC7, "", fill_nop=True)
|
||||
rom.patch(0x18, 0x0DE2, 0x0DEB, ASM("ld hl, wTradeSequenceItem2\nres 1, [hl]"), fill_nop=True) # Take the trade item
|
||||
rom.patch(0x18, 0x0E1D, 0x0E20, "", fill_nop=True)
|
||||
rom.patch(0x18, 0x0D13, "9A149C14", "D01CD21C")
|
||||
|
||||
|
||||
def patchFisherman(rom):
|
||||
# Not sure what this first check is for
|
||||
rom.patch(0x07, 0x02F8, 0x0300, ASM("""
|
||||
"""), fill_nop=True)
|
||||
# Check for the hook
|
||||
rom.patch(0x07, 0x04BF, 0x04C6, ASM("""
|
||||
ld a, [wTradeSequenceItem2]
|
||||
and $04 ; hook
|
||||
jr z, $08
|
||||
"""))
|
||||
rom.patch(0x07, 0x04F3, 0x04F6, "", fill_nop=True)
|
||||
rom.patch(0x07, 0x057D, 0x0586, ASM("ld hl, wTradeSequenceItem2\nres 2, [hl]"), fill_nop=True) # Take the trade item
|
||||
rom.patch(0x04, 0x1F88, 0x1F8B, "", fill_nop=True)
|
||||
|
||||
|
||||
def patchMermaid(rom):
|
||||
# Check for the right trade item
|
||||
rom.patch(0x07, 0x0797, 0x079E, ASM("""
|
||||
ld a, [wTradeSequenceItem2]
|
||||
and $08 ; necklace
|
||||
jr z, $0B
|
||||
"""))
|
||||
rom.patch(0x07, 0x0854, 0x085B, ASM("ld hl, wTradeSequenceItem2\nres 3, [hl]"), fill_nop=True) # Take the trade item
|
||||
|
||||
|
||||
def patchMermaidStatue(rom):
|
||||
rom.patch(0x18, 0x095D, 0x0962, "", fill_nop=True)
|
||||
rom.patch(0x18, 0x0966, 0x097A, ASM("""
|
||||
ld a, [wTradeSequenceItem2]
|
||||
and $10 ; scale
|
||||
ret z
|
||||
ldh a, [$F8]
|
||||
and $20
|
||||
ret nz
|
||||
"""), fill_nop=True)
|
||||
|
||||
|
||||
def patchSharedCode(rom):
|
||||
# Trade item render code override.
|
||||
rom.patch(0x07, 0x1535, 0x1575, ASM("""
|
||||
ldh a, [$F9]
|
||||
and a
|
||||
jr z, notSideScroll
|
||||
|
||||
ldh a, [$EC]; hActiveEntityVisualPosY
|
||||
add a, $02
|
||||
ldh [$EC], a
|
||||
notSideScroll:
|
||||
; Render sprite
|
||||
ld a, $0F
|
||||
rst 8
|
||||
"""), fill_nop=True)
|
||||
# Trade item message code
|
||||
# rom.patch(0x07, 0x159F, 0x15B9, ASM("""
|
||||
# ld a, $09 ; give message and item (from alt item table)
|
||||
# rst 8
|
||||
# """), fill_nop=True)
|
||||
rom.patch(0x07, 0x159F, 0x15B9, ASM("""
|
||||
ldh a, [$F6] ; map room
|
||||
cp $B2
|
||||
jr nz, NotYipYip
|
||||
add a, 2 ; Add 2 to room to set room pointer to an empty room for trade items
|
||||
ldh [$F6], a
|
||||
ld a, $0e ; giveItemMultiworld
|
||||
rst 8
|
||||
ldh a, [$F6] ; map room
|
||||
sub a, 2 ; ...and undo it
|
||||
ldh [$F6], a
|
||||
jr Done
|
||||
NotYipYip:
|
||||
ld a, $0e ; giveItemMultiworld
|
||||
rst 8
|
||||
Done:
|
||||
"""), fill_nop=True)
|
||||
|
||||
|
||||
# Prevent changing the 2nd trade item memory
|
||||
rom.patch(0x07, 0x15BD, 0x15C1, ASM("""
|
||||
call $7F7F
|
||||
xor a ; we need to exit with A=00
|
||||
"""), fill_nop=True)
|
||||
rom.patch(0x07, 0x3F7F, "00" * 7, ASM("ldh a, [$F8]\nor $20\nldh [$F8], a\nret"))
|
||||
|
||||
|
||||
def patchVarious(rom, boomerang_option):
|
||||
# Make the zora photo work with the magnifier
|
||||
rom.patch(0x18, 0x09F3, 0x0A02, ASM("""
|
||||
ld a, [wTradeSequenceItem2]
|
||||
and $20 ; MAGNIFYING_GLASS
|
||||
jp z, $7F08 ; ClearEntityStatusBank18
|
||||
"""), fill_nop=True)
|
||||
rom.patch(0x03, 0x0B6D, 0x0B75, ASM("""
|
||||
ld a, [wTradeSequenceItem2]
|
||||
and $20 ; MAGNIFYING_GLASS
|
||||
jp z, $3F8D ; UnloadEntity
|
||||
"""), fill_nop=True)
|
||||
# Mimic invisibility
|
||||
rom.patch(0x18, 0x2AC8, 0x2ACE, "", fill_nop=True)
|
||||
# Ignore trade quest state for marin at beach
|
||||
rom.patch(0x18, 0x219E, 0x21A6, "", fill_nop=True)
|
||||
# Shift the magnifier 8 pixels
|
||||
rom.patch(0x03, 0x0F68, 0x0F6F, ASM("""
|
||||
ldh a, [$F6] ; map room
|
||||
cp $97 ; check if we are in the maginfier room
|
||||
jp z, $4F83
|
||||
"""), fill_nop=True)
|
||||
# Something with the photographer
|
||||
rom.patch(0x36, 0x0948, 0x0950, "", fill_nop=True)
|
||||
|
||||
if boomerang_option not in {'trade', 'gift'}: # Boomerang cave is not patched, so adjust it
|
||||
rom.patch(0x19, 0x05EC, ASM("ld a, [wTradeSequenceItem]\ncp $0E\njp nz, $7E61"), ASM("ld a, [wTradeSequenceItem2]\nand $20\njp z, $7E61")) # show the guy
|
||||
rom.patch(0x00, 0x3199, ASM("ld a, [wTradeSequenceItem]\ncp $0E\njr nz, $06"), ASM("ld a, [wTradeSequenceItem2]\nand $20\njr z, $06")) # load the proper room layout
|
||||
rom.patch(0x19, 0x05F4, 0x05FB, "", fill_nop=True)
|
||||
|
||||
|
||||
def patchInventoryMenu(rom):
|
||||
# Never draw the trade item the normal way
|
||||
rom.patch(0x20, 0x1A2E, ASM("ld a, [wTradeSequenceItem2]\nand a\njr nz, $23"), ASM("jp $5A57"), fill_nop=True)
|
||||
|
||||
rom.patch(0x20, 0x1EB5, ASM("ldh a, [$FE]\nand a\njr z, $34"), ASM("ld a, $10\nrst 8"), fill_nop=True)
|
||||
3
worlds/ladx/LADXR/patches/trendy.py
Normal file
3
worlds/ladx/LADXR/patches/trendy.py
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
def fixTrendy(rom):
|
||||
rom.patch(0x04, 0x2F29, "04", "02") # Patch the trendy game shield to be a ruppee
|
||||
45
worlds/ladx/LADXR/patches/tunicFairy.py
Normal file
45
worlds/ladx/LADXR/patches/tunicFairy.py
Normal file
@@ -0,0 +1,45 @@
|
||||
from ..utils import formatText
|
||||
from ..assembler import ASM
|
||||
|
||||
|
||||
def upgradeTunicFairy(rom):
|
||||
rom.texts[0x268] = formatText("Welcome, #####. I admire you for coming this far.")
|
||||
rom.texts[0x0CC] = formatText("Got the {RED_TUNIC}! You can change Tunics at the phone booths.")
|
||||
rom.texts[0x0CD] = formatText("Got the {BLUE_TUNIC}! You can change Tunics at the phone booths.")
|
||||
|
||||
rom.patch(0x36, 0x111C, 0x1133, ASM("""
|
||||
call $3B12
|
||||
ld a, [$DDE1]
|
||||
and $10
|
||||
jr z, giveItems
|
||||
ld [hl], $09
|
||||
ret
|
||||
|
||||
giveItems:
|
||||
ld a, [$DDE1]
|
||||
or $10
|
||||
ld [$DDE1], a
|
||||
"""), fill_nop=True)
|
||||
rom.patch(0x36, 0x1139, 0x1144, ASM("""
|
||||
ld a, $04
|
||||
ldh [$F6], a
|
||||
ld a, $0E
|
||||
rst 8
|
||||
"""), fill_nop=True)
|
||||
|
||||
rom.patch(0x36, 0x1162, 0x1192, ASM("""
|
||||
ld a, $01
|
||||
ldh [$F6], a
|
||||
ld a, $0E
|
||||
rst 8
|
||||
"""), fill_nop=True)
|
||||
|
||||
rom.patch(0x36, 0x119D, 0x11A2, "", fill_nop=True)
|
||||
rom.patch(0x36, 0x11B5, 0x11BE, ASM("""
|
||||
; Skip to the end ignoring all the tunic giving animation.
|
||||
call $3B12
|
||||
ld [hl], $09
|
||||
"""), fill_nop=True)
|
||||
|
||||
rom.banks[0x36][0x11BF] = 0x87
|
||||
rom.banks[0x36][0x11C0] = 0x88
|
||||
64
worlds/ladx/LADXR/patches/weapons.py
Normal file
64
worlds/ladx/LADXR/patches/weapons.py
Normal file
@@ -0,0 +1,64 @@
|
||||
from ..assembler import ASM
|
||||
from ..roomEditor import RoomEditor
|
||||
|
||||
|
||||
def patchSuperWeapons(rom):
|
||||
# Feather jump height
|
||||
rom.patch(0x00, 0x1508, ASM("ld a, $20"), ASM("ld a, $2C"))
|
||||
# Boots charge speed
|
||||
rom.patch(0x00, 0x1731, ASM("cp $20"), ASM("cp $01"))
|
||||
# Power bracelet pickup speed
|
||||
rom.patch(0x00, 0x2121, ASM("ld e, $08"), ASM("ld e, $01"))
|
||||
# Throwing speed (of pickups and bombs)
|
||||
rom.patch(0x14, 0x1313, "30D0000018E80000", "60A0000040C00000")
|
||||
rom.patch(0x14, 0x1323, "0000D0300000E818", "0000A0600000C040")
|
||||
|
||||
# Allow as many bombs to be placed as you want!
|
||||
rom.patch(0x00, 0x135F, ASM("ret nc"), "", fill_nop=True)
|
||||
|
||||
# Maximum amount of arrows in the air
|
||||
rom.patch(0x00, 0x13C5, ASM("cp $02"), ASM("cp $05"))
|
||||
# Delay between arrow shots
|
||||
rom.patch(0x00, 0x13C9, ASM("ld a, $10"), ASM("ld a, $01"))
|
||||
|
||||
# Maximum amount of firerod fires
|
||||
rom.patch(0x00, 0x12E4, ASM("cp $02"), ASM("cp $05"))
|
||||
|
||||
# Projectile speed (arrows, firerod)
|
||||
rom.patch(0x00, 0x13AD,
|
||||
"30D0000040C00000" "0000D0300000C040",
|
||||
"60A0000060A00000" "0000A0600000A060")
|
||||
|
||||
# Hookshot shoot speed
|
||||
rom.patch(0x02, 0x024C,
|
||||
"30D00000" "0000D030",
|
||||
"60A00000" "0000A060")
|
||||
# Hookshot retract speed
|
||||
rom.patch(0x18, 0x3C41, ASM("ld a, $30"), ASM("ld a, $60"))
|
||||
# Hookshot pull speed
|
||||
rom.patch(0x18, 0x3C21, ASM("ld a, $30"), ASM("ld a, $60"))
|
||||
|
||||
# Super shovel, always price!
|
||||
rom.patch(0x02, 0x0CC6, ASM("jr nz, $57"), "", fill_nop=True)
|
||||
|
||||
# Unlimited boomerangs!
|
||||
rom.patch(0x00, 0x1387, ASM("ret nz"), "", fill_nop=True)
|
||||
|
||||
# Increase shield push power
|
||||
rom.patch(0x03, 0x2FC5, ASM("ld a, $08"), ASM("ld a, $10"))
|
||||
rom.patch(0x03, 0x2FCA, ASM("ld a, $20"), ASM("ld a, $40"))
|
||||
# Decrease link pushback of shield
|
||||
rom.patch(0x03, 0x2FB9, ASM("ld a, $12"), ASM("ld a, $04"))
|
||||
rom.patch(0x03, 0x2F9A, ASM("ld a, $0C"), ASM("ld a, $03"))
|
||||
|
||||
# Super charge the ocarina
|
||||
rom.patch(0x02, 0x0AD8, ASM("cp $38"), ASM("cp $08"))
|
||||
rom.patch(0x02, 0x0B05, ASM("cp $14"), ASM("cp $04"))
|
||||
|
||||
re = RoomEditor(rom, 0x23D)
|
||||
tiles = re.getTileArray()
|
||||
tiles[11] = 0x0D
|
||||
tiles[12] = 0xA7
|
||||
tiles[22] = 0x98
|
||||
re.buildObjectList(tiles)
|
||||
re.store(rom)
|
||||
58
worlds/ladx/LADXR/patches/witch.py
Normal file
58
worlds/ladx/LADXR/patches/witch.py
Normal file
@@ -0,0 +1,58 @@
|
||||
from ..assembler import ASM
|
||||
from ..roomEditor import RoomEditor
|
||||
|
||||
|
||||
def updateWitch(rom):
|
||||
# Add a heartpiece at the toadstool, the item patches turn this into a 1 time toadstool item
|
||||
# Or depending on flags, in something else.
|
||||
re = RoomEditor(rom, 0x050)
|
||||
re.addEntity(2, 3, 0x35)
|
||||
re.store(rom)
|
||||
|
||||
# Change what happens when you trade the toadstool with the witch
|
||||
# Note that the 2nd byte of this code gets patched with the item to give from the witch.
|
||||
rom.patch(0x05, 0x08D4, 0x08F0, ASM("""
|
||||
; Get the room flags and mark the witch as done.
|
||||
ld hl, $DAA2
|
||||
ld a, [hl]
|
||||
and $30
|
||||
set 4, [hl]
|
||||
set 5, [hl]
|
||||
jr z, item
|
||||
powder:
|
||||
ld e, $09 ; give powder every time after the first time.
|
||||
ld a, e
|
||||
ldh [$F1], a
|
||||
ld a, $11
|
||||
rst 8
|
||||
jp $48F0
|
||||
item:
|
||||
ld a, $0E
|
||||
rst 8
|
||||
"""), fill_nop=True)
|
||||
|
||||
# Patch the toadstool to unload when you haven't delivered something to the witch yet.
|
||||
rom.patch(0x03, 0x1D4B, ASM("""
|
||||
ld hl, $DB4B
|
||||
ld a, [$DB4C]
|
||||
or [hl]
|
||||
jp nz, $3F8D
|
||||
"""), ASM("""
|
||||
ld a, [$DAA2]
|
||||
and $20
|
||||
jp z, $3F8D
|
||||
"""), fill_nop=True)
|
||||
|
||||
# Patch what happens when we pickup the toadstool, call our chest code to give a toadstool.
|
||||
rom.patch(0x03, 0x1D6F, 0x1D7D, ASM("""
|
||||
ld a, $50
|
||||
ldh [$F1], a
|
||||
ld a, $02 ; give item
|
||||
rst 8
|
||||
|
||||
ld hl, $DAA2
|
||||
res 5, [hl]
|
||||
"""), fill_nop=True)
|
||||
|
||||
def witchIsPatched(rom):
|
||||
return sum(rom.banks[0x05][0x08D4:0x08F0]) != 0x0DC2
|
||||
Reference in New Issue
Block a user