diff --git a/assets/asm/ZSCustomOverworld_v3.asm b/assets/asm/ZSCustomOverworld_v3.asm new file mode 100644 index 00000000..599308b0 --- /dev/null +++ b/assets/asm/ZSCustomOverworld_v3.asm @@ -0,0 +1,5770 @@ +; ============================================================================== +; ZScream Custom Overworld ASM +; Written by Jared_Brian_ +; With help and testing from Jeimuzu, Letterbomb, Scawful, and Zarby89 +; ============================================================================== +; The purpose of this ASM is to give users the ability to customize many +; aspects of the ALTTP overworld that were previously hardcoded. +; +; Features include: +; • The ability to add a mosaic on any transition. +; • The ability to change the main palette for each area. +; • The ability to give each area a custom background transparent color. +; • The ability to give each area its own tile GFX set. +; • The ability to give each area its own animated tile set. +; • The ability to add or remove a subscreen overlay on each area. +; (rain, fog, sky, lava, pyramid, etc.) +; • The ability to disable the rain in the beginning phase. +; • Removed hardcoded exits playing music instead of using the area's set +; music. +; • The ability to change the layout of "small" (1x1) and "large" (2x2) areas +; already present in the vanilla game. +; • The ability to have "wide" (2x1) and "tall" (1x2) areas that were not +; present in the vanilla game. +; • The ability to use the other previously unused "secial world" areas +; as if they were a normal area. Including the use of items, entrances, +; exits, whirlpools, bird transports, sign messages, overworld transitions, +; entrance overlays, and subscreen overlays. +; • The ability to have sprites on the DW and SW during phase 0. +; • Fixes several bugs present in the vanilla game that prevent certain normal +; overworld transitions such as "staggered" layouts or transitions in the +; middle of 2 large areas that are next to each other. See the diagrams in +; the OverworldScreenTileMapChange section below for more details. +; +; To achieve this, large portions of the game's vanilla code had to be edited +; or even re-written entirely to instead read from tables in expanded space. +; These tables are written to and generated by ZScream. Tables based on the +; vanilla configuration can be used by changing the debug variable !UseVanillaPool +; down below to a 1, thus removing the need for ZScream although this is not +; reccomended for your average user. +; Some of the new features require a bit more computation time (to decompress +; GFX for example) causing load times to be slightly longer (1-2 frames more at +; most). Because of this, I have made it so certain features can be disabled to +; instead use the original vanilla code if speed is prefered. See the +; EnableTable below for more details. +; +; There are certain things that are still hardcoded here as a result but can +; be changed if you know a bit of ASM, such as: +; • The rain that is originally present in the Misery Mire area. +; • The Lost Woods changing to the tree canopy overlay after obtaining the +; master sword. +; • The fog overlay being disabled after obtaining the master sword in the +; master sword area. +; • The bridge overlay present in the under the bridge area. +; • The BG color present in the under the bridge area. +; • The pyramid overlay only scrolling properly on area $5B. +; • The smaller camera boundaries present in the master sword area and the +; area under the bridge. +; ============================================================================== +; Non-Expanded Space +; ============================================================================== + +; TODO: Entrance overlay SRM + +pushpc + +incsrc HardwareRegisters.asm + +; Free RAM + +TransGFXModule_PriorSheets = $04CB ; [0x08] May use more in the future here. +NewNMISource1 = $04D5 ; [0x02] +NewNMITarget1 = $04D3 ; [0x02] +NewNMICount1 = $04D7 ; [0x02] +NewNMITarget2 = $04D9 ; [0x02] +NewNMISource2 = $04DB ; [0x02] +NewNMICount2 = $04DD ; [0x02] +OWCameraBoundsS = $0716 ; [0x02] +OWCameraBoundsE = $0718 ; [0x02] +TransGFXModuleFrame = $0CF3 ; [0x01] +AnimatedTileGFXSet = $0FC0 ; [0x01] +ExpandedSpritePalArray = $7EFDC0 ; [0x40] + +; $0716 is not actually free, but labled as such for the sake of organization. +; $0718 is free RAM and took the horizontal responsibility away from $0716. +; ($0716 is labled as OWCameraBoundsSE in the disassembly). + +; Hooks +Sound_LoadLightWorldSongBank = $008913 ; $000913 +EnableForceBlank = $00893D ; $00093D +GFXSheetPointers_sprite_bank = $00CFF3 ; $004FF3 +GFXSheetPointers_sprite_high = $00D0D2 ; $0050D2 +GFXSheetPointers_sprite_low = $00D1B1 ; $0051B1 +DecompOwAnimatedTiles = $00D394 ; $005394 +GetAnimatedSpriteTile = $00D4DB ; $0054DB +GetAnimatedSpriteTile_variable = $00D4ED ; $0054ED +LoadTransAuxGFX_sprite_continue = $00D706 ; $005706 +SheetsTable_0AA4 = $00D8F4 ; $0058F4 +PrepTransAuxGFX = $00DF1A ; $005F1A +Do3To4High16Bit = $00DF4F ; $005F4F +Do3To4Low16Bit = $00DFB8 ; $005FB8 +InitTilesets = $00E19B ; $00619B +CopyFontToVram = $00E556 ; $006556 +Decomp_bg_variable = $00E78F ; $00678F +GFX0AA2ValsOW = $00FC9C ; $007C9C + +Credits_LoadScene_PrepGFX_sprite_gfx = $0285E2 ; $0105E2 +Credits_LoadScene_PrepGFX_sprite_palette = $0285F3 ; $0105F3 +DeleteCertainAncillaeStopDashing = $028B0C ; $010B0C +OWOverlay_HShift = $02A46D ; $01246D +OWOverlay_VShift = $02A471 ; $012471 +Overworld_LoadMapProperties = $02AB08 ; $012B08 +Overworld_FinishTransGfx_firstHalf_Retrun = $02ABC5 ; $012BC5 +Overworld_LoadSubscreenAndSilenceSFX1 = $02AF19 ; $012F19 +Overworld_ReloadSubscreenOverlayAndAdvance = $02B1F4 ; $0131F4 +Dungeon_LoadPalettes_cacheSettings = $02C65F ; $01465F +SpecialOverworld_CopyPalettesToCache = $02C6EB ; $0146EB +Overworld_CgramAuxToMain = $02C769 ; $014769 +UnderworldExitData_overworld_id = $02DD8A ; $015D8A +Pool_LoadSpecialOverworld_GFX_0AA3 = $02E6E1 ; $0166E1 +Pool_LoadSpecialOverworld_palette_prop_b = $02E701 ; $016701 +Pool_LoadSpecialOverworld_GFX_0AA2 = $02E821 ; $016821 +Overworld_ScrollMap = $02F273 ; $017273 +LoadSubscreenOverlay = $02FD0D ; $017D0D + +Link_ItemReset_FromOverworldThings = $07B107 ; $03B107 +Player_IsScreenTransitionPermitted = $07F439 ; $03F439 + +Tagalong_Init = $099EFC ; $049EFC +Sprite_ReinitWarpVortex = $09AF89 ; $04AF89 +Sprite_ResetAll = $09C44E ; $04C44E +Sprite_OverworldReloadAll = $09C499 ; $04C499 +OverworldPalettesScreenToSet_New = $09C635 ; $04C635 + +BirdTravel_LoadAmbientOverlay = $0AB948 ; $053948 + +Overworld_SetFixedColorAndScroll = $0BFE70 ; $05FE70 + +Overworld_LoadPalettes = $0ED5A8 ; $0755A8 +Palette_SetOwBgColor_Long = $0ED618 ; $075618 +Overworld_SetScreenBGColorCacheOnly = $0ED61D ; $07561D +LoadGearPalettes_bunny = $0ED6DD ; $0756DD +Overworld_CheckForSpecialOverworldTrigger = $0EDE49 ; $075E49 +SpecialOverworld_CheckForReturnTrigger = $0EDEE3 ; $075EE3 +Overworld_DwDeathMountainPaletteAnimation = $0EF582 ; $077582 + +Overworld_Entrance = $1BBBF4 ; $0DBBF4 +PaletteIDtoOffset_OW_Main = $1BEC3B ; $0DEC3B +Palette_SpriteAux3 = $1BEC77 ; $0DEC77 +Palette_MainSpr = $1BEC9E ; $0DEC9E +Palette_SpriteAux1 = $1BECC5 ; $0DECC5 +Palette_SpriteAux2 = $1BECE4 ; $0DECE4 +Palette_Sword = $1BED03 ; $0DED03 +Palette_Shield = $1BED29 ; $0DED29 +Palette_MiscSpr = $1BED6E ; $0DED6E +Palette_ArmorAndGloves = $1BEDF9 ; $0DEDF9 +Palette_Hud = $1BEE52 ; $0DEE52 +Palette_OverworldBgAux3 = $1BEEA8 ; $0DEEA8 +Palette_OverworldBgMain = $1BEEC7 ; $0DEEC7 +PaletteData_owmain = $1BE6C8 ; $0DE6C8 + +; ============================================================================== +; Debug addresses: +; ============================================================================== + +; These can be used to turn off each hook used. Some are reliant on eachother +; and disabling only some can break entire features. +; TODO: Create a log of dependencies and change the naming structure of the +; vars themseleves to be more reflective of those features. + +; Makes the game decompress the 3 static OW tile sheets on transition. +; $00D585 +!Func00D585 = $01 + +; Animated tiles on warp. +; $00D8D5 +!Func00D8D5 = $01 + +; Enable/Disable subscreen. +; $00DA63 +!Func00DA63 = $01 + +; Changes the InitTilesets function to call from the long tables. +; $00E221 +!Func00E221 = $01 + +; Zeros out the BG color when mirror warping to the pyramid area. +; $00EEBB +!Func00EEBB = $01 + +; $007C67 +!Func00FC67 = $01 + +; BG scrolling for HC and the pyramid area. +; $00FF7C +!Func00FF7C = $01 + +; Changes the function that loads overworld properties when exiting a dungeon. +; Includes removing asm that plays music in certain areas and changing how +; animated tiles are loaded. +; $0283EE +!Func0283EE = $01 + +; Changes a function that loads animated tiles under certain conditions. +; $028632 +!Func028632 = $01 + +; Changes part of a function that changes the sub mask color when leaving +; dungeons. +; $029A37 +!Func029A37 = $01 + +; Rain animation code. +; $02A4CD +!Func02A4CD = $01 + +; $02A5D3 +!Func02A5D3 = $01 + +; $02A62C +!Func02A62C = $01 + +; $02A9C4 +!Func02A9C4 = $01 + +; $02AB64 +!Func02AB64 = $01 + +; Transition animated and main palette. +; $02ABBE +!Func02ABBE = $01 + +; $02AC40 +!Func02AC40 = $01 + +; Main subscreen loading function. +; $02AF58 +!Func02AF58 = $01 + +; turns on subscreen for pyramid. +; $02B2D4 +!Func02B2D4 = $01 + +; Activate subscreen durring pyramid warp. +; $02B391 +!Func02B391 = $01 + +; Reset a var needed for whirpool GFX transfer. +; $02B490 +!Func02B490 = $01 + +; Controls overworld vertical subscreen movement for the pyramid BG. +; $02BC44 +!Func02BC44 = $01 + +; Changes how the pyramid BG scrolls durring transition. +; $02C02D +!Func02C02D = $01 + +; $02C0C3 +!Func02C0C3 = $01 + +; Main palette loading routine. +; $02C692 +!Func02C692 = $01 + +; $02E598 +!Func02E598 = $01 + +; $02E931 +!Func02E931 = $01 + +; $02EF44 +!Func02EF44 = $01 + +; $03B518 +!Func07B518 = $01 + +; $04C4C7 +!Func09C4C7 = $01 + +; Loads different animated tiles when returning from bird travel. +; $0AB8F5 +!Func0AB8F5 = $01 + +; Loads the animated tiles after the overworld map is closed. +; $0ABC5A +!Func0ABC5A = $01 + +; Load overlay, fixed color, and BG color. +; $0BFEB6 +!Func0BFEB6 = $01 + +; Transparent color durring warp and during special area enter. +; $0ED627 +!Func0ED627 = $01 + +; Resets the area special color after the screen flashes. +; $0ED8AE +!Func0ED8AE = $01 + +; $1BC8B1 +!Func1BC8B1 = $01 + +; If 1, all of the default vanilla pool values will be applied. 00 by default. +!UseVanillaPool = $00 + +; Use this var to disable all of the debug vars above. +!AllOff = $00 + +if !AllOff == 1 +!Func00D585 = $00 +!Func00D8D5 = $00 +!Func00DA63 = $00 +!Func00E221 = $00 +!Func00EEBB = $00 +!Func00FC67 = $00 +!Func00FF7C = $00 + +!Func0283EE = $00 +!Func028632 = $00 +!Func029A37 = $00 +!Func02A4CD = $00 +!Func02A5D3 = $00 +!Func02A62C = $00 +!Func02A9C4 = $00 +!Func02AB64 = $00 +!Func02ABBE = $00 +!Func02AC40 = $00 +!Func02AF58 = $00 +!Func02B2D4 = $00 +!Func02B391 = $00 +!Func02B490 = $00 +!Func02BC44 = $00 +!Func02C02D = $00 +!Func02C0C3 = $00 +!Func02C692 = $00 +!Func02E598 = $00 +!Func02E931 = $00 +!Func02EF44 = $00 + +!Func07B518 = $00 + +!Func09C4C7 = $00 + +!Func0AB8F5 = $00 +!Func0ABC5A = $00 + +!Func0BFEB6 = $00 + +!Func0ED627 = $00 +!Func0ED8AE = $00 + +!Func1BC8B1 = $00 +endif + +; ============================================================================== +; Fixing old hooks: +; ============================================================================== + +; TODO: Eventually remove these? I'm not sure. If anyone used an old ZS on their +; ROM these will need to be fixed but also could block people from hooking into +; these spots. We could potentially add these to a "repair ROM" asm feature. + +; Main Palette loading routine. +org $0ED5E7 ; $0755E7 + JSL.l Palette_OverworldBgAux3 + +; Repairs an old ZS call. +org $02ABB8 ; $012BB8 + db $A9, $09, $80, $02 + +; ============================================================================== +; Expanded Space +; ============================================================================== + +; Reserved ZS space. +; Avoid moving this at all costs. If you do, you will have to change where ZS +; saves this data as well and previous data will be lost or corrupted. +org $288000 ; $140000 +Pool: +{ + ; Valid values: + ; 555 color value $0000 to $7FFF. + ; $2669 LW green grass color + ; $2A32 DW dead grass color + ; $19C6 SW dark green shadow color + .BGColorTable ; $140000 + if !UseVanillaPool == 1 + ; LW + dw $2669, $2669, $2669, $0000, $0000, $0000, $0000, $0000 + dw $2669, $2669, $2669, $0000, $0000, $0000, $0000, $2669 + dw $2669, $2669, $2669, $2669, $2669, $2669, $2669, $2669 + dw $2669, $2669, $2669, $2669, $2669, $2669, $2669, $2669 + dw $2669, $2669, $2669, $2669, $2669, $2669, $2669, $2669 + dw $2669, $2669, $2669, $2669, $2669, $2669, $2669, $2669 + dw $2669, $2669, $2669, $2669, $2669, $2669, $2669, $2669 + dw $2669, $2669, $2669, $2669, $2669, $2669, $2669, $2669 + + ; DW + dw $2A32, $2A32, $2A32, $0000, $0000, $0000, $0000, $0000 + dw $2A32, $2A32, $2A32, $0000, $0000, $0000, $0000, $2A32 + dw $2A32, $2A32, $2A32, $2A32, $2A32, $2A32, $2A32, $2A32 + dw $2A32, $2A32, $2A32, $0000, $0000, $2A32, $2A32, $2A32 + dw $2A32, $2A32, $2A32, $0000, $0000, $2A32, $2A32, $2A32 + dw $2A32, $2A32, $2A32, $2A32, $2A32, $2A32, $2A32, $2A32 + dw $2A32, $2A32, $2A32, $2A32, $2A32, $2A32, $2A32, $2A32 + dw $2A32, $2A32, $2A32, $2A32, $2A32, $2A32, $2A32, $2A32 + + ; SW + dw $19C6, $19C6, $19C6, $0000, $0000, $0000, $0000, $0000 + dw $0000, $19C6, $19C6, $0000, $0000, $0000, $0000, $0000 + dw $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000 + dw $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000 + endif + warnpc $288140 + + ; Valid values: + ; $00 - Disabled + ; Non $00 - Enabled + org $288140 ; $140140 + .EnableTable ; 0x20 + + org $288140 ; $140140 + .EnableBGColor ; 0x01 + if !UseVanillaPool > 0 + db $01 + endif + + org $288141 ; $140141 + .EnableMainPalette ; 0x01 + if !UseVanillaPool > 0 + db $01 + endif + + org $288142 ; $140142 + .EnableMosaic ; 0x01 Unused for now. + db $01 + + ; When non 0 this will allow animated tiles to be updated between OW + ; transitions. Default is $FF. + org $288143 ; $140143 + .EnableAnimated ; 0x01 + if !UseVanillaPool > 0 + db $01 + endif + + ; When non 0 this will allow Subscreen Overlays to be updated between OW + ; transitions. Default is $FF. + org $288144 ; $140144 + .EnableSubScreenOverlay ; 0x01 + if !UseVanillaPool > 0 + db $01 + endif + + ; This is a reserved value that ZS will write to when it has applied the + ; ASM. That way the next time ZS loads the ROM it knows to read the custom + ; values instead of using the default ones. The current version is 03. + org $288145 ; $140145 + .ZSAppliedASM ; 0x01 + db $03 + + ; When non 0 this will cause rain to appear on all areas in the beginning + ; phase. Default is $FF. + org $288146 ; $140146 + .EnableBeginningRain ; 0x01 + ;if !UseVanillaPool > 0 + db $FF + ;endif + + ; TODO: Add a place to change this in ZS. Once that is done add this to the + ; vanilla pool checks as well. + ; When non 0 this will disable the ambiant sound that plays in the mire + ; area after the event is triggered. Default is $FF. + org $288147 ; $140147 + .EnableRainMireEvent ; 0x01 + db $FF + + ; When non 0 this will make the game reload all gfx in between OW + ; transitions. Default is $FF. + org $288148 ; $140143 + .EnableTransitionGFXGroupLoad ; 0x01 + if !UseVanillaPool > 0 + db $01 + endif + + ; TODO: Vanilla pool check disabled for now until we put an actual place to + ; change it. + ; The bridge color is different from the Master Sword area so we are going to + ; hard code it here for now. Default is $2669 which is the vanilla LW green. + org $288149 ; $140149 + .BGColorTable_Bridge ; 0x02 + ;if !UseVanillaPool > 0 + dw $2669 + ;endif + + ; The rest of these are extra bytes that can be used for anything else + ; later on. + ;db $00, $00, $00, $00, $00, $00, $00, $00 + ;db $00, $00, $00, $00, $00, $00, $00, $00 + ;db $00, $00, $00, $00, $00 + warnpc $288160 + + ; Valid values: + ; Main overworld palette index $00 to $05. + ; $00 is the normal light world palette. + ; $01 is the normal dark world palette. + ; $02 is the normal light world death mountain palette. + ; $03 is the normal dark world death mountain palette. + ; $04 is the Triforce room palette. + ; $05 is the title screen palette? + org $288160 ; $140160 + .MainPaletteTable ; 0xA0 + if !UseVanillaPool == 1 + ; LW + db $00, $00, $00, $02, $00, $02, $00, $02 + db $00, $00, $00, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + + ; DW + db $01, $01, $01, $03, $01, $03, $01, $03 + db $01, $01, $01, $01, $01, $01, $01, $01 + db $01, $01, $01, $01, $01, $01, $01, $01 + db $01, $01, $01, $01, $01, $01, $01, $01 + db $01, $01, $01, $01, $01, $01, $01, $01 + db $01, $01, $01, $01, $01, $01, $01, $01 + db $01, $01, $01, $01, $01, $01, $01, $01 + db $01, $01, $01, $01, $01, $01, $01, $01 + + ; SW + db $00, $00, $00, $00, $00, $00, $00, $00 + db $04, $00, $00, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + endif + warnpc $288200 + + ; Valid values: + ; .... udlr + ; u - Up + ; d - Down + ; l - Left + ; r - Right + org $288200 ; $140200 + .MosaicTable ; 0xA0 + if !UseVanillaPool == 1 + ; LW + db $05, $00, $02, $00, $00, $00, $00, $00 + db $00, $00, $02, $00, $00, $00, $00, $08 + db $08, $08, $00, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + + ; DW + db $05, $00, $02, $00, $00, $00, $00, $00 + db $00, $00, $02, $00, $00, $00, $00, $00 + db $08, $08, $00, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + + ; SW + db $04, $04, $00, $00, $00, $00, $00, $00 + db $04, $00, $00, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + endif + warnpc $2882A0 + + ; Not the same as OWGFXGroupTable_sheet7. The game uses a combination of $59 + ; and $5B to create the sheet in sheet #7. This is done by first transfering + ; all the gfx that is needed for the bottom half of the sheet (the door + ; frames for example) which is different depending on whether we are in the + ; LW or DW. It then loads the actual animated tile frames into a buffer + ; where it can transfer over from durring NMI based on whether we are on + ; Death Mountain or not (LW or DW). This table is to control the latter. + ; Valid values: + ; GFX index $00 to $FF. + ; In vanilla, $59 are the DW door frames and clouds and $5B are the Lw door + ; frames and the regular water tiles. + org $2882A0 ; $1402A0 + .AnimatedTable ; 0xA0 + if !UseVanillaPool == 1 + ; LW + db $5B, $5B, $5B, $59, $5B, $59, $5B, $59 + db $5B, $5B, $5B, $5B, $5B, $5B, $5B, $5B + db $5B, $5B, $5B, $5B, $5B, $5B, $5B, $5B + db $5B, $5B, $5B, $5B, $5B, $5B, $5B, $5B + db $5B, $5B, $5B, $5B, $5B, $5B, $5B, $5B + db $5B, $5B, $5B, $5B, $5B, $5B, $5B, $5B + db $5B, $5B, $5B, $5B, $5B, $5B, $5B, $5B + db $5B, $5B, $5B, $5B, $5B, $5B, $5B, $5B + + ; DW + db $5B, $5B, $5B, $59, $5B, $59, $5B, $59 + db $5B, $5B, $5B, $5B, $5B, $5B, $5B, $5B + db $5B, $5B, $5B, $5B, $5B, $5B, $5B, $5B + db $5B, $5B, $5B, $5B, $5B, $5B, $5B, $5B + db $5B, $5B, $5B, $5B, $5B, $5B, $5B, $5B + db $5B, $5B, $5B, $5B, $5B, $5B, $5B, $5B + db $5B, $5B, $5B, $5B, $5B, $5B, $5B, $5B + db $5B, $5B, $5B, $5B, $5B, $5B, $5B, $5B + + ; SW + db $5B, $5B, $5B, $5B, $5B, $5B, $5B, $5B + db $5B, $5B, $5B, $5B, $5B, $5B, $5B, $5B + db $5B, $5B, $5B, $5B, $5B, $5B, $5B, $5B + db $5B, $5B, $5B, $5B, $5B, $5B, $5B, $5B + endif + warnpc $288340 + + ; Valid values: + ; Can be any value $00 to $FF but is stored as 2 bytes instead of one to + ; help the code out below. $FF is for no overlay area. Hopefully no crazy + ; person decides to expand their overworld to $FF areas. + ; $0093 is the triforce room curtain overlay. + ; $0094 is the under the bridge overlay. + ; $0095 is the sky background overlay. + ; $0096 is the pyramid background overlay. + ; $0097 is the first fog overlay. + + ; $009C is the lava background overlay. + ; $009D is the second fog overlay. + ; $009E is the tree canopy overlay. + ; $009F is the rain overlay. + org $288340 ; $140340 + .OverlayTable ; 0x140 + if !UseVanillaPool == 1 + ; LW + dw $009D, $00FF, $00FF, $0095, $00FF, $0095, $00FF, $0095 + dw $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF + dw $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF + dw $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF + dw $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF + dw $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF + dw $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF + dw $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF + + ; DW + dw $009D, $00FF, $00FF, $009C, $00FF, $009C, $00FF, $009C + dw $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF + dw $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF + dw $00FF, $00FF, $00FF, $0096, $00FF, $00FF, $00FF, $00FF + dw $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF + dw $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF + dw $009F, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF + dw $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF + + ; SP + dw $0097, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF + dw $0093, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF + dw $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF + dw $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF, $00FF + endif + warnpc $288480 + + ; Just in case 0xFF is used and there is no sheet to load when warping using + ; the bird, unloading the map, or exiting a dungeon, the DefaultGFXGroups + ; values are used. 0xFF is used instead of 0x00 as the "don't change the + ; sheet" value. That way, we can actually use sheet 00 if we want. + org $288480 ; $140480 + .OWGFXGroupTable ; 0x500 (0xA0 * 0x08) + + ; LW + org $288480 ; $140480 + .OWGFXGroupTable_sheet0 + if !UseVanillaPool == 1 + db $3A ; 0x00 sheet 0 + endif + + org $288481 ; $140481 + .OWGFXGroupTable_sheet1 + if !UseVanillaPool == 1 + db $3B ; 0x00 sheet 1 + endif + + org $288482 ; $140482 + .OWGFXGroupTable_sheet2 + if !UseVanillaPool == 1 + db $3C ; 0x00 sheet 2 + endif + + org $288483 ; $140483 + .OWGFXGroupTable_sheet3 + if !UseVanillaPool == 1 + db $FF ; 0x00 sheet 3 + endif + + org $288484 ; $140484 + .OWGFXGroupTable_sheet4 + if !UseVanillaPool == 1 + db $57 ; 0x00 sheet 4 + endif + + org $288485 ; $140485 + .OWGFXGroupTable_sheet5 + if !UseVanillaPool == 1 + db $4C ; 0x00 sheet 5 + endif + + org $288486 ; $140486 + .OWGFXGroupTable_sheet6 + if !UseVanillaPool == 1 + db $FF ; 0x00 sheet 6 + endif + + org $288487 ; $140487 + .OWGFXGroupTable_sheet7 + if !UseVanillaPool == 1 + db $5B ; 0x00 sheet 7 + + db $3A, $3B, $3C, $FF, $57, $4C, $FF, $5B ; 0x01 + db $3A, $3B, $3C, $FF, $57, $4C, $FF, $5B ; 0x02 + db $3A, $3B, $3C, $FF, $56, $4F, $FF, $5B ; 0x03 + db $3A, $3B, $3C, $FF, $56, $4F, $FF, $5B ; 0x04 + db $3A, $3B, $3C, $FF, $56, $4F, $FF, $5B ; 0x05 + db $3A, $3B, $3C, $FF, $56, $4F, $FF, $5B ; 0x06 + db $3A, $3B, $3C, $FF, $56, $4F, $FF, $5B ; 0x07 + + db $3A, $3B, $3C, $FF, $57, $4C, $FF, $5B ; 0x08 + db $3A, $3B, $3C, $FF, $57, $4C, $FF, $5B ; 0x09 + db $3A, $3B, $3C, $FF, $57, $4C, $FF, $5B ; 0x0A + db $3A, $3B, $3C, $FF, $56, $4F, $FF, $5B ; 0x0B + db $3A, $3B, $3C, $FF, $56, $4F, $FF, $5B ; 0x0C + db $3A, $3B, $3C, $FF, $56, $4F, $FF, $5B ; 0x0D + db $3A, $3B, $3C, $FF, $56, $4F, $FF, $5B ; 0x0E + db $3A, $3B, $3C, $FF, $51, $4E, $FF, $5B ; 0x0F + + db $3A, $3B, $3C, $FF, $53, $4D, $FF, $5B ; 0x10 + db $3A, $3B, $3C, $FF, $53, $4D, $FF, $5B ; 0x11 + db $3A, $3B, $3C, $FF, $FF, $FF, $FF, $5B ; 0x12 + db $3A, $3B, $3C, $FF, $50, $4B, $FF, $5B ; 0x13 + db $3A, $3B, $3C, $FF, $50, $4B, $FF, $5B ; 0x14 + db $3A, $3B, $3C, $FF, $FF, $FF, $FF, $5B ; 0x15 + db $3A, $3B, $3C, $FF, $50, $4B, $FF, $5B ; 0x16 + db $3A, $3B, $3C, $FF, $50, $4B, $FF, $5B ; 0x17 + + db $3A, $3B, $3C, $FF, $53, $4D, $FF, $5B ; 0x18 + db $3A, $3B, $3C, $FF, $53, $4D, $FF, $5B ; 0x19 + db $3A, $3B, $3C, $FF, $FF, $FF, $FF, $5B ; 0x1A + db $3A, $3B, $3C, $FF, $52, $49, $FF, $5B ; 0x1B + db $3A, $3B, $3C, $FF, $52, $49, $FF, $5B ; 0x1C + db $3A, $3B, $3C, $FF, $51, $4E, $FF, $5B ; 0x1D + db $3A, $3B, $3C, $FF, $55, $4A, $FF, $5B ; 0x1E + db $3A, $3B, $3C, $FF, $55, $4A, $FF, $5B ; 0x1F + + db $3A, $3B, $3C, $FF, $53, $4D, $FF, $5B ; 0x20 + db $3A, $3B, $3C, $FF, $53, $4D, $FF, $5B ; 0x21 + db $3A, $3B, $3C, $FF, $53, $4D, $FF, $5B ; 0x22 + db $3A, $3B, $3C, $FF, $52, $49, $FF, $5B ; 0x23 + db $3A, $3B, $3C, $FF, $52, $49, $FF, $5B ; 0x24 + db $3A, $3B, $3C, $FF, $FF, $FF, $FF, $5B ; 0x25 + db $3A, $3B, $3C, $FF, $55, $4A, $FF, $5B ; 0x26 + db $3A, $3B, $3C, $FF, $55, $4A, $FF, $5B ; 0x27 + + db $3A, $3B, $3C, $FF, $53, $4D, $FF, $5B ; 0x28 + db $3A, $3B, $3C, $FF, $53, $4D, $FF, $5B ; 0x29 + db $3A, $3B, $3C, $FF, $57, $4C, $FF, $5B ; 0x2A + db $3A, $3B, $3C, $FF, $FF, $FF, $FF, $5B ; 0x2B + db $3A, $3B, $3C, $FF, $FF, $FF, $FF, $5B ; 0x2C + db $3A, $3B, $3C, $FF, $51, $4E, $FF, $5B ; 0x2D + db $3A, $3B, $3C, $FF, $FF, $FF, $FF, $5B ; 0x2E + db $3A, $3B, $3C, $FF, $55, $4A, $FF, $5B ; 0x2F + + db $3A, $3B, $3C, $FF, $55, $54, $FF, $5B ; 0x30 + db $3A, $3B, $3C, $FF, $55, $54, $FF, $5B ; 0x31 + db $3A, $3B, $3C, $FF, $FF, $FF, $FF, $5B ; 0x32 + db $3A, $3B, $3C, $FF, $51, $4E, $FF, $5B ; 0x33 + db $3A, $3B, $3C, $FF, $51, $4E, $FF, $5B ; 0x34 + db $3A, $3B, $3C, $FF, $51, $4E, $FF, $5B ; 0x35 + db $3A, $3B, $3C, $FF, $51, $4E, $FF, $5B ; 0x36 + db $3A, $3B, $3C, $FF, $51, $4E, $FF, $5B ; 0x37 + + db $3A, $3B, $3C, $FF, $55, $54, $FF, $5B ; 0x38 + db $3A, $3B, $3C, $FF, $55, $54, $FF, $5B ; 0x39 + db $3A, $3B, $3C, $FF, $FF, $FF, $FF, $5B ; 0x3A + db $3A, $3B, $3C, $FF, $51, $4E, $FF, $5B ; 0x3B + db $3A, $3B, $3C, $FF, $51, $4E, $FF, $5B ; 0x3C + db $3A, $3B, $3C, $FF, $51, $4E, $FF, $5B ; 0x3D + db $3A, $3B, $3C, $FF, $51, $4E, $FF, $5B ; 0x3E + db $3A, $3B, $3C, $FF, $51, $4E, $FF, $5B ; 0x3F + + ; DW + db $42, $43, $44, $FF, $2D, $2E, $FF, $59 ; 0x40 + db $42, $43, $44, $FF, $2D, $2E, $FF, $59 ; 0x41 + db $42, $43, $44, $FF, $2D, $2E, $FF, $59 ; 0x42 + db $42, $43, $44, $FF, $33, $34, $FF, $59 ; 0x43 + db $42, $43, $44, $FF, $33, $34, $FF, $59 ; 0x44 + db $42, $43, $44, $FF, $33, $34, $FF, $59 ; 0x45 + db $42, $43, $44, $FF, $33, $34, $FF, $59 ; 0x46 + db $42, $43, $44, $FF, $60, $34, $FF, $59 ; 0x47 + + db $42, $43, $44, $FF, $2D, $2E, $FF, $59 ; 0x48 + db $42, $43, $44, $FF, $2D, $2E, $FF, $59 ; 0x49 + db $42, $43, $44, $FF, $2D, $2E, $FF, $59 ; 0x4A + db $42, $43, $44, $FF, $33, $34, $FF, $59 ; 0x4B + db $42, $43, $44, $FF, $33, $34, $FF, $59 ; 0x4C + db $42, $43, $44, $FF, $33, $34, $FF, $59 ; 0x4D + db $42, $43, $44, $FF, $33, $34, $FF, $59 ; 0x4E + db $42, $43, $44, $FF, $37, $38, $FF, $59 ; 0x4F + + db $42, $43, $44, $FF, $2F, $30, $FF, $59 ; 0x50 + db $42, $43, $44, $FF, $2F, $30, $FF, $59 ; 0x51 + db $42, $43, $44, $FF, $FF, $FF, $FF, $59 ; 0x52 + db $42, $43, $44, $FF, $37, $38, $FF, $59 ; 0x53 + db $42, $43, $44, $FF, $37, $38, $FF, $59 ; 0x54 + db $42, $43, $44, $FF, $FF, $FF, $FF, $59 ; 0x55 + db $42, $43, $44, $FF, $37, $38, $FF, $59 ; 0x56 + db $42, $43, $44, $FF, $FF, $FF, $FF, $59 ; 0x57 + + db $42, $43, $44, $FF, $2F, $30, $FF, $59 ; 0x58 + db $42, $43, $44, $FF, $2F, $30, $FF, $59 ; 0x59 + db $42, $43, $44, $FF, $FF, $FF, $FF, $59 ; 0x5A + db $42, $43, $44, $FF, $35, $36, $FF, $59 ; 0x5B + db $42, $43, $44, $FF, $35, $36, $FF, $59 ; 0x5C + db $42, $43, $44, $FF, $37, $38, $FF, $59 ; 0x5D + db $42, $43, $44, $FF, $2B, $2C, $FF, $59 ; 0x5E + db $42, $43, $44, $FF, $2B, $2C, $FF, $59 ; 0x5F + + db $42, $43, $44, $FF, $2F, $30, $FF, $59 ; 0x60 + db $42, $43, $44, $FF, $2F, $30, $FF, $59 ; 0x61 + db $42, $43, $44, $FF, $2F, $30, $FF, $59 ; 0x62 + db $42, $43, $44, $FF, $35, $36, $FF, $59 ; 0x63 + db $42, $43, $44, $FF, $35, $36, $FF, $59 ; 0x64 + db $42, $43, $44, $FF, $FF, $FF, $FF, $59 ; 0x65 + db $42, $43, $44, $FF, $2B, $2C, $FF, $59 ; 0x66 + db $42, $43, $44, $FF, $2B, $2C, $FF, $59 ; 0x67 + + db $42, $43, $44, $FF, $2F, $30, $FF, $59 ; 0x68 + db $42, $43, $44, $FF, $2F, $30, $FF, $59 ; 0x69 + db $42, $43, $44, $FF, $FF, $FF, $FF, $59 ; 0x6A + db $42, $43, $44, $FF, $FF, $FF, $FF, $59 ; 0x6B + db $42, $43, $44, $FF, $FF, $FF, $FF, $59 ; 0x6C + db $42, $43, $44, $FF, $20, $2B, $FF, $59 ; 0x6D + db $42, $43, $44, $FF, $FF, $FF, $FF, $59 ; 0x6E + db $42, $43, $44, $FF, $2B, $2C, $FF, $59 ; 0x6F + + db $42, $43, $44, $FF, $31, $32, $FF, $59 ; 0x70 + db $42, $43, $44, $FF, $31, $32, $FF, $59 ; 0x71 + db $42, $43, $44, $FF, $FF, $FF, $FF, $59 ; 0x72 + db $42, $43, $44, $FF, $37, $38, $FF, $59 ; 0x73 + db $42, $43, $44, $FF, $37, $38, $FF, $59 ; 0x74 + db $42, $43, $44, $FF, $31, $32, $FF, $59 ; 0x75 + db $42, $43, $44, $FF, $31, $32, $FF, $59 ; 0x76 + db $42, $43, $44, $FF, $37, $38, $FF, $59 ; 0x77 + + db $42, $43, $44, $FF, $31, $32, $FF, $59 ; 0x78 + db $42, $43, $44, $FF, $31, $32, $FF, $59 ; 0x79 + db $42, $43, $44, $FF, $FF, $FF, $FF, $59 ; 0x7A + db $42, $43, $44, $FF, $37, $38, $FF, $59 ; 0x7B + db $42, $43, $44, $FF, $37, $38, $FF, $59 ; 0x7C + db $42, $43, $44, $FF, $31, $32, $FF, $59 ; 0x7D + db $42, $43, $44, $FF, $31, $32, $FF, $59 ; 0x7E + db $42, $43, $44, $FF, $FF, $FF, $FF, $59 ; 0x7F + + ; SW + db $3A, $3B, $3C, $FF, $47, $48, $FF, $5B ; 0x80 + db $3A, $3B, $3C, $FF, $47, $48, $FF, $5B ; 0x81 + db $3A, $3B, $3C, $FF, $47, $48, $FF, $5B ; 0x82 + db $3A, $3B, $3C, $FF, $53, $4D, $FF, $5B ; 0x83 + db $3A, $3B, $3C, $FF, $53, $4D, $FF, $5B ; 0x84 + db $3A, $3B, $3C, $FF, $53, $4D, $FF, $5B ; 0x85 + db $3A, $3B, $3C, $FF, $53, $4D, $FF, $5B ; 0x86 + db $3A, $3B, $3C, $FF, $53, $4D, $FF, $5B ; 0x87 + + db $3A, $3B, $3C, $17, $40, $41, $39, $5B ; 0x88 + db $3A, $3B, $3C, $FF, $47, $48, $FF, $5B ; 0x89 + db $3A, $3B, $3C, $FF, $47, $48, $FF, $5B ; 0x8A + db $3A, $3B, $3C, $FF, $53, $4D, $FF, $5B ; 0x8B + db $3A, $3B, $3C, $FF, $53, $4D, $FF, $5B ; 0x8C + db $3A, $3B, $3C, $FF, $53, $4D, $FF, $5B ; 0x8D + db $3A, $3B, $3C, $FF, $53, $4D, $FF, $5B ; 0x8E + db $3A, $3B, $3C, $FF, $53, $4D, $FF, $5B ; 0x8F + + db $3A, $3B, $3C, $08, $00, $22, $1B, $5B ; 0x90 + db $3A, $3B, $3C, $08, $FF, $22, $1B, $5B ; 0x91 + db $3A, $3B, $3C, $06, $FF, $1F, $18, $5B ; 0x92 + db $3A, $3B, $3C, $08, $FF, $22, $1B, $5B ; 0x93 + db $3A, $3B, $3C, $3D, $53, $47, $48, $5B ; 0x94 + db $3A, $3B, $3C, $3D, $53, $56, $4F, $5B ; 0x95 + db $3A, $3B, $3C, $3D, $35, $36, $3E, $5B ; 0x96 + db $3A, $3B, $3C, $3D, $57, $4C, $3E, $5B ; 0x97 + + db $3A, $3B, $3C, $08, $FF, $22, $1B, $5B ; 0x98 + db $3A, $3B, $3C, $08, $FF, $22, $1B, $5B ; 0x99 + db $3A, $3B, $3C, $06, $FF, $1F, $18, $5B ; 0x9A + db $3A, $3B, $3C, $06, $FF, $1F, $18, $5B ; 0x9B + db $3A, $3B, $3C, $3D, $53, $33, $34, $5B ; 0x9C + db $3A, $3B, $3C, $3D, $53, $57, $4C, $5B ; 0x9D + db $3A, $3B, $3C, $3D, $57, $4C, $3E, $5B ; 0x9E + db $3A, $3B, $3C, $3D, $53, $4D, $3E, $5B ; 0x9F + endif + warnpc $288980 + + ; TODO: Add a way to edit these within ZS? Unsure. + org $288980 ; $140980 + .DefaultGFXGroups + + ; LW + org $288980 ; $140980 + .DefaultGFXGroups_sheet0 + db $3A ; Sheet 0 + + org $288981 ; $140981 + .DefaultGFXGroups_sheet1 + db $3B ; Sheet 1 + + org $288982 ; $140982 + .DefaultGFXGroups_sheet2 + db $3C ; Sheet 2 + + org $288983 ; $140983 + .DefaultGFXGroups_sheet3 + db $3D ; Sheet 3 + + org $288984 ; $140984 + .DefaultGFXGroups_sheet4 + db $53 ; Sheet 4 + + org $288985 ; $140985 + .DefaultGFXGroups_sheet5 + db $4D ; Sheet 5 + + org $288986 ; $140986 + .DefaultGFXGroups_sheet6 + db $3E ; Sheet 6 + + org $288987 ; $140987 + .DefaultGFXGroups_sheet7 + db $5B ; Sheet 7 + + ; DW + db $42, $43, $44, $45, $2F, $30, $3F, $59 + + ; SW + db $3A, $3B, $3C, $3D, $47, $48, $3E, $5B + + ; This tells the game what each area's "parent" area is. + ; For small areas this is it's own area number. + ; For large areas this is the top left area in the 2x2 grid. + ; For wide areas this is the left area in the 2x1 grid. + ; For tall areas this is the top area in the 1x2 grid. + ; In vanilla, this table was shared for all 3 worlds. + org $288998 ; $140998 + .Overworld_ActualScreenID_New + + if !UseVanillaPool > 0 + ; LW + db $00, $00, $02, $03, $03, $05, $05, $07 + db $00, $00, $0A, $03, $03, $05, $05, $0F + db $10, $11, $12, $13, $14, $15, $16, $17 + db $18, $18, $1A, $1B, $1B, $1D, $1E, $1E + db $18, $18, $22, $1B, $1B, $25, $1E, $1E + db $28, $29, $2A, $2B, $2C, $2D, $2E, $2F + db $30, $30, $32, $33, $34, $35, $35, $37 + db $30, $30, $3A, $3B, $3C, $35, $35, $3F + + ; DW + db $40, $40, $42, $43, $43, $45, $45, $47 + db $40, $40, $4A, $43, $43, $45, $45, $4F + db $50, $51, $52, $53, $54, $55, $56, $57 + db $58, $58, $5A, $5B, $5B, $5D, $5E, $5E + db $58, $58, $62, $5B, $5B, $65, $5E, $5E + db $68, $69, $6A, $6B, $6C, $6D, $6E, $6F + db $70, $70, $72, $73, $74, $75, $75, $77 + db $70, $70, $7A, $7B, $7C, $75, $75, $7F + + ; SW + db $80, $81, $81, $83, $84, $85, $86, $87 + db $88, $81, $81, $8B, $8C, $8D, $8E, $8F + db $90, $91, $92, $93, $94, $95, $96, $97 + db $98, $99, $9A, $9B, $9C, $9D, $9E, $9F + endif + + ; Examples: + ; These work in vanilla: │ These do not: + ; ───────────────────────┼─────────────── + ; ┌──┬──┐ ┌──┬──┐ │ ┌──┬──┐ ┌──┬──┐ + ; │ │ │<->│ │ │ │ │ │ │ │ │ │ + ; ├──┼──┤ ├──┼──┤ │ ├──┼──┤<->├──┼──┤ + ; │ │ │<->│ │ │ │ │ │ │ │ │ │ + ; └──┴──┘ └──┴──┘ │ └──┴──┘ └──┴──┘ + ; ┌──┬──┐ │ ┌──┬──┐ + ; │ │ │ │ │ │ │ + ; ├──┼──┤ │ ├──┼──┤ + ; │ │ │ │ │ │ │ + ; └──┴──┘ │ └──┴──┘ + ; ↕ ↕ │ ↕ + ; ┌──┬──┐ │ ┌──┬──┐ + ; │ │ │ │ │ │ │ + ; ├──┼──┤ │ ├──┼──┤ + ; │ │ │ │ │ │ │ + ; └──┴──┘ │ └──┴──┘ + ; See the layout of Zelda: Interconnected Strongholds. + ; + ; None of these work in vanilla: + ; ┌──┬──┐ ┌──┬──┐ + ; │ │ │ │ │ │ + ; ├──┼──┤ ┌──┬──┐ ┌──┬──┐ ├──┼──┤ + ; │ │ │<->│ │ │ │ │ │<->│ │ │ + ; └──┴──┘ ├──┼──┤ ├──┼──┤ └──┴──┘ + ; │ │ │ │ │ │ + ; └──┴──┘ └──┴──┘ + ; ┌──┬──┐ ┌──┬──┐ + ; │ │ │ │ │ │ + ; ├──┼──┤ ├──┼──┤ + ; │ │ │ │ │ │ + ; └──┴──┘ └──┴──┘ + ; ↕ ↕ + ; ┌──┬──┐ ┌──┬──┐ + ; │ │ │ │ │ │ + ; ├──┼──┤ ├──┼──┤ + ; │ │ │ │ │ │ + ; └──┴──┘ └──┴──┘ + ; As of 05/13/25 there aren't any released hacks that use this kind of layout. + + ; These values or for the area you are going to, not the one coming from. + + org $288A38 ; $140A38 + .ByScreen1_New ; Transitioning right + if !UseVanillaPool > 0 + ; LW + dw $0060, $0060, $0060, $0060, $0060, $0060, $0060, $0060 + dw $0060, $0060, $F060, $1060, $1060, $0060, $1060, $F060 + dw $0060, $0060, $0060, $0060, $0060, $0060, $0060, $0060 + dw $0060, $0060, $0060, $0060, $0060, $0060, $0060, $0060 + dw $0060, $0060, $F060, $1060, $1060, $F060, $1060, $1060 + dw $0060, $0060, $0060, $0060, $0060, $0060, $0060, $0060 + dw $0060, $0060, $0060, $0060, $0060, $0060, $0060, $0060 + dw $0060, $0060, $F060, $0060, $0060, $1060, $1060, $F060 + + ; DW + dw $0060, $0060, $0060, $0060, $0060, $0060, $0060, $0060 + dw $0060, $0060, $F060, $1060, $1060, $0060, $1060, $F060 + dw $0060, $0060, $0060, $0060, $0060, $0060, $0060, $0060 + dw $0060, $0060, $0060, $0060, $0060, $0060, $0060, $0060 + dw $0060, $0060, $F060, $1060, $1060, $F060, $1060, $1060 + dw $0060, $0060, $0060, $0060, $0060, $0060, $0060, $0060 + dw $0060, $0060, $0060, $0060, $0060, $0060, $0060, $0060 + dw $0060, $0060, $F060, $0060, $0060, $1060, $1060, $F060 + + ; SW + dw $0060, $0060, $0060, $0060, $0060, $0060, $0060, $0060 + dw $0060, $1060, $1060, $F060, $0060, $0060, $0060, $0060 + dw $0060, $0060, $0060, $0060, $0060, $0060, $0060, $0060 + dw $0060, $0060, $0060, $0060, $0060, $0060, $0060, $0060 + endif + + org $288B78 ; $140B78 + .ByScreen2_New ; Transitioning left + if !UseVanillaPool > 0 + ; LW + dw $0080, $0080, $0040, $0080, $0080, $0080, $0080, $0040 + dw $1080, $1080, $F040, $1080, $0080, $1080, $1080, $0040 + dw $0040, $0040, $0040, $0040, $0040, $0040, $0040, $0040 + dw $0080, $0080, $0040, $0080, $0080, $0040, $0080, $F080 + dw $1080, $1080, $F040, $1080, $1080, $F040, $1080, $1080 + dw $0040, $0040, $0040, $0040, $0040, $0040, $0040, $0040 + dw $0080, $0080, $0040, $0040, $0040, $0080, $0080, $0040 + dw $1080, $1080, $0040, $0040, $F040, $1080, $1080, $0040 + + ; DW + dw $0080, $0080, $0040, $0080, $0080, $0080, $0080, $0040 + dw $1080, $1080, $F040, $1080, $0080, $1080, $1080, $0040 + dw $0040, $0040, $0040, $0040, $0040, $0040, $0040, $0040 + dw $0080, $0080, $0040, $0080, $0080, $0040, $0080, $F080 + dw $1080, $1080, $F040, $1080, $1080, $F040, $1080, $1080 + dw $0040, $0040, $0040, $0040, $0040, $0040, $0040, $0040 + dw $0080, $0080, $0040, $0040, $0040, $0080, $0080, $0040 + dw $1080, $1080, $0040, $0040, $F040, $1080, $1080, $0040 + + ; SW + dw $0040, $0080, $0080, $0040, $0040, $0040, $0040, $0040 + dw $F040, $1080, $1080, $0040, $0040, $0040, $0040, $0040 + dw $0040, $0040, $0040, $0040, $0040, $0040, $0040, $0040 + dw $0040, $0040, $0040, $0040, $0040, $0040, $0040, $0040 + endif + + org $288CB8 ; $140CB8 + .ByScreen3_New ; Transitioning down + if !UseVanillaPool > 0 + ; LW + dw $1800, $1840, $1800, $1800, $1840, $1800, $1840, $1800 + dw $1800, $1840, $1800, $1800, $1840, $1800, $1840, $1800 + dw $1800, $17C0, $1800, $1800, $17C0, $1800, $17C0, $1800 + dw $1800, $1840, $1800, $1800, $1840, $1800, $1800, $1840 + dw $1800, $1840, $1800, $1800, $1840, $1800, $1800, $1840 + dw $1800, $17C0, $1800, $1800, $17C0, $1800, $1800, $17C0 + dw $1800, $1840, $1800, $1800, $1800, $1800, $1840, $1800 + dw $1800, $1840, $1800, $1800, $1800, $1800, $1840, $1800 + + ; DW + dw $1800, $1840, $1800, $1800, $1840, $1800, $1840, $1800 + dw $1800, $1840, $1800, $1800, $1840, $1800, $1840, $1800 + dw $1800, $17C0, $1800, $1800, $17C0, $1800, $17C0, $1800 + dw $1800, $1840, $1800, $1800, $1840, $1800, $1800, $1840 + dw $1800, $1840, $1800, $1800, $1840, $1800, $1800, $1840 + dw $1800, $17C0, $1800, $1800, $17C0, $1800, $1800, $17C0 + dw $1800, $1840, $1800, $1800, $1800, $1800, $1840, $1800 + dw $1800, $1840, $1800, $1800, $1800, $1800, $1840, $1800 + + ; SW + dw $1800, $1800, $1840, $1800, $1800, $1800, $1800, $1800 + dw $1800, $1800, $1840, $1800, $1800, $1800, $1800, $1800 + dw $1800, $1800, $17C0, $1800, $1800, $1800, $1800, $1800 + dw $1800, $1800, $1800, $1800, $1800, $1800, $1800, $1800 + endif + + org $288DF8 ; $140DF8 + .ByScreen4_New ; Transitioning up + if !UseVanillaPool > 0 + ; LW + dw $2000, $2040, $1000, $2000, $2040, $2000, $2040, $1000 + dw $2000, $2040, $1000, $2000, $2040, $2000, $2040, $1000 + dw $1000, $0FC0, $1000, $1000, $0FC0, $1000, $1000, $0FC0 + dw $2000, $2040, $1000, $2000, $2040, $1000, $2000, $2040 + dw $2000, $2040, $1000, $2000, $2040, $1000, $2000, $2040 + dw $1000, $0FC0, $1000, $1000, $1000, $1000, $0FC0, $1000 + dw $2000, $2040, $1000, $1000, $1000, $2000, $2040, $1000 + dw $2000, $2040, $1000, $1000, $1000, $2000, $2040, $1000 + + ; DW + dw $2000, $2040, $1000, $2000, $2040, $2000, $2040, $1000 + dw $2000, $2040, $1000, $2000, $2040, $2000, $2040, $1000 + dw $1000, $0FC0, $1000, $1000, $0FC0, $1000, $1000, $0FC0 + dw $2000, $2040, $1000, $2000, $2040, $1000, $2000, $2040 + dw $2000, $2040, $1000, $2000, $2040, $1000, $2000, $2040 + dw $1000, $0FC0, $1000, $1000, $1000, $1000, $0FC0, $1000 + dw $2000, $2040, $1000, $1000, $1000, $2000, $2040, $1000 + dw $2000, $2040, $1000, $1000, $1000, $2000, $2040, $1000 + + ; SW + dw $1000, $2000, $2040, $1000, $1000, $1000, $1000, $1000 + dw $1000, $2000, $2040, $1000, $1000, $1000, $1000, $1000 + dw $1000, $1000, $1000, $1000, $1000, $1000, $1000, $1000 + dw $1000, $1000, $1000, $1000, $1000, $1000, $1000, $1000 + endif + + ; UNUSED: + ; The table OverworldTransitionPositionY found at $0128C4 was moved + ; here and the original 0x80 bytes are currently unused. + org $288F38 ; $140F38 + .OverworldTransitionPositionY_New + if !UseVanillaPool > 0 + ; LW + dw $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000 + dw $0000, $0000, $0200, $0000, $0000, $0000, $0000, $0200 + dw $0400, $0400, $0400, $0400, $0400, $0400, $0400, $0400 + dw $0600, $0600, $0600, $0600, $0600, $0600, $0600, $0600 + dw $0600, $0600, $0800, $0600, $0600, $0800, $0600, $0600 + dw $0A00, $0A00, $0A00, $0A00, $0A00, $0A00, $0A00, $0A00 + dw $0C00, $0C00, $0C00, $0C00, $0C00, $0C00, $0C00, $0C00 + dw $0C00, $0C00, $0E00, $0E00, $0E00, $0C00, $0C00, $0E00 + + ; DW + dw $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000 + dw $0000, $0000, $0200, $0000, $0000, $0000, $0000, $0200 + dw $0400, $0400, $0400, $0400, $0400, $0400, $0400, $0400 + dw $0600, $0600, $0600, $0600, $0600, $0600, $0600, $0600 + dw $0600, $0600, $0800, $0600, $0600, $0800, $0600, $0600 + dw $0A00, $0A00, $0A00, $0A00, $0A00, $0A00, $0A00, $0A00 + dw $0C00, $0C00, $0C00, $0C00, $0C00, $0C00, $0C00, $0C00 + dw $0C00, $0C00, $0E00, $0E00, $0E00, $0C00, $0C00, $0E00 + + ; SW + dw $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000 + dw $0200, $0000, $0000, $0200, $0200, $0200, $0200, $0200 + dw $0400, $0400, $0400, $0400, $0400, $0400, $0400, $0400 + dw $0600, $0600, $0600, $0600, $0600, $0600, $0600, $0600 + endif + + ; UNUSED: + ; The table OverworldTransitionPositionX found at 012944 was moved + ; here and the original 0x80 bytes are currently unused. + org $289078 ; $141078 + .OverworldTransitionPositionX_New + if !UseVanillaPool > 0 + ; LW + dw $0000, $0000, $0400, $0600, $0600, $0A00, $0A00, $0E00 + dw $0000, $0000, $0400, $0600, $0600, $0A00, $0A00, $0E00 + dw $0000, $0200, $0400, $0600, $0800, $0A00, $0C00, $0E00 + dw $0000, $0000, $0400, $0600, $0600, $0A00, $0C00, $0C00 + dw $0000, $0000, $0400, $0600, $0600, $0A00, $0C00, $0C00 + dw $0000, $0200, $0400, $0600, $0800, $0A00, $0C00, $0E00 + dw $0000, $0000, $0400, $0600, $0800, $0A00, $0A00, $0E00 + dw $0000, $0000, $0400, $0600, $0800, $0A00, $0A00, $0E00 + + ; DW + dw $0000, $0000, $0400, $0600, $0600, $0A00, $0A00, $0E00 + dw $0000, $0000, $0400, $0600, $0600, $0A00, $0A00, $0E00 + dw $0000, $0200, $0400, $0600, $0800, $0A00, $0C00, $0E00 + dw $0000, $0000, $0400, $0600, $0600, $0A00, $0C00, $0C00 + dw $0000, $0000, $0400, $0600, $0600, $0A00, $0C00, $0C00 + dw $0000, $0200, $0400, $0600, $0800, $0A00, $0C00, $0E00 + dw $0000, $0000, $0400, $0600, $0800, $0A00, $0A00, $0E00 + dw $0000, $0000, $0400, $0600, $0800, $0A00, $0A00, $0E00 + + ; SW + dw $0000, $0200, $0200, $0600, $0800, $0A00, $0C00, $0E00 + dw $0000, $0200, $0200, $0600, $0800, $0A00, $0C00, $0E00 + dw $0000, $0200, $0400, $0600, $0800, $0A00, $0C00, $0E00 + dw $0000, $0200, $0400, $0600, $0800, $0A00, $0C00, $0E00 + endif + + ; The original trans_target_north table was moved here from $013EE2. + ; The original 0x0080 bytes space is currently unused. + org $2891B8 ; $1411B8 + .trans_target_north_new + if !UseVanillaPool > 0 + ; LW + dw $FF20, $FF20, $FF20, $FF20, $FF20, $FF20, $FF20, $FF20 + dw $FF20, $FF20, $0120, $FF20, $FF20, $FF20, $FF20, $0120 + dw $0320, $0320, $0320, $0320, $0320, $0320, $0320, $0320 + dw $0520, $0520, $0520, $0520, $0520, $0520, $0520, $0520 + dw $0520, $0520, $0720, $0520, $0520, $0720, $0520, $0520 + dw $0920, $0920, $0920, $0920, $0920, $0920, $0920, $0920 + dw $0B20, $0B20, $0B20, $0B20, $0B20, $0B20, $0B20, $0B20 + dw $0B20, $0B20, $0D20, $0D20, $0D20, $0B20, $0B20, $0D20 + + ; DW + dw $FF20, $FF20, $FF20, $FF20, $FF20, $FF20, $FF20, $FF20 + dw $FF20, $FF20, $0120, $FF20, $FF20, $FF20, $FF20, $0120 + dw $0320, $0320, $0320, $0320, $0320, $0320, $0320, $0320 + dw $0520, $0520, $0520, $0520, $0520, $0520, $0520, $0520 + dw $0520, $0520, $0720, $0520, $0520, $0720, $0520, $0520 + dw $0920, $0920, $0920, $0920, $0920, $0920, $0920, $0920 + dw $0B20, $0B20, $0B20, $0B20, $0B20, $0B20, $0B20, $0B20 + dw $0B20, $0B20, $0D20, $0D20, $0D20, $0B20, $0B20, $0D20 + + ; SW + dw $FF20, $FF20, $FF20, $FF20, $FF20, $FF20, $FF20, $FF20 + dw $0120, $FF20, $FF20, $0120, $0120, $0120, $0120, $0120 + dw $0320, $0320, $0320, $0320, $0320, $0320, $0320, $0320 + dw $0520, $0520, $0520, $0520, $0520, $0520, $0520, $0520 + endif + + ; The original trans_target_west table was moved here from $013F62. + ; The original 0x0080 bytes space is currently unused. + org $2892F8 ; $1412F8 + .trans_target_west_new + if !UseVanillaPool > 0 + ; LW + dw $FF00, $FF00, $0300, $0500, $0500, $0900, $0900, $0D00 + dw $FF00, $FF00, $0300, $0500, $0500, $0900, $0900, $0D00 + dw $FF00, $0100, $0300, $0500, $0700, $0900, $0B00, $0D00 + dw $FF00, $FF00, $0300, $0500, $0500, $0900, $0B00, $0B00 + dw $FF00, $FF00, $0300, $0500, $0500, $0900, $0B00, $0B00 + dw $FF00, $0100, $0300, $0500, $0700, $0900, $0B00, $0D00 + dw $FF00, $FF00, $0300, $0500, $0700, $0900, $0900, $0D00 + dw $FF00, $FF00, $0300, $0500, $0700, $0900, $0900, $0D00 + + ; DW + dw $FF00, $FF00, $0300, $0500, $0500, $0900, $0900, $0D00 + dw $FF00, $FF00, $0300, $0500, $0500, $0900, $0900, $0D00 + dw $FF00, $0100, $0300, $0500, $0700, $0900, $0B00, $0D00 + dw $FF00, $FF00, $0300, $0500, $0500, $0900, $0B00, $0B00 + dw $FF00, $FF00, $0300, $0500, $0500, $0900, $0B00, $0B00 + dw $FF00, $0100, $0300, $0500, $0700, $0900, $0B00, $0D00 + dw $FF00, $FF00, $0300, $0500, $0700, $0900, $0900, $0D00 + dw $FF00, $FF00, $0300, $0500, $0700, $0900, $0900, $0D00 + + ; SW + dw $FF00, $0100, $0100, $0500, $0700, $0900, $0B00, $0D00 + dw $FF00, $0100, $0100, $0500, $0700, $0900, $0B00, $0D00 + dw $FF00, $0100, $0300, $0500, $0700, $0900, $0B00, $0D00 + dw $FF00, $0100, $0300, $0500, $0700, $0900, $0B00, $0D00 + endif + + ; The original Overworld_SpritePointers_state_0 table was moved here from + ; $04C881. The original 0x0080 bytes space is currently unused. + org $289438 ; $141438 + .Overworld_SpritePointers_state_0_New + if !UseVanillaPool > 0 + dw $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41 + dw $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41 + dw $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41 + dw $CB41, $CB41, $CB41, $CB42, $CB41, $CB5B, $CB41, $CB41 + dw $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41 + dw $CB41, $CB41, $CB41, $CB5F, $CB66, $CB41, $CB41, $CB41 + dw $CB41, $CB41, $CB73, $CB41, $CB41, $CB41, $CB41, $CB41 + dw $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41 + + dw $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41 + dw $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41 + dw $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41 + dw $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41 + dw $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41 + dw $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41 + dw $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41 + dw $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41 + + dw $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41 + dw $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41 + dw $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41 + dw $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41 + endif + + ; The original Overworld_SpritePointers_state_1 table was moved here from + ; $04C901. The original 0x0120 bytes space is currently unused. + org $289578 ; $141578 + .Overworld_SpritePointers_state_1_New + if !UseVanillaPool > 0 + dw $CF4C, $CB41, $CF7A, $CF84, $CB41, $CFA6, $CB41, $CFCE + dw $CB41, $CB41, $CFDE, $CB41, $CB41, $CB41, $CB41, $CFFD + dw $D013, $D020, $D02D, $D03A, $D041, $D051, $D05E, $D068 + dw $D078, $CB41, $D0A0, $D0B3, $CB41, $D0DB, $D0EB, $CB41 + dw $CB41, $CB41, $D125, $CB41, $CB41, $D12F, $CB41, $CB41 + dw $D148, $CB41, $D152, $D168, $D175, $D17C, $D186, $D193 + dw $D19D, $CB41, $D1E3, $D1F0, $D1FD, $D213, $CB41, $D259 + dw $CB41, $CB41, $D26C, $D279, $D292, $CB41, $CB41, $D2A8 + + dw $CB7A, $CBB7, $CBB7, $CBC4, $CBCB, $CBCB, $CB41, $CBD5 + dw $CB41, $CB41, $CBD9, $CB41, $CB41, $CB41, $CB41, $CBF5 + dw $CC02, $CC12, $CC25, $CC35, $CC45, $CC5E, $CC74, $CC84 + dw $CC9A, $CB41, $CCCE, $CCE1, $CB41, $CD03, $CD19, $CB41 + dw $CB41, $CB41, $CD59, $CB41, $CB41, $CD6C, $CB41, $CB41 + dw $CD7F, $CD83, $CD87, $CD8B, $CD9B, $CDAB, $CDBE, $CDD1 + dw $CDE1, $CE06, $CE06, $CE16, $CE26, $CE3C, $CE7F, $CE7F + dw $CB41, $CB41, $CE92, $CE9F, $CEB2, $CB41, $CB41, $CEC5 + + dw $CEDB, $CEF4, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41 + dw $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41 + dw $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41 + dw $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41 + endif + + ; The original Overworld_SpritePointers_state_2 table was moved here from + ; $04CA21. The original 0x0120 bytes space is currently unused. + org $2896B8 ; $1416B8 + .Overworld_SpritePointers_state_2_New + if !UseVanillaPool > 0 + dw $D2B8, $CB41, $D2E3, $D2E7, $CB41, $D315, $CB41, $D343 + dw $CB41, $CB41, $D353, $CB41, $CB41, $CB41, $CB41, $D369 + dw $D37F, $D38F, $D39C, $D3A9, $D3B6, $D3C9, $D3D9, $D3E3 + dw $D3F3, $CB41, $D418, $D428, $CB41, $D447, $D454, $CB41 + dw $CB41, $CB41, $D491, $CB41, $CB41, $D49B, $CB41, $CB41 + dw $D4A8, $D4B8, $D4C2, $D4DE, $D4EE, $D4F5, $D502, $D515 + dw $D51F, $CB41, $D55C, $D56F, $D57F, $D58F, $D5D5, $D5D5 + dw $D5E5, $D5E5, $D5E5, $D5FE, $D611, $D621, $D621, $D621 + + dw $CB7A, $CBB7, $CBB7, $CBC4, $CBCB, $CBCB, $CB41, $CBD5 + dw $CB41, $CB41, $CBD9, $CB41, $CB41, $CB41, $CB41, $CBF5 + dw $CC02, $CC12, $CC25, $CC35, $CC45, $CC5E, $CC74, $CC84 + dw $CC9A, $CB41, $CCCE, $CCE1, $CB41, $CD03, $CD19, $CB41 + dw $CB41, $CB41, $CD59, $CB41, $CB41, $CD6C, $CB41, $CB41 + dw $CD7F, $CD83, $CD87, $CD8B, $CD9B, $CDAB, $CDBE, $CDD1 + dw $CDE1, $CE06, $CE06, $CE16, $CE26, $CE3C, $CE7F, $CE7F + dw $CB41, $CB41, $CE92, $CE9F, $CEB2, $CB41, $CB41, $CEC5 + + dw $CEDB, $CEF4, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41 + dw $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41 + dw $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41 + dw $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41, $CB41 + endif + + ; The original Overworld_SignText table was moved here from + ; $03F51D. The original 0x0120 bytes space is currently unused. + org $2897F8 ; $1417F8 + .Overworld_SignText_New: + if !UseVanillaPool > 0 + dw $00A7, $00A7, $0048, $0040, $0040, $00A7, $00A7, $00A7 + dw $00A7, $00A7, $003C, $0040, $0040, $00A7, $00A7, $003E + dw $003D, $0049, $0042, $0042, $00A7, $00A7, $003F, $00B0 + dw $003B, $003B, $00A7, $003B, $003B, $0044, $00A7, $00A7 + dw $003B, $003B, $00A7, $003B, $003B, $0045, $00A7, $00A7 + dw $00A7, $00A7, $00A7, $00A7, $00A7, $0041, $00A7, $00A7 + dw $00A7, $00A7, $00A7, $0042, $00A7, $0046, $0046, $00A7 + dw $00A7, $00A7, $0047, $0043, $00A7, $0046, $0046, $00A7 + + dw $00A7, $00A7, $00A7, $00A7, $00A7, $00A7, $00A7, $00A7 + dw $00A7, $00A7, $00A8, $00A7, $00A7, $00A7, $00A7, $00A9 + dw $00A7, $00AA, $00AB, $00A7, $00A7, $00A7, $00A7, $00B1 + dw $00AF, $00AF, $00A7, $00A7, $00A7, $00A7, $00A7, $00A7 + dw $00AF, $00AF, $00A7, $00A7, $00A7, $00AC, $00A7, $00A7 + dw $00A7, $00A7, $00A7, $00A7, $00A7, $00AD, $00A7, $00A7 + dw $00A7, $00A7, $00A7, $00A7, $00A7, $00A7, $00A7, $00A7 + dw $00A7, $00A7, $00A7, $00AE, $00A7, $00A7, $00A7, $00A7 + + dw $00AF, $00AF, $00A7, $00A7, $00A7, $00AC, $00A7, $00A7 + dw $00A7, $00A7, $00A7, $00A7, $00A7, $00AD, $00A7, $00A7 + dw $00A7, $00A7, $00A7, $00A7, $00A7, $00A7, $00A7, $00A7 + dw $00A7, $00A7, $00A7, $00AE, $00A7, $00A7, $00A7, $00A7 + endif +} +warnpc $289938 ; $141938 + +; ============================================================================== +; Start of function space. +; ============================================================================== + +org $289940 ; $141940 +pushpc + +; ============================================================================== + +if !Func00D8D5 == 1 + +; Replaces a function that decompresses animated tiles in certain mirror warp +; conditions. +org $00D8D5 ; $0058D5 +AnimateMirrorWarp_DecompressAnimatedTiles: +{ + PHX + + ; The decompression function increases it by 1 so subtract 1 here. + JSL.l ReadAnimatedTable : DEC : TAY + + PLX + + JSL.l DecompOwAnimatedTiles + + RTL +} +warnpc $00D8EE + +else + +org $00D8D5 ; $0058D5 +db $A0, $58, $A5, $8A, $29, $BF, $C9, $03 +db $F0, $0A, $C9, $05, $F0, $06, $C9, $07 +db $F0, $02, $A0, $5A, $22, $94, $D3, $00 +db $6B + +endif + +pullpc +ReadAnimatedTable: +{ + PHB : PHK : PLB + + REP #$30 ; Set A, X, and Y in 16bit mode. + LDA.b $8A : TAX + AND.w #$00C0 : LSR #3 : TAY ; (Area / 8) = LW, DW, or SW *8 + SEP #$20 ; Set A in 8bit mode. + + ; TODO: For the sake of speed, remove these checks. + ; $00 crashes the game so just double check that. + LDA.w Pool_AnimatedTable, X : BNE .not00 + LDA.w Pool_DefaultGFXGroups_sheet7, Y + + BRA .notFF + + .not00 + + ; Load the default sheet if the value is FF. + CMP.b #$FF : BNE .notFF + LDA.w Pool_DefaultGFXGroups_sheet7, Y + + .notFF + + SEP #$10 ; Set X and Y in 8bit mode. + + PLB + + RTL +} +pushpc + +; ============================================================================== + +if !Func00DA63 == 1 + +; The first half of this function enables or disables BG1 for subscreen overlay +; use depending on the area. The second half reloads global sprite #2 sheet +; (rock vs skulls, different bush gfx, fish vs bone fish, etc.) based on what +; world we are in. +org $00DA63 ; $005A63 +AnimateMirrorWarp_LoadSubscreen: +{ + JSL.l ActivateSubScreen + + ; From this point on it is the vanilla function. + PHB : PHK : PLB + + ; TODO: Eventually un-hardcode this. + ; X = 0 for LW, 8 for DW + LDA.l SheetsTable_0AA4, X : TAY + + ; Get the pointer for one of the 2 Global sprite #2 sheets. + LDA.w GFXSheetPointers_sprite_low, Y : STA.b $00 + LDA.w GFXSheetPointers_sprite_high, Y : STA.b $01 + LDA.w GFXSheetPointers_sprite_bank, Y : STA.b $02 + STA.b $05 + + PLB + + REP #$31 ; Set A, X, and Y in 16bit mode. +1 no idea. + + ; Source address is determined above, number of tiles is 0x0040, base + ; target address is $7F0000. + LDX.w #$0000 + LDY.w #$0040 + LDA.b $00 + JSR.w Do3To4High16Bit + + SEP #$30 ; Set A, X, and Y in 8bit mode. + + RTL +} +warnpc $00DABB + +else + +org $00DA63 ; $005A63 +db $64, $1D, $A5, $8A, $F0, $24, $C9, $70 +db $F0, $20, $C9, $40, $F0, $1C, $C9, $5B +db $F0, $18, $C9, $03, $F0, $14, $C9, $05 +db $F0, $10, $C9, $07, $F0, $0C, $C9, $43 +db $F0, $08, $C9, $45, $F0, $04, $C9, $47 +db $D0, $04, $A9, $01, $85, $1D, $8B, $4B +db $AB, $BF, $F4, $D8, $00, $A8, $B9, $B1 +db $D1, $85, $00, $B9, $D2, $D0, $85, $01 +db $B9, $F3, $CF, $85, $02, $85, $05, $AB +db $C2, $31, $A2, $00, $00, $A0, $40, $00 +db $A5, $00, $20, $4F, $DF, $E2, $30, $6B + +endif + +pullpc +ActivateSubScreen: +{ + PHB : PHK : PLB + + STZ.b $1D + + PHX + + REP #$20 ; Set A in 16bit mode. + + LDA.b $8A : BNE .notForest + ; Check if we have the master sword. + LDA.l $7EF300 : AND.w #$0040 : BEQ .notForest + ; The forest canopy overlay. + BRA .turnOn + + .notForest + + ; Check if we need to disable the rain in the misery mire. + LDA.w Pool_EnableRainMireEvent : BEQ .notMire + LDA.b $8A : CMP.w #$0070 : BNE .notMire + ; Has Misery Mire been triggered yet? + LDA.l $7EF2F0 : AND.w #$0020 : BNE .notMire + BRA .turnOn + + .notMire + + ; Check if we are in the beginning phase, if not, no rain. + ; If $7EF3C5 >= 0x02. + LDA.l $7EF3C5 : AND.w #$00FF : CMP.w #$0002 : BCS .noRain + BRA .turnOn + + .noRain + + ; Get the overlay value for this overworld area. + ; ReadOverlayArray + LDA.b $8A : ASL : TAX + LDA.w Pool_OverlayTable, X : CMP.w #$00FF : BEQ .normal + ; If not $FF, assume we want an overlay. + + .turnOn + SEP #$20 ; Set A in 8bit mode. + + ; Turn on BG1. + LDA.b #$01 : STA.b $1D + + .normal + + SEP #$20 ; Set A in 8bit mode. + + PLX + + PLB + + RTL +} +pushpc + +; ============================================================================== + +if !Func00EEBB == 1 + +; Zeros out the BG color when mirror warping from an area with the pyramid BG. +; This is done to prevent a case where the black transparent color is faded to +; white on top of the pyramid BG, resulting in a double faded effect on +; transparent tiles. +org $00EEBB ; $006EBB +Palette_InitWhiteFilter_Interrupt: +{ + ; Check if we are currently in an area that is using an overlay. + ; By this point $8A is already set to the area we are going to so flip the + ; #$40 bit to get the one we are currently in. + LDA.b $8A : EOR.w #$0040 : ASL : TAX + LDA.l Pool_OverlayTable, X : CMP.w #$0096 : BNE .notPyramidBG + ; If so, don't fade that color to white because then we will get the + ; double fading. + JSL.l EraseBGColors + + .notPyramidBG + + SEP #$20 ; Set A in 8bit mode. + + LDA.b #$08 : STA.w $06BB + STZ.w $06BA + + RTL +} +warnpc $00EEE0 + +else + +org $00EEBB ; $006EBB +db $A5, $8A, $C9, $1B, $00, $D0, $13, $A9 +db $00, $00, $8F, $00, $C3, $7E, $8F, $40 +db $C3, $7E, $8F, $00, $C5, $7E, $8F, $40 +db $C5, $7E, $E2, $20, $A9, $08, $8D, $BB +db $06, $9C, $BA, $06, $6B + +endif + +pullpc +EraseBGColors: +{ + LDA.w #$0000 + STA.l $7EC300 : STA.l $7EC340 + STA.l $7EC500 : STA.l $7EC540 + + RTL +} +pushpc + +; ============================================================================== + +if !Func00FF7C == 1 + +; Controls the BG scrolling for HC and the pyramid area. +org $00FF7C ; $007F7C +MirrorWarp_BuildDewavingHDMATable_Interrupt: +{ + LDA.w $1C80 : ORA.w $1C90 : ORA.w $1CA0 : ORA.w $1CB0 : CMP.b $E2 : BNE .BRANCH_DELTA + SEP #$30 ; Set A, X, and Y in 8bit mode. + + STZ.b $9B + + INC.b $B0 + + JSL.l Overworld_SetFixedColorAndScroll + + REP #$30 ; Set A, X, and Y in 16bit mode. + + ; Check if we are warping to an area with the pyramid BG. + JSL.l ReadOverlayArray : CMP.w #$0096 : BEQ .dont_align_bgs + LDA.b $E2 : STA.b $E0 + STA.w $0120 + STA.w $011E + + LDA.b $E8 : STA.b $E6 + STA.w $0122 + STA.w $0124 + + .dont_align_bgs + .BRANCH_DELTA + + SEP #$30 ; Set A, X, and Y in 8bit mode. + + RTL +} +; NOTE: This end point also uses up a null block at the end of the function. +warnpc $00FFC0 + +else + +org $00FF7C ; $007F7C +db $AD, $80, $1C, $0D, $90, $1C, $0D, $A0 +db $1C, $0D, $B0, $1C, $C5, $E2, $D0, $28 +db $E2, $20, $64, $9B, $E6, $B0, $22, $70 +db $FE, $0B, $A5, $8A, $29, $3F, $C9, $1B +db $F0, $16, $C2, $20, $A5, $E2, $85, $E0 +db $8D, $20, $01, $8D, $1E, $01, $A5, $E8 +db $85, $E6, $8D, $22, $01, $8D, $24, $01 +db $E2, $30, $6B, $FF, $FF, $FF, $FF, $FF +db $FF, $FF, $FF, $FF + +endif + +; ============================================================================== + +if !Func0283EE == 1 + +; Replaces a bunch of calls to a shared function. +; Intro_SetupScreen: +org $028027 ; $010027 + JSR.w Overworld_LoadMusicIfNeeded + +warnpc $02802B + +; Dungeon_LoadSongBankIfNeeded: +org $029C0C ; $011C0C + JMP.w Overworld_LoadMusicIfNeeded + +warnpc $029C0F + +; Mirror_LoadMusic: +org $029D1E ; $011D1E + JSR.w Overworld_LoadMusicIfNeeded + +warnpc $029D21 + +; GanonEmerges_LoadPyramidArea: +org $029F82 ; $011F82 + JSR.w Overworld_LoadMusicIfNeeded + +warnpc $029F85 + +; Changes the function that loads overworld properties when exiting a dungeon. +; Includes removing asm that plays music in certain areas and changing how +; animated tiles are loaded. +org $0283EE ; $0103EE +PreOverworld_LoadProperties_Interrupt: +{ + LDX.b #$F3 + + ; If the volume was set to half, set it back to full. + LDA.w $0132 : CMP.b #$F2 : BEQ .setToFull + ; If we're in the dark world + ; If area number is < 0x40 or >= 80 we are not in the dark world. + LDA.b $8A : CMP.b #$40 : BCC .setNormalSong + CMP.b #$80 : BCS .setNormalSong + ; Does Link have a moon pearl? + LDA.l $7EF357 : BNE .setNormalSong + ; If not, play the music that plays when you're a bunny in the + ; Dark World. + LDX.b #$04 + + BRA .setToFull + + .setNormalSong + + LDX.b $8A + LDA.l $7F5B00, X : AND.b #$0F : TAX + + .setToFull + + ; The value written here will take effect during NMI. + STX.w $0132 + + ; Set the ambient sound. This is a bug present in vanilla. This was removed + ; because this is also done later on and does not need to be done twice. + ; Doing so creates a slight pause and causes the ambient sound to stop and + ; start playing again rather than just continuing to play. + ;LDX.b $8A + ;LDA.l $7F5B00, X : LSR #4 : STA.w $012D + + ; The decompression function increases it by 1 so subtract 1 here. + JSL.l ReadAnimatedTable : DEC : TAY + JSL.l DecompOwAnimatedTiles + + ; Decompress all other graphics. + JSL.l InitTilesets + + ; Load palettes for overworld. + JSR.w Overworld_LoadAreaPalettes + + LDX.b $8A + LDA.l $7EFD40, X : STA.b $00 + LDA.l OverworldPalettesScreenToSet_New, X + + ; Load some other palettes. + JSL.l Overworld_LoadPalettes + + ; Sets the background color (changes depending on area). + JSL.l Palette_SetOwBgColor_Long + + LDA.b $10 : CMP.b #$08 : BNE .specialArea2 + ; Copies $7EC300[0x200] to $7EC500[0x200]. + JSR.w Dungeon_LoadPalettes_cacheSettings + + BRA .normalArea2 + + .specialArea2 + + ; Apparently special overworld handles palettes a bit differently? + JSR.w SpecialOverworld_CopyPalettesToCache + + .normalArea2 + + ; Sets fixed colors and scroll values. + JSL.l Overworld_SetFixedColorAndScroll + + ; Set darkness level to zero for the overworld. + LDA.b #$00 : STA.l $7EC017 + + ; Sets up properties in the event a tagalong shows up. + JSL.l Tagalong_Init + + ; Set animated sprite gfx for area 0x00 and 0x40. + LDA.b $8A : AND.b #$3F : BNE .notForestArea + LDA.b #$1E + JSL.l GetAnimatedSpriteTile_variable + + .notForestArea + + ; 0x09 is the normal overworld $10 module. + LDX.b #$09 + + ; Check if we are going to a SW area. If so we need to move into the SW + ; mode after we are done loading. + LDA.b $8A : AND.b #$80 : BEQ .notSWArea + ; 0x0B is the SW overworld $10 module. + LDX.b #$0B + + .notSWArea + + ; Cache the overworld mode. + STX.w $010C + + JSL.l Sprite_OverworldReloadAll + + ; Are we in the dark world? If so, there's no warp vortex there. + LDA.b $8A : AND.b #$40 : BNE .noWarpVortex + JSL.l Sprite_ReinitWarpVortex + + .noWarpVortex + + ; Check if Blind disguised as a crystal maiden was following us when + ; we left the dungeon area. + LDA.l $7EF3CC : CMP.b #$06 : BNE .notBlindGirl + ; If it is Blind, kill her! + LDA.b #$00 : STA.l $7EF3CC + + .notBlindGirl + + ; Reset player variables. + STZ.b $6C ; In doorway flag + STZ.b $3A ; BY Bitfield + STZ.b $3C ; B Button timer + STZ.b $50 ; Link strafe + STZ.b $5E ; Link speed handler + STZ.w $0351 ; Link feet gfx fx + + ; Reinitialize many of Link's gameplay variables. + JSR.w DeleteCertainAncillaeStopDashing + + LDA.l $7EF357 : BNE .notBunny + LDA.l $7EF3CA : BEQ .notBunny + LDA.b #$01 : STA.w $02E0 + STA.b $56 + + LDA.b #$17 : STA.b $5D + + JSL.l LoadGearPalettes_bunny + + .notBunny + + ; Set screen to mode 1 with BG3 priority. + LDA.b #$09 : STA.b $94 + + LDA.b #$00 : STA.l $7EC005 + + STZ.w $046C ; Collision BG1 flag + STZ.b $EE ; Reset Link layer to BG2 + STZ.w $0476 ; Another layer flag + + ; Move to Overworld_LoadSubscreenAndSilenceSFX1 which is the 1st + ; submodule of Module_PreOverworld. + INC.b $11 + INC.b $16 ; NMI HUD Update flag + + STZ.w $0402 : STZ.w $0403 + + ; Bleeds into the next function +} + +; Vanilla alternate entry point. Called in 4 different locations all of +; which are overwritten above. +Overworld_LoadMusicIfNeeded: +{ + LDA.w $0136 : BEQ .no_music_load_needed + SEI + + ; Shut down NMI until music loads. + STZ.w SNES.NMIVHCountJoypadEnable + + ; Stop all HDMA. + STZ.w SNES.HDMAChannelEnable + + STZ.w $0136 + + LDA.b #$FF : STA.w SNES.APUIOPort0 + + JSL.l Sound_LoadLightWorldSongBank + + ; Re-enable NMI and joypad. + LDA.b #$81 : STA.w SNES.NMIVHCountJoypadEnable + + .no_music_load_needed + + ; PLACE CUSTOM GFX LOAD HERE! + ;JSL.l CheckForChangeGraphicsNormalLoadCastle + + RTS +} +warnpc $02856A ; $01056A + +else + +org $028027 ; $010027 + db $20, $4C, $85 + +org $029C0C ; $011C0C + db $4C, $4C, $85 + +org $029D1E ; $011D1E + db $20, $4C, $85 + +org $029F82 ; $011F82 + db $20, $4C, $85 + +org $0283EE ; $0103EE +db $A0, $58, $A2, $02, $A5, $8A, $C9, $03 +db $F0, $6F, $C9, $05, $F0, $6B, $C9, $07 +db $F0, $67, $A2, $09, $A5, $8A, $C9, $43 +db $F0, $5F, $C9, $45, $F0, $5B, $C9, $47 +db $F0, $57, $A0, $5A, $A5, $8A, $C9, $40 +db $B0, $3A, $A2, $07, $AF, $C5, $F3, $7E +db $C9, $03, $90, $02, $A2, $02, $A5, $A0 +db $C9, $E3, $F0, $3D, $C9, $18, $F0, $39 +db $C9, $2F, $F0, $35, $A5, $A0, $C9, $1F +db $D0, $06, $A5, $8A, $C9, $18, $F0, $29 +db $A2, $05, $AF, $00, $F3, $7E, $29, $40 +db $F0, $02, $A2, $02, $A5, $A0, $F0, $19 +db $C9, $E1, $F0, $15, $A2, $F3, $AD, $32 +db $01, $C9, $F2, $F0, $30, $A2, $02, $AF +db $C5, $F3, $7E, $C9, $02, $B0, $02, $A2 +db $03, $AF, $CA, $F3, $7E, $F0, $1E, $A2 +db $0D, $A5, $8A, $C9, $40, $F0, $0E, $C9 +db $43, $F0, $0A, $C9, $45, $F0, $06, $C9 +db $47, $F0, $02, $A2, $09, $AF, $57, $F3 +db $7E, $D0, $02, $A2, $04, $8E, $32, $01 +db $22, $94, $D3, $00, $22, $9B, $E1, $00 +db $20, $92, $C6, $A6, $8A, $BF, $40, $FD +db $7E, $85, $00, $BF, $1C, $FD, $00, $22 +db $A8, $D5, $0E, $22, $18, $D6, $0E, $A5 +db $10, $C9, $08, $D0, $05, $20, $5F, $C6 +db $80, $03, $20, $EB, $C6, $22, $70, $FE +db $0B, $A9, $00, $8F, $17, $C0, $7E, $22 +db $FC, $9E, $09, $A5, $8A, $29, $3F, $D0 +db $06, $A9, $1E, $22, $ED, $D4, $00, $A9 +db $09, $8D, $0C, $01, $22, $99, $C4, $09 +db $A5, $8A, $29, $40, $D0, $04, $22, $89 +db $AF, $09, $A2, $05, $AF, $C5, $F3, $7E +db $C9, $02, $B0, $02, $A2, $01, $8E, $2D +db $01, $AF, $CC, $F3, $7E, $C9, $06, $D0 +db $06, $A9, $00, $8F, $CC, $F3, $7E, $64 +db $6C, $64, $3A, $64, $3C, $64, $50, $64 +db $5E, $9C, $51, $03, $20, $0C, $8B, $AF +db $57, $F3, $7E, $D0, $15, $AF, $CA, $F3 +db $7E, $F0, $0F, $A9, $01, $8D, $E0, $02 +db $85, $56, $A9, $17, $85, $5D, $22, $DD +db $D6, $0E, $A9, $09, $85, $94, $A9, $00 +db $8F, $05, $C0, $7E, $9C, $6C, $04, $64 +db $EE, $9C, $76, $04, $E6, $11, $E6, $16 +db $9C, $02, $04, $9C, $03, $04, $AD, $36 +db $01, $F0, $18, $78, $9C, $00, $42, $9C +db $0C, $42, $9C, $36, $01, $A9, $FF, $8D +db $40, $21, $22, $13, $89, $00, $A9, $81 +db $8D, $00, $42, $60 + +endif + +; ============================================================================== + +if !Func028632 == 1 + +; Changes a function that loads animated tiles under certain conditions. +org $028632 ; $010632 +Credits_LoadScene_Overworld_PrepGFX_Interrupt: +{ + ; The decompression function increases it by 1 so subtract 1 here. + JSL.l ReadAnimatedTable : DEC : TAY + JSL.l DecompOwAnimatedTiles + + ; The current scene of the Module_EndSequence module. Example: 0x04 is + ; the shot of kakariko and 0x06 is the shot of the desert palace. + LDA.b $11 : LSR : TAX + LDA.l Credits_LoadScene_PrepGFX_sprite_gfx, X : STA.w $0AA3 + LDA.l Credits_LoadScene_PrepGFX_sprite_palette, X : PHA + + JSL.l InitTilesets + + ; Load Palettes. + JSR.w Overworld_LoadAreaPalettes + + PLA : STA.b $00 + + LDX.b $8A + LDA.l OverworldPalettesScreenToSet_New, X + JSL.l Overworld_LoadPalettes + + LDA.b #$01 : STA.w $0AB2 + + JSL.l Palette_Hud + + LDA.l $11 : BNE .BRANCH_4 + JSL.l CopyFontToVram + + .BRANCH_4 + + JSR.w Dungeon_LoadPalettes_cacheSettings + JSL.l Overworld_SetFixedColorAndScroll + + LDA.l $8A : CMP.b #$80 : BCC .BRANCH_5 + JSL.l Palette_SetOwBgColor_Long + + .BRANCH_5 + + LDA.b #$09 : STA.b $94 + + INC.b $B0 + + RTS +} +warnpc $028697 ; $010697 + +else + +org $028632 ; $010632 +db $A0, $58, $A5, $8A, $29, $BF, $C9, $03 +db $F0, $0A, $C9, $05, $F0, $06, $C9, $07 +db $F0, $02, $A0, $5A, $22, $94, $D3, $00 +db $A5, $11, $4A, $AA, $BF, $E2, $85, $02 +db $8D, $A3, $0A, $BF, $F3, $85, $02, $48 +db $22, $9B, $E1, $00, $20, $92, $C6, $68 +db $85, $00, $A6, $8A, $BF, $1C, $FD, $00 +db $22, $A8, $D5, $0E, $A9, $01, $8D, $B2 +db $0A, $22, $52, $EE, $1B, $A5, $11, $D0 +db $04, $22, $56, $E5, $00, $20, $5F, $C6 +db $22, $70, $FE, $0B, $A5, $8A, $C9, $80 +db $90, $04, $22, $18, $D6, $0E, $A9, $09 +db $85, $94, $E6, $B0, $60 + +endif + +; ============================================================================== + +if !Func029A37 == 1 + +; Changes part of a function that changes the sub mask color when leaving +; dungeons. +org $029A37 ; $011A37 +Spotlight_ConfigureTableAndControl_Interrupt: +{ + LDA.b $10 : CMP.b #$09 : BEQ .dontPrepForDungeon + CMP.b #$0B : BEQ .dontPrepForDungeon + ; Force V-blank in preperation for Dungeon mode. + JSL.l EnableForceBlank + + JSL.l Link_ItemReset_FromOverworldThings + + .dontPrepForDungeon + + LDA.b $10 : CMP.b #$09 : BEQ .inOWMode + CMP.b #$0B : BNE .notInOWMode + .inOWMode + + LDA.b $A1 : BNE .BRANCH_DELTA + LDA.b $A0 : CMP.b #$20 : BEQ .BRANCH_EPSILON + + .BRANCH_DELTA + + LDA.b #$0A + + LDX.b $2F : BNE .BRANCH_ZETA + LDA.b #$0B + + .BRANCH_ZETA + + STA.b $11 + + .BRANCH_EPSILON + + LDA.b #$10 : STA.w $069A + + ; Not an extended door type (palace or sanctuary). + LDA.w $0696 : ORA.w $0698 : BEQ .BRANCH_GAMMA + LDA.w $0699 : BEQ .BRANCH_GAMMA + LDX.b #$00 + + ASL : BCC .BRANCH_THETA + LDX.b #$18 + + .BRANCH_THETA + + LDA.w $0699 : AND.b #$7F : STA.w $0699 + + STX.w $0692 + STZ.w $0690 + + LDA.b #$09 : STA.b $11 + + STZ.b $B0 + + LDA.b #$15 : STA.w $012F + + .BRANCH_GAMMA + .notInOWMode + + STZ.b $96 : STZ.b $97 : STZ.b $98 + STZ.b $1E : STZ.b $1F : STZ.w $03EF + + REP #$30 + + ; Setup fixed color values based on area number. + LDX.w #$4C26 + LDY.w #$8C4C + + ; TODO: Wtf why is this 0x00? + ; Check for LW death mountain. + JSL.l ReadOverlayArray : CMP.w #$0095 : BEQ .mountain + LDX.w #$4A26 + LDY.w #$874A + + ; Check for DW death mountain. + CMP.w #$009C : BEQ .mountain + BRA .other + + .mountain + + STX.b $9C + STY.b $9D + + .other + + SEP #$30 ; Set A, X, and Y in 8bit mode. + + RTS +} +warnpc $029AD3 ; $011AD3 + +else + +org $029A37 ; $011A37 +db $A5, $10, $C9, $09, $F0, $08, $22, $3D +db $89, $00, $22, $07, $B1, $07, $A5, $10 +db $C9, $09, $D0, $46, $A5, $A1, $D0, $06 +db $A5, $A0, $C9, $20, $F0, $0A, $A9, $0A +db $A6, $2F, $D0, $02, $A9, $0B, $85, $11 +db $A9, $10, $8D, $9A, $06, $AD, $96, $06 +db $0D, $98, $06, $F0, $25, $AD, $99, $06 +db $F0, $20, $A2, $00, $0A, $90, $02, $A2 +db $18, $AD, $99, $06, $29, $7F, $8D, $99 +db $06, $8E, $92, $06, $9C, $90, $06, $A9 +db $09, $85, $11, $64, $B0, $A9, $15, $8D +db $2F, $01, $64, $96, $64, $97, $64, $98 +db $64, $1E, $64, $1F, $9C, $EF, $03, $C2 +db $30, $A2, $26, $4C, $A0, $4C, $8C, $A5 +db $8A, $C9, $03, $00, $F0, $1F, $C9, $05 +db $00, $F0, $1A, $C9, $07, $00, $F0, $15 +db $A2, $26, $4A, $A0, $4A, $87, $C9, $43 +db $00, $F0, $0A, $C9, $45, $00, $F0, $05 +db $C9, $47, $00, $D0, $04, $86, $9C, $84 +db $9D, $E2, $30, $60 + +endif + +; ============================================================================== + +if !Func02AF58 == 1 + +; Main subscreen overlay loading function. Changed so that they will load +; from a table. This does not change the event overlays like the lost woods +; changing to the tree canopy, the master sword area, or the misery mire rain. +; This also does not change the overlay for under the bridge because it shares +; an area with the master sword. +org $02AF58 ; $012F58 +Overworld_ReloadSubscreenOverlay_Interrupt: +{ + SEP #$20 ; Set A in 8bit mode. + + ; Check to see if we are using the mirror so that our $A0 doesn't + ; accidentally persist and we trigger rain sounds when we don't want them. + LDA.b $11 : CMP.b #$23 : BEQ .mirrorWarp + CMP.b #$24 : BEQ .mirrorWarp + CMP.b #$2C : BEQ .mirrorWarp + ; We can't warp to or from a special area anyway so this is fine. + + REP #$20 ; Set A in 16bit mode. + + ; Check to see if we are in a SW overworld area. + LDA.b $8A : CMP.w #$0080 : BCC .notExtendedArea + ; $0182 is the exit room number used for getting to Zora's Domain. + LDA.b $A0 : CMP.w #$0182 : BNE .notZoraFalls + SEP #$20 ; Set A in 8bit mode. + + ; Play rain (waterfall) sound. + ; TODO: Write a patch to change/disable this. + LDA.b #$01 : STA.w $012D + + REP #$20 ; Set A in 16bit mode. + + .notZoraFalls + + ; Check for exit rooms (the faked way of getting from one overworld + ; area to another). $0180 is the exit room number used for getting + ; into the mastersword area. + LDA.b $A0 : CMP.w #$0180 : BNE .notMasterSwordArea + ; If the Master sword is retrieved, don't do the mist overlay. + LDA.l $7EF300 : AND.w #$0040 : BNE .masterSwordRecieved + JSL.l ReadOverlayArray : TAX + + .loadOverlayShortcut + + ; Save the overlay for later. + PHX + + JMP.w .loadSubScreenOverlay + + .masterSwordRecieved + + ; TODO: Write a patch to change what overlay is loaded here? + BRA .noSubscreenOverlay + + .notMasterSwordArea + + ; TODO: Write a patch to change what overlay is loaded here? + ; The second mastersword/under the bridge area. + LDX.w #$0094 + + ; $0181 is the exit room number used for getting into the under the + ; bridge area. + LDA.b $A0 : CMP.w #$0181 : BEQ .loadOverlayShortcut + ; TODO: Write a patch to change what overlay is loaded here? + ; The second Triforce room area. + LDX.w #$0093 + + ; $0189 is the exit room number used for getting to the + ; Triforce room. + CMP.w #$0189 : BEQ .loadOverlayShortcut + .noSubscreenOverlay + + SEP #$30 ; Set A, X, and Y in 8bit mode. + + ; Clear TSQ PPU Register, to be handled in NMI. + STZ.b $1D + + ; Submodule 0x18 (Module09_18:) of Module 0x0B + ; (Overworld Mode (special overworld)) + INC.b $11 + + RTS + + .notExtendedArea + .mirrorWarp + + REP #$20 ; Set A in 16bit mode. + + JSL.l ReadOverlayArray : TAX + + LDA.b $8A : BNE .notForest + ; Check if we have the master sword. + LDA.l $7EF300 : AND.w #$0040 : BEQ .notForest + ; TODO: Write a patch to change this? + ; The forest canopy overlay. + LDX.w #$009E + + .notForest + + ; Check if we need to disable the rain in the misery mire. + LDA.l Pool_EnableRainMireEvent : BEQ .notMire + LDA.b $8A : CMP.w #$0070 : BNE .notMire + ; Has Misery Mire been triggered yet? + LDA.l $7EF2F0 : AND.w #$0020 : BNE .notMire + ; The rain overlay. + LDX.w #$009F + + SEP #$20 ; Set A in 8bit mode. + + ; Load the rain sound effect. + ; This is done here because of some jank in the vanilla code in + ; this function a bit further down. Basically it loads the + ; overlay's ambient sound instead of the acutal areas, which + ; only seems to benefit us here. + LDA.b #$01 : STA.w $012D + + REP #$20 ; Set A in 16bit mode. + + .notMire + + ; Check if we are in the beginning phase, if not, no rain. + ; If $7EF3C5 >= 0x02. + LDA.l Pool_EnableBeginningRain : AND.w #$00FF : BEQ .noRain + LDA.l $7EF3C5 : AND.w #$00FF : CMP.w #$0002 : BCS .noRain + ; The rain overlay. + LDX.w #$009F + + .noRain + + ; Store the overlay for later. + PHX + + ; If the value is 0xFF that means we didn't set any overlay so load the + ; pyramid one by default. This is done in vanilla to not have to load the + ; BG during a normal transition from area 0x65 to the pyramid area. + CPX.w #$00FF : BNE .notFF + ; The pyramid background. + LDX.w #$0096 + + .notFF + + .loadSubScreenOverlay + + STY.b $84 + + STX.b $8A : STX.b $8C + + ; Overworld map16 buffer manipulation during scrolling. + LDA.b $84 : SEC : SBC.w #$0400 : AND.w #$0F80 : ASL : XBA : STA.b $88 + LDA.b $84 : SEC : SBC.w #$0010 : AND.w #$003E : LSR : STA.b $86 + + STZ.w $0418 : STZ.w $0410 : STZ.w $0416 + + SEP #$30 ; Set A, X, and Y in 8bit mode. + + ; Color +/- buffered register. + LDA.b #$82 : STA.b $99 + + ; Puts OBJ, BG2, and BG3 on the main screen. + LDA.b #$16 : STA.b $1C + + ; Puts BG1 on the subscreen. + LDA.b #$01 : STA.b $1D + + ; Pull the 16 bit overlay from earlier and just discard the high byte. + PLX : PLA + + ; One possible configuration for SNES.AddSubtractSelectAndEnable (CGADSUB). + LDA.b #$72 + + ; Comparing different screen types. + CPX.b #$97 : BEQ .loadOverlay ; Fog 1 + CPX.b #$94 : BEQ .loadOverlay ; Master sword/bridge 2 + CPX.b #$93 : BEQ .loadOverlay ; Triforce room 2 + CPX.b #$9D : BEQ .loadOverlay ; Fog 2 + CPX.b #$9E : BEQ .loadOverlay ; Tree canopy + CPX.b #$9F : BEQ .loadOverlay ; Rain + ; Alternative setting for CGADSUB (only background is enabled on + ; subscreen). + LDA.b #$20 + + CPX.b #$95 : BEQ .loadOverlay ; Sky + CPX.b #$9C : BEQ .loadOverlay ; Lava + CPX.b #$96 : BEQ .loadOverlay ; Pyramid BG + ; TODO: Investigate what these checks are for. + LDX.b $11 : CPX.b #$23 : BEQ .loadOverlay + CPX.b #$2C : BEQ .loadOverlay + STZ.b $1D + + .loadOverlay + + ; Apply the selected settings to CGADSUB's mirror ($9A). + STA.b $9A + + JSR.w LoadSubscreenOverlay + + ; This is the "under the bridge" area. + LDA.b $8C : CMP.b #$94 : BNE .notUnderBridge + ; All this is doing is setting the X coordinate of BG1 to 0x0100 + ; rather than 0x0000. (this area uses the second half of the data only, + ; similar to the master sword area). + LDA.b $E7 : ORA.b #$01 : STA.b $E7 + + .notUnderBridge + + REP #$20 ; Set A in 16bit mode. + + ; We were pretending to be in a different area to load the subscreen + ; overlay, so we're restoring all those settings. + LDA.l $7EC213 : STA.b $8A + LDA.l $7EC215 : STA.b $84 + LDA.l $7EC217 : STA.b $88 + LDA.l $7EC219 : STA.b $86 + + LDA.l $7EC21B : STA.w $0418 + LDA.l $7EC21D : STA.w $0410 + LDA.l $7EC21F : STA.w $0416 + + SEP #$20 ; Set A in 8bit mode. + + RTS +} +warnpc $02B0D2 ; $0130D2 + +else + +org $02AF58 ; $012F58 +db $A5, $8A, $C9, $80, $00, $90, $44, $A2 +db $97, $00, $A5, $A0, $C9, $80, $01, $D0 +db $12, $A2, $80, $00, $BF, $80, $F2, $7E +db $A2, $97, $00, $29, $40, $00, $D0, $24 +db $4C, $0B, $B0, $A2, $94, $00, $C9, $81 +db $01, $F0, $F5, $A2, $93, $00, $C9, $89 +db $01, $F0, $ED, $C9, $82, $01, $F0, $05 +db $C9, $83, $01, $D0, $07, $E2, $30, $A9 +db $01, $8D, $2D, $01, $E2, $30, $64, $1D +db $E6, $11, $60, $29, $3F, $00, $D0, $1B +db $A5, $8A, $29, $40, $00, $D0, $0F, $A2 +db $80, $00, $BF, $80, $F2, $7E, $A2, $9E +db $00, $29, $40, $00, $D0, $4D, $A2, $9D +db $00, $80, $48, $A2, $95, $00, $A5, $8A +db $C9, $03, $00, $F0, $3E, $C9, $05, $00 +db $F0, $39, $C9, $07, $00, $F0, $34, $A2 +db $9C, $00, $C9, $43, $00, $F0, $2C, $C9 +db $45, $00, $F0, $27, $C9, $47, $00, $F0 +db $22, $C9, $70, $00, $D0, $0B, $AF, $F0 +db $F2, $7E, $29, $20, $00, $D0, $14, $80 +db $0F, $A2, $96, $00, $AF, $C5, $F3, $7E +db $29, $FF, $00, $C9, $02, $00, $B0, $03 +db $A2, $9F, $00, $84, $84, $86, $8A, $86 +db $8C, $A5, $84, $38, $E9, $00, $04, $29 +db $80, $0F, $0A, $EB, $85, $88, $A5, $84 +db $38, $E9, $10, $00, $29, $3E, $00, $4A +db $85, $86, $9C, $18, $04, $9C, $10, $04 +db $9C, $16, $04, $E2, $30, $A9, $82, $85 +db $99, $A9, $16, $85, $1C, $A9, $01, $85 +db $1D, $DA, $A6, $8A, $BF, $00, $5B, $7F +db $4A, $4A, $4A, $4A, $8D, $2D, $01, $FA +db $A9, $72, $E0, $97, $F0, $39, $E0, $94 +db $F0, $35, $E0, $93, $F0, $31, $E0, $9D +db $F0, $2D, $E0, $9E, $F0, $29, $E0, $9F +db $F0, $25, $A9, $20, $E0, $95, $F0, $1F +db $E0, $9C, $F0, $1B, $AF, $13, $C2, $7E +db $AA, $A9, $20, $E0, $5B, $F0, $10, $E0 +db $1B, $D0, $0A, $A6, $11, $E0, $23, $F0 +db $06, $E0, $2C, $F0, $02, $64, $1D, $85 +db $9A, $20, $0D, $FD, $A5, $8C, $C9, $94 +db $D0, $06, $A5, $E7, $09, $01, $85, $E7 +db $C2, $20, $AF, $13, $C2, $7E, $85, $8A +db $AF, $15, $C2, $7E, $85, $84, $AF, $17 +db $C2, $7E, $85, $88, $AF, $19, $C2, $7E +db $85, $86, $AF, $1B, $C2, $7E, $8D, $18 +db $04, $AF, $1D, $C2, $7E, $8D, $10, $04 +db $AF, $1F, $C2, $7E, $8D, $16, $04, $E2 +db $20, $60 + +endif + +; ============================================================================== + +if !Func02B2D4 == 1 + +; Turns on the subscreen if the pyramid is loaded. +org $02B2D4 ; $0132D4 +Func02B2D4: +{ + JSR.w Overworld_LoadSubscreenAndSilenceSFX1 + + ; In vanilla a check for the overlay is done here but we don't need + ; it at all. It is handled in Func02B391 later on. + ;JSL.l EnableSubScreenCheckForPyramid + + RTL +} +warnpc $02B2E6 ; $0132E6 + +else + +org $02B2D4 ; $0132D4 +db $20, $19, $AF, $A5, $8A, $C9, $1B, $F0 +db $04, $C9, $5B, $D0, $04, $A9, $01, $85 +db $1D, $6B + +endif + +pullpc +EnableSubScreenCheckForPyramid: +{ + REP #$20 ; Set A in 16bit mode. + + LDA.b $8A : ASL : TAX + LDA.w Pool_OverlayTable, X : CMP.w #$0096 : BNE .notPyramidOrCastle + SEP #$20 ; Set A in 8bit mode. + + LDA.b #$01 : STA.b $1D + + .notPyramidOrCastle + + SEP #$20 ; Set A in 8bit mode. + + RTL +} +pushpc + +; ============================================================================== + +if !Func02B391 == 1 + +; Handles activating the subscreen and special BG color when warping to an area +; with the pyramid BG. +org $02B391 ; $013391 +MirrorWarp_LoadSpritesAndColors_Interrupt: +{ + LDA.l OverworldPalettesScreenToSet_New, X + JSL.l Overworld_LoadPalettes + + JSL.l Overworld_SetScreenBGColorCacheOnly + JSL.l Overworld_SetFixedColorAndScroll + + JSL.l EnableSubScreenCheckForPyramid + + REP #$20 ; Set A in 16bit mode. + + LDX.b #$00 + LDA.w #$7FFF + + .setBgPalettesToWhite + + STA.l $7EC540, X : STA.l $7EC560, X + STA.l $7EC580, X : STA.l $7EC5A0, X + STA.l $7EC5C0, X : STA.l $7EC5E0, X + INX : INX : CPX.b #$20 : BNE .setBgPalettesToWhite + + ; Also set the background color to white. + STA.l $7EC500 + + JSL.l ReadOverlayArray + + ; This sets the color to transparent so that we don't see an additional + ; white layer on top of the pyramid bg. + CMP.w #$0096 : BNE .notPyramidOfPower + LDA.w #$0000 : STA.l $7EC500 + STA.l $7EC540 + + .notPyramidOfPower + + SEP #$20 ; Set A in 8bit mode. + + JSL.l Sprite_ResetAll + JSL.l Sprite_OverworldReloadAll + JSL.l Link_ItemReset_FromOverworldThings + JSR.w DeleteCertainAncillaeStopDashing + + LDA.b #$14 : STA.b $5D + + LDA.b $8A : AND.b #$40 : BNE .darkWorld + JSL.l Sprite_ReinitWarpVortex + + .darkWorld + + RTL +} +warnpc $02B40A ; $01340A + +else + +org $02B391 ; $013391 +db $BF, $1C, $FD, $00, $22, $A8, $D5, $0E +db $22, $1D, $D6, $0E, $22, $70, $FE, $0B +db $A5, $8A, $C9, $1B, $F0, $04, $C9, $5B +db $D0, $04, $A9, $01, $85, $1D, $C2, $20 +db $A2, $00, $A9, $FF, $7F, $9F, $40, $C5 +db $7E, $9F, $60, $C5, $7E, $9F, $80, $C5 +db $7E, $9F, $A0, $C5, $7E, $9F, $C0, $C5 +db $7E, $9F, $E0, $C5, $7E, $E8, $E8, $E0 +db $20, $D0, $E2, $8F, $00, $C5, $7E, $A5 +db $8A, $C9, $5B, $00, $D0, $0B, $A9, $00 +db $00, $8F, $00, $C5, $7E, $8F, $40, $C5 +db $7E, $E2, $20, $22, $4E, $C4, $09, $22 +db $99, $C4, $09, $22, $07, $B1, $07, $20 +db $0C, $8B, $A9, $14, $85, $5D, $A5, $8A +db $29, $40, $D0, $04, $22, $89, $AF, $09 +db $6B + +endif + +; ============================================================================== + +if !Func02BC44 == 1 + +; Controls overworld vertical subscreen movement for the pyramid BG. +org $02BC44 ; $013C44 +Overworld_OperateCameraScroll_Interrupt: +{ + ; Check for the pyramid BG. + JSL.l ReadOverlayArray : CMP.w #$0096 : BNE .BRANCH_IOTA + JSL.l BGControl + + BRA .BRANCH_IOTA + + warnpc $02BC60 ; $013C60 + + org $02BC60 ; $013C60 + .BRANCH_IOTA +} +warnpc $02BC60 ; $013C60 + +else + +org $02BC44 ; $013C44 +db $A5, $8A, $29, $3F, $00, $C9, $1B, $00 +db $D0, $12, $A9, $00, $06, $C5, $E6, $90 +db $02, $85, $E6, $A9, $C0, $06, $C5, $E6 +db $B0, $02, $85, $E6 + +endif + +pullpc +ReadOverlayArray: +{ + PHB : PHK : PLB + + LDA.b $8A : ASL : TAX + LDA.w Pool_OverlayTable, X + + PLB + + RTL +} + +; TODO: These comparison values will need to be calculated somehow or set +; depending on the area. Right now they are hardcoded to work with the +; pyramid area. +BGControl: +{ + ; TODO: I'm pretty sure this part was AHE specific. Verify. + ; Check link's Y position. This will need to be changed per area and per + ; need. + ;LDA.b $20 : CMP.w #$08E0 : BCC .startShowingMountains + ; Lock the position so that nothing shows through the trees. + ;LDA.w #$06C0 : STA.b $E6 + + ;RTL + + ;.startShowingMountains + + ; Don't let the BG scroll down further than the "top" of the bg when + ; walking up. + LDA.w #$0600 : CMP.b $E6 : BCC .dontLock + STA.b $E6 + + .dontLock + + ; Don't let the BG scroll up further than the "bottom" of the bg when + ; walking down. + LDA.w #$06C0 : CMP.b $E6 : BCS .dontLock2 + STA.b $E6 + + .dontLock2 + + RTL +} +pushpc + +; ============================================================================== + +if !Func02C02D == 1 + +; Changes how the pyramid BG scrolls durring transition. +org $02C02D ; $01402D +OverworldScrollTransition_Interrupt: +{ + PHA + JSL.l ReadOverlayArray2 + PLA + + ; Check for the pyramid BG. + CPY.b #$96 : BEQ .dontMoveBg1 + ; This shifts the BG over by a half small area's width. This is to + ; line up the mountain with the tower in the distance at the appropriate + ; location when coming into the pyramid area from the right. + ; This also keeps the BG aligned when entering the area from below, + ; keeping you from seeing the mountains through the trees. + STA.b $E0, X + + ; NOTE: There is currently a bug in vanilla where if you exit a dungeon + ; into the LW death mountain the sky background will become miss-aligned + ; and this movement will cause the sky to flicker or jump when moving to + ; another area. In order to fix this you would have to find the + ; alignment exit code and change how the game aligns BG2 when exiting. + ; Possibly when using the bird too. + + .dontMoveBg1 +} +warnpc $02C039 ; $014039 + +else + +org $02C02D ; $01402D +db $A4, $8A, $C0, $1B, $F0, $06, $C0, $5B +db $F0, $02, $95, $E0 + +endif + +pullpc +ReadOverlayArray2: +{ + PHX + + ; A is already 16 bit here. + REP #$10 ; Set X and Y in 16bit mode. + + ; ReadOverlayArray + LDA.b $8A : ASL : TAX + LDA.l Pool_OverlayTable, X : TAY + + SEP #$10 ; Set X and Y in 8bit mode. + + PLX + + RTL +} +pushpc + +; ============================================================================== + +if !Func02C692 == 1 + +; Replaces a call to a shared function. Normally this is goes to .lightworld +; to change the main color palette manually but we change it here so that it +; just uses the same table as everything else. +org $02A07A ; $01207A + JSR.w Overworld_LoadAreaPalettes + +warnpc $02A07D ; $01207D + +; The main overworld palette loading routine un-hardcoded to load the custom +; main palette. +org $02C692 ; $014692 +Overworld_LoadAreaPalettes: +{ + ; $0AB3 = + ; 0 - LW + ; 1 - DW + ; 2 - LW death mountain + ; 3 - DW death mountain + ; 4 - triforce room + LDX.b $8A + LDA.l Pool_MainPaletteTable, X : STA.w $0AB3 + + ; Reset pal buffer high byte. + STZ.w $0AA9 + + ; Load SP1 through SP4. + JSL.l Palette_MainSpr + + ; Load SP0 (2nd half) and SP6 (2nd half). + JSL.l Palette_MiscSpr + + ; Load SP5 (1st half). + JSL.l Palette_SpriteAux1 + + ; Load SP6 (1st half). + JSL.l Palette_SpriteAux2 + + ; Load SP5 (2nd half, 1st 3 colors), which is the sword palette. + JSL.l Palette_Sword + + ; Load SP5 (2nd half, next 4 colors), which is the shield. + JSL.l Palette_Shield + + ; Load SP7 (full) Link's whole palette, including Armor. + JSL.l Palette_ArmorAndGloves + + LDX.b #$01 + + ; Changes the Palette_SpriteAux3 load depending on if we are in the LW or + ; not. Will probably need it own custom table in the future? not sure. + LDA.l $7EF3CA : AND.b #$40 : BEQ .lightWorld2 + LDX.b #$03 + + .lightWorld2 + + ; Reset pal buffer0. + STX.w $0AAC + + ; Load SP0 (first half) (or SP7 (first half)). + JSL.l Palette_SpriteAux3 + + ; Load BP0 and BP1 (first halves). + JSL.l Palette_Hud + + ; Load BP2 through BP5 (first halves). + JSL.l Palette_OverworldBgMain + + RTS +} +warnpc $02C6EB ; $0146EB + +else + +org $02A07A ; $01207A +db $20, $AD, $C6 + +org $02C692 ; $014692 +db $A2, $02, $A5, $8A, $29, $3F, $C9, $03 +db $F0, $0A, $C9, $05, $F0, $06, $C9, $07 +db $F0, $02, $A2, $00, $A5, $8A, $29, $40 +db $F0, $01, $E8, $8E, $B3, $0A, $9C, $A9 +db $0A, $22, $9E, $EC, $1B, $22, $6E, $ED +db $1B, $22, $C5, $EC, $1B, $22, $E4, $EC +db $1B, $22, $03, $ED, $1B, $22, $29, $ED +db $1B, $22, $F9, $ED, $1B, $A2, $01, $AF +db $CA, $F3, $7E, $29, $40, $F0, $02, $A2 +db $03, $8E, $AC, $0A, $22, $77, $EC, $1B +db $22, $52, $EE, $1B, $22, $C7, $EE, $1B +db $60 + +endif + +; ============================================================================== + +if !Func02A4CD == 1 + +; Rain animation code. Just replaces a single check that checks for the +; misery mire to instead check the current overlay to see if it's rain. +org $02A4CD ; $0124CD +RainAnimation: +{ + LDA.b $8C : CMP.b #$9F : BEQ .rainOverlaySet + ; Check the progress indicator. + LDA.l $7EF3C5 : CMP.b #$02 : BRA .skipMovement + .rainOverlaySet + + ; If misery mire has been opened already, we're done. + ;LDA.l $7EF2F0 : AND.b #$20 : BNE .skipMovement + ; Check the frame counter. + ; On the 0x03rd frame, cue the lightning. + LDA.b $1A : CMP.b #$03 : BEQ .lightning + ; On the 0x05th frame, normal light level. + CMP.b #$05 : BEQ .normalLight + ; On the 0x24th frame, cue the thunder. + CMP.b #$24 : BEQ .thunder + ; On the 0x2Cth frame, normal light level. + CMP.b #$2C : BEQ .normalLight + ; On the 0x58th frame, cue the lightning. + CMP.b #$58 : BEQ .lightning + ; On the 0x5Ath frame, normal light level. + CMP.b #$5A : BNE .moveOverlay + + .normalLight + + ; Keep the screen semi-dark. + LDA.b #$72 + + BRA .setBrightness + + .thunder + + ; Play the thunder sound when outdoors. + LDX.b #$36 : STX.w $012E + + .lightning + + ; Make the screen flash with lightning. + LDA.b #$32 + + .setBrightness + + STA.b $9A + + .moveOverlay + + ; Overlay is only moved every 4th frame. + LDA.b $1A : AND.b #$03 : BNE .skipMovement + LDA.w $0494 : INC : AND.b #$03 : STA.w $0494 + TAX + + LDA.b $E1 : CLC : ADC.l OWOverlay_HShift, X : STA.b $E1 + LDA.b $E7 : CLC : ADC.l OWOverlay_VShift, X : STA.b $E7 + + .skipMovement + + RTL +} +warnpc $02A52D ; $01252D + +else + +org $02A4CD ; $0124CD +db $A5, $8A, $C9, $70, $F0, $08, $AF, $C5 +db $F3, $7E, $C9, $02, $B0, $51, $AF, $F0 +db $F2, $7E, $29, $20, $D0, $49, $A5, $1A +db $C9, $03, $F0, $1D, $C9, $05, $F0, $10 +db $C9, $24, $F0, $10, $C9, $2C, $F0, $08 +db $C9, $58, $F0, $0D, $C9, $5A, $D0, $0D +db $A9, $72, $80, $07, $A2, $36, $8E, $2E +db $01, $A9, $32, $85, $9A, $A5, $1A, $29 +db $03, $D0, $1C, $AD, $94, $04, $1A, $29 +db $03, $8D, $94, $04, $AA, $A5, $E1, $18 +db $7F, $6D, $A4, $02, $85, $E1, $A5, $E7 +db $18, $7F, $71, $A4, $02, $85, $E7, $6B + +endif + +; ============================================================================== + +if !Func02ABBE == 1 + +org $02ABBE ; $012BBE + JSL.l NewOverworld_FinishTransGfx + NOP : NOP : NOP + +warnpc $02ABC5 ; $012BC5 + +else + +org $02ABBE ; $012BBE +db $85, $17, $8D, $10, $07, $E6, $11 + +endif + +pullpc +; Loads the animated tiles after most of the transition gfx changes take place. +NewOverworld_FinishTransGfx: +{ + PHB : PHK : PLB + + ; The whirlpool code resuses this code so don't do any of the custom stuff if + ; we are in the whirlpool module. + LDA.b $11 : CMP.b #$2E : BEQ .whirpool + LDA.w TransGFXModuleFrame : BNE .notFirstFrame + JSR.w CheckForChangeGraphicsTransitionLoad + + ; Prep the new static gfx tile sets. + JSR.w LoadTransMainGFX + + ; A check to see if we need to Prep the GFX in the buffer. + ; Saves about a frame. + LDA.b $04 : BEQ .dontPrep + JSR.w PrepTransMainGFX + + .dontPrep + + ; Move on to next submodule. + INC.b $11 + + .notFirstFrame + + LDA.b #$08 : STA.b $06 + + JSR.w BlockGFXCheck + + ; If we haven't made it to frame 8, don't move on yet. + CPY.b #$08 : BCC .return + ; Move on to next submodule. + INC.b $11 + + .return + + PLB + + RTL + + .whirpool + + ; On the "second" frame, upload the animated tiles. + LDA.b $B0 : CMP.b #$08 : BEQ .loadAnimated + LDA.w TransGFXModuleFrame : BNE .notFirstFrame2 + JSR.w CheckForChangeGraphicsTransitionLoad + + ; Prep the new static gfx tile sets. + JSR.w LoadTransMainGFX + + ; A check to see if we need to Prep the GFX in the buffer. + ; Saves about a frame. + LDA.b $04 : BEQ .dontPrep2 + JSR.w PrepTransMainGFX + + .dontPrep2 + + .notFirstFrame2 + + LDA.b #$08 : STA.b $06 + + JSR.w BlockGFXCheck + + ; If we haven't made it to frame 8, don't move on yet. + CPY.b #$08 : BCS .MoveOn + ; Don't move on to next submodule yet. + DEC.b $B0 + + .MoveOn + + ; Move on to next submodule. This will get undone by the vanilla + ; whirlpool code because it shared the function with the OW + ; transition code which uses $11 as its module index but the + ; whirlpool uses $B0 instead. + INC.b $11 + + PLB + + RTL + + .loadAnimated + + ; The NMI_DoUpdates function is never actually run while the whirpool is + ; happening. So we need to upload the animated tiles manually here while + ; the screen is still blue to cover up the change. + + ; Set the bank for the source to $7E. + LDA.b #$7E : STA.w DMA.0_SourceAddrBank + + REP #$20 + + LDA.w #DMA.0_TransferParameters : STA.w SNES.VRAMAddrReadWriteLow + + LDA.w $0ADC : STA.w DMA.0_SourceAddrOffsetLow + + ; Set the target VRAM address. + LDA.w $0134 : STA.w SNES.VRAMAddrReadWriteLow + + ; Transfer #$400 = 4 * 256 = 1024 bytes = 1 Kbyte + LDA.w #$0400 : STA.w DMA.0_TransferSizeLow + + SEP #$20 + + ; Activate line 0. + LDA.b #$01 : STA.w SNES.DMAChannelEnable + + ; Move on to next submodule. This will get undone by the vanilla + ; whirlpool code because it shared the function with the OW + ; transition code which uses $11 as its module index but the + ; whirlpool uses $B0 instead. + INC.b $11 + + PLB + + RTL +} + +BlockGFXCheck: +{ + REP #$30 + + ; $0E = $8A * 8 + LDA.b $8A : AND.w #$00FF : ASL #3 : STA.b $0E + + STZ.b $02 + STZ.b $04 + STZ.w NewNMITarget1 + STZ.w NewNMISource1 + STZ.w NewNMICount1 + STZ.w NewNMITarget2 + STZ.w NewNMISource2 + STZ.w NewNMICount2 + + SEP #$30 + + LDY.w TransGFXModuleFrame + .loop + + ; Get the sheet that needs to be loaded. + LDA.w .sheetLoadOrder, Y : STA $02 + + REP #$30 + AND.w #$00FF : CLC : ADC.b $0E : TAX + SEP #$20 + LDA.l Pool_OWGFXGroupTable_sheet0, X : STA.b $00 + SEP #$10 + + ; Check if it is #$FF. + CMP.b #$FF : BEQ .dontLoadThisSheet + ; Get the sheet that is currently loaded and check if the sheets + ; are the same. + LDX.b $02 + LDA.w TransGFXModule_PriorSheets, X : CMP.b $00 : BEQ .dontLoadThisSheet + LDA.b $00 : STA.w TransGFXModule_PriorSheets, X + + ; Trigger NMI module: NMI_DoNothing which we replaced with + ; NMI_UpdateChr_Bg2HalfAndAnimated down below. + LDA.b #$06 : STA.b $17 + STA.w $0710 + + TXA : ASL : TAX + + REP #$20 + + LDA.b $04 : BNE .second + LDA.w .sheetTarget, X : STA.w NewNMITarget1 + LDA.w .sheetSource, X : STA.w NewNMISource1 + LDA.w .sheetCount, X : STA.w NewNMICount1 + + SEP #$20 + + INC.b $04 + + BRA .first + + .second + + LDA.w .sheetTarget, X : STA.w NewNMITarget2 + LDA.w .sheetSource, X : STA.w NewNMISource2 + LDA.w .sheetCount, X : STA.w NewNMICount2 + + SEP #$20 + + INC.b $04 + + INY + + BRA .twoReady + + .first + .dontLoadThisSheet + INY : CPY.b $06 : BCC .loop + + .twoReady + + STY.w TransGFXModuleFrame + + RTS + + .sheetLoadOrder + db $03, $04, $05, $06, $00, $01, $02, $07 + + .sheetTarget + dw #$2000, #$2400, #$2800, #$2C00, #$3000, #$3400, #$3800, #$3E00 + + .sheetSource + dw #$2000, #$2800, #$3000, #$0000, #$0800, #$1000, #$1800, #$3C00 + + .sheetCount + dw #$0800, #$0800, #$0800, #$0800, #$0800, #$0800, #$0800, #$0400 + + ; Only copy the latter half of the sheet to prevent the animated tiles + ; from flickering on transition. +} + +CheckForChangeGraphicsTransitionLoad: +{ + ; Are we currently in a mosaic? + LDA.b $11 : CMP.b #$0F : BEQ .mosaic + ; Are we entering a special area? + CMP.b #$1A : BEQ .mosaic + ; Are we leaving a special area? + CMP.b #$26 : BEQ .mosaic + ; Just a normal transition, Not a mosaic. + LDA.l Pool_EnableAnimated : BEQ .dontUpdateAnimated1 + ; Check to see if we need to update the animated tiles + ; by checking what was previously loaded. + JSL.l ReadAnimatedTable : CMP.w AnimatedTileGFXSet : BEQ .dontUpdateAnimated1 + STA.w AnimatedTileGFXSet + DEC : TAY + + ; This forces the game toupdate the animated tiles + ; when going from one area to another. + JSL.l DecompOwAnimatedTiles + + .dontUpdateAnimated1 + + LDA.w Pool_EnableMainPalette : BEQ .dontUpdateMain1 + ; Check to see if we need to update the main palette by + ; checking what was previously loaded. + LDX.b $8A + LDA.w Pool_MainPaletteTable, X : CMP.w $0AB3 : BEQ .dontUpdateMain1 + STA.w $0AB3 + + ; Run the modified routine that loads the buffer + ; and normal color ram. + JSL.l Palette_OverworldBgMain2 + + .dontUpdateMain1 + + LDA.w Pool_EnableBGColor : BEQ .dontUpdateBGColor1 + REP #$30 ; Set A, X, and Y in 16bit mode. + + ; Get area code and times it by 2. + LDA.b $8A : ASL : TAX + + ; Where ZS saves the array of palettes + LDA.w Pool_BGColorTable, X + STA.l $7EC300 : STA.l $7EC500 + STA.l $7EC540 : STA.l $7EC340 + + SEP #$30 ; Set A, X, and Y in 8bit mode. + + ; Don't update the CRAM until later when the overlays are + ; loaded so that way the BG overlays have a chance to hide + ; the cracks. + ;INC.b $15 + + .dontUpdateBGColor1 + + RTS + + .mosaic + + ; Check to see if we need to update the animated tiles by checking what + ; was previously loaded. + JSL.l ReadAnimatedTable : CMP.w AnimatedTileGFXSet : BEQ .dontUpdateAnimated2 + STA.w AnimatedTileGFXSet + DEC : TAY + + ; This forces the game to update the animated tiles when going + ; from one area to another. + JSL.l DecompOwAnimatedTiles + + .dontUpdateAnimated2 + + ; Check to see if we need to update the main palette by checking + ; what was previously loaded. + LDX.b $8A + LDA.w Pool_MainPaletteTable, X : CMP.w $0AB3 : BEQ .dontUpdateMain2 + STA.w $0AB3 + + ; Run the vanilla routine that only loads the buffer. + JSL.l Palette_OverworldBgMain + + .dontUpdateMain2 + + REP #$30 ; Set A, X, and Y in 16bit mode. + + ; $0181 is the exit room number used for getting into the under the bridge + ; area. + LDA.b $A0 : CMP.w #$0181 : BNE .notBridge + LDA.w Pool_BGColorTable_Bridge + + BRA .storeColor + + .notBridge + + ; Get area code and times it by 2. + LDA.b $8A : ASL : TAX + + ; Where ZS saves the array of palettes. + LDA.w Pool_BGColorTable, X + + .storeColor + + ; Set transparent color. only set the buffer so it fades in right + ; during mosaic transition. + STA.l $7EC300 : STA.l $7EC340 + + ; Write the fixed color. + LDX.w #$4020 : STX.b $9C + LDX.w #$8040 : STX.b $9D + + LDX.w #$4F33 + LDY.w #$894F + + ; Change the fixed color depending on our sub screen overlay. + ; Lost woods and skull woods. + LDA.b $8A : ASL : TAX + LDA.w Pool_OverlayTable, X : CMP.w #$009D : BEQ .noSpecialColor + CMP.w #$0040 : BEQ .noSpecialColor + ; Pyramid area. + CMP.w #$0096 : BEQ .specialColor + LDX.w #$4C26 + LDY.w #$8C4C + + ; LW death mountain. + CMP.w #$0095 : BEQ .specialColor + LDX.w #$4A26 + LDY.w #$874A + + ; DW death mountain. + CMP.w #$009C : BEQ .specialColor + BRA .noSpecialColor + + .specialColor + + ; Write the fixed color. + STX.b $9C + STY.b $9D + + .noSpecialColor + + SEP #$30 ; Set A, X, and Y in 8bit mode. + + ; Don't update the CRAM until later when the overlays are loaded so + ; that way the BG overlays have a chance to hide the cracks. + ;INC.b $15 + + ; PLACE CUSTOM GFX LOAD HERE! + ;JML.l CheckForChangeGraphicsTransitionLoadCastle + + CheckForChangeGraphicsTransitionLoadRetrun: + + RTS + + SkipOverworld_FinishTransGfx_firstHalf: + + ; Move on to next submodule. + INC.b $11 + + RTS +} + +; The following 2 functions are copied from the bank 0x1B but they only +; copied colors into the buffer so these copy colors into the normal ram as +; well. +Palette_OverworldBgMain2: +{ + REP #$21 + + LDA.w $0AB3 : ASL : TAX + LDA.l PaletteIDtoOffset_OW_Main, X : ADC.w #PaletteData_owmain : STA.b $00 + + REP #$10 + + ; Target BP2 through BP6 (first halves). + ; Each palette has 7 colors. + ; Load 5 palettes. + LDA.w #$0042 + LDX.w #$0006 + LDY.w #$0004 + JSR.w Palette_MultiLoad_NonBuffer + + SEP #$30 + + RTL +} + +; Description: Generally used to load multiple palettes for BGs. +; Upon close inspection, one sees that this algorithm is almost the same as +; the last subroutine. +; Name = Palette_MultiLoad(A, X, Y). + +; Parameters: X = (number of colors in the palette - 1). +; A = offset to add to $7EC300, in other words, where to write +; in palette memory. +; Y = (number of palettes to load - 1). +Palette_MultiLoad_NonBuffer: +{ + STA.b $04 ; Save the values for future reference. + STX.b $06 + STY.b $08 + + ; The absolute address at $00 was planted in the calling function. This + ; value is the bank #$1B ( => D in Rom) The address is found from $0AB6 and + ; of course, store it at $02. + LDA.w #$001B : STA.b $02 + + .nextPalette + ; $0AA8 + A parameter will be the X value. + LDA.w $0AA8 : CLC : ADC.b $04 : TAX + + LDY.b $06 ; Tell me how long the palette is. + + .copyColors + ; We're loading A from the address set up in the calling function. + LDA.b [$00] : STA.l $7EC300, X + STA.l $7EC500, X + + ; Increment the absolute portion of the address by two, and + ; decrease the color count by one. + INC.b $00 : INC.b $00 + + INX : INX + + ; So basically loop (Y+1) times, taking (Y * 2 bytes) to $7EC300, X. + DEY : BPL .copyColors + + ; This technique bumps us up to the next 4bpp (16 color) palette. + LDA.b $04 : CLC : ADC.w #$0020 : STA.b $04 + + ; Decrease the number of palettes we have to load. + DEC.b $08 + + BPL .nextPalette + + ; We're done loading palettes. + + RTS +} + +LoadTransMainGFX: +{ + ; Setup the decompression buffer address. + ; $00[3] = $7E4000 + STZ.b $00 + LDA.b #$40 : STA.b $01 + LDA.b #$7E : STA.b $02 + + STZ.b $04 + + REP #$30 + ; $0E = $8A * 8 + LDA.b $8A : AND.w #$00FF : ASL #3 : STA.b $0E + SEP #$20 + + ; Sheet 0 (static 0) + LDX.b $0E + LDA.w Pool_OWGFXGroupTable_sheet0, X : CMP.b #$FF : BEQ .noBgGfxChange0 + SEP #$10 + CMP.w TransGFXModule_PriorSheets+0 : BEQ .noBgGfxChange0 + TAY + + INC.b $04 + + JSL.l Decomp_bg_variableLONG + + .noBgGfxChange0 + + SEP #$10 + + ; Increment buffer address by 0x0600. + LDA.b $01 : CLC : ADC.b #$06 : STA.b $01 + REP #$10 + + ; Sheet 1 (static 1) + LDX.b $0E + LDA.w Pool_OWGFXGroupTable_sheet1, X : CMP.b #$FF : BEQ .noBgGfxChange1 + SEP #$10 + CMP.w TransGFXModule_PriorSheets+1 : BEQ .noBgGfxChange1 + TAY + + INC.b $04 + + JSL.l Decomp_bg_variableLONG + + .noBgGfxChange1 + + SEP #$10 + + ; Increment buffer address by 0x0600. + LDA.b $01 : CLC : ADC.b #$06 : STA.b $01 + REP #$10 + + ; Sheet 2 (static 2) + LDX.b $0E + LDA.w Pool_OWGFXGroupTable_sheet2, X : CMP.b #$FF : BEQ .noBgGfxChange2 + SEP #$10 + CMP.w TransGFXModule_PriorSheets+2 : BEQ .noBgGfxChange2 + TAY + + INC.b $04 + + JSL.l Decomp_bg_variableLONG + + .noBgGfxChange2 + + SEP #$10 + + ; Increment buffer address by 0x0600. + LDA.b $01 : CLC : ADC.b #$06 : STA.b $01 + REP #$10 + + ; Sheet 7 (animated) + LDX.b $0E + LDA.w Pool_OWGFXGroupTable_sheet7, X : CMP.b #$FF : BEQ .noBgGfxChange7 + SEP #$10 + CMP.w TransGFXModule_PriorSheets+7 : BEQ .noBgGfxChange7 + TAY + + INC.b $04 + + JSL.l Decomp_bg_variableLONG + + .noBgGfxChange7 + + RTS +} + +; Prepares the transition graphics to be transferred to VRAM during NMI. +; This could occur either during this frame or any subsequent frame. +PrepTransMainGFX: +{ + ; Set bank for source address. + LDA.b #$7E : STA.b $02 + STA.b $05 + + REP #$31 + + ; Source address is $7E4000, number of tiles is 0x40, + ; base address is $7F0000. + LDX.w #$2000 + LDY.w #$0040 + LDA.w #$4000 + + ; The first graphics pack always uses the higher 8 palette values. + JSL.l Do3To4High16BitLONG + + ; Number of tiles for next set is 0xC0. + LDY.w #$00C0 + LDA.b $03 + JSL.l Do3To4Low16BitLONG + + SEP #$30 + + RTS +} +pushpc + +; ============================================================================== + +if !Func0ABC5A == 1 + +org $0ABC5A ; $053C5A + JSL.l CheckForChangeGraphicsNormalLoad + +warnpc $0ABC5E ; $053C5E + +else + +org $0ABC5A ; $053C5A +db $22, $9B, $E1, $00 + +endif + +pullpc +; Loads the animated tiles after the overworld map is closed. +CheckForChangeGraphicsNormalLoad: +{ + PHB : PHK : PLB + + JSL.l InitTilesets ; Replaced code. + + JSL.l ReadAnimatedTable : STA.w AnimatedTileGFXSet + DEC : TAY + + ; This function is not needed here and is handled somewhere else. This + ; forces the game to update the animated tiles when going from one area to + ; another. + ;JSL.l DecompOwAnimatedTiles + + ; PLACE CUSTOM GFX LOAD HERE! + ;JSL.l CheckForChangeGraphicsNormalLoadCastle + + ; TODO: Instead of the place custom gfx load here, pre-allocate a function. + ; Some free space + ; ZSOW_LoadCustomGraphics: + ; Maybe register push/pops or leave that to users + ; User defined custom graphics code + ; RTL + + PLB + + RTL +} +pushpc + +; ============================================================================== + +if !Func0AB8F5 == 1 + +; Loads different animated tiles when returning from bird travel. +org $0AB8F5 ; $0538F5 +BirdTravel_LoadTargetArea_Interrupt: +{ + JSL.l ReadAnimatedTable : STA.w AnimatedTileGFXSet + DEC : TAY + + ; From this point on it is the vanilla function. + JSL.l DecompOwAnimatedTiles + JSL.l Overworld_SetFixedColorAndScroll + + STZ.w $0AA9 + STZ.w $0AB2 + + JSL.l InitTilesets + + ; Move to the next submodule (BirdTravel_LoadAmbientOverlay) the next frame. + INC.w $0200 + + STZ.b $B2 + + JSL.l Overworld_ReloadSubscreenOverlayAndAdvance + + ; Play sound effect indicating we're coming out of map mode. + LDA.b #$10 : STA.w $012F + + JSL.l LoadAmbientSound + + ; If it's a different music track than was playing where we came from, + ; simply change to it (as opposed to setting volume back to full). + LDA.l $7F5B00, X : AND.b #$0F : TAX : CPX.w $0130 : BNE .different_music + ; Otherwise, just set the volume back to full. + LDX.b #$F3 + + .different_music + + STX.w $012C + + ; PLACE CUSTOM GFX LOAD HERE! + ;JSL.l CheckForChangeGraphicsNormalLoadCastle + + RTL +} +warnpc $0AB948 ; $053948 + +else + +org $0AB8F5 ; $0538F5 +db $A0, $58, $A5, $8A, $29, $BF, $C9, $03 +db $F0, $0A, $C9, $05, $F0, $06, $C9, $07 +db $F0, $02, $A0, $5A, $22, $94, $D3, $00 +db $22, $70, $FE, $0B, $9C, $A9, $0A, $9C +db $B2, $0A, $22, $9B, $E1, $00, $EE, $00 +db $02, $64, $B2, $22, $F4, $B1, $02, $A9 +db $10, $8D, $2F, $01, $A6, $8A, $BF, $00 +db $5B, $7F, $4A, $4A, $4A, $4A, $8D, $2D +db $01, $BF, $00, $5B, $7F, $29, $0F, $AA +db $EC, $30, $01, $D0, $02, $A2, $F3, $8E +db $2C, $01, $6B + +endif + +pullpc +LoadAmbientSound: +{ + PHB : PHK : PLB + + ; Reset the ambient sound effect to what it was. + LDX.b $8A + LDA.l $7F5B00, X : LSR #4 : STA.w $012D + + ; Check if we need to stop the rain sound in the misery mire. + LDA.w Pool_EnableRainMireEvent : BEQ .disableRainSound + LDA.b $8A : CMP.b #$70 : BNE .disableRainSound + ; Has Misery Mire been triggered yet? + LDA.l $7EF2F0 : AND.b #$20 : BNE .disableRainSound + LDA.b #$01 : STA.w $012D + + .disableRainSound + + PLB + + RTL +} +pushpc + +; ============================================================================== + +if !Func0BFEB6 == 1 + +; There is a STZ.b $1D here in vanilla and I'm not sure why. It might have been +; to hide something but then just gets set a second later. So all this does in +; function is give the game a chance to hit NMI and flash a transparent color +; on screen when while warping from and area that has a different transparent +; color set. The whole function is NOT overwritten so that the default BG color +; values that get set here will retain their positions in ROM and can be changed +; in ZS. +org $0BFE70 ; $05FE70 + NOP : NOP + +; Loads different special transparent colors and overlay speeds based on the +; overlay during transition and under other certain cases. TODO: Exact cases need +; to be investigated. When leaving dungeon. +org $0BFEB6 ; $05FEB6 +Overworld_LoadBGColorAndSubscreenOverlay: +{ + JSL.l ReplaceBGColor + + ; Set fixed color to neutral. + LDA.w #$4020 : STA.b $9C + LDA.w #$8040 : STA.b $9D + + ; Check if we need to load the rain in the misery mire. + LDA.l Pool_EnableRainMireEvent : BEQ .notMire + LDA.b $8A : CMP.w #$0070 : BNE .notMire + ; Has Misery Mire been triggered yet? + LDA.l $7EF2F0 : AND.w #$0020 : BNE .notMire + JMP.w .subscreenOnAndReturn + + .notMire + + JSL.l ReadOverlayArray + + ; Check for misery mire. + CMP.w #$009F : BNE .notRain + JMP.w .subscreenOnAndReturn + + .notRain + + ; Change the fixed color depending on our sub screen overlay. + ; Check for lost woods?, skull woods, and pyramid area. + CMP.w #$009D : BEQ .noCustomFixedColor + CMP.w #$0096 : BEQ .noCustomFixedColor + LDX.w #$4C26 + LDY.w #$8C4C + + ; Check for LW Death mountain. + CMP.w #$0095 : BEQ .setCustomFixedColor + LDX.w #$4A26 + LDY.w #$874A + + ; Check for DW Death mountain. (not turtle rock?). + CMP.w #$009C : BEQ .setCustomFixedColor + SEP #$30 ; Set A, X, and Y in 8bit mode. + + ; Don't set the subscreen during a warp to hide the transparent + ; color change. This will get set properly later in the warp + ; but not everywhere else. + LDA.b $11 : CMP.b #$23 : BEQ .inWarp + STZ.b $1D + + .inWarp + + ; Update CGRAM this frame. + INC.b $15 + + RTL + + .setCustomFixedColor + + ; Set the fixed color addition color values. + STX.b $9C + STY.b $9D + + .noCustomFixedColor + + LDA.b $11 : AND.w #$00FF : CMP.w #$0004 : BEQ .BRANCH_11 + ; Make sure BG2 and BG1 Y scroll values are synchronized. + ; Same for X scroll. + LDA.b $E8 : STA.b $E6 + LDA.b $E2 : STA.b $E0 + + ; Just because I need a bit more space. + JSL.l ReadOverlayArray + + ; Are we at Hyrule Castle or Pyramid of Power? + CMP.w #$0096 : BNE .subscreenOnAndReturn + JSL.l SpecialBgHorizOffsetAdjustment + + BRA .subscreenOnAndReturn + + .BRANCH_11 + + ; Check for the pyramid BG. + JSL.l ReadOverlayArray : CMP.w #$0096 : BNE .subscreenOnAndReturn + ; Synchronize Y scrolls on BG0 and BG1. Same for X scrolls. + LDA.b $E8 : STA.b $E6 + LDA.b $E2 : STA.b $E0 + + LDA.w $0410 : AND.w #$00FF : CMP.w #$0008 : BEQ .BRANCH_12 + ; Handles scroll for special areas maybe? + LDA.w #$0838 : STA.b $E0 + + .BRANCH_12 + + LDA.w #$06C0 : STA.b $E6 + + .subscreenOnAndReturn + + SEP #$30 ; Set A, X, and Y in 8bit mode. + + ; Put BG0 on the subscreen. + LDA.b #$01 : STA.b $1D + + ; Update palette. + INC.b $15 + + RTL +} +warnpc $0BFFA8 ; $05FFA8 + +else + +org $0BFE70 ; $05FE70 +STZ.b $1D + +org $0BFEB6 ; $05FEB6 +db $8F, $00, $C5, $7E, $8F, $00, $C3, $7E +db $8F, $40, $C5, $7E, $8F, $40, $C3, $7E +db $A9, $20, $40, $85, $9C, $A9, $40, $80 +db $85, $9D, $A5, $8A, $F0, $40, $C9, $70 +db $00, $D0, $03, $4C, $9D, $FF, $C9, $40 +db $00, $F0, $33, $C9, $5B, $00, $F0, $2E +db $A2, $26, $4C, $A0, $4C, $8C, $C9, $03 +db $00, $F0, $1F, $C9, $05, $00, $F0, $1A +db $C9, $07, $00, $F0, $15, $A2, $26, $4A +db $A0, $4A, $87, $C9, $43, $00, $F0, $0A +db $C9, $45, $00, $F0, $05, $E2, $30, $E6 +db $15, $6B, $86, $9C, $84, $9D, $A5, $11 +db $29, $FF, $00, $C9, $04, $00, $F0, $58 +db $A5, $E8, $85, $E6, $A5, $E2, $85, $E0 +db $A5, $8A, $29, $3F, $00, $C9, $1B, $00 +db $D0, $6D, $A5, $E2, $38, $E9, $78, $07 +db $4A, $A8, $29, $00, $40, $F0, $05, $98 +db $09, $00, $80, $A8, $84, $00, $A5, $E2 +db $38, $E5, $00, $85, $E0, $A5, $E6, $C9 +db $C0, $06, $90, $17, $38, $E9, $00, $06 +db $29, $FF, $03, $C9, $80, $01, $B0, $06 +db $4A, $09, $00, $06, $80, $0E, $A9, $C0 +db $06, $80, $09, $A5, $E6, $29, $FF, $00 +db $4A, $09, $00, $06, $85, $E6, $80, $27 +db $A5, $8A, $29, $3F, $00, $C9, $1B, $00 +db $D0, $1D, $A5, $E8, $85, $E6, $A5, $E2 +db $85, $E0, $AD, $10, $04, $29, $FF, $00 +db $C9, $08, $00, $F0, $05, $A9, $38, $08 +db $85, $E0, $A9, $C0, $06, $85, $E6, $E2 +db $20, $A9, $01, $85, $1D, $E2, $30, $E6 +db $15, $6B + +endif + +pullpc +ReplaceBGColor: +{ + PHB : PHK : PLB + + SEP #$20 ; Set A in 8bit mode. + + LDA.w Pool_EnableBGColor : BNE .custom + REP #$20 ; Set A in 16bit mode. + + PLB + + RTL + + .custom + + REP #$20 ; Set A in 16bit mode. + + ; Get area code and times it by 2. Get the color. + LDA.b $8A : ASL : TAX + LDA.w Pool_BGColorTable, X : PHA + + SEP #$20 ; Set A in 8bit mode. + + ; TODO: Pretty sure this is needed. Just keep an eye out for it. + ; Set the buffer color when exiting to the OW to prevent a bug when using + ; the map in an area with a subscreen overlay. + LDA.b $10 : CMP.b #$08 : BEQ .setBuffer + CMP.b #$0A : BEQ .setBuffer + ; Set the buffer color during warps. + LDA.b $11 : CMP.b #$23 : BNE .notWarp + .setBuffer + + REP #$20 ; Set A in 16bit mode. + + ; Set the BG color buffer. + PLA : STA.l $7EC300 + STA.l $7EC340 + + BRA .skipActualColor + + .notWarp + + REP #$20 ; Set A in 16bit mode. + + ; Set the BG color. + PLA : STA.l $7EC500 + STA.l $7EC540 + + .skipActualColor + + PLB + + RTL +} + +; This sets the initial scroll offsets for the pyramid BG. It seems highly +; hardcoded and overly complicated. it could probably be changed to just a +; standard clamp function to keep it from being too high or too low. +SpecialBgHorizOffsetAdjustment: +{ + LDA.b $E2 : SEC : SBC.w #$0778 : LSR : TAY : AND.w #$4000 : BEQ .BRANCH_7 + TYA : ORA.w #$8000 : TAY + + .BRANCH_7 + + STY.b $00 + + LDA.b $E2 : SEC : SBC.b $00 : STA.b $E0 + + LDA.b $E6 : CMP.w #$06C0 : BCC .BRANCH_9 + SEC : SBC.w #$0600 : AND.w #$03FF : CMP.w #$0180 : BCS .BRANCH_8 + LSR : ORA.w #$0600 + + BRA .BRANCH_10 + + .BRANCH_8 + + LDA.w #$06C0 + + BRA .BRANCH_10 + + .BRANCH_9 + + LDA.b $E6 : AND.w #$00FF : LSR : ORA.w #$0600 + + .BRANCH_10 + + ; Set BG1 vertical scroll. + STA.b $E6 + + RTL +} +pushpc + +; ============================================================================== + +if !Func0ED627 == 1 + +; Loads the transparent color during mirror\warp, entering/leaving special +; overworlds, exiting dungeons, loading end credits overworld scenes, whirlpool +; warps, and bird travel. +org $0ED627 ; $075627 + JML.l InitColorLoad2 + NOP + +warnpc $0ED62C ; $07562C + +else + +org $0ED627 ; $075627 +db $A5, $8A, $C9, $80, $00 + +endif + +org $0ED652 ; $075652 +InitColorLoad2_Return: + +pullpc + +InitColorLoad2: +{ + PHB : PHK : PLB + + ; $0181 is the exit room number used for getting into the under the bridge + ; area. + LDA.b $A0 : CMP.w #$0181 : BNE .notBridge + LDA.w Pool_BGColorTable_Bridge + + BRA .storeColor + + .notBridge + + ; Get area code and times it by 2. + LDA.b $8A : ASL : TAX + + ; Get the color. + LDA.w Pool_BGColorTable, X + + .storeColor + + ; Set transparent color. + STA.l $7EC300 + STA.l $7EC340 + + ; TODO: Based on the conditions as explained above, double check that this is + ; not needed for any of them. + ;STA.l $7EC500 + ;STA.l $7EC540 + + INC.b $15 + + PLB + + JML.l InitColorLoad2_Return +} + +pushpc + +; ============================================================================== + +if !Func0ED8AE == 1 + +; Resets the area special color after the screen flashes. +org $0ED8AE ; $0758AE +Palette_RestoreFixedColor_Interrupt: +{ + LDA.b $1B : BNE .noSpecialColor + REP #$30 ; Set A, X, and Y in 16bit mode. + + LDX.w #$4020 : STX.b $9C + LDX.w #$8040 : STX.b $9D + + LDX.w #$4F33 + LDY.w #$894F + + ; Change the fixed color depending on our sub screen overlay. + ; Lost woods and skull woods. + JSL.l ReadOverlayArray : CMP.w #$009D : BEQ .noSpecialColor + CMP.w #$0040 : BEQ .noSpecialColor + ; Pyramid area. + CMP.w #$0096 : BEQ .specialColor + LDX.w #$4C26 + LDY.w #$8C4C + + ; LW death mountain. + CMP.w #$0095 : BEQ .specialColor + LDX.w #$4A26 + LDY.w #$874A + + ; DW death mountain. + CMP.w #$009C : BEQ .specialColor + BRA .noSpecialColor + + .specialColor + + STX.b $9C + STY.b $9D + + .noSpecialColor + + SEP #$30 ; Set A, X, and Y in 8bit mode. + + RTL +} +warnpc $0ED8FB ; $0758FB + +else + +org $0ED8AE ; $0758AE +db $A5, $1B, $D0, $46, $C2, $10, $A2, $20 +db $40, $86, $9C, $A2, $40, $80, $86, $9D +db $A2, $33, $4F, $A0, $4F, $89, $A5, $8A +db $F0, $30, $C9, $40, $F0, $2C, $C9, $5B +db $F0, $24, $A2, $26, $4C, $A0, $4C, $8C +db $C9, $03, $F0, $1A, $C9, $05, $F0, $16 +db $C9, $07, $F0, $12, $A2, $26, $4A, $A0 +db $4A, $87, $C9, $43, $F0, $08, $C9, $45 +db $F0, $04, $C9, $47, $D0, $04, $86, $9C +db $84, $9D, $E2, $10, $6B + +endif + +; ============================================================================== + +if !Func00D585 == 1 + +; Interrupts the vanilla LoadTransAuxGFX function +org $00D673 ; $005673 + JML.l NewLoadTransAuxGFX + +warnpc $00D677 ; $005677 + +org $00D677 ; $005677 +LoadTransAuxGFX_return: + +org $008C8A ; $000C8A + dw NMI_UpdateChr_Bg2HalfAndAnimated + +warnpc $008C8C ; $000C8C + +org $02ABB4 ; $012BB4 + JSL.l NewPrepTransAuxGFX + +warnpc $02ABB8 ; $012BB8 + +; Replaces the UNREACHABLE_00D585 which is unused. +org $00D585 ; $005585 +Decomp_bg_variableLONG: +{ + PHB : PHK : PLB + + JSR.w Decomp_bg_variable + + PLB + + RTL +} + +Do3To4Low16BitLONG: +{ + PHB : PHK : PLB + + JSR.w Do3To4Low16Bit + + PLB + + RTL +} + +Do3To4High16BitLONG: +{ + PHB : PHK : PLB + + JSR.w Do3To4High16Bit + + PLB + + RTL +} + +NMI_UpdateChr_Bg2HalfAndAnimated: +{ + JSL.l NMI_UpdateChr_Bg2HalfAndAnimatedLONG + + RTS +} + +warnpc $00D5CB ; $0055CB + +else + +org $00D673 ; $005673 +db $A9, $60, $85, $01 + +org $008C8A ; $000C8A +db $4B, $8E + +org $00D585 ; $005585 +db $A0, $08, $00, $84, $0E, $85, $00, $18 +db $69, $10, $00, $85, $03, $A0, $07, $00 +db $A7, $00, $9F, $00, $90, $7E, $E6, $00 +db $E6, $00, $A7, $03, $29, $FF, $00, $9F +db $10, $90, $7E, $E6, $03, $E8, $E8, $88 +db $10, $E6, $8A, $18, $69, $10, $00, $AA +db $A5, $03, $29, $78, $00, $D0, $08, $A5 +db $03, $18, $69, $80, $01, $85, $03, $A5 +db $03, $C6, $0E, $D0, $C0, $60 + +endif + +pullpc +NewLoadTransAuxGFX: +{ + PHB : PHK : PLB + + LDA.b $1B : BNE .indoors + LDA.w Pool_EnableTransitionGFXGroupLoad : BNE .notNormalLoad + .indoors + + PLB + + ; Replaced code: + LDA.b #$60 : STA.b $01 + + ; Return to regular code. + JML.l LoadTransAuxGFX_return + + .notNormalLoad + + ; Setup the decompression buffer address. + ; $00[3] = $7E6000 + STZ.b $00 + LDA.b #$60 : STA.b $01 + LDA.b #$7E : STA.b $02 + + STZ.b $04 + + REP #$30 + ; $0E = $8A * 8 + LDA.b $8A : AND.w #$00FF : ASL #3 : STA.b $0E + SEP #$20 + + ; Sheet 3 (variable 0) + LDX.b $0E + LDA.w Pool_OWGFXGroupTable_sheet3, X : CMP.b #$FF : BEQ .noBgGfxChange3 + SEP #$10 + CMP.w TransGFXModule_PriorSheets+3 : BEQ .noBgGfxChange3 + TAY + + INC.b $04 + + JSL.l Decomp_bg_variableLONG + + .noBgGfxChange3 + + SEP #$10 + ; Increment buffer address by 0x0600. + LDA.b $01 : CLC : ADC.b #$06 : STA.b $01 + REP #$10 + + ; Sheet 4 (variable 1) + LDX.b $0E + LDA.w Pool_OWGFXGroupTable_sheet4, X : CMP.b #$FF : BEQ .noBgGfxChange4 + SEP #$10 + CMP.w TransGFXModule_PriorSheets+4 : BEQ .noBgGfxChange4 + TAY + + INC.b $04 + + JSL.l Decomp_bg_variableLONG + + .noBgGfxChange4 + + SEP #$10 + ; Increment buffer address by 0x0600. + LDA.b $01 : CLC : ADC.b #$06 : STA.b $01 + REP #$10 + + ; Sheet 5 (variable 2) + LDX.b $0E + LDA.w Pool_OWGFXGroupTable_sheet5, X : CMP.b #$FF : BEQ .noBgGfxChange5 + SEP #$10 + CMP.w TransGFXModule_PriorSheets+5 : BEQ .noBgGfxChange5 + TAY + + INC.b $04 + + JSL.l Decomp_bg_variableLONG + + .noBgGfxChange5 + + SEP #$10 + ; Increment buffer address by 0x0600. + LDA.b $01 : CLC : ADC.b #$06 : STA.b $01 + REP #$10 + + ; Sheet 6 (variable 3) + LDX.b $0E + LDA.w Pool_OWGFXGroupTable_sheet6, X : CMP.b #$FF : BEQ .noBgGfxChange6 + SEP #$10 + CMP.w TransGFXModule_PriorSheets+6 : BEQ .noBgGfxChange6 + TAY + + INC.b $04 + + JSL.l Decomp_bg_variableLONG + + .noBgGfxChange6 + + SEP #$10 + ; Increment buffer address by 0x0600. + LDA.b $01 : CLC : ADC.b #$06 : STA.b $01 + REP #$10 + + STZ.w TransGFXModuleFrame + + PLB + + ; $005706 Return to regular code. + JML.l LoadTransAuxGFX_sprite_continue +} + +NMI_UpdateChr_Bg2HalfAndAnimatedLONG: +{ + PHB : PHK : PLB + + REP #$20 + + ; Increment on writes to SNES.VRAMDataWriteHigh. + LDY.b #$80 : STY.w SNES.VRAMAddrIncrementVal + + ; Target is SNES.VRAMDataWriteLow, write two registers once + ; (SNES.VRAMDataWriteLow / SNES.VRAMDataWriteHigh). + LDA.w #$1801 : STA.w DMA.0_TransferParameters + + LDA.w NewNMICount1 : BEQ .skipFirst + ; Sheet 1 + ; Target address + LDA.w NewNMITarget1 : STA.w SNES.VRAMAddrReadWriteLow + + ; Source address + LDA.w NewNMISource1 : STA.w DMA.0_SourceAddrOffsetLow + LDY.b #$7F : STY.w DMA.0_SourceAddrBank + + ; Write count + LDA.w NewNMICount1 : STA.w DMA.0_TransferSizeLow + + ; Transfer data on channel 0. + LDY.b #$01 : STY.w SNES.DMAChannelEnable + + .skipFirst + + LDA.w NewNMICount2 : BEQ .skipSecond + ; Sheet 2 + ; Target address + LDA.w NewNMITarget2 : STA.w SNES.VRAMAddrReadWriteLow + + ; Source address + LDA.w NewNMISource2 : STA.w DMA.0_SourceAddrOffsetLow + LDY.b #$7F : STY.w DMA.0_SourceAddrBank + + ; Write count + LDA.w NewNMICount2 : STA.w DMA.0_TransferSizeLow + + ; Transfer data on channel 0. + LDY.b #$01 : STY.w SNES.DMAChannelEnable + + .skipSecond + + SEP #$20 + + STZ.w $0710 + + PLB + + RTL +} + +NewPrepTransAuxGFX: +{ + LDA.b $04 : BEQ .dontPrep + JSL.l PrepTransAuxGFX + + .dontPrep + + RTL +} + +pushpc + +; ============================================================================== + +if !Func00E221 == 1 + +org $00E221 ; $006221 + JML.l InitTilesetsLongCalls + +warnpc $00E225 ; $006225 + +org $00D904 ; $005904 + JML.l AnimateMirrorWarp_DecompressNewTileSetsLongCalls + +warnpc $00D908 ; $005908 + +org $00D97D ; $00597D + JML.l AnimateMirrorWarp_DecompressNewTileSetsLongCalls2 + +warnpc $00D981 ; $005981 + +org $00D9BC ; $0059BC + JML.l AnimateMirrorWarp_DecompressBackgroundsALongCalls + +warnpc $00D9C1 ; $0059C1 + +org $00DA2F ; $005A2F + JML.l AnimateMirrorWarp_DecompressBackgroundsCLongCalls + +else + +org $00E221 ; $006221 +db $AD, $A1, $0A, $29 + +org $00D904 ; $005904 +db $AD, $A1, $0A, $29 + +org $00D97D ; $00597D +db $BF, $EF, $D8, $00 + +org $00D9BC ; $0059BC +db $BF, $F1, $D8, $00 + +org $00DA2F ; $005A2F +db $BF, $F3, $D8, $00 + +endif + +pullpc +InitTilesetsLongCalls: +{ + SEP #$20 + + ; TODO: This will eventually be changed when changing the dungeon GFX. + LDA.b $10 : CMP.b #$0E : BNE .notMapMode + ; Mode 0x0E is the map mode for both the OW and in dungeons. + ; So we need to check where we are here. + LDA.b $1B : BEQ .outdoors + ; Indoors + + .notMapMode + + ; TODO: This will eventually be changed when changing the dungeon GFX. + ; Only trigger the new code when in certain outdoor modes. + ; Modes 0x08 through 0x0B are outdoor related modes. + LDA.b $10 : CMP.b #$08 : BCC .regularLoad + CMP.b #$0C : BCC .outdoors + .regularLoad + + REP #$30 + + ; Replaced code. + LDA.w $0AA1 : AND.w #$00FF + + ; Return to normal code. + JML.l $00E227 ; $006227 + + .outdoors + + PHB : PHK : PLB + + REP #$30 + LDA.b $8A : AND.w #$00FF : ASL #3 : TAX + LDA.b $8A : AND.w #$00C0 : LSR #3 : TAY ; (Area / 8) = LW, DW, or SW *8 + SEP #$20 + + LDA.w Pool_OWGFXGroupTable_sheet0, X : CMP.b #$FF : BNE .notFF0 + LDA.w Pool_DefaultGFXGroups_sheet0, Y + + .notFF0 + + STA.b $0D + STA.w TransGFXModule_PriorSheets+0 + + LDA.w Pool_OWGFXGroupTable_sheet1, X : CMP.b #$FF : BNE .notFF1 + LDA.w Pool_DefaultGFXGroups_sheet1, Y + + .notFF1 + + STA.b $0C + STA.w TransGFXModule_PriorSheets+1 + + LDA.w Pool_OWGFXGroupTable_sheet2, X : CMP.b #$FF : BNE .notFF2 + LDA.w Pool_DefaultGFXGroups_sheet2, Y + + .notFF2 + + STA.b $0B + STA.w TransGFXModule_PriorSheets+2 + + LDA.w Pool_OWGFXGroupTable_sheet3, X : CMP.b #$FF : BNE .notFF3 + LDA.w Pool_DefaultGFXGroups_sheet3, Y + + .notFF3 + + STA.l $7EC2F8 + STA.b $0A + STA.w TransGFXModule_PriorSheets+3 + + LDA.w Pool_OWGFXGroupTable_sheet4, X : CMP.b #$FF : BNE .notFF4 + LDA.w Pool_DefaultGFXGroups_sheet4, Y + + .notFF4 + + STA.l $7EC2F9 + STA.b $09 + STA.w TransGFXModule_PriorSheets+4 + + LDA.w Pool_OWGFXGroupTable_sheet5, X : CMP.b #$FF : BNE .notFF5 + LDA.w Pool_DefaultGFXGroups_sheet5, Y + + .notFF5 + + STA.l $7EC2FA + STA.b $08 + STA.w TransGFXModule_PriorSheets+5 + + LDA.w Pool_OWGFXGroupTable_sheet6, X : CMP.b #$FF : BNE .notFF6 + LDA.w Pool_DefaultGFXGroups_sheet6, Y + + .notFF6 + + STA.l $7EC2FB + STA.b $07 + STA.w TransGFXModule_PriorSheets+6 + + LDA.w Pool_OWGFXGroupTable_sheet7, X : CMP.b #$FF : BNE .notFF7 + LDA.w Pool_DefaultGFXGroups_sheet7, Y + + .notFF7 + + STA.b $06 + STA.w TransGFXModule_PriorSheets+7 + + PLB + + ; $006282 Skip normal sheet load. + JML.l $00E282 +} + +AnimateMirrorWarp_DecompressNewTileSetsLongCalls: +{ + PHB : PHK : PLB + + LDA.b $8A : AND.w #$00FF : ASL #3 : TAX + LDA.b $8A : AND.w #$00C0 : LSR #3 : TAY ; (Area / 8) = LW, DW, or SW *8 + + SEP #$20 + + LDA.w Pool_OWGFXGroupTable_sheet3, X : CMP.b #$FF : BNE .notFF3 + LDA.w Pool_DefaultGFXGroups_sheet3, Y + + .notFF3 + + STA.l $7EC2F8 + STA.w TransGFXModule_PriorSheets+3 + + LDA.w Pool_OWGFXGroupTable_sheet4, X : CMP.b #$FF : BNE .notFF4 + LDA.w Pool_DefaultGFXGroups_sheet4, Y + + .notFF4 + + STA.l $7EC2F9 + STA.w TransGFXModule_PriorSheets+4 + + LDA.w Pool_OWGFXGroupTable_sheet5, X : CMP.b #$FF : BNE .notFF5 + LDA.w Pool_DefaultGFXGroups_sheet5, Y + + .notFF5 + + STA.l $7EC2FA + STA.w TransGFXModule_PriorSheets+5 + + LDA.w Pool_OWGFXGroupTable_sheet6, X : CMP.b #$FF : BNE .notFF6 + LDA.w Pool_DefaultGFXGroups_sheet6, Y + + .notFF6 + + STA.l $7EC2FB + STA.w TransGFXModule_PriorSheets+6 + + PLB + + ; $005949 Skip normal sheet load. + JML.l $00D949 +} + +AnimateMirrorWarp_DecompressNewTileSetsLongCalls2: +{ + PHB : PHK : PLB + + REP #$30 + LDA.b $8A : AND.w #$00FF : ASL #3 : TAX + LDA.b $8A : AND.w #$00C0 : LSR #3 : TAY ; (Area / 8) = LW, DW, or SW *8 + SEP #$20 + + LDA.w Pool_OWGFXGroupTable_sheet1, X : CMP.b #$FF : BNE .notFF1 + LDA.w Pool_DefaultGFXGroups_sheet1, Y + + .notFF1 + + STA.b $08 + STA.w TransGFXModule_PriorSheets+1 + + LDA.w Pool_OWGFXGroupTable_sheet0, X : CMP.b #$FF : BNE .notFF0 + LDA.w Pool_DefaultGFXGroups_sheet0, Y + + .notFF0 + + TAY + STA.w TransGFXModule_PriorSheets+0 + + SEP #$10 + + PLB + + ; $005988 Skip normal sheet load. + JML.l $00D988 +} + +AnimateMirrorWarp_DecompressBackgroundsALongCalls: +{ + PHB : PHK : PLB + + REP #$30 + LDA.b $8A : AND.w #$00FF : ASL #3 : TAX + LDA.b $8A : AND.w #$00C0 : LSR #3 : TAY ; (Area / 8) = LW, DW, or SW *8 + SEP #$20 + + LDA.w Pool_OWGFXGroupTable_sheet3, X : CMP.b #$FF : BNE .notFF3 + LDA.w Pool_DefaultGFXGroups_sheet3, Y + + .notFF3 + + STA.b $08 + STA.w TransGFXModule_PriorSheets+3 + + LDA.w Pool_OWGFXGroupTable_sheet2, X : CMP.b #$FF : BNE .notFF2 + LDA.w Pool_DefaultGFXGroups_sheet2, Y + + .notFF2 + + TAY + STA.w TransGFXModule_PriorSheets+2 + + SEP #$10 + + PLB + + ; $0059C7 Skip normal sheet load. + JML.l $00D9C7 +} + +AnimateMirrorWarp_DecompressBackgroundsCLongCalls: +{ + PHB : PHK : PLB + + REP #$30 + LDA.b $8A : AND.w #$00FF : ASL #3 : TAX + LDA.b $8A : AND.w #$00C0 : LSR #3 : TAY ; (Area / 8) = LW, DW, or SW *8 + SEP #$20 + + LDA.w Pool_OWGFXGroupTable_sheet7, X : CMP.b #$FF : BNE .notFF7 + LDA.w Pool_DefaultGFXGroups_sheet7, Y + + .notFF7 + + STA.b $08 + STA.w AnimatedTileGFXSet + STA.w TransGFXModule_PriorSheets+7 + + LDA.w Pool_OWGFXGroupTable_sheet6, X : CMP.b #$FF : BNE .notFF6 + LDA.w Pool_DefaultGFXGroups_sheet6, Y + + .notFF6 + + TAY + STA.w TransGFXModule_PriorSheets+6 + + SEP #$10 + + PLB + + ; $005A3A Skip normal sheet load. + JML.l $00DA3A +} + +pushpc + +; ============================================================================== + +if !Func00E221 == 1 + +org $02B490 ; $013490 + JSL.l Whirlpool_LoadDestinationMap_Interrupt + +else + +org $02B490 ; $013490 + JSL.l BirdTravel_LoadAmbientOverlay + +endif + +pullpc + +Whirlpool_LoadDestinationMap_Interrupt: +{ + ; Replaced code. + JSL.l BirdTravel_LoadAmbientOverlay + + STZ.w TransGFXModuleFrame + + RTL +} + +pushpc + +; ============================================================================== + +if !Func02A9C4 == 1 + +org $02A9C4 ; $0129C4 +OverworldHandleTransitions: +{ + ; Tells us which direction we're scrolling in. + LDA.w $0416 : BEQ .noScroll + JSR.w Overworld_ScrollMap + + .noScroll + + REP #$20 + + ; Check if link is moving up/down. + LDA.b $30 : AND.w #$00FF : BEQ .noDeltaY + LDA.b $67 : AND.w #$000C : STA.b $00 + + REP #$10 + LDA.b $8A : ASL : TAX + LDA.b $20 : SEC : SBC.l Pool_OverworldTransitionPositionY_New, X + SEP #$10 + + ; Transitioning up. + LDY.b #$06 + LDX.b #$08 + + CMP.w #$0004 : BCC .checkDirection + ; Transitioning down. + LDY.b #$04 + LDX.b #$04 + + CMP.w OWCameraBoundsS : BCS .checkDirection + + .noDeltaY + + ; Check if Link is moving right/left. + LDA.b $31 : AND.w #$00FF : BEQ .noDeltaX + ; Add an offset to the X position. + LDA.w OWCameraBoundsE : CLC : ADC.w #$0004 : STA.b $02 + + LDA.b $67 : AND.w #$0003 : STA.b $00 + + REP #$10 + LDA.b $8A : ASL : TAX + LDA.b $22 : SEC : SBC.l Pool_OverworldTransitionPositionX_New, X + SEP #$10 + + ; Transitioning left. + LDY.b #$02 + LDX.b #$02 + + CMP.w #$0006 : BCC .checkDirection + ; Transitioning right. + LDY.b #$00 + LDX.b #$01 + + CMP.b $02 : BCC .noTransition + + .checkDirection + + ; Check if the direction the player is moving matches the boundary we hit: + CPX.b $00 : BEQ .transition + .noTransition + .noDeltaX + + JSL.l Overworld_CheckForSpecialOverworldTrigger + + RTS + + ; Triggers when Link finally reaches the edge of the screen and is moving + ; in that direction. + .transition + + SEP #$20 + + ; Just makes sure we're not using a medallion or input is disabled. + JSL.l Player_IsScreenTransitionPermitted : BCS .noTransition + STY.b $02 : STZ.b $03 + + JSR.w DeleteCertainAncillaeStopDashing + + REP #$31 + + ; Remove potential large world offest. + LDX.b $02 + LDA.b $84 : AND.l OverworldScreenTileMapChange_Masks, X : STA.b $84 + + ; $0700 does not store the world we are in, so we need to extract it + ; from $8A and then apply it to $0700. We cannot just shift $8A instead + ; because $0700 is the true area and not the "parent" area. + LDA.b $8A : AND.w #$00C0 : ASL + ORA.w $0700 : CLC : ADC.l OverworldScreenIDChange, X : STA.b $04 + + ; X here equals which direction we are currently moving to. + ; 0x00 - Right + ; 0x02 - Left + ; 0x04 - Down + ; 0x06 - Up + CLC : ADC.l .ByScreenAddresses, X : TAX + LDA.b $84 : CLC : ADC.l Pool_ByScreen1_New, X : STA.b $84 + + LDA.b $04 : LSR : TAX + + SEP #$30 + + LDA.b $8A : PHA + + ; Set the OW area number. + LDA.l Pool_Overworld_ActualScreenID_New, X : STA.b $8A + STA.w $040A + TAX + + ; HARDCODED: Bunny music. + LDA.l $7EF3CA : BEQ .lightWorld + ; Check for moon pearl. + LDA.l $7EF357 : BEQ .noMusicChange + + .lightWorld + + ; Extract the ambient sound from this array. + LDA.l $7F5B00, X : LSR #4 : BNE .ambientSound + LDA.b #$05 : STA.w $012D ; No ambient sound. + + .ambientSound + + LDA.l $7F5B00, X : AND.b #$0F : CMP.w $0130 : BEQ .noMusicChange + LDA.b #$F1 : STA.w $012C + + .noMusicChange + + JSR.w Overworld_LoadMapProperties + + LDA.b #$01 : STA.b $11 + + LDA.b $00 : STA.w $0410 + STA.w $0416 + + LDX.b #$04 + + ; Converts a bitwise direction indicator to a value based one. + .loop + DEX + LSR : BCC .loop + + STX.w $0418 + STX.w $069C + + STZ.w $0696 : STZ.w $0698 : STZ.w $0126 + + ; ----udlr + ; u - Up + ; d - Down + ; l - Left + ; r - Right + ; Check if the area we are in needs a mosaic. + ; Filter out the the direction of the transition we are looking for. + PLX + LDA.l Pool_MosaicTable, X : AND.w $0416 : BEQ .noMosaic + ; Trigger a mosaic transition. + + ; Send us to a submodule that will handle a mosaic transition. + LDA.b #$0D : STA.b $11 + + ; Reset mosaic settings. + LDA.b #$00 : STA.b $95 + STA.l $7EC011 + STA.b $B0 + + RTS + + .noMosaic + + LDX.b $8A + LDA.l $7EFD40, X : STA.b $00 + LDA.l OverworldPalettesScreenToSet_New, X + JSL.l Overworld_LoadPalettes + JSR.w Overworld_CgramAuxToMain + + RTS +} +warnpc $02AB08 ; $012B08 + +org $02A62C ; $01262C +OverworldScreenTileMapChange: +{ + ; These mask values are changed to fix several vanilla issues surrounding + ; large areas. Moving from one large area to another twords the center of + ; the side would cause a broken transition. A large area next to another + ; but offset by the length of another would also cause a broken transition. + ; $01262C + .Masks + if !Func02A62C == 1 + dw $1F80, $1F80, $007F, $007F + else + dw $0F80, $0F80, $003F, $003F + endif +} +warnpc $02A634 ; $012634 + +; This table was moved from its original location at $012834 to make more +; space for the bigger tables down below. Replaces a few bytes from +; OverworldScreenTileMapChange_ByScreen1. +org $02A634 ; $012634 +OverworldScreenIDChange: +{ + dw $0002, $FFFE, $0010, $FFF0 +} +warnpc $02A63C ; $01263C + +; This table was moved from its original location at $01283C to make more +; space for the bigger tables down below. This now replaces a few bytes from +; OverworldScreenTileMapChange_ByScreen1. +org $02A63C ; $01263C +OverworldMixedCoordsChange: +{ + dw $FFF0, $0010, $FFFE, $0002 +} +warnpc $02A644 ; $012644 + +; This table was moved from its original location at $016DC5. This now replaces +; OverworldScreenTileMapChange_ByScreen1, OverworldScreenTileMapChange_ByScreen2 +; and part of OverworldScreenTileMapChange_ByScreen3. +org $02A644 ; $012644 +Overworld_HandleOverlaysAndBombDoors_bombable_door_location_New: + +; This table was moved from its original location at $0DC2F9. This now replaces +; part of OverworldScreenTileMapChange_ByScreen3 and all of the following +; OverworldScreenTileMapChange_ByScreen4, +; OverworldScreenIDChange, OverworldMixedCoordsChange, +; OverworldScreenSizeFlag, and OverworldScreenSizeHighByte. +; The bytes of space at $0DC2F9 is now unused. The references to this table are +; updated by ZS itself. +org $02A784 ; $012784 +OverworldData_HiddenItems_New: + +; Update this address. +org $02C098 ; $014098 +ADC.w OverworldMixedCoordsChange, Y + +else + +org $02A9C4 ; $0129C4 +db $AD, $16, $04, $F0, $03, $20, $73, $F2 +db $C2, $20, $A5, $30, $29, $FF, $00, $F0 +db $23, $A5, $67, $29, $0C, $00, $85, $00 +db $AE, $00, $07, $A5, $20, $38, $FF, $C4 +db $A8, $02, $A0, $06, $A2, $08, $C9, $04 +db $00, $90, $3B, $A0, $04, $A2, $04, $CD +db $16, $07, $B0, $32, $A5, $31, $29, $FF +db $00, $F0, $2F, $AD, $16, $07, $18, $69 +db $04, $00, $85, $02, $A5, $67, $29, $03 +db $00, $85, $00, $AE, $00, $07, $A5, $22 +db $38, $FF, $44, $A9, $02, $A0, $02, $A2 +db $02, $C9, $06, $00, $90, $08, $A0, $00 +db $A2, $01, $C5, $02, $90, $04, $E4, $00 +db $F0, $05, $22, $49, $DE, $0E, $60, $E2 +db $20, $22, $39, $F4, $07, $B0, $F3, $84 +db $02, $64, $03, $20, $0C, $8B, $C2, $31 +db $A6, $02, $A5, $84, $3F, $2C, $A6, $02 +db $85, $84, $AD, $00, $07, $18, $7F, $34 +db $A8, $02, $48, $85, $04, $8A, $0A, $0A +db $0A, $0A, $0A, $0A, $05, $04, $AA, $A5 +db $84, $18, $7F, $34, $A6, $02, $85, $84 +db $68, $4A, $AA, $E2, $30, $A5, $8A, $48 +db $C9, $2A, $D0, $05, $A9, $80, $8D, $2D +db $01, $BF, $EC, $A5, $02, $0F, $CA, $F3 +db $7E, $85, $8A, $8D, $0A, $04, $AA, $AF +db $CA, $F3, $7E, $F0, $06, $AF, $57, $F3 +db $7E, $F0, $1F, $BF, $00, $5B, $7F, $4A +db $4A, $4A, $4A, $D0, $05, $A9, $05, $8D +db $2D, $01, $BF, $00, $5B, $7F, $29, $0F +db $CD, $30, $01, $F0, $05, $A9, $F1, $8D +db $2C, $01, $20, $08, $AB, $A9, $01, $85 +db $11, $A5, $00, $8D, $10, $04, $8D, $16 +db $04, $A2, $04, $CA, $4A, $90, $FC, $8E +db $18, $04, $8E, $9C, $06, $9C, $96, $06 +db $9C, $98, $06, $9C, $26, $01, $68, $29 +db $3F, $F0, $06, $A5, $8A, $29, $BF, $D0 +db $0F, $64, $B0, $A9, $0D, $85, $11, $A9 +db $00, $85, $95, $8F, $11, $C0, $7E, $60 +db $A6, $8A, $BF, $40, $FD, $7E, $85, $00 +db $BF, $1C, $FD, $00, $22, $A8, $D5, $0E +db $20, $69, $C7, $60 + +org $02A62C ; $01262C +dw $0F80, $0F80, $003F, $003F + +org $02C098 ; $014098 +db $79, $3C, $A8 + +endif + +pullpc + +OverworldHandleTransitions_ByScreenAddresses: +{ + dw Pool_ByScreen1_New-Pool_ByScreen1_New + dw Pool_ByScreen2_New-Pool_ByScreen1_New + dw Pool_ByScreen3_New-Pool_ByScreen1_New + dw Pool_ByScreen4_New-Pool_ByScreen1_New +} + +pushpc + +; ============================================================================== + +; This section changes how all of the camera values get set. + +if !Func02C0C3 == $01 + +org $02C0C3 ; $0140C3 +Overworld_SetCameraBounds_Interrupt: +{ + JSL.l NewOverworld_SetCameraBounds + + RTS +} +warnpc $02C0F8 ; $0140F8 + +else + +org $02C0C3 ; $0140C3 +db $B9, $C4, $A8, $8D, $00, $06, $18, $7D +db $E2, $BF, $8D, $02, $06, $B9, $44, $A9 +db $8D, $04, $06, $18, $7D, $E6, $BF, $8D +db $06, $06, $B9, $E2, $BE, $8D, $10, $06 +db $18, $7D, $EA, $BF, $8D, $12, $06, $B9 +db $62, $BF, $8D, $14, $06, $18, $7D, $EE +db $BF, $8D, $16, $06, $60 + +endif + +pullpc + +; Y - The overworld area number * 2 we are going to. Note: NOT the parent +; number. Meaning if you are going to hyrule castle from Link's house, +; this will be 0x48 (0x24 * 2) and not 0x36 (0x1B * 2). +; X - 0 for small map, 2 for large map +NewOverworld_SetCameraBounds: +{ + PHB : PHK : PLB + + LDX.b $8A + LDA.l Pool_BufferAndBuildMap16Stripes_overworldScreenSize, X + AND.w #$00FF : ASL : TAX + + REP #$10 + + LDA.b $8A : ASL : TAY + LDA.w Pool_OverworldTransitionPositionY_New, Y : STA.w $0600 + CLC : ADC.w .boundary_y_size, X : STA.w $0602 + + LDA.w Pool_OverworldTransitionPositionX_New, Y : STA.w $0604 + CLC : ADC.w .boundary_x_size, X : STA.w $0606 + + LDA.w Pool_trans_target_north_new, Y : STA.w $0610 + CLC : ADC.w .trans_target_south_offset, X : STA.w $0612 + + LDA.w Pool_trans_target_west_new, Y : STA.w $0614 + CLC : ADC.w .trans_target_east_offset, X : STA.w $0616 + + SEP #$10 + + PLB + + RTL + + ; Small, Large, Wide, Tall + .boundary_y_size + dw $011E, $031E, $011E, $031E + + .boundary_x_size + dw $0100, $0300, $0300, $0100 + + .trans_target_south_offset + dw $02E0, $04E0, $02E0, $04E0 + + .trans_target_east_offset + dw $0300, $0500, $0500, $0300 +} + +; NOTE: UNUSED: +; The $0712 check at $01408D in OverworldScrollTransition and at $0165AA +; in Overworld_LoadNewScreenProperties are now unused because of the +; new Overworld_SetCameraBounds function. + +pushpc + +; ============================================================================== + +; This changes how OverworldScreenSizeHighByte is used. Using OWCameraBoundsE +; ($0718) which is free RAM to be the new X boundary check. + +if !Func02E598 == $01 + +org $02E598 ; $016598 + JSL.l Copy0716 + NOP +warnpc $02E59D ; $01659D + +org $02EADC ; $016ADC + JSL.l Copy0716 + NOP +warnpc $02EAE1 ; $016AE1 + +; This function returns carry set if the hookshot is off screen when used. +; It's only use is to prevent the hookshot from interacting with anything +; that is offscreen. +; Changed to use the new x value and the new OverworldTransitionPositionX and Y +; tables. +org $08FA49 ; $047A49 +Hookshot_IsCollisionCheckFutile_Interrupt: +{ + LDA.w $0C72, X : AND.w #$0002 : BNE .moving_horizontally + LDX.w $0700 + LDA.b $00 : SEC : SBC.l Pool_OverworldTransitionPositionY_New, X + CMP.w #$0004 : BCC .off_screen + CMP.w OWCameraBoundsS : BCS .off_screen + BRA .not_at_screen_edge + + .moving_horizontally + + LDX.w $0700 + LDA.b $02 : SEC : SBC.l Pool_OverworldTransitionPositionX_New, X + CMP.w #$0006 : BCC .off_screen + CMP.w OWCameraBoundsE : BCC .not_at_screen_edge + + .off_screen + + SEP #$20 + + PLY + PLX + + SEC + + RTS + warnpc $08FA81 + + org $08FA81 + .not_at_screen_edge +} +warnpc $08FA81 ; $047A81 + +; Change an old OverworldScreenSizeFlag use to set the X value instead. +org $02AB0D ; $012B0D +Overworld_LoadMapProperties_Interrupt: +{ + CPX.b #$80 : BCS .inSW + ; $0AA3 is the sprite graphics index. + LDA.l $7EFCC0, X + + BRA .write0AA3 + + .inSW + + LDA.l Pool_LoadSpecialOverworld_GFX_0AA3-$80, X + + .write0AA3 + + ; $0AA3 is the sprite graphics index. + STA.w $0AA3 + + ; $0AA2 is the secondary background graphics index. + LDA.l GFX0AA2ValsOW, X + + ; In PrepTransAuxGFX the game checks if $0AA2 is below 0x20, if it is, + ; it will load 3 of the aux sheets as using the low palette instead of + ; the high palette. So since $0AA2 isn't really used on the overworld + ; anymore, we can just OR it so it will always load properly. + ORA.b #$20 : STA.w $0AA2 + + ; Code from vanilla that is still needed. + LDA.w $0712 : STA.w $0714 + + LDA.l Pool_BufferAndBuildMap16Stripes_overworldScreenSize, X : TAX + LDA.l .xSize, X : STA.w $0719 + LDA.l .ySize, X : STA.w $0717 + + LDY.b #$20 + LDX.b #$00 + + LDA.b $8A : AND.b #$40 : BEQ .lightWorld + ; $0AA1 = 0x21 for dark world, 0x20 for light world. + INY + + ; 0x08 for dark world, 0x00 for light world. + LDX.b #$08 + + .lightWorld + + STY.w $0AA1 + + ; X = 0x01 in LW, 0x0B in DW. + LDA.l SheetsTable_0AA4, X : STA.w $0AA4 + + REP #$30 + + JSL.l AreaSizeCheck + + SEP #$30 + + RTS + + ; 0x01 - Small map + ; 0x03 - Large map + .xSize + db $01, $03, $03, $01 + + .ySize + db $01, $03, $01, $03 +} +warnpc $02AB7B ; $012B7B + +else + +org $02E598 ; $016598 +db $A9, $E4, $8D, $16, $07 + +org $02EADC ; $016ADC +db $A9, $E4, $8D, $16, $07 + +org $08FA49 ; $047A49 +db $BD, $72, $0C, $29, $02, $00, $D0, $16 +db $AE, $00, $07, $A5, $00, $38, $FF, $C4 +db $A8, $02, $C9, $04, $00, $90, $1B, $CD +db $16, $07, $B0, $16, $80, $1A, $AE, $00 +db $07, $A5, $02, $38, $FF, $44, $A9, $02 +db $C9, $06, $00, $90, $05, $CD, $16, $07 +db $90, $06, $E2, $20, $7A, $FA, $38 + +org $02AB0D ; $012B0D +db $BF, $C0, $FC, $7E, $8D, $A3, $0A, $BF +db $9C, $FC, $00, $8D, $A2, $0A, $8A, $29 +db $3F, $AA, $AD, $12, $07, $8D, $14, $07 +db $BF, $44, $A8, $02, $8D, $12, $07, $BF +db $84, $A8, $02, $8D, $17, $07, $A0, $20 +db $A2, $00, $A5, $8A, $29, $40, $F0, $03 +db $C8, $A2, $08, $8C, $A1, $0A, $BF, $F4 +db $D8, $00, $8D, $A4, $0A, $C2, $30, $A5 +db $8A, $29, $BF, $00, $0A, $AA, $BF, $C4 +db $A8, $02, $8D, $08, $07, $BF, $44, $A9 +db $02, $4A, $4A, $4A, $8D, $0C, $07, $A9 +db $F0, $03, $AE, $12, $07, $D0, $03, $A9 +db $F0, $01, $8D, $0A, $07, $4A, $4A, $4A +db $8D, $0E, $07, $E2, $30, $60 + +endif + +pullpc + +Copy0716: +{ + LDA.b #$E4 : STA.w OWCameraBoundsS + STA.w OWCameraBoundsE + + RTL +} + +AreaSizeCheck: +{ + PHB : PHK : PLB + + LDA.b $8A : ASL : TAX + LDA.l Pool_OverworldTransitionPositionY_New, X : STA.w $0708 + LDA.l Pool_OverworldTransitionPositionX_New, X : LSR #3 : STA.w $070C + + LDX.b $8A + LDA.l Pool_BufferAndBuildMap16Stripes_overworldScreenSize, X + AND.w #$00FF : ASL : TAX + LDA.w .YSize, X : STA.w $070A + LDA.w .XSize, X : STA.w $070E + + PLB + + RTL + + ; Small, Large, Wide, Tall + .YSize + dw $01F0, $03F0, $01F0, $03F0 + + .XSize + dw $003E, $007E, $007E, $003E +} + +pushpc + +; ============================================================================== + +if !Func09C4C7 == $01 + +org $09C4C7 ; $04C4C7 +LoadOverworldSprites_Interrupt: +{ + LDX.w $040A + LDA.l Pool_BufferAndBuildMap16Stripes_overworldScreenSize, X : TAY + + LDA.w .xSize, Y : STA.w $0FB9 + STZ.w $0FB8 + + LDA.w .ySize, Y : STA.w $0FBB + STZ.w $0FBA + + ; What phase are we in? + LDA.l $7EF3C5 : ASL : TAY + + REP #$30 + + ; And then, what overworld area are we in? + TXA : ASL : CLC : ADC.w .phaseOffset, Y : TAX + + ; Get the overworld sprite pointer based on the overworld area and game phase. + LDA.l Pool_Overworld_SpritePointers_state_0_New, X : STA.b $00 + + SEP #$20 + + BRA .skip + + .xSize + db $02, $04, $04, $02 + + .ySize + db $02, $04, $02, $04 + + .phaseOffset + dw $0000, $0000, $0140, $0280 + + ; We have some extra bytes of space here. + NOP : NOP : NOP + + org $09C50D ; $04C50D + .skip +} +warnpc $09C50D ; $04C50D + +; The table OverworldScreenSizeForLoading which is located at $04C635 and +; used by the vanilla LoadOverworldSprites function is no longer needed for +; its original purpose. This is for controlling the boundaries used by sprites +; to check if they should be loaded. This is now unused in favor of just +; getting a value based on the size of the area. Its 0xC0 bytes of space is +; now used by OverworldPalettesScreenToSet_New which was moved here from is +; original loaction at $007D1C. The old 0x88 bytes of space at $007D1C is +; now unused. + +else + +org $09C4C7 ; $04C4C7 +db $AD, $0A, $04, $A8, $BE, $35, $C6, $8E +db $B9, $0F, $9C, $B8, $0F, $8E, $BB, $0F +db $9C, $BA, $0F, $C2, $30, $AD, $0A, $04 +db $0A, $A8, $E2, $20, $AF, $C5, $F3, $7E +db $C9, $03, $F0, $0E, $C9, $02, $F0, $14 +db $B9, $81, $C8, $85, $00, $B9, $82, $C8 +db $80, $12, $B9, $21, $CA, $85, $00, $B9 +db $22, $CA, $80, $08, $B9, $01, $C9, $85 +db $00, $B9, $02, $C9 + +endif + +; ============================================================================== + +; This is the new truth table as to what each area's size is. +org $02F88D ; $01788D +Pool_BufferAndBuildMap16Stripes_overworldScreenSize: +{ + ; The large area value and small area values were swapped. + ; 0x00 was large before and 0x01 was small. + + ; 0x00 - Small area (1x1) + ; 0x01 - Large area (2x2) + ; 0x02 - Wide area (2x1) + ; 0x03 - Tall area (1x2) + + if !UseVanillaPool > 0 + ; LW + db $01, $01, $00, $01, $01, $01, $01, $00 + db $01, $01, $00, $01, $01, $01, $01, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + db $01, $01, $00, $01, $01, $00, $01, $01 + db $01, $01, $00, $01, $01, $00, $01, $01 + db $00, $00, $00, $00, $00, $00, $00, $00 + db $01, $01, $00, $00, $00, $01, $01, $00 + db $01, $01, $00, $00, $00, $01, $01, $00 + + ; DW + db $01, $01, $00, $01, $01, $01, $01, $00 + db $01, $01, $00, $01, $01, $01, $01, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + db $01, $01, $00, $01, $01, $00, $01, $01 + db $01, $01, $00, $01, $01, $00, $01, $01 + db $00, $00, $00, $00, $00, $00, $00, $00 + db $01, $01, $00, $00, $00, $01, $01, $00 + db $01, $01, $00, $00, $00, $01, $01, $00 + + ; SW + db $00, $01, $01, $00, $00, $00, $00, $00 + db $00, $01, $01, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + + ; The later half of the SW doesn't exist but this table does have values for + ; them here. So this space could be used for something else. + db $00, $00, $00, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + endif +} +warnpc $02F94D ; $01794D + +if !Func02AC40 == $01 + +; Change a bunch of Pool_BufferAndBuildMap16Stripes_overworldScreenSize checks +; from a BEQ to a BNE. +org $02AC40 ; $012C40 + db $D0 + +org $02AC70 ; $012C70 + db $D0 + +org $02B2FA ; $0132FA + db $D0 + +org $02B356 ; $013356 + db $D0 + +org $02ED39 ; $016D39 + db $D0 + +org $02ED6D ; $016D6D + db $D0 + +; Change a bunch of Pool_BufferAndBuildMap16Stripes_overworldScreenSize checks +; from a BNE to a BEQ. + +org $02F039 ; $017039 + db $F0 + +org $02F2EF ; $0172EF + db $F0 + +org $02F323 ; $017323 + db $F0 + +org $02F361 ; $017361 + db $F0 + +org $02F39B ; $01739B + db $F0 + +else + +org $02AC40 ; $012C40 + db $F0 + +org $02AC70 ; $012C70 + db $F0 + +org $02B2FA ; $0132FA + db $F0 + +org $02B356 ; $013356 + db $F0 + +org $02ED39 ; $016D39 + db $F0 + +org $02ED6D ; $016D6D + db $F0 + +org $02F039 ; $017039 + db $D0 + +org $02F2EF ; $0172EF + db $D0 + +org $02F323 ; $017323 + db $D0 + +org $02F361 ; $017361 + db $D0 + +org $02F39B ; $01739B + db $D0 + +endif + +; ============================================================================== + +if !Func02E931 == $01 + +org $02E931 ; $016931 +LoadSpecialOverworld_Interrupt: +{ + LDA.b $8A : SEC : SBC.b #$80 : TAX + + ; GFX $0AA3 + LDA.l Pool_LoadSpecialOverworld_GFX_0AA3, X : STA.w $0AA3 + + ; GFX $0AA2 + LDA.l Pool_LoadSpecialOverworld_GFX_0AA2, X : STA.w $0AA2 + + ; Palette property b + LDA.l Pool_LoadSpecialOverworld_palette_prop_b, X : STA.b $00 + + ; This table call was changed to read from the same one as the rest of the + ; areas and is no longer SW specific. + ; Property property a + LDX.b $8A + LDA.l OverworldPalettesScreenToSet_New, X + JSL.l Overworld_LoadPalettes + + PLA : STA.b $A0 + + REP #$30 + + ; These 2 exits need the special smaller camera bounds instead of the usual + ; ones. Such as the master sword area being half of a small area. + LDA.b $A0 : CMP.w #$0180 : BEQ .SpecialCameraBounds + CMP.w #$0181 : BEQ .SpecialCameraBounds + LDA.b $8A : AND.w #$00FF : ASL : TAX + LDA.l Pool_OverworldTransitionPositionY_New, X : STA.w $0708 + LDA.l Pool_OverworldTransitionPositionX_New, X : LSR #3 : STA.w $070C + + JSL.l AreaSizeCheck + + JSL.l NewOverworld_SetCameraBounds + + BRA .end + + .SpecialCameraBounds + + JSL.l SetupSpecialCameraBounds + + .end + + SEP #$30 + + PLB + + JSL.l Overworld_SetScreenBGColorCacheOnly + + RTS +} +warnpc $02E9BC ; $0169BC + +else + +org $02E931 ; $016931 +db $BF, $11, $E8, $02, $8D, $A3, $0A, $BF +db $21, $E8, $02, $8D, $A2, $0A, $DA, $BF +db $41, $E8, $02, $85, $00, $BF, $31, $E8 +db $02, $22, $A8, $D5, $0E, $FA, $C2, $30 +db $A9, $F0, $03, $85, $00, $A5, $A0, $29 +db $3F, $00, $0A, $AA, $BF, $E1, $E6, $02 +db $8D, $08, $07, $BF, $E1, $E7, $02, $4A +db $4A, $4A, $8D, $0C, $07, $A5, $00, $8D +db $0A, $07, $A5, $00, $4A, $4A, $4A, $8D +db $0E, $07, $A5, $A0, $0A, $A8, $E2, $10 +db $B9, $E1, $E6, $8D, $00, $06, $B9, $01 +db $E7, $8D, $02, $06, $B9, $21, $E7, $8D +db $04, $06, $B9, $41, $E7, $8D, $06, $06 +db $B9, $61, $E7, $8D, $10, $06, $B9, $A1 +db $E7, $8D, $12, $06, $B9, $81, $E7, $8D +db $14, $06, $B9, $C1, $E7, $8D, $16, $06 +db $E2, $20, $68, $85, $A0, $AB, $22, $1D +db $D6, $0E, $60 + +endif + +pullpc + +SetupSpecialCameraBounds: +{ + PHB : PHK : PLB + + LDA.w #$03F0 : STA.b $00 + + LDA.b $A0 : SEC : SBC.w #$0080 : AND.w #$003F : ASL : TAX + LDA.w .SpecialCamera600, X : STA.w $0708 + LDA.w .SpecialCamera70C, X : LSR #3 : STA.w $070C + + LDA.b $00 : STA.w $070A + LDA.b $00 : LSR #3 : STA.w $070E + + SEP #$10 + + LDA.w .SpecialCamera600, X : STA.w $0600 + LDA.w .SpecialCamera602, X : STA.w $0602 + LDA.w .SpecialCamera604, X : STA.w $0604 + LDA.w .SpecialCamera606, X : STA.w $0606 + LDA.w .SpecialCamera610, X : STA.w $0610 + LDA.w .SpecialCamera612, X : STA.w $0612 + LDA.w .SpecialCamera614, X : STA.w $0614 + LDA.w .SpecialCamera616, X : STA.w $0616 + + PLB + + RTL + + ; These are the camera values that are used for the master sword area and + ; the area under the bridge. + .SpecialCamera600 + dw $0000, $0000 + + .SpecialCamera602 + dw $0120, $0020 + + .SpecialCamera604 + dw $0000, $0100 + + .SpecialCamera606 + dw $0000, $0100 + + .SpecialCamera610 + dw $FF20, $FF20 + + .SpecialCamera612 + dw $FFFC, $0100 + + .SpecialCamera614 + dw $FF20, $FF20 + + .SpecialCamera616 + dw $0004, $0104 + + .SpecialCamera70C + dw $0000, $0000 +} + +pushpc + +; ============================================================================== + +if !Func02A5D3 == $01 + +org $02A5D3 ; $0125D3 +Overworld_PlayerControl_Interrupt: +{ + JSL.l Overworld_Entrance + JSL.l Overworld_DwDeathMountainPaletteAnimation + + ; If not in SW mode skip this part. + LDA.b $8A : CMP.b #$80 : BCC .notSpecialOverworld + ; Checks for tiles that lead back to normal overworld. + JSL.l SpecialOverworld_CheckForReturnTrigger + + ; If $11 == 0x24, that means we did trigger a special overworld tile + LDA.b $11 : CMP.b #$24 : BNE .noSpecialTrigger + ; Tell the game we are in the SW mode. + LDA.b #$0B : STA.b $10 + + RTS + + .noSpecialTrigger + .notSpecialOverworld + + JSR.w OverworldHandleTransitions + + .return + + ; TODO: I think this SEP is not needed but am too scared to comit to + ; removing it. + SEP #$20 + + RTS +} +warnpc $02A62C ; $01262C + +; NOTE: This overwrites the unused table found at $0125EC-$01262B + +else + +org $02A5D3 ; $0125D3 +db $A5, $10, $C9, $0B, $F0, $0D, $22, $F4 +db $BB, $1B, $22, $82, $F5, $0E, $20, $C4 +db $A9, $80, $03, $20, $7B, $AB, $E2, $20 +db $60, $00, $00, $02, $03, $03, $05, $05 +db $07, $00, $00, $0A, $03, $03, $05, $05 +db $0F, $10, $11, $12, $13, $14, $15, $16 +db $17, $18, $18, $1A, $1B, $1B, $1D, $1E +db $1E, $18, $18, $22, $1B, $1B, $25, $1E +db $1E, $28, $29, $2A, $2B, $2C, $2D, $2E +db $2F, $30, $30, $32, $33, $34, $35, $35 +db $37, $30, $30, $3A, $3B, $3C, $35, $35 +db $3F + +endif + +; ============================================================================== + +if !Func00FC67 == $01 + +org $00FC67 ; $007C67 +JSL.l Sprite_LoadGfxProperties_Interrupt +NOP : NOP : NOP + +org $0286DB ; $0106DB +LDA.l OverworldPalettesScreenToSet_New, X + +org $02B0FB ; $0130FB +LDA.l OverworldPalettesScreenToSet_New, X + +org $02B4CD ; $0134CD +LDA.l OverworldPalettesScreenToSet_New, X + +org $02EAAB ; $016AAB +LDA.l OverworldPalettesScreenToSet_New, X + +org $02ECE8 ; $016CE8 +LDA.l OverworldPalettesScreenToSet_New, X + +else + +org $00FC67 ; $007C67 +db $A0, $3E, $00, $AF, $C5, $F3, $7E + +org $0286DB ; $0106DB +db $BF, $1C, $FD, $00 + +org $02B0FB ; $0130FB +db $BF, $1C, $FD, $00 + +org $02B4CD ; $0134CD +db $BF, $1C, $FD, $00 + +org $02EAAB ; $016AAB +db $BF, $1C, $FD, $00 + +org $02ECE8 ; $016CE8 +db $BF, $1C, $FD, $00 + +endif + +pullpc + +Sprite_LoadGfxProperties_Interrupt: +{ + LDX.w #$003E + + .loop + + ; The free RAM used here is right after $7EFD40 which is where + ; vanilla stores the sprite palettes for the LW and DW. Very convenient + ; for our needs, we don't even have to update the read. + LDA.l Pool_LoadSpecialOverworld_palette_prop_b, X + STA.l ExpandedSpritePalArray, X + DEX : DEX : BPL .loop + + ; Replaced code. + LDY.w #$003E + LDA.l $7EF3C5 + + RTL +} + +pushpc + +; ============================================================================== + +if !Func1BC8B1 == $01 + +; Remove the SW overworld item check. +org $1BC8B4 ; $0DC8B4 +Overworld_RevealSecret_Interrupt: +{ + NOP : NOP +} +warnpc $1BC8B6 ; $0DC8B6 + +org $02EF64 ; $016F64 +LDA.l Overworld_HandleOverlaysAndBombDoors_bombable_door_location_New, X + +else + +org $1BC8B4 ; $0DC8B4 +db $B0, $7D + +org $02EF64 ; $016F64 +db $BF, $C5, $ED, $02 + +endif + +; ============================================================================== + +if !Func07B518 == $01 + +org $07B518 ; $03B518 +JSL Link_Read_Interrupt + +else + +org $07B518 ; $03B518 +db $A8, $B9, $1D, $F5 + +endif + +pullpc + +Link_Read_Interrupt: +{ + PHB : PHK : PLB + + TAY + LDA.w Pool_Overworld_SignText_New, Y + + PLB + + RTL +} + +pushpc + +; ============================================================================== + +if !Func02EF44 == $01 + +; Remove a check so that entrance overlays can be used on the SW. +org $02EF44 ; $016F44 +Overworld_LoadMapData_Interrupt: +{ + NOP : NOP : NOP : NOP +} + +else + +org $02EF44 ; $016F44 +db $E0, $80, $B0, $0C + +endif + +; ============================================================================== + +; TODO: Check HandleEdgeTransition_AdjustCameraBounds for possible needed changes. +; Currently I don't think anything is needed here. + +; $013CFB +; TODO: In the fog scrolling code, there is a bit that checks for the turtle +; rock area. If left unchanged, this will prevent the fog and lava from working +; poperly in this area. + +; ============================================================================== + +; NOTE: A second pullpc is needed here just in case someone incorperates this +; ASM into their own code base. + +pullpc +pullpc diff --git a/src/app/editor/overworld/overworld_editor.cc b/src/app/editor/overworld/overworld_editor.cc index 31e41791..68c52dd6 100644 --- a/src/app/editor/overworld/overworld_editor.cc +++ b/src/app/editor/overworld/overworld_editor.cc @@ -243,9 +243,9 @@ void OverworldEditor::DrawToolset() { } } -constexpr std::array kMapSettingsColumnNames = { - "##WorldId", "##GfxId", "##PalId", "##SprGfxId", - "##5thCol", "##6thCol", "##7thCol", "##8thCol"}; +constexpr std::array kMapSettingsColumnNames = { + "##WorldId", "##GfxId", "##PalId", "##SprGfxId", "##5thCol", + "##6thCol", "##7thCol", "##8thCol", "##AreaSize"}; void OverworldEditor::DrawOverworldMapSettings() { if (BeginTable(kOWMapTable.data(), 8, kOWMapFlags, ImVec2(0, 0), -1)) { @@ -318,7 +318,7 @@ void OverworldEditor::DrawOverworldMapSettings() { } void OverworldEditor::DrawCustomOverworldMapSettings() { - if (BeginTable(kOWMapTable.data(), 8, kOWMapFlags, ImVec2(0, 0), -1)) { + if (BeginTable(kOWMapTable.data(), 9, kOWMapFlags, ImVec2(0, 0), -1)) { for (const auto &name : kMapSettingsColumnNames) ImGui::TableSetupColumn(name); @@ -395,6 +395,35 @@ void OverworldEditor::DrawCustomOverworldMapSettings() { overworld_.mutable_overworld_map(current_map_)->mutable_mosaic()); HOVER_HINT("Enable Mosaic effect for the current map"); + TableNextColumn(); + // Add area size selection for v3 support + static uint8_t asm_version = + (*rom_)[zelda3::OverworldCustomASMHasBeenApplied]; + if (asm_version != 0xFF) { + if (BeginTable("AreaSizeTable", 2, kOWMapFlags, ImVec2(0, 0), -1)) { + ImGui::TableSetupColumn("Area Size"); + ImGui::TableSetupColumn("Value"); + + TableNextColumn(); + Text("Area Size"); + + TableNextColumn(); + static const char *area_size_names[] = {"Small (1x1)", "Large (2x2)", + "Wide (2x1)", "Tall (1x2)"}; + int current_area_size = static_cast( + overworld_.overworld_map(current_map_)->area_size()); + if (ImGui::Combo("##AreaSize", ¤t_area_size, area_size_names, + 4)) { + overworld_.mutable_overworld_map(current_map_) + ->SetAreaSize( + static_cast(current_area_size)); + RefreshOverworldMap(); + } + + ImGui::EndTable(); + } + } + ImGui::EndTable(); } } @@ -580,10 +609,14 @@ absl::Status OverworldEditor::Copy() { // Determine width/height in tile16 based on selection bounds const auto start = ow_map_canvas_.selected_points()[0]; const auto end = ow_map_canvas_.selected_points()[1]; - const int start_x = static_cast(std::floor(std::min(start.x, end.x) / 16.0f)); - const int end_x = static_cast(std::floor(std::max(start.x, end.x) / 16.0f)); - const int start_y = static_cast(std::floor(std::min(start.y, end.y) / 16.0f)); - const int end_y = static_cast(std::floor(std::max(start.y, end.y) / 16.0f)); + const int start_x = + static_cast(std::floor(std::min(start.x, end.x) / 16.0f)); + const int end_x = + static_cast(std::floor(std::max(start.x, end.x) / 16.0f)); + const int start_y = + static_cast(std::floor(std::min(start.y, end.y) / 16.0f)); + const int end_y = + static_cast(std::floor(std::max(start.y, end.y) / 16.0f)); const int width = end_x - start_x + 1; const int height = end_y - start_y + 1; @@ -618,8 +651,10 @@ absl::Status OverworldEditor::Paste() { const ImVec2 anchor = ow_map_canvas_.drawn_tile_position(); // Compute anchor in tile16 grid within the current map - const int tile16_x = (static_cast(anchor.x) % kOverworldMapSize) / kTile16Size; - const int tile16_y = (static_cast(anchor.y) % kOverworldMapSize) / kTile16Size; + const int tile16_x = + (static_cast(anchor.x) % kOverworldMapSize) / kTile16Size; + const int tile16_y = + (static_cast(anchor.y) % kOverworldMapSize) / kTile16Size; auto &selected_world = (current_world_ == 0) ? overworld_.mutable_map_tiles()->light_world diff --git a/src/app/zelda3/overworld/overworld.cc b/src/app/zelda3/overworld/overworld.cc index c49b1522..cd4dc35e 100644 --- a/src/app/zelda3/overworld/overworld.cc +++ b/src/app/zelda3/overworld/overworld.cc @@ -527,6 +527,7 @@ absl::Status Overworld::Save(Rom *rom) { RETURN_IF_ERROR(SaveOverworldMaps()) RETURN_IF_ERROR(SaveEntrances()) RETURN_IF_ERROR(SaveExits()) + RETURN_IF_ERROR(SaveAreaSizes()) return absl::OkStatus(); } @@ -1596,5 +1597,29 @@ absl::Status Overworld::SaveMapProperties() { return absl::OkStatus(); } +absl::Status Overworld::SaveAreaSizes() { + util::logf("Saving V3 Area Sizes"); + + // Check if this is a v3 ROM + uint8_t asm_version = (*rom_)[zelda3::OverworldCustomASMHasBeenApplied]; + if (asm_version < 3 || asm_version == 0xFF) { + return absl::OkStatus(); // Not a v3 ROM, nothing to do + } + + // Save area sizes to the expanded table + for (int i = 0; i < kNumOverworldMaps; i++) { + uint8_t area_size_byte = static_cast(overworld_maps_[i].area_size()); + RETURN_IF_ERROR(rom()->WriteByte(kOverworldScreenSize + i, area_size_byte)); + } + + // Save message IDs to expanded table + for (int i = 0; i < kNumOverworldMaps; i++) { + uint16_t message_id = overworld_maps_[i].message_id(); + RETURN_IF_ERROR(rom()->WriteShort(kOverworldMessagesExpanded + (i * 2), message_id)); + } + + return absl::OkStatus(); +} + } // namespace zelda3 } // namespace yaze diff --git a/src/app/zelda3/overworld/overworld.h b/src/app/zelda3/overworld/overworld.h index c91171d4..3ea0cf82 100644 --- a/src/app/zelda3/overworld/overworld.h +++ b/src/app/zelda3/overworld/overworld.h @@ -138,6 +138,7 @@ class Overworld { absl::Status SaveMap32Tiles(); absl::Status SaveMapProperties(); + absl::Status SaveAreaSizes(); auto rom() const { return rom_; } auto mutable_rom() { return rom_; } diff --git a/src/app/zelda3/overworld/overworld_map.cc b/src/app/zelda3/overworld/overworld_map.cc index 9f5e0f31..f62833d2 100644 --- a/src/app/zelda3/overworld/overworld_map.cc +++ b/src/app/zelda3/overworld/overworld_map.cc @@ -6,10 +6,10 @@ #include #include "app/core/features.h" +#include "app/gfx/snes_color.h" #include "app/gfx/snes_tile.h" #include "app/rom.h" #include "app/zelda3/overworld/overworld.h" -#include "util/log.h" namespace yaze { namespace zelda3 { @@ -64,102 +64,81 @@ absl::Status OverworldMap::BuildMap(int count, int game_state, int world, } void OverworldMap::LoadAreaInfo() { - if (index_ != kSpecialWorldMapIdStart) { - if (index_ <= 128) - large_map_ = ((*rom_)[kOverworldMapSize + (index_ & 0x3F)] != 0); - else { - large_map_ = - index_ == 129 || index_ == 130 || index_ == 137 || index_ == 138; + uint8_t asm_version = (*rom_)[OverworldCustomASMHasBeenApplied]; + + // Load message ID and area size based on ASM version + if (asm_version < 3 || asm_version == 0xFF) { + // v2 and vanilla: use original message table + message_id_ = (*rom_)[kOverworldMessageIds + (parent_ * 2)] | + ((*rom_)[kOverworldMessageIds + (parent_ * 2) + 1] << 8); + + // Load area size for v2/vanilla + if (index_ < 0x80) { + // For LW and DW, check the screen size byte + uint8_t size_byte = (*rom_)[kOverworldScreenSize + (index_ & 0x3F)]; + switch (size_byte) { + case 0: + area_size_ = AreaSizeEnum::LargeArea; + break; + case 1: + default: + area_size_ = AreaSizeEnum::SmallArea; + break; + case 2: + area_size_ = AreaSizeEnum::WideArea; + break; + case 3: + area_size_ = AreaSizeEnum::TallArea; + break; + } + } else { + // For SW, use hardcoded values for v2 compatibility + area_size_ = + (index_ == 0x81 || index_ == 0x82 || index_ == 0x89 || index_ == 0x8A) + ? AreaSizeEnum::LargeArea + : AreaSizeEnum::SmallArea; } - } - - auto message_id = rom_->ReadWord(kOverworldMessageIds + (parent_ * 2)); - if (message_id.ok()) { - message_id_ = message_id.value(); } else { - message_id_ = 0; - util::logf("Error reading message id for map %d", parent_); + // v3: use expanded message table and area size table + message_id_ = + (*rom_)[kOverworldMessagesExpanded + (parent_ * 2)] | + ((*rom_)[kOverworldMessagesExpanded + (parent_ * 2) + 1] << 8); + area_size_ = + static_cast((*rom_)[kOverworldScreenSize + index_]); } + // Update large_map_ based on area size + large_map_ = (area_size_ == AreaSizeEnum::LargeArea); + + // Load area-specific data based on index range if (index_ < kDarkWorldMapIdStart) { - area_graphics_ = (*rom_)[kAreaGfxIdPtr + parent_]; - area_palette_ = (*rom_)[kOverworldMapPaletteIds + parent_]; - - area_music_[0] = (*rom_)[kOverworldMusicBeginning + parent_]; - area_music_[1] = (*rom_)[kOverworldMusicZelda + parent_]; - area_music_[2] = (*rom_)[kOverworldMusicMasterSword + parent_]; - area_music_[3] = (*rom_)[kOverworldMusicAgahnim + parent_]; - + // Light World (LW) areas sprite_graphics_[0] = (*rom_)[kOverworldSpriteset + parent_]; sprite_graphics_[1] = (*rom_)[kOverworldSpriteset + parent_ + kDarkWorldMapIdStart]; sprite_graphics_[2] = (*rom_)[kOverworldSpriteset + parent_ + kSpecialWorldMapIdStart]; + area_graphics_ = (*rom_)[kAreaGfxIdPtr + parent_]; + area_palette_ = (*rom_)[kOverworldPalettesScreenToSetNew + parent_]; + sprite_palette_[0] = (*rom_)[kOverworldSpritePaletteIds + parent_]; sprite_palette_[1] = (*rom_)[kOverworldSpritePaletteIds + parent_ + kDarkWorldMapIdStart]; sprite_palette_[2] = (*rom_)[kOverworldSpritePaletteIds + parent_ + kSpecialWorldMapIdStart]; - } else if (index_ < kSpecialWorldMapIdStart) { - area_graphics_ = (*rom_)[kAreaGfxIdPtr + parent_]; - area_palette_ = (*rom_)[kOverworldMapPaletteIds + parent_]; - area_music_[0] = (*rom_)[kOverworldMusicDarkWorld + (parent_ - 64)]; - sprite_graphics_[0] = - (*rom_)[kOverworldSpriteset + parent_ + kSpecialWorldMapIdStart]; - sprite_graphics_[1] = - (*rom_)[kOverworldSpriteset + parent_ + kSpecialWorldMapIdStart]; - sprite_graphics_[2] = - (*rom_)[kOverworldSpriteset + parent_ + kSpecialWorldMapIdStart]; + area_music_[0] = (*rom_)[kOverworldMusicBeginning + parent_]; + area_music_[1] = (*rom_)[kOverworldMusicZelda + parent_]; + area_music_[2] = (*rom_)[kOverworldMusicMasterSword + parent_]; + area_music_[3] = (*rom_)[kOverworldMusicAgahnim + parent_]; - sprite_palette_[0] = - (*rom_)[kOverworldSpritePaletteIds + parent_ + kSpecialWorldMapIdStart]; - sprite_palette_[1] = - (*rom_)[kOverworldSpritePaletteIds + parent_ + kSpecialWorldMapIdStart]; - sprite_palette_[2] = - (*rom_)[kOverworldSpritePaletteIds + parent_ + kSpecialWorldMapIdStart]; - } else { - if (index_ == 0x94) { - parent_ = 0x80; - } else if (index_ == 0x95) { - parent_ = 0x03; - } else if (index_ == 0x96) { - parent_ = 0x5B; // pyramid bg use 0x5B map - } else if (index_ == 0x97) { - parent_ = 0x00; // pyramid bg use 0x5B map - } else if (index_ == 0x9C) { - parent_ = 0x43; - } else if (index_ == 0x9D) { - parent_ = 0x00; - } else if (index_ == 0x9E) { - parent_ = 0x00; - } else if (index_ == 0x9F) { - parent_ = 0x2C; - } else if (index_ == 0x88) { - parent_ = 0x88; - } else if (index_ == 129 || index_ == 130 || index_ == 137 || - index_ == 138) { - parent_ = 129; - } - - area_palette_ = - (*rom_)[kOverworldSpecialPalGroup + parent_ - kSpecialWorldMapIdStart]; - if ((index_ >= kSpecialWorldMapIdStart && index_ <= 0x8A && - index_ != 0x88) || - index_ == 0x94) { - area_graphics_ = (*rom_)[kOverworldSpecialGfxGroup + - (parent_ - kSpecialWorldMapIdStart)]; - area_palette_ = (*rom_)[kOverworldSpecialPalGroup + 1]; - } else if (index_ == 0x88) { - area_graphics_ = 0x51; - area_palette_ = 0x00; - } else { - // pyramid bg use 0x5B map - area_graphics_ = (*rom_)[kAreaGfxIdPtr + parent_]; + // For v2/vanilla, use original palette table + if (asm_version < 3 || asm_version == 0xFF) { area_palette_ = (*rom_)[kOverworldMapPaletteIds + parent_]; } - + } else if (index_ < kSpecialWorldMapIdStart) { + // Dark World (DW) areas sprite_graphics_[0] = (*rom_)[kOverworldSpriteset + parent_ + kSpecialWorldMapIdStart]; sprite_graphics_[1] = @@ -167,47 +146,169 @@ void OverworldMap::LoadAreaInfo() { sprite_graphics_[2] = (*rom_)[kOverworldSpriteset + parent_ + kSpecialWorldMapIdStart]; + area_graphics_ = (*rom_)[kAreaGfxIdPtr + parent_]; + area_palette_ = (*rom_)[kOverworldPalettesScreenToSetNew + parent_]; + sprite_palette_[0] = (*rom_)[kOverworldSpritePaletteIds + parent_ + kSpecialWorldMapIdStart]; sprite_palette_[1] = (*rom_)[kOverworldSpritePaletteIds + parent_ + kSpecialWorldMapIdStart]; sprite_palette_[2] = (*rom_)[kOverworldSpritePaletteIds + parent_ + kSpecialWorldMapIdStart]; + + area_music_[0] = + (*rom_)[kOverworldMusicDarkWorld + (parent_ - kDarkWorldMapIdStart)]; + + // For v2/vanilla, use original palette table + if (asm_version < 3 || asm_version == 0xFF) { + area_palette_ = (*rom_)[kOverworldMapPaletteIds + parent_]; + } + } else { + // Special World (SW) areas + // Message ID already loaded above based on ASM version + + // For v3, use expanded sprite tables + if (asm_version >= 3 && asm_version != 0xFF) { + sprite_graphics_[0] = + (*rom_)[kOverworldSpecialSpriteGfxGroupExpandedTemp + parent_ - + kSpecialWorldMapIdStart]; + sprite_graphics_[1] = + (*rom_)[kOverworldSpecialSpriteGfxGroupExpandedTemp + parent_ - + kSpecialWorldMapIdStart]; + sprite_graphics_[2] = + (*rom_)[kOverworldSpecialSpriteGfxGroupExpandedTemp + parent_ - + kSpecialWorldMapIdStart]; + + sprite_palette_[0] = (*rom_)[kOverworldSpecialSpritePaletteExpandedTemp + + parent_ - kSpecialWorldMapIdStart]; + sprite_palette_[1] = (*rom_)[kOverworldSpecialSpritePaletteExpandedTemp + + parent_ - kSpecialWorldMapIdStart]; + sprite_palette_[2] = (*rom_)[kOverworldSpecialSpritePaletteExpandedTemp + + parent_ - kSpecialWorldMapIdStart]; + } else { + // For v2/vanilla, use original sprite tables + sprite_graphics_[0] = (*rom_)[kOverworldSpecialGfxGroup + parent_ - + kSpecialWorldMapIdStart]; + sprite_graphics_[1] = (*rom_)[kOverworldSpecialGfxGroup + parent_ - + kSpecialWorldMapIdStart]; + sprite_graphics_[2] = (*rom_)[kOverworldSpecialGfxGroup + parent_ - + kSpecialWorldMapIdStart]; + + sprite_palette_[0] = (*rom_)[kOverworldSpecialPalGroup + parent_ - + kSpecialWorldMapIdStart]; + sprite_palette_[1] = (*rom_)[kOverworldSpecialPalGroup + parent_ - + kSpecialWorldMapIdStart]; + sprite_palette_[2] = (*rom_)[kOverworldSpecialPalGroup + parent_ - + kSpecialWorldMapIdStart]; + } + + area_graphics_ = (*rom_)[kAreaGfxIdPtr + parent_]; + area_palette_ = (*rom_)[kOverworldPalettesScreenToSetNew + parent_]; + + // For v2/vanilla, use original palette table and handle special cases + if (asm_version < 3 || asm_version == 0xFF) { + area_palette_ = (*rom_)[kOverworldMapPaletteIds + parent_]; + + // Handle special world area cases + if (index_ == 0x88 || index_ == 0x93) { + area_graphics_ = 0x51; + area_palette_ = 0x00; + } else if (index_ == 0x80) { + area_graphics_ = (*rom_)[kOverworldSpecialGfxGroup + + (parent_ - kSpecialWorldMapIdStart)]; + area_palette_ = (*rom_)[kOverworldSpecialPalGroup + 1]; + } else if (index_ == 0x81 || index_ == 0x82 || index_ == 0x89 || + index_ == 0x8A) { + // Zora's Domain areas - use special sprite graphics + sprite_graphics_[0] = 0x0E; + sprite_graphics_[1] = 0x0E; + sprite_graphics_[2] = 0x0E; + + area_graphics_ = (*rom_)[kOverworldSpecialGfxGroup + + (parent_ - kSpecialWorldMapIdStart)]; + area_palette_ = (*rom_)[kOverworldSpecialPalGroup + 1]; + } else if (index_ == 0x94) { + // Make this the same GFX as the true master sword area + area_graphics_ = (*rom_)[kOverworldSpecialGfxGroup + + (0x80 - kSpecialWorldMapIdStart)]; + area_palette_ = (*rom_)[kOverworldSpecialPalGroup + 1]; + } else if (index_ == 0x95) { + // Make this the same GFX as the LW death mountain areas + area_graphics_ = (*rom_)[kAreaGfxIdPtr + 0x03]; + area_palette_ = (*rom_)[kOverworldMapPaletteIds + 0x03]; + } else if (index_ == 0x96) { + // Make this the same GFX as the pyramid areas + area_graphics_ = (*rom_)[kAreaGfxIdPtr + 0x5B]; + area_palette_ = (*rom_)[kOverworldMapPaletteIds + 0x5B]; + } else if (index_ == 0x9C) { + // Make this the same GFX as the DW death mountain areas + area_graphics_ = (*rom_)[kAreaGfxIdPtr + 0x43]; + area_palette_ = (*rom_)[kOverworldMapPaletteIds + 0x43]; + } else { + // Default case + area_graphics_ = (*rom_)[kAreaGfxIdPtr + 0x00]; + area_palette_ = (*rom_)[kOverworldMapPaletteIds + 0x00]; + } + } } } void OverworldMap::LoadCustomOverworldData() { - // Set the main palette values. - if (index_ < kDarkWorldMapIdStart) { - area_palette_ = 0; - } else if (index_ >= kDarkWorldMapIdStart && - index_ < kSpecialWorldMapIdStart) { - area_palette_ = 1; - } else if (index_ >= kSpecialWorldMapIdStart && index_ < 0xA0) { - area_palette_ = 0; + // Set the main palette values based on ZScream logic + if (index_ < 0x40 || index_ == 0x95) { // LW + main_palette_ = 0; + } else if ((index_ >= 0x40 && index_ < 0x80) || index_ == 0x96) { // DW + main_palette_ = 1; + } else if (index_ >= 0x80 && index_ < 0xA0) { // SW + main_palette_ = 0; } - if (index_ == 0x03 || index_ == 0x05 || index_ == 0x07) { - area_palette_ = 2; - } else if (index_ == 0x43 || index_ == 0x45 || index_ == 0x47) { - area_palette_ = 3; - } else if (index_ == 0x88) { - area_palette_ = 4; + if (index_ == 0x03 || index_ == 0x05 || + index_ == 0x07) { // LW Death Mountain + main_palette_ = 2; + } else if (index_ == 0x43 || index_ == 0x45 || + index_ == 0x47) { // DW Death Mountain + main_palette_ = 3; + } else if (index_ == 0x88 || index_ == 0x93) { // Triforce room + main_palette_ = 4; } - // Set the mosaic values. - mosaic_ = index_ == 0x00 || index_ == kDarkWorldMapIdStart || - index_ == kSpecialWorldMapIdStart || index_ == 0x81 || - index_ == 0x88; + // Set the mosaic values based on ZScream logic + switch (index_) { + case 0x00: // Leaving Skull Woods / Lost Woods + case 0x40: + mosaic_expanded_ = {false, true, false, true}; + break; + case 0x02: // Going into Skull woods / Lost Woods west + case 0x0A: + case 0x42: + case 0x4A: + mosaic_expanded_ = {false, false, true, false}; + break; + case 0x0F: // Going into Zora's Domain North + case 0x10: // Going into Skull Woods / Lost Woods North + case 0x11: + case 0x50: + case 0x51: + mosaic_expanded_ = {true, false, false, false}; + break; + case 0x80: // Leaving Zora's Domain, the Master Sword area, and the + // Triforce area + case 0x81: + case 0x88: + mosaic_expanded_ = {false, true, false, false}; + break; + default: + mosaic_expanded_ = {false, false, false, false}; + break; + } + // Set up world index for GFX groups int index_world = 0x20; - if (parent_ >= kDarkWorldMapIdStart && - parent_ < kSpecialWorldMapIdStart) // DW - { + parent_ < kSpecialWorldMapIdStart) { // DW index_world = 0x21; - } else if (parent_ == 0x88) // Triforce room - { + } else if (parent_ == 0x88 || parent_ == 0x93) { // Triforce room index_world = 0x24; } @@ -222,7 +323,8 @@ void OverworldMap::LoadCustomOverworldData() { const auto overworldgfxGroups = rom_->version_constants().kOverworldGfxGroups1; - // Replace the variable tiles with the variable ones. + + // Replace the variable tiles with the variable ones uint8_t temp = (*rom_)[overworldgfxGroups + (area_graphics_ * 4)]; if (temp != 0) { custom_gfx_ids_[3] = temp; @@ -251,121 +353,74 @@ void OverworldMap::LoadCustomOverworldData() { custom_gfx_ids_[6] = 0xFF; } - // Set the animated GFX values. + // Set the animated GFX values if (index_ == 0x03 || index_ == 0x05 || index_ == 0x07 || index_ == 0x43 || - index_ == 0x45 || index_ == 0x47) { + index_ == 0x45 || index_ == 0x47 || index_ == 0x95) { animated_gfx_ = 0x59; } else { animated_gfx_ = 0x5B; } - // Set the subscreen overlay values. + // Set the subscreen overlay values subscreen_overlay_ = 0x00FF; - if (index_ == 0x00 || - index_ == - kDarkWorldMapIdStart) // Add fog 2 to the lost woods and skull woods. - { + if (index_ == 0x00 || index_ == 0x01 || index_ == 0x08 || index_ == 0x09 || + index_ == 0x40 || index_ == 0x41 || index_ == 0x48 || + index_ == 0x49) { // Add fog 2 to the lost woods and skull woods subscreen_overlay_ = 0x009D; - } else if (index_ == 0x03 || index_ == 0x05 || - index_ == 0x07) // Add the sky BG to LW death mountain. - { + } else if (index_ == 0x03 || index_ == 0x04 || index_ == 0x0B || + index_ == 0x0C || index_ == 0x05 || index_ == 0x06 || + index_ == 0x0D || index_ == 0x0E || + index_ == 0x07) { // Add the sky BG to LW death mountain subscreen_overlay_ = 0x0095; - } else if (index_ == 0x43 || index_ == 0x45 || - index_ == 0x47) // Add the lava to DW death mountain. - { + } else if (index_ == 0x43 || index_ == 0x44 || index_ == 0x4B || + index_ == 0x4C || index_ == 0x45 || index_ == 0x46 || + index_ == 0x4D || index_ == 0x4E || + index_ == 0x47) { // Add the lava to DW death mountain subscreen_overlay_ = 0x009C; - } else if (index_ == 0x5B) // TODO: Might need this one too "index == 0x1B" - // but for now I don't think so. - { + } else if (index_ == 0x5B || index_ == 0x5C || index_ == 0x63 || + index_ == 0x64) { // TODO: Might need this one too "index == 0x1B" + // but for now I don't think so subscreen_overlay_ = 0x0096; - } else if (index_ == 0x80) // Add fog 1 to the master sword area. - { + } else if (index_ == 0x80) { // Add fog 1 to the master sword area subscreen_overlay_ = 0x0097; } else if (index_ == - 0x88) // Add the triforce room curtains to the triforce room. - { + 0x88) { // Add the triforce room curtains to the triforce room subscreen_overlay_ = 0x0093; } - - // Set the main palette values. - if (index_ < 0x40) // LW - { - area_palette_ = 0; - } else if (index_ >= 0x40 && index_ < 0x80) // DW - { - area_palette_ = 1; - } else if (index_ >= 0x80 && index_ < 0xA0) // SW - { - area_palette_ = 0; - } - - if (index_ == 0x03 || index_ == 0x05 || index_ == 0x07) // LW Death Mountain - { - area_palette_ = 2; - } else if (index_ == 0x43 || index_ == 0x45 || - index_ == 0x47) // DW Death Mountain - { - area_palette_ = 3; - } else if (index_ == 0x88) // Triforce room - { - area_palette_ = 4; - } - - // Set the mosaic values. - switch (index_) { - case 0x00: // Leaving Skull Woods / Lost Woods - case 0x40: - mosaic_expanded_ = {false, true, false, true}; - break; - case 0x02: // Going into Skull woods / Lost Woods west - case 0x0A: - case 0x42: - case 0x4A: - mosaic_expanded_ = {false, false, true, false}; - break; - case 0x0F: // Going into Zora's Domain North - case 0x10: // Going into Skull Woods / Lost Woods North - case 0x11: - case 0x50: - case 0x51: - mosaic_expanded_ = {true, false, false, false}; - break; - case 0x80: // Leaving Zora's Domain, the Master Sword area, and the - // Triforce area - case 0x81: - case 0x88: - mosaic_expanded_ = {false, true, false, false}; - break; - } } void OverworldMap::SetupCustomTileset(uint8_t asm_version) { - area_palette_ = (*rom_)[OverworldCustomMainPaletteArray + index_]; + // Load custom palette and mosaic settings + main_palette_ = (*rom_)[OverworldCustomMainPaletteArray + index_]; mosaic_ = (*rom_)[OverworldCustomMosaicArray + index_] != 0x00; uint8_t mosaicByte = (*rom_)[OverworldCustomMosaicArray + index_]; mosaic_expanded_ = {(mosaicByte & 0x08) != 0x00, (mosaicByte & 0x04) != 0x00, (mosaicByte & 0x02) != 0x00, (mosaicByte & 0x01) != 0x00}; - // This is just to load the GFX groups for ROMs that have an older version - // of the Overworld ASM already applied. + // Load area size for v3 + if (asm_version >= 3 && asm_version != 0xFF) { + uint8_t size_byte = (*rom_)[kOverworldScreenSize + index_]; + area_size_ = static_cast(size_byte); + large_map_ = (area_size_ == AreaSizeEnum::LargeArea); + } + + // Load custom GFX groups based on ASM version if (asm_version >= 0x01 && asm_version != 0xFF) { + // Load from custom GFX group array for (int i = 0; i < 8; i++) { custom_gfx_ids_[i] = (*rom_)[OverworldCustomTileGFXGroupArray + (index_ * 8) + i]; } - animated_gfx_ = (*rom_)[OverworldCustomAnimatedGFXArray + index_]; } else { + // Fallback to vanilla logic for ROMs without custom ASM int index_world = 0x20; - if (parent_ >= kDarkWorldMapIdStart && - parent_ < kSpecialWorldMapIdStart) // DW - { + parent_ < kSpecialWorldMapIdStart) { // DW index_world = 0x21; - } else if (parent_ == 0x88) // Triforce room - { + } else if (parent_ == 0x88 || parent_ == 0x93) { // Triforce room index_world = 0x24; } @@ -379,9 +434,9 @@ void OverworldMap::SetupCustomTileset(uint8_t asm_version) { const auto overworldgfxGroups = rom_->version_constants().kOverworldGfxGroups1; - // Replace the variable tiles with the variable ones. + // Replace the variable tiles with the variable ones // If the variable is 00 set it to 0xFF which is the new "don't load - // anything" value. + // anything" value uint8_t temp = (*rom_)[overworldgfxGroups + (area_graphics_ * 4)]; if (temp != 0x00) { custom_gfx_ids_[3] = temp; @@ -410,7 +465,7 @@ void OverworldMap::SetupCustomTileset(uint8_t asm_version) { custom_gfx_ids_[6] = 0xFF; } - // Set the animated GFX values. + // Set the animated GFX values if (index_ == 0x03 || index_ == 0x05 || index_ == 0x07 || index_ == 0x43 || index_ == 0x45 || index_ == 0x47) { animated_gfx_ = 0x59; @@ -419,6 +474,7 @@ void OverworldMap::SetupCustomTileset(uint8_t asm_version) { } } + // Load subscreen overlay subscreen_overlay_ = (*rom_)[OverworldCustomSubscreenOverlayArray + (index_ * 2)]; } @@ -642,10 +698,22 @@ absl::StatusOr OverworldMap::GetPalette( } absl::Status OverworldMap::LoadPalette() { - int previous_pal_id = - index_ > 0 ? (*rom_)[kOverworldMapPaletteIds + parent_ - 1] : 0; - int previous_spr_pal_id = - index_ > 0 ? (*rom_)[kOverworldSpritePaletteIds + parent_ - 1] : 0; + uint8_t asm_version = (*rom_)[OverworldCustomASMHasBeenApplied]; + + int previous_pal_id = 0; + int previous_spr_pal_id = 0; + + if (index_ > 0) { + // Load previous palette ID based on ASM version + if (asm_version < 3 || asm_version == 0xFF) { + previous_pal_id = (*rom_)[kOverworldMapPaletteIds + parent_ - 1]; + } else { + // v3 uses expanded palette table + previous_pal_id = (*rom_)[kOverworldPalettesScreenToSetNew + parent_ - 1]; + } + + previous_spr_pal_id = (*rom_)[kOverworldSpritePaletteIds + parent_ - 1]; + } area_palette_ = std::min((int)area_palette_, 0xA3); @@ -664,33 +732,50 @@ absl::Status OverworldMap::LoadPalette() { auto grass_pal_group = rom_->palette_group().grass; auto bgr = grass_pal_group[0][0]; + // Handle 0xFF palette references (use previous palette) + if (pal1 == 0xFF) { + pal1 = (*rom_)[rom_->version_constants().kOverworldMapPaletteGroup + + (previous_pal_id * 4)]; + } + + if (pal2 == 0xFF) { + pal2 = (*rom_)[rom_->version_constants().kOverworldMapPaletteGroup + + (previous_pal_id * 4) + 1]; + } + + if (pal3 == 0xFF) { + pal3 = (*rom_)[rom_->version_constants().kOverworldMapPaletteGroup + + (previous_pal_id * 4) + 2]; + } + auto ow_aux_pal_group = rom_->palette_group().overworld_aux; ASSIGN_OR_RETURN(gfx::SnesPalette aux1, GetPalette(ow_aux_pal_group, pal1, previous_pal_id, 20)); ASSIGN_OR_RETURN(gfx::SnesPalette aux2, GetPalette(ow_aux_pal_group, pal2, previous_pal_id, 20)); - // Additional handling of `pal3` and `parent_` - if (pal3 == 255) { - pal3 = (*rom_)[rom_->version_constants().kOverworldMapPaletteGroup + - (previous_pal_id * 4) + 2]; + // Set background color based on world type and area-specific settings + bool use_area_specific_bg = (*rom_)[OverworldCustomAreaSpecificBGEnabled] != 0x00; + if (use_area_specific_bg) { + // Use area-specific background color from custom array + area_specific_bg_color_ = (*rom_)[OverworldCustomAreaSpecificBGPalette + (parent_ * 2)] | + ((*rom_)[OverworldCustomAreaSpecificBGPalette + (parent_ * 2) + 1] << 8); + // Convert 15-bit SNES color to palette color + bgr = gfx::SnesColor(area_specific_bg_color_); + } else { + // Use default world-based background colors + if (parent_ < kDarkWorldMapIdStart) { + bgr = grass_pal_group[0][0]; // LW + } else if (parent_ >= kDarkWorldMapIdStart && + parent_ < kSpecialWorldMapIdStart) { + bgr = grass_pal_group[0][1]; // DW + } else if (parent_ >= 128 && parent_ < kNumOverworldMaps) { + bgr = grass_pal_group[0][2]; // SW + } } - if (parent_ < kDarkWorldMapIdStart) { - pal0 = parent_ == 0x03 || parent_ == 0x05 || parent_ == 0x07 ? 2 : 0; - bgr = grass_pal_group[0][0]; - } else if (parent_ >= kDarkWorldMapIdStart && - parent_ < kSpecialWorldMapIdStart) { - pal0 = parent_ == 0x43 || parent_ == 0x45 || parent_ == 0x47 ? 3 : 1; - bgr = grass_pal_group[0][1]; - } else if (parent_ >= 128 && parent_ < kNumOverworldMaps) { - pal0 = 0; - bgr = grass_pal_group[0][2]; - } - - if (parent_ == 0x88) { - pal0 = 4; - } + // Use main palette from the overworld map data (matches ZScream logic) + pal0 = main_palette_; auto ow_main_pal_group = rom_->palette_group().overworld_main; ASSIGN_OR_RETURN(gfx::SnesPalette main, @@ -703,6 +788,23 @@ absl::Status OverworldMap::LoadPalette() { auto hud_pal_group = rom_->palette_group().hud; gfx::SnesPalette hud = hud_pal_group[0]; + // Handle 0xFF sprite palette references (use previous sprite palette) + if (pal4 == 0xFF) { + pal4 = (*rom_)[kOverworldSpritePaletteGroup + (previous_spr_pal_id * 2)]; + } + + if (pal4 == 0xFF) { + pal4 = 0; // Fallback to 0 if still 0xFF + } + + if (pal5 == 0xFF) { + pal5 = (*rom_)[kOverworldSpritePaletteGroup + (previous_spr_pal_id * 2) + 1]; + } + + if (pal5 == 0xFF) { + pal5 = 0; // Fallback to 0 if still 0xFF + } + ASSIGN_OR_RETURN(gfx::SnesPalette spr, GetPalette(rom_->palette_group().sprites_aux3, pal4, previous_spr_pal_id, 24)); diff --git a/src/app/zelda3/overworld/overworld_map.h b/src/app/zelda3/overworld/overworld_map.h index b516e523..2b2468aa 100644 --- a/src/app/zelda3/overworld/overworld_map.h +++ b/src/app/zelda3/overworld/overworld_map.h @@ -17,6 +17,7 @@ namespace zelda3 { static constexpr int kTileOffsets[] = {0, 8, 4096, 4104}; // 1 byte, not 0 if enabled +// vanilla, v2, v3 constexpr int OverworldCustomASMHasBeenApplied = 0x140145; // 2 bytes for each overworld area (0x140) @@ -54,6 +55,24 @@ constexpr int OverworldCustomTileGFXGroupArray = 0x140480; // 1 byte, not 0 if enabled constexpr int OverworldCustomTileGFXGroupEnabled = 0x140148; +// v3 expanded constants +constexpr int kOverworldMessagesExpanded = 0x1417F8; +constexpr int kOverworldMapParentIdExpanded = 0x140998; +constexpr int kOverworldTransitionPositionYExpanded = 0x140F38; +constexpr int kOverworldTransitionPositionXExpanded = 0x141078; +constexpr int kOverworldScreenTileMapChangeByScreen1Expanded = 0x140A38; +constexpr int kOverworldScreenTileMapChangeByScreen2Expanded = 0x140B78; +constexpr int kOverworldScreenTileMapChangeByScreen3Expanded = 0x140CB8; +constexpr int kOverworldScreenTileMapChangeByScreen4Expanded = 0x140DF8; + +constexpr int kOverworldSpecialSpriteGFXGroup = 0x016811; +constexpr int kOverworldSpecialGFXGroup = 0x016821; +constexpr int kOverworldSpecialPALGroup = 0x016831; +constexpr int kOverworldSpecialSpritePalette = 0x016841; +constexpr int kOverworldPalettesScreenToSetNew = 0x4C635; +constexpr int kOverworldSpecialSpriteGfxGroupExpandedTemp = 0x0166E1; +constexpr int kOverworldSpecialSpritePaletteExpandedTemp = 0x016701; + constexpr int kDarkWorldMapIdStart = 0x40; constexpr int kSpecialWorldMapIdStart = 0x80; @@ -71,6 +90,13 @@ typedef struct OverworldMapTiles { OverworldBlockset special_world; // 32 maps } OverworldMapTiles; +enum class AreaSizeEnum { + SmallArea = 0, + LargeArea = 1, + WideArea = 2, + TallArea = 3, +}; + /** * @brief Represents a single Overworld map screen. */ @@ -109,6 +135,15 @@ class OverworldMap : public gfx::GfxContext { auto area_music(int i) const { return area_music_[i]; } auto static_graphics(int i) const { return static_graphics_[i]; } auto large_index() const { return large_index_; } + auto area_size() const { return area_size_; } + + auto main_palette() const { return main_palette_; } + void set_main_palette(uint8_t palette) { main_palette_ = palette; } + + auto area_specific_bg_color() const { return area_specific_bg_color_; } + void set_area_specific_bg_color(uint16_t color) { + area_specific_bg_color_ = color; + } auto mutable_current_graphics() { return ¤t_gfx_; } auto mutable_area_graphics() { return &area_graphics_; } @@ -133,6 +168,7 @@ class OverworldMap : public gfx::GfxContext { parent_ = parent_index; large_index_ = quadrant; large_map_ = true; + area_size_ = AreaSizeEnum::LargeArea; } void SetAsSmallMap(int index = -1) { @@ -142,6 +178,12 @@ class OverworldMap : public gfx::GfxContext { parent_ = index_; large_index_ = 0; large_map_ = false; + area_size_ = AreaSizeEnum::SmallArea; + } + + void SetAreaSize(AreaSizeEnum size) { + area_size_ = size; + large_map_ = (size == AreaSizeEnum::LargeArea); } void Destroy() { @@ -185,25 +227,29 @@ class OverworldMap : public gfx::GfxContext { int index, int previous_index, int limit); - Rom *rom_; + Rom* rom_; bool built_ = false; bool large_map_ = false; bool initialized_ = false; bool mosaic_ = false; - int index_ = 0; // Map index - int parent_ = 0; // Parent map index - int large_index_ = 0; // Quadrant ID [0-3] - int world_ = 0; // World ID [0-2] - int game_state_ = 0; // Game state [0-2] - int main_gfx_id_ = 0; // Main Gfx ID + int index_ = 0; // Map index + int parent_ = 0; // Parent map index + int large_index_ = 0; // Quadrant ID [0-3] + int world_ = 0; // World ID [0-2] + int game_state_ = 0; // Game state [0-2] + int main_gfx_id_ = 0; // Main Gfx ID + AreaSizeEnum area_size_ = AreaSizeEnum::SmallArea; // Area size for v3 uint16_t message_id_ = 0; uint8_t area_graphics_ = 0; uint8_t area_palette_ = 0; + uint8_t main_palette_ = 0; // Custom Overworld Main Palette ID uint8_t animated_gfx_ = 0; // Custom Overworld Animated ID uint16_t subscreen_overlay_ = 0; // Custom Overworld Subscreen Overlay ID + uint16_t area_specific_bg_color_ = + 0; // Custom Overworld Area-Specific Background Color std::array custom_gfx_ids_; std::array sprite_graphics_;