mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 20:21:32 -06:00
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:
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"))
|
||||
Reference in New Issue
Block a user