Files
2026-08-14 01:42:59 -04:00

1749 lines
26 KiB
NASM

UnfreezeEverything::
call UnfreezeAllObjects
call UnfreezePlayer
ret
; Runs a map script indexed by wMapScriptNumber
RunMapScript::
push hl
push de
push bc
ld a, [wMapScriptNumber]
add a, a
add a, a
ld d, 0
ld e, a
add hl, de
ld a, [hli]
ld h, [hl]
ld l, a
ld de, .return
push de
jp hl
.return
pop bc
pop de
pop hl
ret
SetMapStatus::
push af
ld a, [wMapStatus]
ld [wLastMapStatus], a
pop af
ld [wMapStatus], a
ret
ClearMapBuffer::
ld hl, wMapBuffer
ld bc, wMapBufferEnd - wMapBuffer
ld a, 0
call ByteFill
ret
SetUpMapBuffer::
call ClearMapBuffer
ldh a, [hROMBank]
push af
ld a, BANK(MapScenes)
call Bankswitch
ld hl, MapScenes
ld a, [wMapGroup]
ld b, a
ld a, [wMapId]
ld c, a
.search
ld a, [hli]
cp $FF
jr z, .done
cp b
jr nz, .next_with_id
ld a, [hli]
cp c
jr nz, .next_without_id
; Match found!
ld de, wMapScriptNumberLocation
call GetMapScriptNumber ; Read map script from pointed location
call CopyWord ; Copy map script pointer
ld de, wMapScriptPointerLocation
call CopyWord
.done
pop af
call Bankswitch
ret
.next_with_id
ld de, 7
add hl, de
jr .search
.next_without_id
ld de, 6
add hl, de
jr .search
GetMapScriptNumber::
push hl
ld a, [hli]
ld h, [hl]
ld l, a
ld a, [hl]
ld [wMapScriptNumber], a
pop hl
ret
CopyWord::
ld a, [hli]
ld [de], a
ld a, [hli]
inc de
ld [de], a
ret
SetMapScriptNumber:: ; unreferenced
ld [wMapScriptNumber], a
ret
IncMapScriptNumber:: ; unreferenced
ld hl, wMapScriptNumber
inc [hl]
ret
DecMapScriptNumber:: ; unreferenced
ld hl, wMapScriptNumber
dec [hl]
ret
WriteBackMapScriptNumber::
ld a, [wMapScriptNumberLocation]
ld l, a
ld a, [wMapScriptNumberLocation + 1]
ld h, a
ld a, [wMapScriptNumber]
ld [hl], a
ret
GetMapPointer::
ld a, [wMapGroup]
ld b, a
ld a, [wMapId]
ld c, a
GetAnyMapPointer::
push bc
dec b
ld c, b
ld b, 0
ld hl, MapGroupPointers
add hl, bc
add hl, bc
ld a, [hli]
ld h, [hl]
ld l, a
pop bc
dec c
ld b, 0
ld a, 8
call AddNTimes
ret
SwitchToMapBank::
ld a, [wMapGroup]
ld b, a
ld a, [wMapId]
ld c, a
SwitchToAnyMapBank::
push hl
ld a, BANK(MapGroupPointers)
call Bankswitch
call GetAnyMapPointer
ld a, [hl]
call Bankswitch
pop hl
ret
CopyMapPartial::
ldh a, [hROMBank]
push af
ld a, BANK(MapGroupPointers)
call Bankswitch
call GetMapPointer
ld de, wMapPartial
ld bc, wMapPartialEnd - wMapPartial
call CopyBytes
pop af
call Bankswitch
ret
GetMapAttributesPointer::
push bc
ldh a, [hROMBank]
push af
ld a, BANK(MapGroupPointers)
call Bankswitch
ld a, [wMapGroup]
ld b, a
ld a, [wMapId]
ld c, a
call GetAnyMapPointer
ld bc, MAP_MAPATTRIBUTES
add hl, bc
ld a, [hli]
ld h, [hl]
ld l, a
pop af
call Bankswitch
pop bc
ret
GetMapEnvironment::
push hl
push bc
ldh a, [hROMBank]
push af
ld a, BANK(MapGroupPointers)
call Bankswitch
call GetMapPointer
ld bc, MAP_ENVIRONMENT
add hl, bc
ld b, [hl]
pop af
call Bankswitch
ld a, b
pop bc
pop hl
ret
GetAnyMapEnvironment::
ldh a, [hROMBank]
push af
ld a, BANK(MapGroupPointers)
call Bankswitch
call GetAnyMapPointer
ld bc, MAP_ENVIRONMENT
add hl, bc
ld b, [hl]
pop af
call Bankswitch
ld a, b
ret
GetWorldMapLocation::
ldh a, [hROMBank]
push af
ld a, BANK(MapGroupPointers)
call Bankswitch
call GetAnyMapPointer
ld bc, MAP_LOCATION
add hl, bc
ld b, [hl]
pop af
call Bankswitch
ld a, b
ret
DummyMapFunction::
ret
LoadMap::
ldh a, [hMapEntryMethod]
and a ; Possible bug: if the entry method is $X0, this will overflow
ret z
and $0F
dec a
ld hl, .jumptable
call CallJumptable
xor a
ldh [hMapEntryMethod], a
scf
ret
.jumptable
dw MapSetup_NewGame
dw MapSetup_Continue
dw MapSetup_Fight
dw MapSetup_FallingWarp
dw MapSetup_FallingWarp
dw MapSetup_Warp
dw MapSetup_Connection
dw MapSetup_Link
MapSetup_Link::
ldh a, [hROMBank]
push af
call MapSetup_Continue
pop af
call Bankswitch
ret
MapSetup_Fight::
call DisableLCD
call DisableAudio
call VolumeOff
call SwitchToMapBank
call LoadGraphics
call ChangeMap
call SaveScreen
call LoadMapTimeOfDay
call EnableLCD
call PlayMapMusic
ld a, (1 << MUSIC_FADE_IN_F) | 8
ld [wMusicFade], a
ld b, SGB_MAP_PALS
call GetSGBLayout
call LoadWildMonData
call FadeIn
ret
MapSetup_Continue::
call DisableLCD
call DisableAudio
call VolumeOff
call SwitchToMapBank
call SetUpMapBuffer
call InitObjectMasks
call LoadGraphics
call ChangeMap
call LoadMapTimeOfDay
call EnableLCD
call PlayMapMusic
ld a, (1 << MUSIC_FADE_IN_F) | 8
ld [wMusicFade], a
ld b, SGB_MAP_PALS
call GetSGBLayout
call FadeIn
ret
MapSetup_FallingWarp::
callfar OverworldFadeOut
MapSetup_NewGame::
call DisableLCD
call DisableAudio
call VolumeOff
callfar LoadSpawnPoint
call CopyMapPartialAndAttributes
call SetUpMapBuffer
call InitObjectMasks
call RefreshPlayerCoords
call GetCoordOfUpperLeftCorner
call LoadGraphics
call ChangeMap
call LoadMapTimeOfDay
call InitializeVisibleSprites
call EnableLCD
call PlayMapMusic
ld a, (1 << MUSIC_FADE_IN_F) | 8
ld [wMusicFade], a
ld b, SGB_MAP_PALS
call GetSGBLayout
call LoadWildMonData
call SetPlayerFacingDown
call FadeIn
ret
MapSetup_Warp::
callfar OverworldFadeOut
call DisableLCD
call WarpEnvironmentCheck
ld a, [wNextWarp]
ld [wWarpNumber], a
ld a, [wNextMapGroup]
ld [wMapGroup], a
ld a, [wNextMapNumber]
ld [wMapId], a
call CopyMapPartialAndAttributes
call SetUpMapBuffer
call InitObjectMasks
call GetWarpDestCoords
call RefreshPlayerCoords
call LoadGraphics
call ChangeMap
call LoadMapTimeOfDay
call InitializeVisibleSprites
call EnableLCD
call PlayMapMusic
ld b, SGB_MAP_PALS
call GetSGBLayout
call LoadWildMonData
call FadeIn
call CheckExitTiles
ret
LoadMapTimeOfDay::
callfar ReplaceTimeOfDayPals
call LoadMapPart
call .ClearBGMap
call .PushAttrMap
ret
.ClearBGMap
ld a, HIGH(vBGMap0)
ld [wBGMapAnchor + 1], a
xor a ; LOW(vBGMap0)
ld [wBGMapAnchor], a
ldh [hSCY], a
ldh [hSCX], a
ld a, '■'
ld bc, vBGMap1 - vBGMap0
hlbgcoord 0, 0
call ByteFill
ret
.PushAttrMap::
decoord 0, 0
hlbgcoord 0, 0
ld c, SCREEN_WIDTH
ld b, SCREEN_HEIGHT
.row
push bc
.column
ld a, [de]
inc de
ld [hli], a
dec c
jr nz, .column
ld bc, TILEMAP_WIDTH - SCREEN_WIDTH
add hl, bc
pop bc
dec b
jr nz, .row
ret
LoadWildMonData::
callfar _LoadWildMonData
ret
LoadGraphics::
call LoadTileset
call LoadTilesetGFX
farcall RefreshSprites
call LoadFontExtra
ret
InitializeVisibleSprites::
callfar _InitializeVisibleSprites
ret
FadeIn:: ; This is not OverworldFadeIn, but I don't know what it is
call InitToolgearBuffer
call RefreshTiles
ld hl, wStateFlags
set SPRITE_UPDATES_DISABLED_F, [hl]
call CheckExitTiles
callfar InitSprites
call DelayFrame
callfar OverworldFadeIn
ret
CheckExitTiles::
ld a, movement_step_sleep
ld [wPlayerMovement], a
xor a
ld [wPlayerStepFrame], a
ld a, [wPlayerFacing]
and %00001100
ld [wPlayerFacing], a
ld a, [wPlayerTile]
and COLLMASK_TYPE
cp COLLMASK_TYPE_WARPS
ret nz
ld a, [wPlayerTile]
cp COLL_LADDER
ret z
cp COLL_CARPET
ret z
cp COLL_CARPET | COLLFLAG_ENCOUNTER
ret z
SetPlayerFacingDown::
ld a, $0
ld [wPlayerFacing], a
ld a, $0
ld d, DOWN
call SetObjectFacing
ret
MapSetup_Connection::
call EnterMapConnection
call CopyMapPartialAndAttributes
call SetUpMapBuffer
call InitObjectMasks
call RefreshPlayerCoords
call InitializeVisibleSprites
call ChangeMap
call SaveScreen
call FadeToMapMusic
ld b, SGB_MAP_PALS
call GetSGBLayout
call LoadWildMonData
scf
ret
CheckMovingOffEdgeOfMap::
ld a, [wPlayerStepDirection]
cp STANDING
ret z
and a ; DOWN
jr z, .down
cp UP
jr z, .up
cp LEFT
jr z, .left
cp RIGHT
jr z, .right
and a
ret
.down
ld a, [wPlayerMapY]
sub 4
ld b, a
ld a, [wMapHeight]
add a
cp b
jr z, .ok
and a
ret
.up
ld a, [wPlayerMapY]
sub 4
cp -1
jr z, .ok
and a
ret
.left
ld a, [wPlayerMapX]
sub 4
cp -1
jr z, .ok
and a
ret
.right
ld a, [wPlayerMapX]
sub 4
ld b, a
ld a, [wMapWidth]
add a
cp b
jr z, .ok
and a
ret
.ok
ld a, MAPSETUP_CONNECTION
ldh [hMapEntryMethod], a
scf
ret
EnterMapConnection:
; Return carry if a connection has been entered.
ld a, [wPlayerStepDirection]
and a
jp z, .south
cp UP
jp z, .north
cp LEFT
jp z, .west
cp RIGHT
jp z, .east
ret
.west
ld a, [wWestConnectedMapGroup]
ld [wMapGroup], a
ld a, [wWestConnectedMapNumber]
ld [wMapId], a
ld a, [wWestConnectionStripXOffset]
ld [wXCoord], a
ld a, [wWestConnectionStripYOffset]
ld hl, wYCoord
add [hl]
ld [hl], a
ld c, a
ld hl, wWestConnectionWindow
ld a, [hli]
ld h, [hl]
ld l, a
srl c
jr z, .skip_to_load
ld a, [wWestConnectedMapWidth]
add 6
ld e, a
ld d, 0
.loop
add hl, de
dec c
jr nz, .loop
.skip_to_load
ld a, l
ld [wOverworldMapAnchor], a
ld a, h
ld [wOverworldMapAnchor + 1], a
jp .done
.east
ld a, [wEastConnectedMapGroup]
ld [wMapGroup], a
ld a, [wEastConnectedMapNumber]
ld [wMapId], a
ld a, [wEastConnectionStripXOffset]
ld [wXCoord], a
ld a, [wEastConnectionStripYOffset]
ld hl, wYCoord
add [hl]
ld [hl], a
ld c, a
ld hl, wEastConnectionWindow
ld a, [hli]
ld h, [hl]
ld l, a
srl c
jr z, .skip_to_load2
ld a, [wEastConnectedMapWidth]
add 6
ld e, a
ld d, 0
.loop2
add hl, de
dec c
jr nz, .loop2
.skip_to_load2
ld a, l
ld [wOverworldMapAnchor], a
ld a, h
ld [wOverworldMapAnchor + 1], a
jp .done
.north
ld a, [wNorthConnectedMapGroup]
ld [wMapGroup], a
ld a, [wNorthConnectedMapNumber]
ld [wMapId], a
ld a, [wNorthConnectionStripYOffset]
ld [wYCoord], a
ld a, [wNorthConnectionStripXOffset]
ld hl, wXCoord
add [hl]
ld [hl], a
ld c, a
ld hl, wNorthConnectionWindow
ld a, [hli]
ld h, [hl]
ld l, a
ld b, 0
srl c
add hl, bc
ld a, l
ld [wOverworldMapAnchor], a
ld a, h
ld [wOverworldMapAnchor + 1], a
jp .done
.south
ld a, [wSouthConnectedMapGroup]
ld [wMapGroup], a
ld a, [wSouthConnectedMapNumber]
ld [wMapId], a
ld a, [wSouthConnectionStripYOffset]
ld [wYCoord], a
ld a, [wSouthConnectionStripXOffset]
ld hl, wXCoord
add [hl]
ld [hl], a
ld c, a
ld hl, wSouthConnectionWindow
ld a, [hli]
ld h, [hl]
ld l, a
ld b, 0
srl c
add hl, bc
ld a, l
ld [wOverworldMapAnchor], a
ld a, h
ld [wOverworldMapAnchor + 1], a
.done
scf
ret
WarpCheck::
call GetDestinationWarpPointer
ret nc
ld a, [hli]
ld [wNextWarp], a
ld a, [hli]
ld [wNextMapGroup], a
ld a, [hli]
ld [wNextMapNumber], a
ld a, c
ld [wPrevWarp], a
ld a, MAPSETUP_WARP
ldh [hMapEntryMethod], a
scf
ret
GetDestinationWarpPointer:
ld a, [wPlayerMapY]
sub 4
ld d, a
ld a, [wPlayerMapX]
sub 4
ld e, a
ld a, [wCurMapWarpCount]
ld c, a
and a
ret z
ld hl, wCurMapWarps
.next
ld a, [hli]
cp d
jr nz, .nope
ld a, [hl]
cp e
jr z, .found_warp
.nope
push de
ld de, MAP_MAPATTRIBUTES_HI
add hl, de
pop de
dec c
jr nz, .next
xor a
ret
.found_warp
ld a, [wCurMapWarpCount]
inc a
sub c
ld c, a
inc hl
scf
ret
CopyMapPartialAndAttributes::
call SwitchToMapBank
call CopyAndReadHeaders
call ReadObjectEvents
ret
CopyAndReadHeaders::
call CopyMapPartial
call GetMapAttributesPointer
ld hl, wMapAttributesPtr
ld a, [hli]
ld h, [hl]
ld l, a
ld de, wMapAttributes
ld c, wMapAttributesEnd - wMapAttributes
.copy
ld a, [hli]
ld [de], a
inc de
dec c
jr nz, .copy
call GetMapConnections
ld hl, wMapObjectsPtr
ld a, [hli]
ld h, [hl]
ld l, a
inc hl
inc hl
call ReadWarps
call ReadBGEvents
ret
GetMapConnections::
ld a, $ff
ld [wNorthConnectedMapGroup], a
ld [wSouthConnectedMapGroup], a
ld [wWestConnectedMapGroup], a
ld [wEastConnectedMapGroup], a
ld a, [wMapConnections]
ld b, a
bit 3, b
jr z, .no_north
ld de, wNorthMapConnection
call GetMapConnection
.no_north
bit 2, b
jr z, .no_south
ld de, wSouthMapConnection
call GetMapConnection
.no_south
bit 1, b
jr z, .no_west
ld de, wWestMapConnection
call GetMapConnection
.no_west
bit 0, b
jr z, .no_east
ld de, wEastMapConnection
call GetMapConnection
.no_east
ret
GetMapConnection::
ld c, wSouthMapConnection - wNorthMapConnection
.copy
ld a, [hli]
ld [de], a
inc de
dec c
jr nz, .copy
ret
ReadWarps::
ld a, [hli]
ld [wCurMapWarpCount], a
and a
ret z
ld c, a
ld de, wCurMapWarps
.next
ld b, MAP_LOCATION
.copy
ld a, [hli]
ld [de], a
inc de
dec b
jr nz, .copy
inc hl
inc hl
dec c
jr nz, .next
ret
ReadBGEvents::
ld a, [hli]
ld [wCurMapBGEventCount], a
and a
ret z
ld c, a
ld de, wCurMapBGEvents
.next
ld b, BG_EVENT_SIZE
.copy
ld a, [hli]
ld [de], a
inc de
dec b
jr nz, .copy
dec c
jr nz, .next
ret
ReadObjectEvents::
push hl
call ClearObjectStructs
pop de
ld hl, wMap2Object
ld a, [de]
inc de
ld [wCurMapObjectCount], a
and a
jr z, .skip
ld c, a
.next
push bc
push hl
ld a, $ff
ld [hli], a
ld b, OBJECT_EVENT_SIZE
.copy
ld a, [de]
inc de
ld [hli], a
dec b
jr nz, .copy
pop hl
ld bc, MAPOBJECT_LENGTH
add hl, bc
pop bc
dec c
jr nz, .next
.skip
ld a, [wCurMapObjectCount]
ld c, a
ld a, NUM_OBJECTS
sub c
jr z, .finish
ld bc, 1
add hl, bc ; Very thorough optimization. Don't do this at home, kids.
ld bc, MAPOBJECT_LENGTH
.clear
ld [hl], 0
add hl, bc
dec a
jr nz, .clear
.finish
ld h, d
ld l, e
ret
ClearObjectStructs::
xor a
ld [wReservedObjectStruct], a
ld hl, wObject2Struct
ld de, OBJECT_LENGTH
ld c, 7
.clear_struct
ld [hl], a
add hl, de
dec c
jr nz, .clear_struct
ld hl, wMinorObjects
ld de, MINOR_OBJECT_LENGTH
ld c, 4
xor a
.clear_cmd_queue
ld [hl], a
add hl, de
dec c
jr nz, .clear_cmd_queue
ret
Unreferenced_ReadWord::
ld e, [hl]
inc hl
ld d, [hl]
inc hl
ret
; Initializes all object masks except the first two entries: the player and follower.
InitObjectMasks::
xor a
ld hl, wObjectMasks
ld [hli], a
ld [hli], a
ld hl, wObjectMasks + NUM_RESERVED_OBJECTS
ld bc, NUM_OBJECTS - NUM_RESERVED_OBJECTS
ld a, $ff
call ByteFill
ld hl, wMapScriptPointerLocation
ld e, [hl]
inc hl
ld d, [hl]
ld a, e
or d
jr z, .null
ld a, [wMapBuffer]
ld l, a
ld h, 0
add hl, hl
add hl, hl
add hl, de
inc hl
inc hl
ld c, [hl]
inc hl
ld b, [hl]
ld de, wObjectMasks
.next
ld a, [bc]
inc bc
cp $ff ; Could have used one of the `inc a` below
jr z, .done
inc a
inc a
and $0f
ld l, a
ld h, 0
add hl, de
ld [hl], 0
jr .next
.null
ld hl, wObjectMasks + NUM_RESERVED_OBJECTS
ld bc, NUM_OBJECTS - NUM_RESERVED_OBJECTS
xor a
call ByteFill
.done
ret
GetWarpDestCoords::
ld hl, wMapObjectsPtr
ld a, [hli]
ld h, [hl]
ld l, a
rept 3 ; get to the warp coords
inc hl
endr
ld a, [wWarpNumber]
dec a
ld c, a
ld b, 0
ld a, WARP_EVENT_SIZE
call AddNTimes
ld a, [hli]
ld [wYCoord], a
ld a, [hli]
ld [wXCoord], a
call GetCoordOfUpperLeftCorner
ret
.unreferenced_pass
inc hl
inc hl
inc hl
ld a, [hli]
ld [wOverworldMapAnchor], a
ld a, [hl]
ld [wOverworldMapAnchor + 1], a
ld a, [wYCoord]
and 1
ld [wMetatileNextY], a
ld a, [wXCoord]
and 1
ld [wMetatileNextX], a
ret
GetCoordOfUpperLeftCorner::
ld hl, wOverworldMapBlocks
ld a, [wXCoord]
bit 0, a
jr nz, .increment_then_halve1
srl a
add a, 1
jr .resume
.increment_then_halve1
add a, 1
srl a
.resume
ld c, a
ld b, 0
add hl, bc
ld a, [wMapWidth]
add a, 6
ld c, a
ld b, 0
ld a, [wYCoord]
bit 0, a
jr nz, .increment_then_halve2
srl a
add a, 1
jr .resume2
.increment_then_halve2
add a, 1
srl a
.resume2
call AddNTimes
ld a, l
ld [wOverworldMapAnchor], a
ld a, h
ld [wOverworldMapAnchor + 1], a
ld a, [wYCoord]
and 1
ld [wMetatileNextY], a
ld a, [wXCoord]
and 1
ld [wMetatileNextX], a
ret
WarpEnvironmentCheck::
call GetMapEnvironment
cp ROUTE
jr z, .interior
cp TOWN
jr z, .interior
ret
.interior
ld a, [wNextMapGroup]
ld b, a
ld a, [wNextMapNumber]
ld c, a
call GetAnyMapEnvironment
cp INDOOR
jr z, .exterior
cp CAVE
jr z, .exterior
cp GATE
jr z, .exterior ; BUG: ENVIRONMENT_5, and DUNGEON are missing.
ret
.exterior
ld hl, wDigWarpNumber
ld a, [wPrevWarp]
ld [hli], a
ld a, [wMapGroup]
ld [hli], a
ld a, [wMapId]
ld [hli], a
ret
LoadMapPart::
callfar UpdateTimeOfDayPal
ldh a, [hROMBank]
push af
ld a, [wTilesetBank]
call Bankswitch
call LoadMetatiles
ld a, '■'
hlcoord 0, 0
ld bc, SCREEN_AREA
call ByteFill
call ApplyFlashlight
pop af
call Bankswitch
ret
LoadMetatiles::
ld a, [wOverworldMapAnchor]
ld e, a
ld a, [wOverworldMapAnchor + 1]
ld d, a
ld hl, wTileMapBackup
ld b, SCREEN_META_HEIGHT
.row
push de
push hl
ld c, SCREEN_META_WIDTH
.tile
push bc
push de
push hl
ld a, [de]
ld c, a
call DrawMetatile
pop hl
ld bc, METATILE_WIDTH
add hl, bc
pop de
inc de
pop bc
dec c
jr nz, .tile
pop hl
ld de, TILEMAP_WIDTH * 3
add hl, de
pop de
ld a, [wMapWidth]
add a, SCREEN_META_WIDTH
add a, e
ld e, a
jr nc, .nocarry
inc d
.nocarry
dec b
jr nz, .row
ret
ApplyFlashlight::
ld hl, wTileMapBackup
ld a, [wMetatileNextY]
and a
jr z, .top_row
ld bc, SURROUNDING_WIDTH * 2
add hl, bc
.top_row
ld a, [wMetatileNextX]
and a
jr z, .left_col
inc hl
inc hl
.left_col
ldh a, [hOverworldFlashlightEffect]
and a
jr z, .no_flashlight
cp 1
jr z, .force_1
cp 2
jr z, .force_2
cp 3
jr z, .force_3
jp .force_4
.no_flashlight
ld de, wTileMap
ld b, SCREEN_HEIGHT
.row
ld c, SCREEN_WIDTH
.tile
ld a, [hli]
ld [de], a
inc de
dec c
jr nz, .tile
ld a, l
add a, 4
ld l, a
jr nc, .nocarry
inc h
.nocarry
dec b
jr nz, .row
ret
; redraw_with_flashlight force
; force = 1, 2 or 3
; 0 and 4 have special handling, see above and below
MACRO redraw_with_flashlight
decoord \1 * 2, \1 * 2
ld bc, SURROUNDING_WIDTH * (\1 * 2) + (\1 * 2)
add hl, bc
ld c, SCREEN_HEIGHT - \1 * 4
.row\1
ld b, SCREEN_HEIGHT - \1 * 4
.tile\1
ld a, [hli]
ld [de], a
inc de
dec b
jr nz, .tile\1
ld a, l
add a, 6 + \1 * 4
ld l, a
jr nc, .nohlcarry\1
inc h
.nohlcarry\1
ld a, e
add a, 2 + \1 * 4
ld e, a
jr nc, .nodecarry\1
inc d
.nodecarry\1
dec c
jr nz, .row\1
ENDM
.force_1
redraw_with_flashlight 1
ret
.force_2
redraw_with_flashlight 2
ret
.force_3
redraw_with_flashlight 3
ret
.force_4
; This also applies to larger values than 4
decoord 4 * 2, 4 * 2
ld bc, SURROUNDING_WIDTH * (4 * 2) + (4 * 2)
add hl, bc
ld a, [hli]
ld [de], a
inc de
ld a, [hli]
ld [de], a
ld bc, 6 + 4 * 4
add hl, bc
ld a, e
add a, 2 + 4 * 4 + 1 ; Compensate missing `inc de`
ld e, a
jr nc, .nocarry9001
inc d
.nocarry9001
ld a, [hli]
ld [de], a
inc de
ld a, [hli]
ld [de], a
ret
DrawMetatile::
push hl
ld hl, wTilesetBlocksAddress
ld a, [hli]
ld h, [hl]
ld l, a
swap c
ld a, c
and $0f
ld b, a
ld a, c
and $f0
ld c, a
add hl, bc
pop de
lb bc, SCREEN_WIDTH, 4
.row
REPT 4
ld a, [hli]
ld [de], a
inc de
ENDR
ld a, e
add a, b
ld e, a
jr nc, .nocarry
inc d
.nocarry
dec c
jr nz, .row
ret
ChangeMap::
ld hl, wOverworldMapBlocks
ld bc, wOverworldMapBlocksEnd - wOverworldMapBlocks
ld a, 0
call ByteFill
ld hl, wOverworldMapBlocks
ld a, [wMapWidth]
ldh [hConnectedMapWidth], a
add a, 6
ldh [hConnectionStripLength], a
ld c, a
ld b, 0
add hl, bc
add hl, bc
add hl, bc
ld c, 3
add hl, bc
ld a, [wMapBlocksPointer]
ld e, a
ld a, [wMapBlocksPointer + 1]
ld d, a
ld a, [wMapHeight]
ld b, a
.row
push hl
ldh a, [hConnectedMapWidth]
ld c, a
.col
ld a, [de]
inc de
ld [hli], a
dec c
jr nz, .col
pop hl
ldh a, [hConnectionStripLength]
add l
ld l, a
jr nc, .okay
inc h
.okay
dec b
jr nz, .row
; FillMapConnections::
ld a, [wNorthConnectedMapGroup]
cp $ff
jr z, .south
ld b, a
ld a, [wNorthConnectedMapNumber]
ld c, a
call SwitchToAnyMapBank
ld a, [wNorthConnectionStripPointer]
ld l, a
ld a, [wNorthConnectionStripPointer + 1]
ld h, a
ld a, [wNorthConnectionStripLocation]
ld e, a
ld a, [wNorthConnectionStripLocation + 1]
ld d, a
ld a, [wNorthConnectionStripLength]
ldh [hConnectionStripLength], a
ld a, [wNorthConnectedMapWidth]
ldh [hConnectedMapWidth], a
call FillNorthConnectionStrip
.south
ld a, [wSouthConnectedMapGroup]
cp $ff
jr z, .west
ld b, a
ld a, [wSouthConnectedMapNumber]
ld c, a
call SwitchToAnyMapBank
ld a, [wSouthConnectionStripPointer]
ld l, a
ld a, [wSouthConnectionStripPointer + 1]
ld h, a
ld a, [wSouthConnectionStripLocation]
ld e, a
ld a, [wSouthConnectionStripLocation + 1]
ld d, a
ld a, [wSouthConnectionStripLength]
ldh [hConnectionStripLength], a
ld a, [wSouthConnectedMapWidth]
ldh [hConnectedMapWidth], a
call FillSouthConnectionStrip
.west
ld a, [wWestConnectedMapGroup]
cp $ff
jr z, .east
ld b, a
ld a, [wWestConnectedMapNumber]
ld c, a
call SwitchToAnyMapBank
ld a, [wWestConnectionStripPointer]
ld l, a
ld a, [wWestConnectionStripPointer + 1]
ld h, a
ld a, [wWestConnectionStripLocation]
ld e, a
ld a, [wWestConnectionStripLocation + 1]
ld d, a
ld a, [wWestConnectionStripLength]
ld b, a
ld a, [wWestConnectedMapWidth]
ldh [hConnectionStripLength], a
call FillWestConnectionStrip
.east
ld a, [wEastConnectedMapGroup]
cp $ff
jr z, .done
ld b, a
ld a, [wEastConnectedMapNumber]
ld c, a
call SwitchToAnyMapBank
ld a, [wEastConnectionStripPointer]
ld l, a
ld a, [wEastConnectionStripPointer + 1]
ld h, a
ld a, [wEastConnectionStripLocation]
ld e, a
ld a, [wEastConnectionStripLocation + 1]
ld d, a
ld a, [wEastConnectionStripLength]
ld b, a
ld a, [wEastConnectedMapWidth]
ldh [hConnectionStripLength], a
call FillEastConnectionStrip
.done
ret
FillNorthConnectionStrip::
FillSouthConnectionStrip::
ld c, 3
.y
push de
push hl
ldh a, [hConnectionStripLength]
ld b, a
.x
ld a, [hli]
ld [de], a
inc de
dec b
jr nz, .x
pop hl
ldh a, [hConnectedMapWidth]
ld e, a
ld d, 0
add hl, de
pop de
ld a, [wMapWidth]
add a, 6
add e
ld e, a
jr nc, .okay
inc d
.okay
dec c
jr nz, .y
ret
FillWestConnectionStrip::
FillEastConnectionStrip::
.loop
ld a, [wMapWidth]
add a, 6
ldh [hConnectedMapWidth], a
push de
push hl
ld a, [hli]
ld [de], a
inc de
ld a, [hli]
ld [de], a
inc de
ld a, [hli]
ld [de], a
inc de
pop hl
ldh a, [hConnectionStripLength]
ld e, a
ld d, 0
add hl, de
pop de
ldh a, [hConnectedMapWidth]
add e
ld e, a
jr nc, .okay
inc d
.okay
dec b
jr nz, .loop
ret
OverworldLoop::
.loop
call LoadMap
call _OverworldLoop
jr .loop
_OverworldLoop::
push hl
push de
push bc
push af
ld a, [wMapStatus]
and $f
add a
ld e, a
ld d, $0
ld hl, .Pointers
add hl, de
add hl, de
ld a, [hli]
call Bankswitch
inc hl
ld a, [hli]
ld h, [hl]
ld l, a
ld de, .Return
push de
jp hl
.Return:
pop af
pop bc
pop de
pop hl
ret
; Battle-related functions are run in bank $0e, even though they're in bank $f now.
; This doesn't change anything in practice because we still call a predef to go to that bank.
MACRO owloop
IF _NARG == 2
db BANK(OverworldLoop_\1) ; bank
ELSE
db \3 ; incorrect bank
ENDC
db \2 ; unused?
dw OverworldLoop_\1 ; pointer to function
ENDM
.Pointers:
owloop Main, $55
owloop EventRunning, $55
owloop Unused_02, $55
owloop StartBattle, $33, $0e
owloop ReturnToMain, $55
owloop UnusedBattle, $33, $0e
owloop Unused_06, $33
owloop Unused_07, $33
owloop StartBattle, $33, $0e
owloop DebugMapViewer, $55
owloop UnusedDarkness, $55
owloop ExitBattle, $33, $0e
owloop ReturnFromBattle, $33
OverworldLoop_Main::
.loop:
ld hl, wJoypadDisable
set JOYPAD_DISABLE_CUTSCENE_F, [hl]
set JOYPAD_DISABLE_SYNC_MUTEX_F, [hl]
call UpdateTime
call TimeOfDayPals
ld hl, wJoypadDisable
res JOYPAD_DISABLE_CUTSCENE_F, [hl]
res JOYPAD_DISABLE_SYNC_MUTEX_F, [hl]
call GetJoypad
call RunMapTextSubroutine
ld hl, wOverworldFlags
bit OVERWORLD_PAUSE_MAP_PROCESSES_F, [hl]
res OVERWORLD_PAUSE_MAP_PROCESSES_F, [hl]
ret nz
call TestWildBattleStart
ret nz
call OverworldStartButtonCheck
ret nz
callfar OverworldMovementCheck
ldh a, [hMapEntryMethod]
and a
ret nz
call HandleMapObjects
jr nc, .loop
farcall CheckObjectEnteringVisibleRange
ld a, [wOverworldFlags]
bit OVERWORLD_DISABLE_MAP_CONNECTIONS_F, a
jr nz, .loop
call CheckMovingOffEdgeOfMap
ret c
call WarpCheck
ret c
jr .loop
OverworldLoop_ReturnToMain::
ld hl, wJoypadDisable
res JOYPAD_DISABLE_CUTSCENE_F, [hl]
res JOYPAD_DISABLE_SYNC_MUTEX_F, [hl]
ld hl, wDebugFlags
res UNK_DEBUG_FLAG_6_F, [hl]
res SKIP_MAP_SCRIPT_F, [hl]
ld hl, wStateFlags
res SCRIPTED_MOVEMENT_STATE_F, [hl]
ld a, MAPSTATUS_MAIN
call SetMapStatus
ret
OverworldLoop_EventRunning::
.loop
call UpdateTime
ld a, [wStateFlags]
bit SCRIPTED_MOVEMENT_STATE_F, a
jr z, OverworldLoop_ReturnToMain
ldh a, [hMapEntryMethod]
and a
ret nz
call HandleMapObjects
jr nc, .loop
farcall CheckObjectEnteringVisibleRange
call CheckMovingOffEdgeOfMap
ret c
call WarpCheck
ret c
jr .loop
OverworldLoop_Unused_02::
ret
OverworldLoop_Unused_06::
OverworldLoop_Unused_07::
ret
OverworldLoop_DebugMapViewer::
if DEF(_DEBUG)
callfar DebugMapViewer
endc
ld a, MAPSTATUS_RETURN_TO_MAIN
call SetMapStatus
ret
; A pared-down version of the standard overworld loop.
; Wild battles, warps, connections, and scenes won't update.
; Rendering only works correctly if the flashlight effect is on.
OverworldLoop_UnusedDarkness::
.loop
call UpdateTime
call GetJoypad
call OverworldStartButtonCheck
ret nz
callfar OverworldMovementCheck
call .HandleMapObjects
jr nc, .loop
farcall CheckObjectEnteringVisibleRange
jr .loop
.HandleMapObjects:
.loop2
ldh a, [hROMBank]
push af
ld a, BANK(HandleNPCStep)
call Bankswitch
call HandleNPCStep
call LoadMinorObjectGFX
ld a, BANK(_HandlePlayerStep_Unused)
call Bankswitch
call _HandlePlayerStep_Unused
ld a, BANK(InitSprites)
call Bankswitch
call InitSprites
call DelayFrame
call UpdateToolgear
ld hl, wToolgearFlags
set 2, [hl] ; transfer toolgear to window
call DelayFrame
pop af
call Bankswitch
and a
ld a, [wPlayerStepFlags]
bit PLAYERSTEP_CONTINUE_F, a
ret z
bit PLAYERSTEP_STOP_F, a
jr z, .loop2
scf
ret
RunMapTextSubroutine::
ld a, [wDebugFlags]
bit SKIP_MAP_SCRIPT_F, a
ret nz
ld a, [wMapGroup]
ld b, a
ld a, [wMapId]
ld c, a
call SwitchToAnyMapBank
call QueueMapTextSubroutine
ld hl, wMapScriptPtr
ld a, [hli]
ld h, [hl]
ld l, a
ld de, .Return
push de
jp hl
.Return:
ret