Ejemplo n.º 1
0
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)
Ejemplo n.º 2
0
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]
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
def getCleanBossRoom(rom, dungeon_nr):
    re = RoomEditor(rom, BOSS_ROOMS[dungeon_nr][0])
    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
Ejemplo n.º 5
0
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
    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
    rom.banks[0x14][0x1218 + 0xFA] = 0x01  # Photographer