mirror of
https://github.com/ArchipelagoMW/Archipelago.git
synced 2026-03-26 03:33:20 -07:00
handle local items for real, appp cleanup
This commit is contained in:
@@ -139,7 +139,7 @@ class KDL3SNIClient(SNIClient):
|
||||
|
||||
ctx.game = self.game
|
||||
ctx.rom = rom_name
|
||||
ctx.items_handling = 0b111 # always remote items
|
||||
ctx.items_handling = 0b101 # default local items with remote start inventory
|
||||
ctx.allow_collect = True
|
||||
if "gift" not in ctx.command_processor.commands:
|
||||
ctx.command_processor.commands["gift"] = cmd_gift
|
||||
@@ -147,6 +147,7 @@ class KDL3SNIClient(SNIClient):
|
||||
death_link = await snes_read(ctx, KDL3_DEATH_LINK_ADDR, 1)
|
||||
if death_link:
|
||||
await ctx.update_death_link(bool(death_link[0] & 0b1))
|
||||
ctx.items_handling |= (death_link[0] & 0b10) # set local items if enabled
|
||||
return True
|
||||
|
||||
async def pop_item(self, ctx, in_stage):
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
import random
|
||||
from dataclasses import dataclass
|
||||
|
||||
from Options import DeathLink, Choice, Toggle, OptionDict, Range, PlandoBosses, DefaultOnToggle, \
|
||||
from Options import DeathLinkMixin, Choice, Toggle, OptionDict, Range, PlandoBosses, DefaultOnToggle, \
|
||||
PerGameCommonOptions
|
||||
from .Names import LocationName
|
||||
|
||||
|
||||
class RemoteItems(DefaultOnToggle):
|
||||
"""
|
||||
Enables receiving items from your own world, primarily for co-op play.
|
||||
"""
|
||||
display_name = "Remote Items"
|
||||
|
||||
|
||||
class Goal(Choice):
|
||||
"""
|
||||
Zero: collect the Heart Stars, and defeat Zero in the Hyper Zone.
|
||||
@@ -26,6 +33,7 @@ class Goal(Choice):
|
||||
return cls.name_lookup[value].upper()
|
||||
return super().get_option_name(value)
|
||||
|
||||
|
||||
class GoalSpeed(Choice):
|
||||
"""
|
||||
Normal: the goal is unlocked after purifying the five bosses
|
||||
@@ -292,6 +300,7 @@ class KirbyFlavor(OptionDict):
|
||||
A custom color for Kirby. To use a custom color, set the preset to Custom and then define a dict of keys from "1" to
|
||||
"15", with their values being an HTML hex color.
|
||||
"""
|
||||
display_name = "Custom Kirby Flavor"
|
||||
default = {
|
||||
"1": "B01810",
|
||||
"2": "F0E0E8",
|
||||
@@ -348,6 +357,7 @@ class GooeyFlavor(OptionDict):
|
||||
A custom color for Gooey. To use a custom color, set the preset to Custom and then define a dict of keys from "1" to
|
||||
"15", with their values being an HTML hex color.
|
||||
"""
|
||||
display_name = "Custom Gooey Flavor"
|
||||
default = {
|
||||
"1": "000808",
|
||||
"2": "102838",
|
||||
@@ -399,8 +409,8 @@ class Gifting(Toggle):
|
||||
|
||||
|
||||
@dataclass
|
||||
class KDL3Options(PerGameCommonOptions):
|
||||
death_link: DeathLink
|
||||
class KDL3Options(PerGameCommonOptions, DeathLinkMixin):
|
||||
remote_items: RemoteItems
|
||||
game_language: GameLanguage
|
||||
goal: Goal
|
||||
goal_speed: GoalSpeed
|
||||
|
||||
@@ -273,11 +273,6 @@ class RomData:
|
||||
def write_bytes(self, offset: int, values: typing.Sequence) -> None:
|
||||
self.file[offset:offset + len(values)] = values
|
||||
|
||||
def write_crc(self) -> None:
|
||||
crc = (sum(self.file[:0x7FDC] + self.file[0x7FE0:]) + 0x01FE) & 0xFFFF
|
||||
inv = crc ^ 0xFFFF
|
||||
self.write_bytes(0x7FDC, [inv & 0xFF, (inv >> 8) & 0xFF, crc & 0xFF, (crc >> 8) & 0xFF])
|
||||
|
||||
def get_bytes(self) -> bytes:
|
||||
return bytes(self.file)
|
||||
|
||||
@@ -342,8 +337,9 @@ def write_consumable_sprites(rom: RomData, consumables: bool, stars: bool):
|
||||
|
||||
class KDL3PatchExtensions(APPatchExtension):
|
||||
game = "Kirby's Dream Land 3"
|
||||
|
||||
@staticmethod
|
||||
def apply_post_patch(caller: APProcedurePatch, rom: bytes):
|
||||
def apply_post_patch(_: APProcedurePatch, rom: bytes):
|
||||
rom_data = RomData(rom)
|
||||
target_language = rom_data.read_byte(0x3C020)
|
||||
rom_data.write_byte(0x7FD9, target_language)
|
||||
@@ -361,9 +357,6 @@ class KDL3PatchExtensions(APPatchExtension):
|
||||
rom_data.write_bytes(0x460A, [0x00, 0xA0, 0x39, 0x20, 0xA9, 0x39, 0x30, 0xB2, 0x39, 0x40, 0xBB, 0x39,
|
||||
0x50, 0xC4, 0x39])
|
||||
write_consumable_sprites(rom_data, rom_data.read_byte(0x3D018) > 0, rom_data.read_byte(0x3D01A) > 0)
|
||||
rom_name = rom_data.read_bytes(0x3C000, 21)
|
||||
rom_data.write_bytes(0x7FC0, rom_name)
|
||||
rom_data.write_crc()
|
||||
return rom_data.get_bytes()
|
||||
|
||||
|
||||
@@ -375,6 +368,7 @@ class KDL3ProcedurePatch(APProcedurePatch, APTokenMixin):
|
||||
("apply_bsdiff4", ["kdl3_basepatch.bsdiff4"]),
|
||||
("apply_tokens", ["token_patch.bin"]),
|
||||
("apply_post_patch", []),
|
||||
("write_snes_crc", [])
|
||||
]
|
||||
name: bytes # used to pass to init
|
||||
|
||||
@@ -435,10 +429,12 @@ def patch_rom(world: "KDL3World", patch: KDL3ProcedurePatch):
|
||||
for room in rooms:
|
||||
room.music = world.random.choice(music_choices)
|
||||
for room in room_music:
|
||||
patch.write_token(APTokenTypes.WRITE, room + 2, world.random.choice(music_choices).to_bytes(1, "little"))
|
||||
patch.write_token(APTokenTypes.WRITE, room + 2,
|
||||
world.random.choice(music_choices).to_bytes(1, "little"))
|
||||
for i in range(5):
|
||||
# level themes
|
||||
patch.write_token(APTokenTypes.WRITE, 0x133F2 + i, world.random.choice(music_choices).to_bytes(1, "little"))
|
||||
patch.write_token(APTokenTypes.WRITE, 0x133F2 + i,
|
||||
world.random.choice(music_choices).to_bytes(1, "little"))
|
||||
# Zero
|
||||
patch.write_token(APTokenTypes.WRITE, 0x9AE79, world.random.choice(music_choices).to_bytes(1, "little"))
|
||||
# Heart Star success and fail
|
||||
@@ -446,7 +442,7 @@ def patch_rom(world: "KDL3World", patch: KDL3ProcedurePatch):
|
||||
patch.write_token(APTokenTypes.WRITE, 0x4A38D, world.random.choice(music_choices).to_bytes(1, "little"))
|
||||
|
||||
for room in rooms:
|
||||
room.patch(patch, bool(world.options.consumables.value), True)
|
||||
room.patch(patch, bool(world.options.consumables.value), not bool(world.options.remote_items.value))
|
||||
|
||||
if world.options.virtual_console in [1, 3]:
|
||||
# Flash Reduction
|
||||
@@ -471,14 +467,15 @@ def patch_rom(world: "KDL3World", patch: KDL3ProcedurePatch):
|
||||
struct.pack("H", world.required_heart_stars if world.options.goal_speed == 1 else 0xFFFF))
|
||||
patch.write_token(APTokenTypes.WRITE, 0x3D00C, world.options.goal_speed.value.to_bytes(2, "little"))
|
||||
patch.write_token(APTokenTypes.WRITE, 0x3D00E, world.options.open_world.value.to_bytes(2, "little"))
|
||||
patch.write_token(APTokenTypes.WRITE, 0x3D010, world.options.death_link.value.to_bytes(2, "little"))
|
||||
patch.write_token(APTokenTypes.WRITE, 0x3D010, ((world.options.remote_items.value << 1) +
|
||||
world.options.death_link.value).to_bytes(2, "little"))
|
||||
patch.write_token(APTokenTypes.WRITE, 0x3D012, world.options.goal.value.to_bytes(2, "little"))
|
||||
patch.write_token(APTokenTypes.WRITE, 0x3D014, world.options.stage_shuffle.value.to_bytes(2, "little"))
|
||||
patch.write_token(APTokenTypes.WRITE, 0x3D016, world.options.ow_boss_requirement.value.to_bytes(2, "little"))
|
||||
patch.write_token(APTokenTypes.WRITE, 0x3D018, world.options.consumables.value.to_bytes(2, "little"))
|
||||
patch.write_token(APTokenTypes.WRITE, 0x3D01A, world.options.starsanity.value.to_bytes(2, "little"))
|
||||
patch.write_token(APTokenTypes.WRITE, 0x3D01C, world.options.gifting.value.to_bytes(2, "little")
|
||||
if world.multiworld.players > 1 else bytes([0]))
|
||||
if world.multiworld.players > 1 else bytes([0]))
|
||||
patch.write_token(APTokenTypes.WRITE, 0x3D01E, world.options.strict_bosses.value.to_bytes(2, "little"))
|
||||
# don't write gifting for solo game, since there's no one to send anything to
|
||||
|
||||
@@ -558,6 +555,9 @@ def patch_rom(world: "KDL3World", patch: KDL3ProcedurePatch):
|
||||
patch.write_token(APTokenTypes.WRITE, 0x3C000, bytes(patch.name))
|
||||
patch.write_token(APTokenTypes.WRITE, 0x3C020, world.options.game_language.value.to_bytes(1, "little"))
|
||||
|
||||
patch.write_token(APTokenTypes.COPY, 0x7FC0, (0x3C000, 21))
|
||||
patch.write_token(APTokenTypes.COPY, 0x7FD9, (0x3C020, 1))
|
||||
|
||||
# handle palette
|
||||
if world.options.kirby_flavor_preset.value != 0:
|
||||
for addr in kirby_target_palettes:
|
||||
|
||||
@@ -160,7 +160,6 @@ CopyAbilityAnimalOverride:
|
||||
STA $39DF, X
|
||||
RTL
|
||||
|
||||
org $079A00
|
||||
HeartStarCheck:
|
||||
TXA
|
||||
CMP #$0000 ; is this level 1
|
||||
@@ -201,7 +200,6 @@ HeartStarCheck:
|
||||
SEC
|
||||
RTL
|
||||
|
||||
org $079A80
|
||||
OpenWorldUnlock:
|
||||
PHX
|
||||
LDX $900E ; Are we on open world?
|
||||
@@ -224,7 +222,6 @@ OpenWorldUnlock:
|
||||
PLX
|
||||
RTL
|
||||
|
||||
org $079B00
|
||||
MainLoopHook:
|
||||
STA $D4
|
||||
INC $3524
|
||||
@@ -265,7 +262,6 @@ MainLoopHook:
|
||||
.Return:
|
||||
RTL
|
||||
|
||||
org $079B80
|
||||
HeartStarGraphicFix:
|
||||
LDA #$0000
|
||||
PHX
|
||||
@@ -299,7 +295,6 @@ HeartStarGraphicFix:
|
||||
PLX
|
||||
RTL
|
||||
|
||||
org $079BF0
|
||||
ParseItemQueue:
|
||||
; Local item queue parsing
|
||||
NOP
|
||||
@@ -427,7 +422,6 @@ ParseItemQueue:
|
||||
LDA #$0000
|
||||
BRA .PlaySFXLong
|
||||
|
||||
org $079D00
|
||||
AnimalFriendSpawn:
|
||||
PHA
|
||||
CPX #$0002 ; is this an animal friend?
|
||||
@@ -446,7 +440,6 @@ AnimalFriendSpawn:
|
||||
LDA #$9999
|
||||
RTL
|
||||
|
||||
org $079E00
|
||||
WriteBWRAM:
|
||||
LDY #$6001 ;starting addr
|
||||
LDA #$1FFE ;bytes to write
|
||||
@@ -479,7 +472,6 @@ WriteBWRAM:
|
||||
.Return:
|
||||
RTL
|
||||
|
||||
org $079E80
|
||||
ConsumableSet:
|
||||
PHA
|
||||
PHX
|
||||
@@ -536,7 +528,6 @@ ConsumableSet:
|
||||
AND #$00FF
|
||||
RTL
|
||||
|
||||
org $079F00
|
||||
NormalGoalSet:
|
||||
PHX
|
||||
LDA $07D012
|
||||
@@ -557,7 +548,6 @@ NormalGoalSet:
|
||||
STA $5AC1 ; cutscene
|
||||
RTL
|
||||
|
||||
org $079F80
|
||||
FinalIcebergFix:
|
||||
PHX
|
||||
PHY
|
||||
@@ -591,7 +581,6 @@ FinalIcebergFix:
|
||||
PLX
|
||||
RTL
|
||||
|
||||
org $07A000
|
||||
StrictBosses:
|
||||
PHX
|
||||
LDA $901E ; Do we have strict bosses enabled?
|
||||
@@ -618,7 +607,6 @@ StrictBosses:
|
||||
LDA $53CD
|
||||
RTL
|
||||
|
||||
org $07A030
|
||||
NintenHalken:
|
||||
LDX #$0005
|
||||
.Halken:
|
||||
@@ -636,7 +624,6 @@ NintenHalken:
|
||||
LDA #$0001
|
||||
RTL
|
||||
|
||||
org $07A080
|
||||
StageCompleteSet:
|
||||
PHX
|
||||
LDA $5AC1 ; completed stage cutscene
|
||||
@@ -667,6 +654,16 @@ StageCompleteSet:
|
||||
DEC
|
||||
ASL
|
||||
TAX
|
||||
PHX
|
||||
LDA $8200, X
|
||||
AND #$00FF
|
||||
BNE .ApplyClear
|
||||
TXA
|
||||
LSR
|
||||
INC
|
||||
JSL ApplyLocalCheck
|
||||
.ApplyClear:
|
||||
PLX
|
||||
LDA #$0001
|
||||
ORA $8200, X
|
||||
STA $8200, X
|
||||
@@ -676,7 +673,6 @@ StageCompleteSet:
|
||||
CMP $53CB
|
||||
RTL
|
||||
|
||||
org $07A100
|
||||
OpenWorldBossUnlock:
|
||||
PHX
|
||||
PHY
|
||||
@@ -740,7 +736,6 @@ OpenWorldBossUnlock:
|
||||
PLX
|
||||
RTL
|
||||
|
||||
org $07A180
|
||||
GooeySpawn:
|
||||
PHY
|
||||
PHX
|
||||
@@ -776,7 +771,6 @@ GooeySpawn:
|
||||
PLY
|
||||
RTL
|
||||
|
||||
org $07A200
|
||||
SpeedTrap:
|
||||
PHX
|
||||
LDX $8082 ; do we have slowness
|
||||
@@ -788,7 +782,6 @@ SpeedTrap:
|
||||
EOR #$FFFF
|
||||
RTL
|
||||
|
||||
org $07A280
|
||||
HeartStarVisual:
|
||||
CPX #$0000
|
||||
BEQ .SkipInx
|
||||
@@ -852,7 +845,6 @@ HeartStarVisual:
|
||||
.Return:
|
||||
RTL
|
||||
|
||||
org $07A300
|
||||
LoadFont:
|
||||
JSL $00D29F ; play sfx
|
||||
PHX
|
||||
@@ -923,7 +915,6 @@ LoadFont:
|
||||
PLX
|
||||
RTL
|
||||
|
||||
org $07A380
|
||||
HeartStarVisual2:
|
||||
LDA #$2C80
|
||||
STA $0000, Y
|
||||
@@ -1037,7 +1028,6 @@ HeartStarVisual2:
|
||||
STA $0000, Y
|
||||
RTL
|
||||
|
||||
org $07A480
|
||||
HeartStarSelectFix:
|
||||
PHX
|
||||
TXA
|
||||
@@ -1059,15 +1049,22 @@ HeartStarSelectFix:
|
||||
AND #$00FF
|
||||
RTL
|
||||
|
||||
org $07A500
|
||||
HeartStarCutsceneFix:
|
||||
TAX
|
||||
LDA $53D3
|
||||
DEC
|
||||
STA $5AC3
|
||||
LDA $53A7, X
|
||||
AND #$00FF
|
||||
BNE .Return
|
||||
PHX
|
||||
TXA
|
||||
ORA #$0100
|
||||
JSL ApplyLocalCheck
|
||||
PLX
|
||||
.Return
|
||||
RTL
|
||||
|
||||
org $07A510
|
||||
GiftGiving:
|
||||
CMP #$0008
|
||||
.This:
|
||||
@@ -1083,7 +1080,6 @@ GiftGiving:
|
||||
PLX
|
||||
JML $CABC18
|
||||
|
||||
org $07A550
|
||||
PauseMenu:
|
||||
JSL $00D29F
|
||||
PHX
|
||||
@@ -1144,7 +1140,6 @@ PauseMenu:
|
||||
PLX
|
||||
RTL
|
||||
|
||||
org $07A600
|
||||
StarsSet:
|
||||
PHA
|
||||
PHX
|
||||
@@ -1214,11 +1209,10 @@ StarsSet:
|
||||
STA $39D7
|
||||
BRA .Return
|
||||
|
||||
org $07A680
|
||||
ApplyLocalCheck:
|
||||
; args: A-address of check following $08B000
|
||||
TAX
|
||||
LDA $08B000, X
|
||||
LDA $09B000, X
|
||||
AND #$00FF
|
||||
TAY
|
||||
LDX #$0000
|
||||
@@ -1231,7 +1225,8 @@ ApplyLocalCheck:
|
||||
BCC .Loop
|
||||
BRA .Return ; this is dangerous, could lose a check here
|
||||
.Apply:
|
||||
STY $C000, X
|
||||
TYA
|
||||
STA $C000, X
|
||||
.Return:
|
||||
RTL
|
||||
|
||||
@@ -1272,4 +1267,4 @@ org $07E040
|
||||
db $3D, $05
|
||||
|
||||
org $07F000
|
||||
incbin "APPauseIcons.bin"
|
||||
incbin "APPauseIcons.dat"
|
||||
Reference in New Issue
Block a user