pokecrystal-board/home/map.asm

2304 lines
33 KiB
NASM

; Functions dealing with rendering and interacting with maps.
ClearUnusedMapBuffer::
ld hl, wUnusedMapBuffer
ld bc, wUnusedMapBufferEnd - wUnusedMapBuffer
ld a, 0
call ByteFill
ret
CheckScenes::
; Checks wCurMapSceneScriptPointer. If it's empty, returns -1 in a. Otherwise, returns the active scene ID in a.
push hl
ld hl, wCurMapSceneScriptPointer
ld a, [hli]
ld h, [hl]
ld l, a
or h
ld a, [hl]
jr nz, .scene_exists
ld a, -1
.scene_exists
pop hl
ret
GetCurrentMapSceneID::
; Grabs the wram map scene script pointer for the current map and loads it into wCurMapSceneScriptPointer.
; If there is no scene, both bytes of wCurMapSceneScriptPointer are wiped clean.
; Copy the current map group and number into bc. This is needed for GetMapSceneID.
ld a, [wMapGroup]
ld b, a
ld a, [wMapNumber]
ld c, a
; Blank out wCurMapSceneScriptPointer; this is the default scenario.
xor a
ld [wCurMapSceneScriptPointer], a
ld [wCurMapSceneScriptPointer + 1], a
call GetMapSceneID
ret c ; The map is not in the scene script table
; Load the scene script pointer from de into wCurMapSceneScriptPointer
ld a, e
ld [wCurMapSceneScriptPointer], a
ld a, d
ld [wCurMapSceneScriptPointer + 1], a
xor a
ret
GetMapSceneID::
; Searches the scene_var table for the map group and number loaded in bc, and returns the wram pointer in de.
; If the map is not in the scene_var table, returns carry.
push bc
ldh a, [hROMBank]
push af
ld a, BANK(MapScenes)
rst Bankswitch
ld hl, MapScenes
.loop
push hl
ld a, [hli] ; map group, or terminator
cp -1
jr z, .end ; the current map is not in the scene_var table
cp b
jr nz, .next ; map group did not match
ld a, [hli] ; map number
cp c
jr nz, .next ; map number did not match
jr .found ; we found our map
.next
pop hl
ld de, 4 ; scene_var size
add hl, de
jr .loop
.end
scf
jr .done
.found
ld e, [hl]
inc hl
ld d, [hl]
.done
pop hl
pop bc
ld a, b
rst Bankswitch
pop bc
ret
OverworldTextModeSwitch::
call LoadMapPart
call SwapTextboxPalettes
ret
LoadMapPart::
ldh a, [hROMBank]
push af
ld a, [wTilesetBlocksBank]
rst Bankswitch
call LoadMetatiles
ld a, "■"
hlcoord 0, 0
ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
call ByteFill
ld a, BANK(_LoadMapPart)
rst Bankswitch
call _LoadMapPart
pop af
rst Bankswitch
ret
LoadMetatiles::
; de <- wOverworldMapAnchor
ld a, [wOverworldMapAnchor]
ld e, a
ld a, [wOverworldMapAnchor + 1]
ld d, a
ld hl, wSurroundingTiles
ld b, SCREEN_META_HEIGHT
.row
push de
push hl
ld c, SCREEN_META_WIDTH
.col
push de
push hl
; Load the current map block.
; If the current map block is a border block, load the border block.
ld a, [de]
and a
jr nz, .ok
ld a, [wMapBorderBlock]
.ok
; Load the current wSurroundingTiles address into de.
ld e, l
ld d, h
; Set hl to the address of the current metatile data ([wTilesetBlocksAddress] + (a) tiles).
; BUG: LoadMetatiles wraps around past 128 blocks (see docs/bugs_and_glitches.md)
add a
ld l, a
ld h, 0
add hl, hl
add hl, hl
add hl, hl
ld a, [wTilesetBlocksAddress]
add l
ld l, a
ld a, [wTilesetBlocksAddress + 1]
adc h
ld h, a
; copy the 4x4 metatile
rept METATILE_WIDTH - 1
rept METATILE_WIDTH
ld a, [hli]
ld [de], a
inc de
endr
ld a, e
add SURROUNDING_WIDTH - METATILE_WIDTH
ld e, a
jr nc, .next\@
inc d
.next\@
endr
rept METATILE_WIDTH
ld a, [hli]
ld [de], a
inc de
endr
; Next metatile
pop hl
ld de, METATILE_WIDTH
add hl, de
pop de
inc de
dec c
jp nz, .col
; Next metarow
pop hl
ld de, SURROUNDING_WIDTH * METATILE_WIDTH
add hl, de
pop de
ld a, [wMapWidth]
add MAP_CONNECTION_PADDING_WIDTH * 2
add e
ld e, a
jr nc, .ok2
inc d
.ok2
dec b
jp nz, .row
ret
ReturnToMapFromSubmenu::
ld a, MAPSETUP_SUBMENU
ldh [hMapEntryMethod], a
farcall RunMapSetupScript
xor a
ldh [hMapEntryMethod], a
ret
CheckWarpTile::
call GetDestinationWarpNumber
ret nc
push bc
farcall CheckDirectionalWarp
pop bc
ret nc
call CopyWarpData
scf
ret
WarpCheck::
call GetDestinationWarpNumber
ret nc
call CopyWarpData
ret
GetDestinationWarpNumber::
farcall CheckWarpCollision
ret nc
ldh a, [hROMBank]
push af
call SwitchToMapScriptsBank
call .GetDestinationWarpNumber
pop de
ld a, d
rst Bankswitch
ret
.GetDestinationWarpNumber:
ld a, [wPlayerMapY]
sub 4
ld e, a
ld a, [wPlayerMapX]
sub 4
ld d, a
ld a, [wCurMapWarpCount]
and a
ret z
ld c, a
ld hl, wCurMapWarpsPointer
ld a, [hli]
ld h, [hl]
ld l, a
.loop
push hl
ld a, [hli]
cp e
jr nz, .next
ld a, [hli]
cp d
jr nz, .next
jr .found_warp
.next
pop hl
ld a, WARP_EVENT_SIZE
add l
ld l, a
jr nc, .okay
inc h
.okay
dec c
jr nz, .loop
xor a
ret
.found_warp
pop hl
call .IncreaseHLTwice
ret nc ; never encountered
ld a, [wCurMapWarpCount]
inc a
sub c
ld c, a
scf
ret
.IncreaseHLTwice:
inc hl
inc hl
scf
ret
CopyWarpData::
ldh a, [hROMBank]
push af
call SwitchToMapScriptsBank
call .CopyWarpData
pop af
rst Bankswitch
scf
ret
.CopyWarpData:
push bc
ld hl, wCurMapWarpsPointer
ld a, [hli]
ld h, [hl]
ld l, a
ld a, c
dec a
ld bc, WARP_EVENT_SIZE
call AddNTimes
ld bc, 2 ; warp number
add hl, bc
ld a, [hli]
cp -1
jr nz, .skip
ld hl, wBackupWarpNumber
ld a, [hli]
.skip
pop bc
ld [wNextWarp], a
ld a, [hli]
ld [wNextMapGroup], a
ld a, [hli]
ld [wNextMapNumber], a
ld a, c
ld [wPrevWarp], a
ld a, [wMapGroup]
ld [wPrevMapGroup], a
ld a, [wMapNumber]
ld [wPrevMapNumber], a
scf
ret
CheckOutdoorMap::
cp ROUTE
ret z
cp TOWN
ret
CheckIndoorMap::
cp INDOOR
ret z
cp CAVE
ret z
cp DUNGEON
ret z
cp GATE
ret
CheckUnknownMap:: ; unreferenced
cp INDOOR
ret z
cp GATE
ret z
cp ENVIRONMENT_5
ret
LoadMapAttributes::
call CopyMapPartialAndAttributes
call SwitchToMapScriptsBank
call ReadMapScripts
xor a ; do not skip object events
call ReadMapEvents
ret
LoadMapAttributes_SkipObjects::
call CopyMapPartialAndAttributes
call SwitchToMapScriptsBank
call ReadMapScripts
ld a, TRUE ; skip object events
call ReadMapEvents
ret
CopyMapPartialAndAttributes::
call CopyMapPartial
call SwitchToMapAttributesBank
call GetMapAttributesPointer
call CopyMapAttributes
call GetMapConnections
ret
ReadMapEvents::
push af
ld hl, wMapEventsPointer
ld a, [hli]
ld h, [hl]
ld l, a
inc hl
inc hl
call ReadWarps
call ReadCoordEvents
call ReadBGEvents
pop af
and a ; skip object events?
ret nz
call ReadObjectEvents
ret
ReadMapScripts::
ld hl, wMapScriptsPointer
ld a, [hli]
ld h, [hl]
ld l, a
call ReadMapSceneScripts
call ReadMapCallbacks
ret
CopyMapAttributes::
ld de, wMapAttributes
ld c, wMapAttributesEnd - wMapAttributes
.loop
ld a, [hli]
ld [de], a
inc de
dec c
jr nz, .loop
ret
GetMapConnections::
ld a, $ff
ld [wNorthConnectedMapGroup], a
ld [wSouthConnectedMapGroup], a
ld [wWestConnectedMapGroup], a
ld [wEastConnectedMapGroup], a
ld a, [wMapConnections]
ld b, a
bit NORTH_F, b
jr z, .no_north
ld de, wNorthMapConnection
call GetMapConnection
.no_north
bit SOUTH_F, b
jr z, .no_south
ld de, wSouthMapConnection
call GetMapConnection
.no_south
bit WEST_F, b
jr z, .no_west
ld de, wWestMapConnection
call GetMapConnection
.no_west
bit EAST_F, b
jr z, .no_east
ld de, wEastMapConnection
call GetMapConnection
.no_east
ret
GetMapConnection::
; Load map connection struct at hl into de.
ld c, wSouthMapConnection - wNorthMapConnection
.loop
ld a, [hli]
ld [de], a
inc de
dec c
jr nz, .loop
ret
ReadMapSceneScripts::
ld a, [hli] ; scene_script count
ld c, a
ld [wCurMapSceneScriptCount], a
ld a, l
ld [wCurMapSceneScriptsPointer], a
ld a, h
ld [wCurMapSceneScriptsPointer + 1], a
ld a, c
and a
ret z
ld bc, SCENE_SCRIPT_SIZE
call AddNTimes
ret
ReadMapCallbacks::
ld a, [hli]
ld c, a
ld [wCurMapCallbackCount], a
ld a, l
ld [wCurMapCallbacksPointer], a
ld a, h
ld [wCurMapCallbacksPointer + 1], a
ld a, c
and a
ret z
ld bc, CALLBACK_SIZE
call AddNTimes
ret
ReadWarps::
ld a, [hli]
ld c, a
ld [wCurMapWarpCount], a
ld a, l
ld [wCurMapWarpsPointer], a
ld a, h
ld [wCurMapWarpsPointer + 1], a
ld a, c
and a
ret z
ld bc, WARP_EVENT_SIZE
call AddNTimes
ret
ReadCoordEvents::
ld a, [hli]
ld c, a
ld [wCurMapCoordEventCount], a
ld a, l
ld [wCurMapCoordEventsPointer], a
ld a, h
ld [wCurMapCoordEventsPointer + 1], a
ld a, c
and a
ret z
ld bc, COORD_EVENT_SIZE
call AddNTimes
ret
ReadBGEvents::
ld a, [hli]
ld c, a
ld [wCurMapBGEventCount], a
ld a, l
ld [wCurMapBGEventsPointer], a
ld a, h
ld [wCurMapBGEventsPointer + 1], a
ld a, c
and a
ret z
ld bc, BG_EVENT_SIZE
call AddNTimes
ret
ReadObjectEvents::
push hl
call ClearObjectStructs
pop de
ld hl, wMap1Object
ld a, [de]
inc de
ld [wCurMapObjectEventCount], a
ld a, e
ld [wCurMapObjectEventsPointer], a
ld a, d
ld [wCurMapObjectEventsPointer + 1], a
ld a, [wCurMapObjectEventCount]
call CopyMapObjectEvents
; get NUM_OBJECTS - [wCurMapObjectEventCount]
; BUG: ReadObjectEvents overflows into wObjectMasks (see docs/bugs_and_glitches.md)
ld a, [wCurMapObjectEventCount]
ld c, a
ld a, NUM_OBJECTS
sub c
jr z, .skip
; could have done "inc hl" instead
ld bc, 1
add hl, bc
ld bc, MAPOBJECT_LENGTH
.loop
ld [hl], 0
inc hl
ld [hl], -1
dec hl
add hl, bc
dec a
jr nz, .loop
.skip
ld h, d
ld l, e
ret
CopyMapObjectEvents::
and a
ret z
ld c, a
.loop
push bc
push hl
ld a, $ff
ld [hli], a
ld b, OBJECT_EVENT_SIZE
.loop2
ld a, [de]
inc de
ld [hli], a
dec b
jr nz, .loop2
pop hl
ld bc, MAPOBJECT_LENGTH
add hl, bc
pop bc
dec c
jr nz, .loop
ret
ClearObjectStructs::
ld hl, wObject1Struct
ld bc, OBJECT_LENGTH * (NUM_OBJECT_STRUCTS - 1)
xor a
call ByteFill
; Just to make sure (this is rather pointless)
ld hl, wObject1Struct
ld de, OBJECT_LENGTH
ld c, NUM_OBJECT_STRUCTS - 1
xor a
.loop
ld [hl], a
add hl, de
dec c
jr nz, .loop
ret
GetWarpDestCoords::
call GetMapScriptsBank
rst Bankswitch
ld hl, wMapEventsPointer
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
; destination warp number
ld a, [hli]
cp -1
jr nz, .skip
call .backup
.skip
farcall GetMapScreenCoords
ret
.backup
ld a, [wPrevWarp]
ld [wBackupWarpNumber], a
ld a, [wPrevMapGroup]
ld [wBackupMapGroup], a
ld a, [wPrevMapNumber]
ld [wBackupMapNumber], a
ret
LoadBlockData::
ld hl, wOverworldMapBlocks
ld bc, wOverworldMapBlocksEnd - wOverworldMapBlocks
ld a, 0
call ByteFill
call ChangeMap
call FillMapConnections
ld a, MAPCALLBACK_TILES
call RunMapCallback
ret
ChangeMap::
ldh a, [hROMBank]
push af
ld hl, wOverworldMapBlocks
ld a, [wMapWidth]
ldh [hConnectedMapWidth], a
add $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, [wMapBlocksBank]
rst Bankswitch
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
pop af
rst Bankswitch
ret
FillMapConnections::
; North
ld a, [wNorthConnectedMapGroup]
cp $ff
jr z, .South
ld b, a
ld a, [wNorthConnectedMapNumber]
ld c, a
call GetAnyMapBlocksBank
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 GetAnyMapBlocksBank
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 GetAnyMapBlocksBank
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 GetAnyMapBlocksBank
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 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 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
LoadMapStatus::
ld [wMapStatus], a
ret
CallScript::
; Call a script at a:hl.
ld [wScriptBank], a
ld a, l
ld [wScriptPos], a
ld a, h
ld [wScriptPos + 1], a
ld a, PLAYEREVENT_MAPSCRIPT
ld [wScriptRunning], a
scf
ret
CallMapScript::
; Call a script at hl in the current bank if there isn't already a script running
ld a, [wScriptRunning]
and a
ret nz
call GetMapScriptsBank
jr CallScript
RunMapCallback::
; Will run the first callback found with execution index equal to a.
ld b, a
ldh a, [hROMBank]
push af
call SwitchToMapScriptsBank
call .FindCallback
jr nc, .done
call GetMapScriptsBank
ld b, a
ld d, h
ld e, l
call ExecuteCallbackScript
.done
pop af
rst Bankswitch
ret
.FindCallback:
ld a, [wCurMapCallbackCount]
ld c, a
and a
ret z
ld hl, wCurMapCallbacksPointer
ld a, [hli]
ld h, [hl]
ld l, a
or h
ret z
ld de, CALLBACK_SIZE
.loop
ld a, [hl]
cp b
jr z, .found
add hl, de
dec c
jr nz, .loop
xor a
ret
.found
inc hl
ld a, [hli]
ld h, [hl]
ld l, a
scf
ret
ExecuteCallbackScript::
; Do map callback de and return to script bank b.
farcall CallCallback
ld a, [wScriptMode]
push af
ld hl, wScriptFlags
ld a, [hl]
push af
set 1, [hl]
farcall EnableScriptMode
farcall ScriptEvents
pop af
ld [wScriptFlags], a
pop af
ld [wScriptMode], a
ret
MapTextbox::
ldh a, [hROMBank]
push af
ld a, b
rst Bankswitch
push hl
call SpeechTextbox
call SafeUpdateSprites
ld a, 1
ldh [hOAMUpdate], a
call ApplyTilemap
pop hl
call PrintTextboxText
xor a
ldh [hOAMUpdate], a
pop af
rst Bankswitch
ret
Call_a_de::
; Call a:de.
ldh [hTempBank], a
ldh a, [hROMBank]
push af
ldh a, [hTempBank]
rst Bankswitch
call .de
pop af
rst Bankswitch
ret
.de
push de
ret
GetMovementData::
; Initialize the movement data for object c at b:hl
ldh a, [hROMBank]
push af
ld a, b
rst Bankswitch
ld a, c
call LoadMovementDataPointer
pop hl
ld a, h
rst Bankswitch
ret
GetScriptByte::
; Return byte at wScriptBank:wScriptPos in a.
push hl
push bc
ldh a, [hROMBank]
push af
ld a, [wScriptBank]
rst Bankswitch
ld hl, wScriptPos
ld c, [hl]
inc hl
ld b, [hl]
ld a, [bc]
inc bc
ld [hl], b
dec hl
ld [hl], c
ld b, a
pop af
rst Bankswitch
ld a, b
pop bc
pop hl
ret
ObjectEvent::
jumptextfaceplayer ObjectEventText
ObjectEventText::
text_far _ObjectEventText
text_end
BGEvent:: ; unreferenced
jumptext BGEventText
BGEventText::
text_far _BGEventText
text_end
CoordinatesEvent:: ; unreferenced
jumptext CoordinatesEventText
CoordinatesEventText::
text_far _CoordinatesEventText
text_end
CheckObjectMask::
ldh a, [hMapObjectIndex]
ld e, a
ld d, 0
ld hl, wObjectMasks
add hl, de
ld a, [hl]
ret
MaskObject::
ldh a, [hMapObjectIndex]
ld e, a
ld d, 0
ld hl, wObjectMasks
add hl, de
ld [hl], -1 ; masked
ret
UnmaskObject::
ldh a, [hMapObjectIndex]
ld e, a
ld d, 0
ld hl, wObjectMasks
add hl, de
ld [hl], 0 ; unmasked
ret
if DEF(_DEBUG)
ComputeROMXChecksum::
ldh a, [hROMBank]
push af
ld a, c
rst Bankswitch
ld hl, $4000 ; ROMX start
.loop
ld a, [hli]
add e
ld e, a
ld a, d
adc 0
ld d, a
ld a, h
cp $80 ; HIGH(ROMX end)
jr c, .loop
pop af
rst Bankswitch
ret
endc
ScrollMapUp::
hlcoord 0, 0
ld de, wBGMapBuffer
call BackupBGMapRow
ld c, 2 * SCREEN_WIDTH
call ScrollBGMapPalettes
ld a, [wBGMapAnchor]
ld e, a
ld a, [wBGMapAnchor + 1]
ld d, a
call UpdateBGMapRow
ld a, $1
ldh [hBGMapUpdate], a
ret
ScrollMapDown::
hlcoord 0, SCREEN_HEIGHT - 2
ld de, wBGMapBuffer
call BackupBGMapRow
ld c, 2 * SCREEN_WIDTH
call ScrollBGMapPalettes
ld a, [wBGMapAnchor]
ld l, a
ld a, [wBGMapAnchor + 1]
ld h, a
ld bc, BG_MAP_WIDTH tiles
add hl, bc
; cap d at HIGH(vBGMap0)
ld a, h
and %00000011
or HIGH(vBGMap0)
ld e, l
ld d, a
call UpdateBGMapRow
ld a, $1
ldh [hBGMapUpdate], a
ret
ScrollMapLeft::
hlcoord 0, 0
ld de, wBGMapBuffer
call BackupBGMapColumn
ld c, 2 * SCREEN_HEIGHT
call ScrollBGMapPalettes
ld a, [wBGMapAnchor]
ld e, a
ld a, [wBGMapAnchor + 1]
ld d, a
call UpdateBGMapColumn
ld a, $1
ldh [hBGMapUpdate], a
ret
ScrollMapRight::
hlcoord SCREEN_WIDTH - 2, 0
ld de, wBGMapBuffer
call BackupBGMapColumn
ld c, 2 * SCREEN_HEIGHT
call ScrollBGMapPalettes
ld a, [wBGMapAnchor]
ld e, a
and %11100000
ld b, a
ld a, e
add SCREEN_HEIGHT
and %00011111
or b
ld e, a
ld a, [wBGMapAnchor + 1]
ld d, a
call UpdateBGMapColumn
ld a, $1
ldh [hBGMapUpdate], a
ret
BackupBGMapRow::
ld c, 2 * SCREEN_WIDTH
.loop
ld a, [hli]
ld [de], a
inc de
dec c
jr nz, .loop
ret
BackupBGMapColumn::
ld c, SCREEN_HEIGHT
.loop
ld a, [hli]
ld [de], a
inc de
ld a, [hl]
ld [de], a
inc de
ld a, SCREEN_WIDTH - 1
add l
ld l, a
jr nc, .skip
inc h
.skip
dec c
jr nz, .loop
ret
UpdateBGMapRow::
ld hl, wBGMapBufferPointers
push de
call .iteration
pop de
ld a, BG_MAP_WIDTH
add e
ld e, a
.iteration
ld c, 10
.loop
ld a, e
ld [hli], a
ld a, d
ld [hli], a
ld a, e
inc a
inc a
and $1f
ld b, a
ld a, e
and $e0
or b
ld e, a
dec c
jr nz, .loop
ld a, SCREEN_WIDTH
ldh [hBGMapTileCount], a
ret
UpdateBGMapColumn::
ld hl, wBGMapBufferPointers
ld c, SCREEN_HEIGHT
.loop
ld a, e
ld [hli], a
ld a, d
ld [hli], a
ld a, BG_MAP_WIDTH
add e
ld e, a
jr nc, .skip
inc d
; cap d at HIGH(vBGMap0)
ld a, d
and %11
or HIGH(vBGMap0)
ld d, a
.skip
dec c
jr nz, .loop
ld a, SCREEN_HEIGHT
ldh [hBGMapTileCount], a
ret
ClearBGMapBuffer:: ; unreferenced
ld hl, wBGMapBuffer
ld bc, wBGMapBufferEnd - wBGMapBuffer
xor a
call ByteFill
ret
LoadTilesetGFX::
ld hl, wTilesetAddress
ld a, [hli]
ld h, [hl]
ld l, a
ld a, [wTilesetBank]
ld e, a
ldh a, [rSVBK]
push af
ld a, BANK(wDecompressScratch)
ldh [rSVBK], a
ld a, e
ld de, wDecompressScratch
call FarDecompress
ld hl, wDecompressScratch
ld de, vTiles2
ld bc, $60 tiles
call CopyBytes
ldh a, [rVBK]
push af
ld a, BANK(vTiles5)
ldh [rVBK], a
ld hl, wDecompressScratch + $60 tiles
ld de, vTiles5
ld bc, $60 tiles
call CopyBytes
pop af
ldh [rVBK], a
pop af
ldh [rSVBK], a
; These tilesets support dynamic per-mapgroup roof tiles.
ld a, [wMapTileset]
cp TILESET_JOHTO
jr z, .load_roof
cp TILESET_JOHTO_MODERN
jr z, .load_roof
cp TILESET_BATTLE_TOWER_OUTSIDE
jr z, .load_roof
jr .skip_roof
.load_roof
farcall LoadMapGroupRoof
.skip_roof
xor a
ldh [hTileAnimFrame], a
ret
BufferScreen::
ld hl, wOverworldMapAnchor
ld a, [hli]
ld h, [hl]
ld l, a
ld de, wScreenSave
ld c, SCREEN_META_HEIGHT
ld b, SCREEN_META_WIDTH
.row
push bc
push hl
.col
ld a, [hli]
ld [de], a
inc de
dec b
jr nz, .col
pop hl
ld a, [wMapWidth]
add 6
ld c, a
ld b, 0
add hl, bc
pop bc
dec c
jr nz, .row
ret
SaveScreen::
ld hl, wOverworldMapAnchor
ld a, [hli]
ld h, [hl]
ld l, a
ld de, wScreenSave
ld a, [wMapWidth]
add 6
ldh [hMapObjectIndex], a
ld a, [wPlayerStepDirection]
and a
jr z, .down
cp UP
jr z, .up
cp LEFT
jr z, .left
cp RIGHT
jr z, .right
ret
.up
ld de, wScreenSave + SCREEN_META_WIDTH
ldh a, [hMapObjectIndex]
ld c, a
ld b, 0
add hl, bc
jr .vertical
.down
ld de, wScreenSave
.vertical
ld b, SCREEN_META_WIDTH
ld c, SCREEN_META_HEIGHT - 1
jr SaveScreen_LoadConnection
.left
ld de, wScreenSave + 1
inc hl
jr .horizontal
.right
ld de, wScreenSave
.horizontal
ld b, SCREEN_META_WIDTH - 1
ld c, SCREEN_META_HEIGHT
jr SaveScreen_LoadConnection
LoadConnectionBlockData::
ld hl, wOverworldMapAnchor
ld a, [hli]
ld h, [hl]
ld l, a
ld a, [wMapWidth]
add 6
ldh [hConnectionStripLength], a
ld de, wScreenSave
ld b, SCREEN_META_WIDTH
ld c, SCREEN_META_HEIGHT
SaveScreen_LoadConnection::
.row
push bc
push hl
push de
.col
ld a, [de]
inc de
ld [hli], a
dec b
jr nz, .col
pop de
ld a, e
add 6
ld e, a
jr nc, .okay
inc d
.okay
pop hl
ldh a, [hConnectionStripLength]
ld c, a
ld b, 0
add hl, bc
pop bc
dec c
jr nz, .row
ret
GetMovementPermissions::
xor a
ld [wTilePermissions], a
call .LeftRight
call .UpDown
; get coords of current tile
ld a, [wPlayerMapX]
ld d, a
ld a, [wPlayerMapY]
ld e, a
call GetCoordTile
ld [wPlayerTile], a
call .CheckHiNybble
ret nz
ld a, [wPlayerTile]
and 7
ld hl, .MovementPermissionsData
add l
ld l, a
ld a, 0
adc h
ld h, a
ld a, [hl]
ld hl, wTilePermissions
or [hl]
ld [hl], a
ret
.MovementPermissionsData:
db DOWN_MASK
db UP_MASK
db LEFT_MASK
db RIGHT_MASK
db DOWN_MASK | RIGHT_MASK
db UP_MASK | RIGHT_MASK
db DOWN_MASK | LEFT_MASK
db UP_MASK | LEFT_MASK
.UpDown:
ld a, [wPlayerMapX]
ld d, a
ld a, [wPlayerMapY]
ld e, a
push de
inc e
call GetCoordTile
ld [wTileDown], a
call .Down
pop de
dec e
call GetCoordTile
ld [wTileUp], a
call .Up
ret
.LeftRight:
ld a, [wPlayerMapX]
ld d, a
ld a, [wPlayerMapY]
ld e, a
push de
dec d
call GetCoordTile
ld [wTileLeft], a
call .Left
pop de
inc d
call GetCoordTile
ld [wTileRight], a
call .Right
ret
.Down:
call .CheckHiNybble
ret nz
ld a, [wTileDown]
and %111
cp COLL_UP_WALL & %111 ; COLL_UP_BUOY & %111
jr z, .ok_down
cp COLL_UP_RIGHT_WALL & %111 ; COLL_UP_RIGHT_BUOY & %111
jr z, .ok_down
cp COLL_UP_LEFT_WALL & %111 ; COLL_UP_LEFT_BUOY & %111
ret nz
.ok_down
ld a, [wTilePermissions]
or FACE_DOWN
ld [wTilePermissions], a
ret
.Up:
call .CheckHiNybble
ret nz
ld a, [wTileUp]
and %111
cp COLL_DOWN_WALL & %111 ; COLL_DOWN_BUOY & %111
jr z, .ok_up
cp COLL_DOWN_RIGHT_WALL & %111 ; COLL_DOWN_RIGHT_BUOY & %111
jr z, .ok_up
cp COLL_DOWN_LEFT_WALL & %111 ; COLL_DOWN_LEFT_BUOY & %111
ret nz
.ok_up
ld a, [wTilePermissions]
or FACE_UP
ld [wTilePermissions], a
ret
.Right:
call .CheckHiNybble
ret nz
ld a, [wTileRight]
and %111
cp COLL_LEFT_WALL & %111 ; COLL_LEFT_BUOY & %111
jr z, .ok_right
cp COLL_DOWN_LEFT_WALL & %111 ; COLL_DOWN_LEFT_BUOY & %111
jr z, .ok_right
cp COLL_UP_LEFT_WALL & %111 ; COLL_UP_LEFT_BUOY & %111
ret nz
.ok_right
ld a, [wTilePermissions]
or FACE_RIGHT
ld [wTilePermissions], a
ret
.Left:
call .CheckHiNybble
ret nz
ld a, [wTileLeft]
and %111
cp COLL_RIGHT_WALL & %111 ; COLL_RIGHT_BUOY & %111
jr z, .ok_left
cp COLL_DOWN_RIGHT_WALL & %111 ; COLL_DOWN_RIGHT_BUOY & %111
jr z, .ok_left
cp COLL_UP_RIGHT_WALL & %111 ; COLL_UP_RIGHT_BUOY & %111
ret nz
.ok_left
ld a, [wTilePermissions]
or FACE_LEFT
ld [wTilePermissions], a
ret
.CheckHiNybble:
and $f0
cp HI_NYBBLE_SIDE_WALLS
ret z
cp HI_NYBBLE_SIDE_BUOYS
ret
GetFacingTileCoord::
; Return map coordinates in (d, e) and tile id in a
; of the tile the player is facing.
ld a, [wPlayerDirection]
and %1100
srl a
srl a
ld l, a
ld h, 0
add hl, hl
add hl, hl
ld de, .Directions
add hl, de
ld d, [hl]
inc hl
ld e, [hl]
inc hl
ld a, [hli]
ld h, [hl]
ld l, a
ld a, [wPlayerMapX]
add d
ld d, a
ld a, [wPlayerMapY]
add e
ld e, a
ld a, [hl]
ret
.Directions:
; x, y
db 0, 1
dw wTileDown
db 0, -1
dw wTileUp
db -1, 0
dw wTileLeft
db 1, 0
dw wTileRight
GetCoordTile::
; Get the collision byte for tile d, e
call GetBlockLocation
ld a, [hl]
and a
jr z, .nope
ld l, a
ld h, 0
add hl, hl
add hl, hl
ld a, [wTilesetCollisionAddress]
ld c, a
ld a, [wTilesetCollisionAddress + 1]
ld b, a
add hl, bc
rr d
jr nc, .nocarry
inc hl
.nocarry
rr e
jr nc, .nocarry2
inc hl
inc hl
.nocarry2
ld a, [wTilesetCollisionBank]
call GetFarByte
ret
.nope
ld a, -1
ret
GetBlockLocation::
ld a, [wMapWidth]
add 6
ld c, a
ld b, 0
ld hl, wOverworldMapBlocks + 1
add hl, bc
ld a, e
srl a
jr z, .nope
and a
.loop
srl a
jr nc, .ok
add hl, bc
.ok
sla c
rl b
and a
jr nz, .loop
.nope
ld c, d
srl c
ld b, 0
add hl, bc
ret
CheckFacingBGEvent::
call GetFacingTileCoord
; Load facing into b.
ld b, a
; Convert the coordinates at de to within-boundaries coordinates.
ld a, d
sub 4
ld d, a
ld a, e
sub 4
ld e, a
; If there are no BG events, we don't need to be here.
ld a, [wCurMapBGEventCount]
and a
ret z
ld c, a
ldh a, [hROMBank]
push af
call SwitchToMapScriptsBank
call CheckIfFacingTileCoordIsBGEvent
pop hl
ld a, h
rst Bankswitch
ret
CheckIfFacingTileCoordIsBGEvent::
; Checks to see if you are facing a BG event. If so, copies it into wCurBGEvent and sets carry.
ld hl, wCurMapBGEventsPointer
ld a, [hli]
ld h, [hl]
ld l, a
.loop
push hl
ld a, [hli]
cp e
jr nz, .next
ld a, [hli]
cp d
jr nz, .next
jr .copysign
.next
pop hl
ld a, BG_EVENT_SIZE
add l
ld l, a
jr nc, .nocarry
inc h
.nocarry
dec c
jr nz, .loop
xor a
ret
.copysign
pop hl
ld de, wCurBGEvent
ld bc, BG_EVENT_SIZE
call CopyBytes
scf
ret
CheckCurrentMapCoordEvents::
; If there are no coord events, we don't need to be here.
ld a, [wCurMapCoordEventCount]
and a
ret z
; Copy the coord event count into c.
ld c, a
ldh a, [hROMBank]
push af
call SwitchToMapScriptsBank
call .CoordEventCheck
pop hl
ld a, h
rst Bankswitch
ret
.CoordEventCheck:
; Checks to see if you are standing on a coord event. If yes, copies the event to wCurCoordEvent and sets carry.
ld hl, wCurMapCoordEventsPointer
ld a, [hli]
ld h, [hl]
ld l, a
; Load the active scene ID into b
call CheckScenes
ld b, a
; Load your current coordinates into de. This will be used to check if your position is in the coord event table for the current map.
ld a, [wPlayerMapX]
sub 4
ld d, a
ld a, [wPlayerMapY]
sub 4
ld e, a
.loop
push hl
ld a, [hli]
cp b
jr z, .got_id
cp -1
jr nz, .next
.got_id
ld a, [hli]
cp e
jr nz, .next
ld a, [hli]
cp d
jr nz, .next
jr .copy_coord_event
.next
pop hl
ld a, COORD_EVENT_SIZE
add l
ld l, a
jr nc, .nocarry
inc h
.nocarry
dec c
jr nz, .loop
xor a
ret
.copy_coord_event
pop hl
ld de, wCurCoordEvent
ld bc, COORD_EVENT_SIZE
call CopyBytes
scf
ret
FadeToMenu::
xor a
ldh [hBGMapMode], a
call LoadStandardMenuHeader
farcall FadeOutPalettes
call ClearSprites
call DisableSpriteUpdates
ret
CloseSubmenu::
call ClearBGPalettes
call ReloadTilesetAndPalettes
call UpdateSprites
call Call_ExitMenu
call GSReloadPalettes
jr FinishExitMenu
ExitAllMenus::
call ClearBGPalettes
call Call_ExitMenu
call ReloadTilesetAndPalettes
call UpdateSprites
call GSReloadPalettes
FinishExitMenu::
ld b, SCGB_MAPPALS
call GetSGBLayout
farcall LoadOW_BGPal7
call WaitBGMap2
farcall FadeInPalettes
call EnableSpriteUpdates
ret
ReturnToMapWithSpeechTextbox::
push af
ld a, $1
ld [wSpriteUpdatesEnabled], a
call ClearBGPalettes
call ClearSprites
call ReloadTilesetAndPalettes
hlcoord 0, 12
lb bc, 4, 18
call Textbox
ld hl, wVramState
set 0, [hl]
call UpdateSprites
call WaitBGMap2
ld b, SCGB_MAPPALS
call GetSGBLayout
farcall LoadOW_BGPal7
call UpdateTimePals
call DelayFrame
ld a, $1
ldh [hMapAnims], a
pop af
ret
ReloadTilesetAndPalettes::
call DisableLCD
call ClearSprites
farcall RefreshSprites
call LoadStandardFont
call LoadFontsExtra
ldh a, [hROMBank]
push af
ld a, [wMapGroup]
ld b, a
ld a, [wMapNumber]
ld c, a
call SwitchToAnyMapAttributesBank
farcall UpdateTimeOfDayPal
call OverworldTextModeSwitch
call LoadTilesetGFX
ld a, 9
call SkipMusic
pop af
rst Bankswitch
call EnableLCD
ret
GetMapPointer::
ld a, [wMapGroup]
ld b, a
ld a, [wMapNumber]
ld c, a
GetAnyMapPointer::
; Prior to calling this function, you must have switched banks so that
; MapGroupPointers is visible.
; inputs:
; b = map group, c = map number
; outputs:
; hl points to the map within its group
push bc ; save map number for later
; get pointer to map group
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 ; restore map number
; find the cth map within the group
dec c
ld b, 0
ld a, MAP_LENGTH
call AddNTimes
ret
GetMapField::
; Extract data from the current map's group entry.
; inputs:
; de = offset of desired data within the map (a MAP_* constant)
; outputs:
; bc = data from the current map's field
; (e.g., de = MAP_TILESET would return a pointer to the tileset id)
ld a, [wMapGroup]
ld b, a
ld a, [wMapNumber]
ld c, a
GetAnyMapField::
; bankswitch
ldh a, [hROMBank]
push af
ld a, BANK(MapGroupPointers)
rst Bankswitch
call GetAnyMapPointer
add hl, de
ld c, [hl]
inc hl
ld b, [hl]
; bankswitch back
pop af
rst Bankswitch
ret
SwitchToMapAttributesBank::
ld a, [wMapGroup]
ld b, a
ld a, [wMapNumber]
ld c, a
SwitchToAnyMapAttributesBank::
call GetAnyMapAttributesBank
rst Bankswitch
ret
GetMapAttributesBank:: ; unreferenced
ld a, [wMapGroup]
ld b, a
ld a, [wMapNumber]
ld c, a
GetAnyMapAttributesBank::
push hl
push de
ld de, MAP_MAPATTRIBUTES_BANK
call GetAnyMapField
ld a, c
pop de
pop hl
ret
CopyMapPartial::
; Copy map data bank, tileset, environment, and map data address
; from the current map's entry within its group.
ldh a, [hROMBank]
push af
ld a, BANK(MapGroupPointers)
rst Bankswitch
call GetMapPointer
ld de, wMapPartial
ld bc, wMapPartialEnd - wMapPartial
call CopyBytes
pop af
rst Bankswitch
ret
SwitchToMapScriptsBank::
ld a, [wMapScriptsBank]
rst Bankswitch
ret
GetMapScriptsBank::
ld a, [wMapScriptsBank]
ret
GetAnyMapBlocksBank::
; Return the blockdata bank for group b map c.
push hl
push de
push bc
push bc
ld de, MAP_MAPATTRIBUTES
call GetAnyMapField
ld l, c
ld h, b
pop bc
push hl
ld de, MAP_MAPATTRIBUTES_BANK
call GetAnyMapField
pop hl
ld de, MAP_MAPATTRIBUTES ; blockdata bank
add hl, de
ld a, c
call GetFarByte
rst Bankswitch
pop bc
pop de
pop hl
ret
GetMapAttributesPointer::
; returns the current map's data pointer in hl.
push bc
push de
ld de, MAP_MAPATTRIBUTES
call GetMapField
ld l, c
ld h, b
pop de
pop bc
ret
GetMapEnvironment::
push hl
push de
push bc
ld de, MAP_ENVIRONMENT
call GetMapField
ld a, c
pop bc
pop de
pop hl
ret
Map_DummyFunction:: ; unreferenced
ret
GetAnyMapEnvironment::
push hl
push de
push bc
ld de, MAP_ENVIRONMENT
call GetAnyMapField
ld a, c
pop bc
pop de
pop hl
ret
GetAnyMapTileset::
ld de, MAP_TILESET
call GetAnyMapField
ld a, c
ret
GetWorldMapLocation::
; given a map group/id in bc, return its location on the Pokégear map.
push hl
push de
push bc
ld de, MAP_LOCATION
call GetAnyMapField
ld a, c
pop bc
pop de
pop hl
ret
GetMapMusic::
push hl
push bc
ld de, MAP_MUSIC
call GetMapField
ld a, c
cp MUSIC_MAHOGANY_MART
jr z, .mahoganymart
bit RADIO_TOWER_MUSIC_F, c
jr nz, .radiotower
farcall Function8b342
ld e, c
ld d, 0
.done
pop bc
pop hl
ret
.radiotower
ld a, [wStatusFlags2]
bit STATUSFLAGS2_ROCKETS_IN_RADIO_TOWER_F, a
jr z, .clearedradiotower
ld de, MUSIC_ROCKET_OVERTURE
jr .done
.clearedradiotower
; the rest of the byte
ld a, c
and RADIO_TOWER_MUSIC - 1
ld e, a
ld d, 0
jr .done
.mahoganymart
ld a, [wStatusFlags2]
bit STATUSFLAGS2_ROCKETS_IN_MAHOGANY_F, a
jr z, .clearedmahogany
ld de, MUSIC_ROCKET_HIDEOUT
jr .done
.clearedmahogany
ld de, MUSIC_CHERRYGROVE_CITY
jr .done
GetMapTimeOfDay::
call GetPhoneServiceTimeOfDayByte
and $f
ret
GetMapPhoneService::
call GetPhoneServiceTimeOfDayByte
and $f0
swap a
ret
GetPhoneServiceTimeOfDayByte::
push hl
push bc
ld de, MAP_PALETTE
call GetMapField
ld a, c
pop bc
pop hl
ret
GetFishingGroup::
push de
push hl
push bc
ld de, MAP_FISHGROUP
call GetMapField
ld a, c
pop bc
pop hl
pop de
ret
LoadMapTileset::
push hl
push bc
ld hl, Tilesets
ld bc, TILESET_LENGTH
ld a, [wMapTileset]
call AddNTimes
ld de, wTilesetBank
ld bc, TILESET_LENGTH
ld a, BANK(Tilesets)
call FarCopyBytes
pop bc
pop hl
ret
DummyEndPredef::
; Unused function at the end of PredefPointers.
rept 16
nop
endr
ret