mirror of
https://github.com/pret/pokeyellow.git
synced 2024-11-27 04:10:21 +00:00
4940 lines
102 KiB
NASM
4940 lines
102 KiB
NASM
|
||
; The rst vectors are unused.
|
||
SECTION "rst 00", ROM0 [$00]
|
||
rst $38
|
||
SECTION "rst 08", ROM0 [$08]
|
||
rst $38
|
||
SECTION "rst 10", ROM0 [$10]
|
||
rst $38
|
||
SECTION "rst 18", ROM0 [$18]
|
||
rst $38
|
||
SECTION "rst 20", ROM0 [$20]
|
||
rst $38
|
||
SECTION "rst 28", ROM0 [$28]
|
||
rst $38
|
||
SECTION "rst 30", ROM0 [$30]
|
||
rst $38
|
||
SECTION "rst 38", ROM0 [$38]
|
||
rst $38
|
||
|
||
; Hardware interrupts
|
||
SECTION "vblank", ROM0 [$40]
|
||
jp VBlank
|
||
SECTION "hblank", ROM0 [$48]
|
||
jp LCDC
|
||
SECTION "timer", ROM0 [$50]
|
||
jp Timer
|
||
SECTION "serial", ROM0 [$58]
|
||
jp Serial
|
||
SECTION "joypad", ROM0 [$60]
|
||
reti
|
||
|
||
|
||
SECTION "Home", ROM0
|
||
|
||
DisableLCD:: ; 0061 (0:0061)
|
||
xor a
|
||
ld [rIF], a
|
||
ld a, [rIE]
|
||
ld b, a
|
||
res 0, a
|
||
ld [rIE], a
|
||
|
||
.wait
|
||
ld a, [rLY]
|
||
cp LY_VBLANK
|
||
jr nz, .wait
|
||
|
||
ld a, [rLCDC]
|
||
and $ff ^ rLCDC_ENABLE_MASK
|
||
ld [rLCDC], a
|
||
ld a, b
|
||
ld [rIE], a
|
||
ret
|
||
|
||
EnableLCD:: ; 007b (0:007b)
|
||
ld a, [rLCDC]
|
||
set rLCDC_ENABLE, a
|
||
ld [rLCDC], a
|
||
ret
|
||
|
||
ClearSprites:: ; 0082 (0:0082)
|
||
xor a
|
||
ld hl, wOAMBuffer
|
||
ld b, 40 * 4
|
||
.loop
|
||
ld [hli], a
|
||
dec b
|
||
jr nz, .loop
|
||
ret
|
||
|
||
HideSprites:: ; 008d (0:008d)
|
||
ld a, 160
|
||
ld hl, wOAMBuffer
|
||
ld de, 4
|
||
ld b, 40
|
||
.loop
|
||
ld [hl], a
|
||
add hl, de
|
||
dec b
|
||
jr nz, .loop
|
||
ret
|
||
|
||
INCLUDE "home/copy.asm"
|
||
|
||
|
||
|
||
SECTION "Entry", ROM0 [$100]
|
||
|
||
nop
|
||
jp Start ; 01ab
|
||
|
||
|
||
SECTION "Header", ROM0 [$104]
|
||
|
||
; The header is generated by rgbfix.
|
||
; The space here is allocated to prevent code from being overwritten.
|
||
|
||
ds $150 - $104
|
||
|
||
|
||
|
||
SECTION "Main", ROM0
|
||
|
||
PlayPikachuPCM:: ; 0150 (0:0150)
|
||
ld a, [H_LOADEDROMBANK]
|
||
push af
|
||
ld a, b
|
||
call BankswitchCommon
|
||
ld a, [hli]
|
||
ld c, a
|
||
ld a, [hli]
|
||
ld b, a
|
||
.loop
|
||
ld a, [hli]
|
||
ld d, a
|
||
ld a, $3
|
||
.playSingleSample
|
||
dec a
|
||
jr nz, .playSingleSample
|
||
|
||
rept 7
|
||
call LoadNextSoundClipSample
|
||
call PlaySoundClipSample
|
||
endr
|
||
|
||
call LoadNextSoundClipSample
|
||
dec bc
|
||
ld a, c
|
||
or b
|
||
jr nz, .loop
|
||
pop af
|
||
call BankswitchCommon
|
||
ret
|
||
|
||
LoadNextSoundClipSample:: ; 0199 (0:0199)
|
||
ld a, d
|
||
and $80
|
||
srl a
|
||
srl a
|
||
ld [rNR32], a
|
||
sla d
|
||
ret
|
||
|
||
PlaySoundClipSample:: ; 01a5 (0:01a5)
|
||
ld a, $3
|
||
.loop
|
||
dec a
|
||
jr nz, .loop
|
||
ret
|
||
|
||
Start:: ; 01ab (0:01ab)
|
||
cp GBC
|
||
jr z, .gbc
|
||
xor a
|
||
jr .ok
|
||
.gbc
|
||
ld a, $1
|
||
.ok
|
||
ld [hGBC], a
|
||
jp Init
|
||
|
||
Joypad:: ; 01b9 (0:01b9)
|
||
homecall_jump _Joypad
|
||
|
||
ReadJoypad:: ; 01c8 (0:01c8)
|
||
homecall_jump ReadJoypad_
|
||
|
||
INCLUDE "home/overworld.asm"
|
||
|
||
CheckForUserInterruption:: ; 10ba (0:10ba)
|
||
; Return carry if Up+Select+B, Start or A are pressed in c frames.
|
||
; Used only in the intro and title screen.
|
||
call DelayFrame
|
||
|
||
push bc
|
||
call JoypadLowSensitivity
|
||
pop bc
|
||
|
||
ld a, [hJoyHeld]
|
||
cp D_UP + SELECT + B_BUTTON
|
||
jr z, .input
|
||
|
||
ld a, [hJoy5]
|
||
and START | A_BUTTON
|
||
jr nz, .input
|
||
|
||
dec c
|
||
jr nz, CheckForUserInterruption
|
||
|
||
and a
|
||
ret
|
||
|
||
.input
|
||
scf
|
||
ret
|
||
|
||
; function to load position data for destination warp when switching maps
|
||
; INPUT:
|
||
; a = ID of destination warp within destination map
|
||
LoadDestinationWarpPosition:: ; 10d5 (0:10d5)
|
||
ld b, a
|
||
ld a, [H_LOADEDROMBANK]
|
||
push af
|
||
ld a, [wPredefParentBank]
|
||
ld [H_LOADEDROMBANK], a
|
||
ld [MBC1RomBank], a
|
||
ld a, b
|
||
add a
|
||
add a
|
||
ld c, a
|
||
ld b, 0
|
||
add hl, bc
|
||
ld bc, 4
|
||
ld de, wCurrentTileBlockMapViewPointer
|
||
call CopyData
|
||
pop af
|
||
ld [H_LOADEDROMBANK], a
|
||
ld [MBC1RomBank], a
|
||
ret
|
||
|
||
|
||
DrawHPBar:: ; 10f8 (0:10f8)
|
||
; Draw an HP bar d tiles long, and fill it to e pixels.
|
||
; If c is nonzero, show at least a sliver regardless.
|
||
; The right end of the bar changes with [wHPBarType].
|
||
|
||
push hl
|
||
push de
|
||
;push bc
|
||
|
||
; Left
|
||
ld a, $71 ; "HP:"
|
||
ld [hli], a
|
||
ld a, $62
|
||
ld [hli], a
|
||
|
||
push hl
|
||
|
||
; Middle
|
||
ld a, $63 ; empty
|
||
.draw
|
||
ld [hli], a
|
||
dec d
|
||
jr nz, .draw
|
||
|
||
; Right
|
||
ld a, [wHPBarType]
|
||
dec a
|
||
ld a, $6d ; status screen and battle
|
||
jr z, .ok
|
||
dec a ; pokemon menu
|
||
.ok
|
||
ld [hl], a
|
||
|
||
pop hl
|
||
|
||
ld a, e
|
||
and a
|
||
jr nz, .fill
|
||
|
||
; If c iz nonzero, draw a pixel anyway.
|
||
ld a, c
|
||
and a
|
||
jr z, .done
|
||
ld e, 1
|
||
|
||
.fill
|
||
ld a, e
|
||
sub 8
|
||
jr c, .partial
|
||
ld e, a
|
||
ld a, $6b ; full
|
||
ld [hli], a
|
||
ld a, e
|
||
and a
|
||
jr z, .done
|
||
jr .fill
|
||
|
||
.partial
|
||
; Fill remaining pixels at the end if necessary.
|
||
ld a, $63 ; empty
|
||
add e
|
||
ld [hl], a
|
||
.done
|
||
;pop bc
|
||
pop de
|
||
pop hl
|
||
ret
|
||
|
||
|
||
; loads pokemon data from one of multiple sources to wLoadedMon
|
||
; loads base stats to wMonHeader
|
||
; INPUT:
|
||
; [wWhichPokemon] = index of pokemon within party/box
|
||
; [wMonDataLocation] = source
|
||
; 00: player's party
|
||
; 01: enemy's party
|
||
; 02: current box
|
||
; 03: daycare
|
||
; OUTPUT:
|
||
; [wcf91] = pokemon ID
|
||
; wLoadedMon = base address of pokemon data
|
||
; W_MONHDEXNUM = base address of base stats
|
||
LoadMonData:: ; 1132 (0:1132)
|
||
jpab LoadMonData_
|
||
|
||
OverwritewMoves:: ; 113a (0:113a)
|
||
; Write c to [wMoves + b]. Unused.
|
||
ld hl, wMoves
|
||
ld e, b
|
||
ld d, 0
|
||
add hl, de
|
||
ld a, c
|
||
ld [hl], a
|
||
ret
|
||
|
||
LoadFlippedFrontSpriteByMonIndex:: ; 1144 (0:1144)
|
||
ld a, 1
|
||
ld [wSpriteFlipped], a
|
||
|
||
LoadFrontSpriteByMonIndex:: ; 1149 (0:1149)
|
||
push hl
|
||
ld a, [wd11e]
|
||
push af
|
||
ld a, [wcf91]
|
||
ld [wd11e], a
|
||
predef IndexToPokedex
|
||
ld hl, wd11e
|
||
ld a, [hl]
|
||
pop bc
|
||
ld [hl], b
|
||
and a
|
||
pop hl
|
||
jr z, .invalidDexNumber ; dex #0 invalid
|
||
cp NUM_POKEMON + 1
|
||
jr c, .validDexNumber ; dex >#151 invalid
|
||
.invalidDexNumber
|
||
ld a, RHYDON ; $1
|
||
ld [wcf91], a
|
||
ret
|
||
.validDexNumber
|
||
push hl
|
||
ld de, vFrontPic
|
||
call LoadMonFrontSprite
|
||
pop hl
|
||
ld a, [H_LOADEDROMBANK]
|
||
push af
|
||
switchbank CopyUncompressedPicToHL
|
||
xor a
|
||
ld [hStartTileID], a
|
||
call CopyUncompressedPicToHL
|
||
xor a
|
||
ld [wSpriteFlipped], a
|
||
pop af
|
||
jp BankswitchCommon
|
||
|
||
PlayCry:: ; 118b (0:118b)
|
||
; Play monster a's cry.
|
||
push bc
|
||
ld b, a
|
||
ld a, [wLowHealthAlarm]
|
||
push af
|
||
xor a
|
||
ld [wLowHealthAlarm], a
|
||
ld a, b
|
||
call GetCryData
|
||
call PlaySound
|
||
call WaitForSoundToFinish
|
||
pop af
|
||
ld [wLowHealthAlarm], a
|
||
pop bc
|
||
ret
|
||
|
||
GetCryData:: ; 11a5 (0:11a5)
|
||
; Load cry data for monster a.
|
||
dec a
|
||
ld c, a
|
||
ld b, 0
|
||
ld hl, CryData
|
||
add hl, bc
|
||
add hl, bc
|
||
add hl, bc
|
||
|
||
ld a, BANK(CryData)
|
||
call BankswitchHome
|
||
ld a, [hli]
|
||
ld b, a ; cry id
|
||
ld a, [hli]
|
||
ld [wFrequencyModifier], a
|
||
ld a, [hl]
|
||
ld [wTempoModifier], a
|
||
call BankswitchBack
|
||
|
||
; Cry headers have 3 channels,
|
||
; and start from index $14,
|
||
; so add 3 times the cry id.
|
||
ld a, b
|
||
ld c, $14
|
||
rlca ; * 2
|
||
add b
|
||
add c
|
||
ret
|
||
|
||
DisplayPartyMenu:: ; 11c8 (0:11c8)
|
||
ld a, [hTilesetType]
|
||
push af
|
||
xor a
|
||
ld [hTilesetType], a
|
||
call GBPalWhiteOutWithDelay3
|
||
call ClearSprites
|
||
call PartyMenuInit
|
||
call DrawPartyMenu
|
||
jp HandlePartyMenuInput
|
||
|
||
GoBackToPartyMenu:: ; 11dd (0:11dd)
|
||
ld a, [hTilesetType]
|
||
push af
|
||
xor a
|
||
ld [hTilesetType], a
|
||
call PartyMenuInit
|
||
call RedrawPartyMenu
|
||
jp HandlePartyMenuInput
|
||
|
||
PartyMenuInit:: ; 11ec (0:11ec)
|
||
ld a, 1 ; hardcoded bank
|
||
call BankswitchHome
|
||
call LoadHpBarAndStatusTilePatterns
|
||
ld hl, wd730
|
||
set 6, [hl] ; turn off letter printing delay
|
||
xor a ; PLAYER_PARTY_DATA
|
||
ld [wMonDataLocation], a
|
||
ld [wMenuWatchMovingOutOfBounds], a
|
||
ld hl, wTopMenuItemY
|
||
inc a
|
||
ld [hli], a ; top menu item Y
|
||
xor a
|
||
ld [hli], a ; top menu item X
|
||
ld a, [wPartyAndBillsPCSavedMenuItem]
|
||
push af
|
||
ld [hli], a ; current menu item ID
|
||
inc hl
|
||
ld a, [wPartyCount]
|
||
and a ; are there more than 0 pokemon in the party?
|
||
jr z, .storeMaxMenuItemID
|
||
dec a
|
||
; if party is not empty, the max menu item ID is ([wPartyCount] - 1)
|
||
; otherwise, it is 0
|
||
.storeMaxMenuItemID
|
||
ld [hli], a ; max menu item ID
|
||
ld a, [wForcePlayerToChooseMon]
|
||
and a
|
||
ld a, A_BUTTON | B_BUTTON
|
||
jr z, .next
|
||
xor a
|
||
ld [wForcePlayerToChooseMon], a
|
||
inc a ; a = A_BUTTON
|
||
.next
|
||
ld [hli], a ; menu watched keys
|
||
pop af
|
||
ld [hl], a ; old menu item ID
|
||
ret
|
||
|
||
HandlePartyMenuInput:: ; 1226 (0:1226)
|
||
ld a, 1
|
||
ld [wMenuWrappingEnabled], a
|
||
ld a, $40
|
||
ld [wPartyMenuAnimMonEnabled], a
|
||
call HandleMenuInputPokemonSelection
|
||
push af ; save hJoy5 OR wMenuWrapping enabled, if no inputs were selected within a certain period of time
|
||
bit 1, a ; was B button pressed?
|
||
ld a, $0
|
||
ld [wPartyMenuAnimMonEnabled], a
|
||
ld a, [wCurrentMenuItem]
|
||
ld [wPartyAndBillsPCSavedMenuItem], a
|
||
jr nz, .asm_1258
|
||
ld a, [wCurrentMenuItem]
|
||
ld [wWhichPokemon], a
|
||
callab IsThisPartymonStarterPikachu_Party ; 3f:4e18
|
||
jr nc, .asm_1258
|
||
call CheckPikachuFollowingPlayer
|
||
jr nz, .asm_128f
|
||
.asm_1258
|
||
pop af
|
||
call PlaceUnfilledArrowMenuCursor
|
||
ld b, a
|
||
ld hl, wd730
|
||
res 6, [hl] ; turn on letter printing delay
|
||
ld a, [wMenuItemToSwap]
|
||
and a
|
||
jp nz, .swappingPokemon
|
||
pop af ; double pop af?
|
||
ld [hTilesetType], a
|
||
bit 1, b
|
||
jr nz, .noPokemonChosen
|
||
ld a, [wPartyCount]
|
||
and a
|
||
jr z, .noPokemonChosen
|
||
ld a, [wCurrentMenuItem]
|
||
ld [wWhichPokemon], a
|
||
ld hl, wPartySpecies
|
||
ld b, 0
|
||
ld c, a
|
||
add hl, bc
|
||
ld a, [hl]
|
||
ld [wcf91], a
|
||
ld [wBattleMonSpecies2], a
|
||
call BankswitchBack
|
||
and a
|
||
ret
|
||
.asm_128f
|
||
pop af
|
||
ld hl, PartyMenuText_12cc
|
||
call PrintText
|
||
xor a
|
||
ld [wMenuItemToSwap], a
|
||
pop af
|
||
ld [hTilesetType], a
|
||
.noPokemonChosen
|
||
call BankswitchBack
|
||
scf
|
||
ret
|
||
.swappingPokemon
|
||
bit 1, b ; was the B button pressed?
|
||
jr z, .handleSwap ; if not, handle swapping the pokemon
|
||
.cancelSwap ; if the B button was pressed
|
||
callba ErasePartyMenuCursors ; 4:5e98
|
||
xor a
|
||
ld [wMenuItemToSwap], a
|
||
ld [wPartyMenuTypeOrMessageID], a
|
||
call RedrawPartyMenu
|
||
jp HandlePartyMenuInput
|
||
.handleSwap
|
||
ld a, [wCurrentMenuItem]
|
||
ld [wWhichPokemon], a
|
||
callba SwitchPartyMon ; 4:61c5
|
||
jp HandlePartyMenuInput
|
||
|
||
PartyMenuText_12cc:: ; 12cc (0:12cc)
|
||
TX_FAR _SleepingPikachuText1 ; 28:411b
|
||
db "@"
|
||
|
||
DrawPartyMenu:: ; 12d1 (0:12d1)
|
||
ld hl, DrawPartyMenu_ ; 4:5875
|
||
jr DrawPartyMenuCommon
|
||
|
||
RedrawPartyMenu:: ; 12d6 (0:12d6)
|
||
ld hl, RedrawPartyMenu_ ; 4:5886
|
||
|
||
DrawPartyMenuCommon:: ; 12d9 (0:12d9)
|
||
ld b, BANK(RedrawPartyMenu_)
|
||
jp Bankswitch
|
||
|
||
; prints a pokemon's status condition
|
||
; INPUT:
|
||
; de = address of status condition
|
||
; hl = destination address
|
||
PrintStatusCondition:: ; 12de (0:12de)
|
||
push de
|
||
dec de
|
||
dec de ; de = address of current HP
|
||
ld a, [de]
|
||
ld b, a
|
||
dec de
|
||
ld a, [de]
|
||
or b ; is the pokemon's HP zero?
|
||
pop de
|
||
jr nz, PrintStatusConditionNotFainted
|
||
; if the pokemon's HP is 0, print "FNT"
|
||
ld a, "F"
|
||
ld [hli], a
|
||
ld a, "N"
|
||
ld [hli], a
|
||
ld [hl], "T"
|
||
and a
|
||
ret
|
||
|
||
PrintStatusConditionNotFainted: ; 12f3 (0:12f3)
|
||
homecall_jump_sf PrintStatusAilment
|
||
|
||
; function to print pokemon level, leaving off the ":L" if the level is at least 100
|
||
; INPUT:
|
||
; hl = destination address
|
||
; [wLoadedMonLevel] = level
|
||
PrintLevel:: ; 1303 (0:1303)
|
||
ld a, $6e ; ":L" tile ID
|
||
ld [hli], a
|
||
ld c, 2 ; number of digits
|
||
ld a, [wLoadedMonLevel] ; level
|
||
cp 100
|
||
jr c, PrintLevelCommon
|
||
; if level at least 100, write over the ":L" tile
|
||
dec hl
|
||
inc c ; increment number of digits to 3
|
||
jr PrintLevelCommon
|
||
|
||
; prints the level without leaving off ":L" regardless of level
|
||
; INPUT:
|
||
; hl = destination address
|
||
; [wLoadedMonLevel] = level
|
||
PrintLevelFull:: ; 1313 (0:1313)
|
||
ld a, $6e ; ":L" tile ID
|
||
ld [hli], a
|
||
ld c, 3 ; number of digits
|
||
ld a, [wLoadedMonLevel] ; level
|
||
|
||
PrintLevelCommon:: ; 131b (0:131b)
|
||
ld [wd11e], a
|
||
ld de, wd11e
|
||
ld b, LEFT_ALIGN | 1 ; 1 byte
|
||
jp PrintNumber
|
||
|
||
GetwMoves:: ; 1326 (0:1326)
|
||
; Unused. Returns the move at index a from wMoves in a
|
||
ld hl, wMoves
|
||
ld c, a
|
||
ld b, 0
|
||
add hl, bc
|
||
ld a, [hl]
|
||
ret
|
||
|
||
; copies the base stat data of a pokemon to wMonHeader
|
||
; INPUT:
|
||
; [wd0b5] = pokemon ID
|
||
GetMonHeader:: ; 132f (0:132f)
|
||
ld a, [H_LOADEDROMBANK]
|
||
push af
|
||
switchbank BaseStats
|
||
push bc
|
||
push de
|
||
push hl
|
||
ld a, [wd11e]
|
||
push af
|
||
ld a, [wd0b5]
|
||
ld [wd11e], a
|
||
ld de, FossilKabutopsPic
|
||
ld b, $66 ; size of Kabutops fossil and Ghost sprites
|
||
cp FOSSIL_KABUTOPS ; Kabutops fossil
|
||
jr z, .specialID
|
||
ld de, GhostPic
|
||
cp MON_GHOST ; Ghost
|
||
jr z, .specialID
|
||
ld de, FossilAerodactylPic
|
||
ld b, $77 ; size of Aerodactyl fossil sprite
|
||
cp FOSSIL_AERODACTYL ; Aerodactyl fossil
|
||
jr z, .specialID
|
||
;cp MEW
|
||
;jr z, .mew
|
||
predef IndexToPokedex ; convert pokemon ID in [wd11e] to pokedex number
|
||
ld a, [wd11e]
|
||
dec a
|
||
ld bc, 28
|
||
ld hl, BaseStats
|
||
call AddNTimes
|
||
ld de, wMonHeader
|
||
ld bc, 28
|
||
call CopyData
|
||
jr .done
|
||
.specialID
|
||
ld hl, wMonHSpriteDim
|
||
ld [hl], b ; write sprite dimensions
|
||
inc hl
|
||
ld [hl], e ; write front sprite pointer
|
||
inc hl
|
||
ld [hl], d
|
||
.done
|
||
ld a, [wd0b5]
|
||
ld [wMonHIndex], a
|
||
pop af
|
||
ld [wd11e], a
|
||
pop hl
|
||
pop de
|
||
pop bc
|
||
pop af
|
||
call BankswitchCommon
|
||
ret
|
||
|
||
; copy party pokemon's name to wcd6d
|
||
GetPartyMonName2:: ; 1394 (0:1394)
|
||
ld a, [wWhichPokemon] ; index within party
|
||
ld hl, wPartyMonNicks
|
||
|
||
; this is called more often
|
||
GetPartyMonName:: ; 139a (0:139a)
|
||
push hl
|
||
push bc
|
||
call SkipFixedLengthTextEntries ; add NAME_LENGTH to hl, a times
|
||
ld de, wcd6d
|
||
push de
|
||
ld bc, NAME_LENGTH
|
||
call CopyData
|
||
pop de
|
||
pop bc
|
||
pop hl
|
||
ret
|
||
|
||
; function to print a BCD (Binary-coded decimal) number
|
||
; de = address of BCD number
|
||
; hl = destination address
|
||
; c = flags and length
|
||
; bit 7: if set, do not print leading zeroes
|
||
; if unset, print leading zeroes
|
||
; bit 6: if set, left-align the string (do not pad empty digits with spaces)
|
||
; if unset, right-align the string
|
||
; bit 5: if set, print currency symbol at the beginning of the string
|
||
; if unset, do not print the currency symbol
|
||
; bits 0-4: length of BCD number in bytes
|
||
; Note that bits 5 and 7 are modified during execution. The above reflects
|
||
; their meaning at the beginning of the functions's execution.
|
||
PrintBCDNumber:: ; 13ad (0:13ad)
|
||
ld b, c ; save flags in b
|
||
res 7, c
|
||
res 6, c
|
||
res 5, c ; c now holds the length
|
||
bit 5, b
|
||
jr z, .loop
|
||
bit 7, b
|
||
jr nz, .loop
|
||
ld [hl], "¥"
|
||
inc hl
|
||
.loop
|
||
ld a, [de]
|
||
swap a
|
||
call PrintBCDDigit ; print upper digit
|
||
ld a, [de]
|
||
call PrintBCDDigit ; print lower digit
|
||
inc de
|
||
dec c
|
||
jr nz, .loop
|
||
bit 7, b ; were any non-zero digits printed?
|
||
jr z, .done ; if so, we are done
|
||
.numberEqualsZero ; if every digit of the BCD number is zero
|
||
bit 6, b ; left or right alignment?
|
||
jr nz, .skipRightAlignmentAdjustment
|
||
dec hl ; if the string is right-aligned, it needs to be moved back one space
|
||
.skipRightAlignmentAdjustment
|
||
bit 5, b
|
||
jr z, .skipCurrencySymbol
|
||
ld [hl], "¥"
|
||
inc hl
|
||
.skipCurrencySymbol
|
||
ld [hl], "0"
|
||
call PrintLetterDelay
|
||
inc hl
|
||
.done
|
||
ret
|
||
|
||
PrintBCDDigit:: ; 13e4 (0:13e4)
|
||
and $f
|
||
and a
|
||
jr z, .zeroDigit
|
||
.nonzeroDigit
|
||
bit 7, b ; have any non-space characters been printed?
|
||
jr z, .outputDigit
|
||
; if bit 7 is set, then no numbers have been printed yet
|
||
bit 5, b ; print the currency symbol?
|
||
jr z, .skipCurrencySymbol
|
||
ld [hl], "¥"
|
||
inc hl
|
||
res 5, b
|
||
.skipCurrencySymbol
|
||
res 7, b ; unset 7 to indicate that a nonzero digit has been reached
|
||
.outputDigit
|
||
add "0"
|
||
ld [hli], a
|
||
jp PrintLetterDelay
|
||
.zeroDigit
|
||
bit 7, b ; either printing leading zeroes or already reached a nonzero digit?
|
||
jr z, .outputDigit ; if so, print a zero digit
|
||
bit 6, b ; left or right alignment?
|
||
ret nz
|
||
inc hl ; if right-aligned, "print" a space by advancing the pointer
|
||
ret
|
||
|
||
; uncompresses the front or back sprite of the specified mon
|
||
; assumes the corresponding mon header is already loaded
|
||
; hl contains offset to sprite pointer ($b for front or $d for back)
|
||
UncompressMonSprite:: ; 1407 (0:1407)
|
||
ld bc, wMonHeader
|
||
add hl, bc
|
||
ld a, [hli]
|
||
ld [W_SPRITEINPUTPTR], a ; fetch sprite input pointer
|
||
ld a, [hl]
|
||
ld [W_SPRITEINPUTPTR+1], a
|
||
; define (by index number) the bank that a pokemon's image is in
|
||
; index = Mew, bank 1
|
||
; index = Kabutops fossil, bank $B
|
||
; index < $1F, bank 9
|
||
; $1F ≤ index < $4A, bank $A
|
||
; $4A ≤ index < $74, bank $B
|
||
; $74 ≤ index < $99, bank $C
|
||
; $99 ≤ index, bank $D
|
||
ld a, [wcf91] ; XXX name for this ram location
|
||
ld b, a
|
||
;cp MEW
|
||
;ld a, BANK(MewPicFront)
|
||
;jr z, .GotBank
|
||
;ld a, b
|
||
cp FOSSIL_KABUTOPS
|
||
ld a, BANK(FossilKabutopsPic)
|
||
jr z, .GotBank
|
||
ld a, b
|
||
cp TANGELA + 1
|
||
ld a, BANK(TangelaPicFront)
|
||
jr c, .GotBank
|
||
ld a, b
|
||
cp MOLTRES + 1
|
||
ld a, BANK(MoltresPicFront)
|
||
jr c, .GotBank
|
||
ld a, b
|
||
cp BEEDRILL + 2
|
||
ld a, BANK(BeedrillPicFront)
|
||
jr c, .GotBank
|
||
ld a, b
|
||
cp STARMIE + 1
|
||
ld a, BANK(StarmiePicFront)
|
||
jr c, .GotBank
|
||
ld a, BANK(VictreebelPicFront)
|
||
.GotBank
|
||
jp UncompressSpriteData ; 23f8
|
||
|
||
; de: destination location
|
||
LoadMonFrontSprite:: ; 143e (0:143e)
|
||
push de
|
||
ld hl, wMonHFrontSprite - wMonHeader
|
||
call UncompressMonSprite
|
||
ld hl, wMonHSpriteDim
|
||
ld a, [hli]
|
||
ld c, a
|
||
pop de
|
||
; fall through
|
||
|
||
; postprocesses uncompressed sprite chunks to a 2bpp sprite and loads it into video ram
|
||
; calculates alignment parameters to place both sprite chunks in the center of the 7*7 tile sprite buffers
|
||
; de: destination location
|
||
; a, c: sprite dimensions (in tiles of 8x8 each)
|
||
LoadUncompressedSpriteData:: ; 1672 (0:1672)
|
||
push de
|
||
and $f
|
||
ld [H_SPRITEWIDTH], a ; each byte contains 8 pixels (in 1bpp), so tiles=bytes for width
|
||
ld b, a
|
||
ld a, $7
|
||
sub b ; 7-w
|
||
inc a ; 8-w
|
||
srl a ; (8-w)/2 ; horizontal center (in tiles, rounded up)
|
||
ld b, a
|
||
add a
|
||
add a
|
||
add a
|
||
sub b ; 7*((8-w)/2) ; skip for horizontal center (in tiles)
|
||
ld [H_SPRITEOFFSET], a
|
||
ld a, c
|
||
swap a
|
||
and $f
|
||
ld b, a
|
||
add a
|
||
add a
|
||
add a ; 8*tiles is height in bytes
|
||
ld [H_SPRITEHEIGHT], a
|
||
ld a, $7
|
||
sub b ; 7-h ; skip for vertical center (in tiles, relative to current column)
|
||
ld b, a
|
||
ld a, [H_SPRITEOFFSET]
|
||
add b ; 7*((8-w)/2) + 7-h ; combined overall offset (in tiles)
|
||
add a
|
||
add a
|
||
add a ; 8*(7*((8-w)/2) + 7-h) ; combined overall offset (in bytes)
|
||
ld [H_SPRITEOFFSET], a
|
||
ld a, $0
|
||
call SwitchSRAMBankAndLatchClockData
|
||
ld hl, S_SPRITEBUFFER0
|
||
call ZeroSpriteBuffer ; zero buffer 0
|
||
ld de, S_SPRITEBUFFER1
|
||
ld hl, S_SPRITEBUFFER0
|
||
call AlignSpriteDataCentered ; copy and align buffer 1 to 0 (containing the MSB of the 2bpp sprite)
|
||
ld hl, S_SPRITEBUFFER1
|
||
call ZeroSpriteBuffer ; zero buffer 1
|
||
ld de, S_SPRITEBUFFER2
|
||
ld hl, S_SPRITEBUFFER1
|
||
call AlignSpriteDataCentered ; copy and align buffer 2 to 1 (containing the LSB of the 2bpp sprite)
|
||
call PrepareRTCDataAndDisableSRAM
|
||
pop de
|
||
jp InterlaceMergeSpriteBuffers ; 14c7
|
||
|
||
; copies and aligns the sprite data properly inside the sprite buffer
|
||
; sprite buffers are 7*7 tiles in size, the loaded sprite is centered within this area
|
||
AlignSpriteDataCentered:: ; 149f (0:149f)
|
||
ld a, [H_SPRITEOFFSET]
|
||
ld b, $0
|
||
ld c, a
|
||
add hl, bc
|
||
ld a, [H_SPRITEWIDTH]
|
||
.columnLoop
|
||
push af
|
||
push hl
|
||
ld a, [H_SPRITEHEIGHT]
|
||
ld c, a
|
||
.columnInnerLoop
|
||
ld a, [de]
|
||
inc de
|
||
ld [hli], a
|
||
dec c
|
||
jr nz, .columnInnerLoop
|
||
pop hl
|
||
ld bc, 7*8 ; 7 tiles
|
||
add hl, bc ; advance one full column
|
||
pop af
|
||
dec a
|
||
jr nz, .columnLoop
|
||
ret
|
||
|
||
; fills the sprite buffer (pointed to in hl) with zeros
|
||
ZeroSpriteBuffer:: ; 14bc (0:14bc)
|
||
ld bc, SPRITEBUFFERSIZE
|
||
.nextByteLoop
|
||
xor a
|
||
ld [hli], a
|
||
dec bc
|
||
ld a, b
|
||
or c
|
||
jr nz, .nextByteLoop
|
||
ret
|
||
|
||
; combines the (7*7 tiles, 1bpp) sprite chunks in buffer 0 and 1 into a 2bpp sprite located in buffer 1 through 2
|
||
; in the resulting sprite, the rows of the two source sprites are interlaced
|
||
; de: output address
|
||
InterlaceMergeSpriteBuffers:: ; 14c7 (0:14c7)
|
||
ld a, $0
|
||
call SwitchSRAMBankAndLatchClockData
|
||
push de
|
||
ld hl, S_SPRITEBUFFER2 + (SPRITEBUFFERSIZE - 1) ; destination: end of buffer 2
|
||
ld de, S_SPRITEBUFFER1 + (SPRITEBUFFERSIZE - 1) ; source 2: end of buffer 1
|
||
ld bc, S_SPRITEBUFFER0 + (SPRITEBUFFERSIZE - 1) ; source 1: end of buffer 0
|
||
ld a, SPRITEBUFFERSIZE/2 ; $c4
|
||
ld [H_SPRITEINTERLACECOUNTER], a
|
||
.interlaceLoop
|
||
ld a, [de]
|
||
dec de
|
||
ld [hld], a ; write byte of source 2
|
||
ld a, [bc]
|
||
dec bc
|
||
ld [hld], a ; write byte of source 1
|
||
ld a, [de]
|
||
dec de
|
||
ld [hld], a ; write byte of source 2
|
||
ld a, [bc]
|
||
dec bc
|
||
ld [hld], a ; write byte of source 1
|
||
ld a, [H_SPRITEINTERLACECOUNTER]
|
||
dec a
|
||
ld [H_SPRITEINTERLACECOUNTER], a
|
||
jr nz, .interlaceLoop
|
||
ld a, [wSpriteFlipped]
|
||
and a
|
||
jr z, .notFlipped
|
||
ld bc, 2*SPRITEBUFFERSIZE
|
||
ld hl, S_SPRITEBUFFER1
|
||
.swapLoop
|
||
swap [hl] ; if flipped swap nybbles in all bytes
|
||
inc hl
|
||
dec bc
|
||
ld a, b
|
||
or c
|
||
jr nz, .swapLoop
|
||
.notFlipped
|
||
pop hl
|
||
ld de, S_SPRITEBUFFER1
|
||
ld c, (2*SPRITEBUFFERSIZE)/16 ; $31, number of 16 byte chunks to be copied
|
||
ld a, [H_LOADEDROMBANK]
|
||
ld b, a
|
||
call CopyVideoData
|
||
jp PrepareRTCDataAndDisableSRAM
|
||
|
||
INCLUDE "home/pikachu.asm"
|
||
;INCLUDE "data/collision.asm"
|
||
|
||
INCLUDE "home/lcdc.asm"
|
||
|
||
IsTilePassable:: ; 15c3 (0:15c3)
|
||
; sets carry if tile is passable, resets carry otherwise
|
||
homecall_sf _IsTilePassable ; 1:4aaa
|
||
ret
|
||
|
||
INCLUDE "home/copy2.asm"
|
||
INCLUDE "home/text.asm"
|
||
INCLUDE "home/vcopy.asm"
|
||
INCLUDE "home/init.asm"
|
||
INCLUDE "home/vblank.asm"
|
||
INCLUDE "home/fade.asm"
|
||
INCLUDE "home/play_time.asm"
|
||
INCLUDE "home/serial.asm"
|
||
INCLUDE "home/timer.asm"
|
||
INCLUDE "home/audio.asm"
|
||
|
||
|
||
UpdateSprites:: ; 231c (0:231c)
|
||
ld a, [wUpdateSpritesEnabled]
|
||
dec a
|
||
ret nz
|
||
ld a, [H_LOADEDROMBANK]
|
||
push af
|
||
switchbank _UpdateSprites
|
||
ld a, $ff
|
||
ld [wUpdateSpritesEnabled], a
|
||
call _UpdateSprites ; 1:4bb7
|
||
ld a, $1
|
||
ld [wUpdateSpritesEnabled], a
|
||
pop af
|
||
call BankswitchCommon
|
||
ret
|
||
|
||
INCLUDE "data/mart_inventories.asm"
|
||
|
||
TextScriptEndingChar:: ; 23d1 (0:23d1)
|
||
db "@"
|
||
TextScriptEnd:: ; 23d2 (0:23d2)
|
||
ld hl, TextScriptEndingChar
|
||
ret
|
||
|
||
ExclamationText:: ; 23d6 (0:23d6)
|
||
TX_FAR _ExclamationText
|
||
db "@"
|
||
|
||
GroundRoseText:: ; 23db (0:23db)
|
||
TX_FAR _GroundRoseText
|
||
db "@"
|
||
|
||
BoulderText:: ; 23e0 (0:23e0)
|
||
TX_FAR _BoulderText
|
||
db "@"
|
||
|
||
MartSignText:: ; 23e5 (0:23e5)
|
||
TX_FAR _MartSignText
|
||
db "@"
|
||
|
||
PokeCenterSignText:: ; 23ea (0:23ea)
|
||
TX_FAR _PokeCenterSignText
|
||
db "@"
|
||
|
||
PickUpItemText:: ; 23ef (0:23ef)
|
||
TX_ASM
|
||
predef PickUpItem
|
||
jp TextScriptEnd
|
||
|
||
|
||
INCLUDE "home/pic.asm"
|
||
|
||
|
||
ResetPlayerSpriteData:: ; 279c (0:279c)
|
||
ld hl, wSpriteStateData1
|
||
call ResetPlayerSpriteData_ClearSpriteData
|
||
ld hl, wSpriteStateData2
|
||
call ResetPlayerSpriteData_ClearSpriteData
|
||
ld a, $1
|
||
ld [wSpriteStateData1], a
|
||
ld [wSpriteStateData2 + $0e], a
|
||
ld hl, wSpriteStateData1 + 4
|
||
ld [hl], $3c ; set Y screen pos
|
||
inc hl
|
||
inc hl
|
||
ld [hl], $40 ; set X screen pos
|
||
ret
|
||
|
||
; overwrites sprite data with zeroes
|
||
ResetPlayerSpriteData_ClearSpriteData:: ; 27ba (0:27ba)
|
||
ld bc, $10
|
||
xor a
|
||
call FillMemory ; XXX why replaced with call + ret?
|
||
ret
|
||
;jp FillMemory
|
||
|
||
FadeOutAudio:: ; 27c2 (0:27c2)
|
||
ld a, [wAudioFadeOutControl]
|
||
and a
|
||
jr nz, .asm_27d3
|
||
ld a, [wd72c]
|
||
bit 1, a
|
||
ret nz
|
||
ld a, $77
|
||
ld [rNR50], a
|
||
ret
|
||
.asm_27d3
|
||
ld a, [wAudioFadeOutCounter]
|
||
and a
|
||
jr z, .counterReachedZero
|
||
dec a
|
||
ld [wAudioFadeOutCounter], a
|
||
ret
|
||
.counterReachedZero
|
||
ld a, [wAudioFadeOutCounterReloadValue]
|
||
ld [wAudioFadeOutCounter], a
|
||
ld a, [rNR50]
|
||
and a
|
||
jr z, .asm_27fa
|
||
ld b, a
|
||
and $f
|
||
dec a
|
||
ld c, a
|
||
ld a, b
|
||
and $f0
|
||
swap a
|
||
dec a
|
||
swap a
|
||
or c
|
||
ld [rNR50], a
|
||
ret
|
||
.asm_27fa
|
||
ld a, [wAudioFadeOutControl]
|
||
ld b, a
|
||
xor a
|
||
ld [wAudioFadeOutControl], a
|
||
call StopAllMusic
|
||
ld a, [wAudioSavedROMBank]
|
||
ld [wAudioROMBank], a
|
||
ld a, b
|
||
ld [wNewSoundID], a
|
||
jp PlaySound
|
||
|
||
UnknownText_2812:: ; 2812 (0:2812)
|
||
TX_FAR _PokemonText ; 2c:749a
|
||
db "@"
|
||
|
||
; this function is used to display sign messages, sprite dialog, etc.
|
||
; INPUT: [hSpriteIndexOrTextID] = sprite ID or text ID
|
||
DisplayTextID:: ; 2817 (0:2817)
|
||
ld a, [H_LOADEDROMBANK]
|
||
push af
|
||
callba DisplayTextIDInit ; initialization
|
||
ld hl, wTextPredefFlag
|
||
bit 0, [hl]
|
||
res 0, [hl]
|
||
jr nz, .skipSwitchToMapBank
|
||
ld a, [wCurMap]
|
||
call SwitchToMapRomBank
|
||
.skipSwitchToMapBank
|
||
ld a, 30 ; half a second
|
||
ld [H_FRAMECOUNTER], a ; used as joypad poll timer
|
||
ld hl, wMapTextPtr
|
||
ld a, [hli]
|
||
ld h, [hl]
|
||
ld l, a ; hl = map text pointer
|
||
ld d, $00
|
||
ld a, [hSpriteIndexOrTextID] ; text ID
|
||
ld [wSpriteIndex], a
|
||
and a
|
||
jp z, DisplayStartMenu
|
||
cp TEXT_PIKACHU_ANIM ; new yellow asm
|
||
jp z, DisplayUnknownText_29c6
|
||
cp TEXT_SAFARI_GAME_OVER
|
||
jp z, DisplaySafariGameOverText
|
||
cp TEXT_MON_FAINTED
|
||
jp z, DisplayPokemonFaintedText
|
||
cp TEXT_BLACKED_OUT
|
||
jp z, DisplayPlayerBlackedOutText
|
||
cp TEXT_REPEL_WORE_OFF
|
||
jp z, DisplayRepelWoreOffText
|
||
ld a, [wNumSprites]
|
||
ld e, a
|
||
ld a, [hSpriteIndexOrTextID] ; sprite ID
|
||
cp e
|
||
jr z, .spriteHandling
|
||
jr nc, .skipSpriteHandling
|
||
.spriteHandling
|
||
; get the text ID of the sprite
|
||
push hl
|
||
;push de
|
||
;push bc
|
||
;callba UpdateSpriteFacingOffsetAndDelayMovement ; update the graphics of the sprite the player is talking to (to face the right direction)
|
||
;pop bc
|
||
;pop de
|
||
ld hl, wMapSpriteData ; NPC text entries
|
||
ld a, [hSpriteIndexOrTextID]
|
||
dec a
|
||
add a
|
||
ld e, a
|
||
ld d, $0
|
||
add hl, de
|
||
inc hl
|
||
ld a, [hl] ; a = text ID of the sprite
|
||
pop hl
|
||
.skipSpriteHandling
|
||
; look up the address of the text in the map's text entries
|
||
dec a
|
||
ld e, a
|
||
ld d, $0
|
||
add hl, de
|
||
add hl, de
|
||
ld a, [hli]
|
||
ld h, [hl]
|
||
ld l, a ; hl = address of the text
|
||
ld a, [hl] ; a = first byte of text
|
||
; check first byte of text for special cases
|
||
cp $fe ; Pokemart NPC
|
||
jp z, DisplayPokemartDialogue
|
||
cp $ff ; Pokemon Center NPC
|
||
jp z, DisplayPokemonCenterDialogue
|
||
cp $fc ; Item Storage PC
|
||
jp z, FuncTX_ItemStoragePC
|
||
cp $fd ; Bill's PC
|
||
jp z, FuncTX_BillsPC
|
||
cp $f9 ; Pokemon Center PC
|
||
jp z, FuncTX_PokemonCenterPC
|
||
cp $f5 ; Vending Machine
|
||
jr nz, .notVendingMachine
|
||
callba VendingMachineMenu ; jump banks to vending machine routine
|
||
jr AfterDisplayingTextID
|
||
.notVendingMachine
|
||
cp $f7 ; slot machine
|
||
jp z, FuncTX_GameCornerPrizeMenu
|
||
cp $f6 ; cable connection NPC in Pokemon Center
|
||
jr nz, .notSpecialCase
|
||
callab CableClubNPC
|
||
jr AfterDisplayingTextID
|
||
.notSpecialCase
|
||
call PrintText_NoCreatingTextBox ; display the text
|
||
ld a, [wDoNotWaitForButtonPressAfterDisplayingText]
|
||
and a
|
||
jr nz, HoldTextDisplayOpen
|
||
|
||
AfterDisplayingTextID:: ; 28c6 (0:28c6)
|
||
ld a, [wEnteringCableClub]
|
||
and a
|
||
jr nz, HoldTextDisplayOpen
|
||
call WaitForTextScrollButtonPress ; wait for a button press after displaying all the text
|
||
|
||
; loop to hold the dialogue box open as long as the player keeps holding down the A button
|
||
HoldTextDisplayOpen:: ; 28cf (0:28cf)
|
||
call Joypad
|
||
ld a, [hJoyHeld]
|
||
bit 0, a ; is the A button being pressed?
|
||
jr nz, HoldTextDisplayOpen
|
||
|
||
CloseTextDisplay:: ; 28d8 (0:28d8)
|
||
ld a, [wCurMap]
|
||
call SwitchToMapRomBank
|
||
ld a, $90
|
||
ld [hWY], a ; move the window off the screen
|
||
call DelayFrame
|
||
call LoadGBPal
|
||
xor a
|
||
ld [H_AUTOBGTRANSFERENABLED], a ; disable continuous WRAM to VRAM transfer each V-blank
|
||
; loop to make sprites face the directions they originally faced before the dialogue
|
||
ld hl, wSpriteStateData2 + $19
|
||
ld c, $0f
|
||
ld de, $0010
|
||
.restoreSpriteFacingDirectionLoop
|
||
ld a, [hl]
|
||
dec h
|
||
ld [hl], a
|
||
inc h
|
||
add hl, de
|
||
dec c
|
||
jr nz, .restoreSpriteFacingDirectionLoop
|
||
call InitMapSprites ; reload sprite tile pattern data (since it was partially overwritten by text tile patterns)
|
||
ld hl, wFontLoaded
|
||
res 0, [hl]
|
||
ld a, [wd732]
|
||
bit 3, a ; used fly warp
|
||
call z, LoadPlayerSpriteGraphics
|
||
call LoadCurrentMapView
|
||
pop af
|
||
call BankswitchCommon
|
||
jp UpdateSprites
|
||
|
||
DisplayPokemartDialogue:: ; 2915 (0:2915)
|
||
push hl
|
||
ld hl, PokemartGreetingText
|
||
call PrintText
|
||
pop hl
|
||
inc hl
|
||
call LoadItemList
|
||
ld a, PRICEDITEMLISTMENU
|
||
ld [wListMenuID], a ; selects between subtypes of menus
|
||
homecall DisplayPokemartDialogue_
|
||
jp AfterDisplayingTextID
|
||
|
||
PokemartGreetingText:: ; 2938 (0:2938)
|
||
TX_FAR _PokemartGreetingText
|
||
db "@"
|
||
|
||
LoadItemList:: ; 293d (0:293d)
|
||
ld a, 1
|
||
ld [wUpdateSpritesEnabled], a
|
||
ld a, h
|
||
ld [wItemListPointer], a
|
||
ld a, l
|
||
ld [wItemListPointer + 1], a
|
||
ld de, wItemList
|
||
.loop
|
||
ld a, [hli]
|
||
ld [de], a
|
||
inc de
|
||
cp $ff
|
||
jr nz, .loop
|
||
ret
|
||
|
||
DisplayPokemonCenterDialogue:: ; 2955 (0:2955)
|
||
; zeroing these doesn't appear to serve any purpose
|
||
xor a
|
||
ld [$ff8b], a
|
||
ld [$ff8c], a
|
||
ld [$ff8d], a
|
||
|
||
inc hl
|
||
homecall DisplayPokemonCenterDialogue_
|
||
jp AfterDisplayingTextID
|
||
|
||
DisplaySafariGameOverText:: ; 296f (0:296f)
|
||
callab PrintSafariGameOverText
|
||
jp AfterDisplayingTextID
|
||
|
||
DisplayPokemonFaintedText:: ; 297a (0:297a)
|
||
ld hl, PokemonFaintedText
|
||
call PrintText
|
||
jp AfterDisplayingTextID
|
||
|
||
PokemonFaintedText:: ; 2983 (0:2983)
|
||
TX_FAR _PokemonFaintedText
|
||
db "@"
|
||
|
||
DisplayPlayerBlackedOutText:: ; 2988 (0:2988)
|
||
ld hl, PlayerBlackedOutText
|
||
call PrintText
|
||
ld a, [wd732]
|
||
res 5, a ; reset forced to use bike bit
|
||
ld [wd732], a
|
||
ld a, [wd790]
|
||
bit 7, a
|
||
jr z, .didnotblackoutinsafari
|
||
xor a
|
||
ld [wNumSafariBalls], a
|
||
ld [wSafariSteps], a
|
||
ld [wSafariSteps+1], a
|
||
ld [wd790], a
|
||
ld [wcf0d], a
|
||
ld [wSafariZoneEntranceCurScript], a
|
||
.didnotblackoutinsafari
|
||
jp HoldTextDisplayOpen
|
||
|
||
PlayerBlackedOutText:: ; 29b3 (0:29b3)
|
||
TX_FAR _PlayerBlackedOutText
|
||
db "@"
|
||
|
||
DisplayRepelWoreOffText:: ; 29b8 (0:29b8)
|
||
ld hl, RepelWoreOffText
|
||
call PrintText
|
||
jp AfterDisplayingTextID
|
||
|
||
RepelWoreOffText:: ; 29c1 (0:29c1)
|
||
TX_FAR _RepelWoreOffText
|
||
db "@"
|
||
|
||
DisplayUnknownText_29c6:: ; 29c6 (0:29c6)
|
||
callab Func_fd004 ; 3f:5004
|
||
jp CloseTextDisplay
|
||
|
||
INCLUDE "engine/menu/start_menu.asm"
|
||
|
||
; function to count how many bits are set in a string of bytes
|
||
; INPUT:
|
||
; hl = address of string of bytes
|
||
; b = length of string of bytes
|
||
; OUTPUT:
|
||
; [wNumSetBits] = number of set bits
|
||
CountSetBits:: ; 2a81 (0:2a81)
|
||
ld c, 0
|
||
.loop
|
||
ld a, [hli]
|
||
ld e, a
|
||
ld d, 8
|
||
.innerLoop ; count how many bits are set in the current byte
|
||
srl e
|
||
ld a, 0
|
||
adc c
|
||
ld c, a
|
||
dec d
|
||
jr nz, .innerLoop
|
||
dec b
|
||
jr nz, .loop
|
||
ld a, c
|
||
ld [wNumSetBits], a
|
||
ret
|
||
|
||
; subtracts the amount the player paid from their money
|
||
; sets carry flag if there is enough money and unsets carry flag if not
|
||
SubtractAmountPaidFromMoney:: ; 2a98 (0:2a98)
|
||
jpba SubtractAmountPaidFromMoney_
|
||
|
||
; adds the amount the player sold to their money
|
||
AddAmountSoldToMoney:: ; 2aa0 (0:2aa0)
|
||
ld de, wPlayerMoney + 2
|
||
ld hl, $ffa1 ; total price of items
|
||
ld c, 3 ; length of money in bytes
|
||
predef AddBCDPredef ; add total price to money
|
||
ld a, MONEY_BOX
|
||
ld [wTextBoxID], a
|
||
call DisplayTextBoxID ; redraw money text box
|
||
ld a, $b2 ; SFX_PURCHASE
|
||
call PlaySoundWaitForCurrent ; play sound
|
||
jp WaitForSoundToFinish ; wait until sound is done playing
|
||
|
||
; function to remove an item (in varying quantities) from the player's bag or PC box
|
||
; INPUT:
|
||
; HL = address of inventory (either wNumBagItems or wNumBoxItems)
|
||
; [wWhichPokemon] = index (within the inventory) of the item to remove
|
||
; [wItemQuantity] = quantity to remove
|
||
RemoveItemFromInventory:: ; 2abd (0:2abd)
|
||
homecall RemoveItemFromInventory_
|
||
ret
|
||
|
||
; function to add an item (in varying quantities) to the player's bag or PC box
|
||
; INPUT:
|
||
; HL = address of inventory (either wNumBagItems or wNumBoxItems)
|
||
; [wcf91] = item ID
|
||
; [wItemQuantity] = item quantity
|
||
; sets carry flag if successful, unsets carry flag if unsuccessful
|
||
AddItemToInventory:: ; 2acd (0:2acd)
|
||
push bc
|
||
homecall_sf AddItemToInventory_
|
||
pop bc
|
||
ret
|
||
|
||
; INPUT:
|
||
; [wListMenuID] = list menu ID
|
||
; [wListPointer] = address of the list (2 bytes)
|
||
DisplayListMenuID:: ; 2ae0 (0:2ae0)
|
||
xor a
|
||
ld [H_AUTOBGTRANSFERENABLED], a ; disable auto-transfer
|
||
ld a, 1
|
||
ld [hJoy7], a ; joypad state update flag
|
||
ld a, [wBattleType]
|
||
and a ; is it the Old Man battle?
|
||
jr nz, .specialBattleType
|
||
ld a, $01 ; hardcoded bank
|
||
jr .bankswitch
|
||
.specialBattleType ; Old Man battle
|
||
ld a, $f ; BANK(DisplayBattleMenu)
|
||
.bankswitch
|
||
call BankswitchHome
|
||
ld hl, wd730
|
||
set 6, [hl] ; turn off letter printing delay
|
||
xor a
|
||
ld [wMenuItemToSwap], a ; 0 means no item is currently being swapped
|
||
ld [wListCount], a
|
||
ld a, [wListPointer]
|
||
ld l, a
|
||
ld a, [wListPointer + 1]
|
||
ld h, a ; hl = address of the list
|
||
ld a, [hl] ; the first byte is the number of entries in the list
|
||
ld [wListCount], a
|
||
ld a, LIST_MENU_BOX
|
||
ld [wTextBoxID], a
|
||
call DisplayTextBoxID ; draw the menu text box
|
||
call UpdateSprites ; disable sprites behind the text box
|
||
; the code up to .skipMovingSprites appears to be useless
|
||
coord hl, 4, 2 ; coordinates of upper left corner of menu text box
|
||
lb de, 9, 14 ; height and width of menu text box
|
||
ld a, [wListMenuID]
|
||
and a ; is it a PC pokemon list?
|
||
jr nz, .skipMovingSprites
|
||
call UpdateSprites
|
||
.skipMovingSprites
|
||
ld a, 1 ; max menu item ID is 1 if the list has less than 2 entries
|
||
ld [wMenuWatchMovingOutOfBounds], a
|
||
ld a, [wListCount]
|
||
cp 2 ; does the list have less than 2 entries?
|
||
jr c, .setMenuVariables
|
||
ld a, 2 ; max menu item ID is 2 if the list has at least 2 entries
|
||
.setMenuVariables
|
||
ld [wMaxMenuItem], a
|
||
ld a, 4
|
||
ld [wTopMenuItemY], a
|
||
ld a, 5
|
||
ld [wTopMenuItemX], a
|
||
ld a, A_BUTTON | B_BUTTON | SELECT
|
||
ld [wMenuWatchedKeys], a
|
||
ld c, 10
|
||
call DelayFrames
|
||
|
||
DisplayListMenuIDLoop:: ; 2b4d (0:2b4d)
|
||
xor a
|
||
ld [H_AUTOBGTRANSFERENABLED], a ; disable transfer
|
||
call PrintListMenuEntries
|
||
ld a, 1
|
||
ld [H_AUTOBGTRANSFERENABLED], a ; enable transfer
|
||
call Delay3
|
||
ld a, [wBattleType]
|
||
and a ; is it the Old Man battle?
|
||
jr z, .notOldManBattle
|
||
.oldManBattle
|
||
ld a, "▶"
|
||
Coorda 5, 4 ; place menu cursor in front of first menu entry
|
||
ld c, 20
|
||
call DelayFrames
|
||
xor a
|
||
ld [wCurrentMenuItem], a
|
||
coord hl, 5, 4
|
||
ld a, l
|
||
ld [wMenuCursorLocation], a
|
||
ld a, h
|
||
ld [wMenuCursorLocation + 1], a
|
||
jr .buttonAPressed
|
||
.notOldManBattle
|
||
call LoadGBPal
|
||
call HandleMenuInput
|
||
push af
|
||
call PlaceMenuCursor
|
||
pop af
|
||
bit 0, a ; was the A button pressed?
|
||
jp z, .checkOtherKeys
|
||
.buttonAPressed
|
||
ld a, [wCurrentMenuItem]
|
||
call PlaceUnfilledArrowMenuCursor
|
||
|
||
; pointless because both values are overwritten before they are read
|
||
ld a, $01
|
||
ld [wMenuExitMethod], a
|
||
ld [wChosenMenuItem], a
|
||
|
||
xor a
|
||
ld [wMenuWatchMovingOutOfBounds], a
|
||
ld a, [wCurrentMenuItem]
|
||
ld c, a
|
||
ld a, [wListScrollOffset]
|
||
add c
|
||
ld c, a
|
||
ld a, [wListCount]
|
||
and a ; is the list empty?
|
||
jp z, ExitListMenu ; if so, exit the menu
|
||
dec a
|
||
cp c ; did the player select Cancel?
|
||
jp c, ExitListMenu ; if so, exit the menu
|
||
ld a, c
|
||
ld [wWhichPokemon], a
|
||
ld a, [wListMenuID]
|
||
cp ITEMLISTMENU
|
||
jr nz, .skipMultiplying
|
||
; if it's an item menu
|
||
sla c ; item entries are 2 bytes long, so multiply by 2
|
||
.skipMultiplying
|
||
ld a, [wListPointer]
|
||
ld l, a
|
||
ld a, [wListPointer + 1]
|
||
ld h, a
|
||
inc hl ; hl = beginning of list entries
|
||
ld b, 0
|
||
add hl, bc
|
||
ld a, [hl]
|
||
ld [wcf91], a
|
||
ld a, [wListMenuID]
|
||
and a ; is it a PC pokemon list?
|
||
jr z, .pokemonList
|
||
push hl
|
||
call GetItemPrice
|
||
pop hl
|
||
ld a, [wListMenuID]
|
||
cp ITEMLISTMENU
|
||
jr nz, .skipGettingQuantity
|
||
; if it's an item menu
|
||
inc hl
|
||
ld a, [hl] ; a = item quantity
|
||
ld [wMaxItemQuantity], a
|
||
.skipGettingQuantity
|
||
ld a, [wcf91]
|
||
ld [wd0b5], a
|
||
ld a, BANK(ItemNames)
|
||
ld [wPredefBank], a
|
||
call GetName
|
||
jr .storeChosenEntry
|
||
.pokemonList
|
||
ld hl, wPartyCount
|
||
ld a, [wListPointer]
|
||
cp l ; is it a list of party pokemon or box pokemon?
|
||
ld hl, wPartyMonNicks
|
||
jr z, .getPokemonName
|
||
ld hl, wBoxMonNicks ; box pokemon names
|
||
.getPokemonName
|
||
ld a, [wWhichPokemon]
|
||
call GetPartyMonName
|
||
.storeChosenEntry ; store the menu entry that the player chose and return
|
||
ld de, wcd6d
|
||
call CopyStringToCF4B ; copy name to wcf4b
|
||
ld a, CHOSE_MENU_ITEM
|
||
ld [wMenuExitMethod], a
|
||
ld a, [wCurrentMenuItem]
|
||
ld [wChosenMenuItem], a
|
||
xor a
|
||
ld [hJoy7], a ; joypad state update flag
|
||
ld hl, wd730
|
||
res 6, [hl] ; turn on letter printing delay
|
||
jp BankswitchBack
|
||
.checkOtherKeys ; check B, SELECT, Up, and Down keys
|
||
bit 1, a ; was the B button pressed?
|
||
jp nz, ExitListMenu ; if so, exit the menu
|
||
bit 2, a ; was the select button pressed?
|
||
jp nz, HandleItemListSwapping ; if so, allow the player to swap menu entries
|
||
ld b, a
|
||
bit 7, b ; was Down pressed?
|
||
ld hl, wListScrollOffset
|
||
jr z, .upPressed
|
||
.downPressed
|
||
ld a, [hl]
|
||
add 3
|
||
ld b, a
|
||
ld a, [wListCount]
|
||
cp b ; will going down scroll past the Cancel button?
|
||
jp c, DisplayListMenuIDLoop
|
||
inc [hl] ; if not, go down
|
||
jp DisplayListMenuIDLoop
|
||
.upPressed
|
||
ld a, [hl]
|
||
and a
|
||
jp z, DisplayListMenuIDLoop
|
||
dec [hl]
|
||
jp DisplayListMenuIDLoop
|
||
|
||
DisplayChooseQuantityMenu:: ; 2c51 (0:2c51)
|
||
; text box dimensions/coordinates for just quantity
|
||
coord hl, 15, 9
|
||
lb bc, 1, 3 ; height and width
|
||
ld a, [wListMenuID]
|
||
cp PRICEDITEMLISTMENU
|
||
jr nz, .drawTextBox
|
||
; text box dimensions/coordinates for quantity and price
|
||
coord hl, 7, 9
|
||
lb bc, 1, 11 ; height and width
|
||
.drawTextBox
|
||
call TextBoxBorder
|
||
coord hl, 16, 10
|
||
ld a, [wListMenuID]
|
||
cp PRICEDITEMLISTMENU
|
||
jr nz, .printInitialQuantity
|
||
coord hl, 8, 10
|
||
.printInitialQuantity
|
||
ld de, InitialQuantityText
|
||
call PlaceString
|
||
xor a
|
||
ld [wItemQuantity], a ; initialize current quantity to 0
|
||
jp .incrementQuantity
|
||
.waitForKeyPressLoop
|
||
call JoypadLowSensitivity
|
||
ld a, [hJoyPressed] ; newly pressed buttons
|
||
bit 0, a ; was the A button pressed?
|
||
jp nz, .buttonAPressed
|
||
bit 1, a ; was the B button pressed?
|
||
jp nz, .buttonBPressed
|
||
bit 6, a ; was Up pressed?
|
||
jr nz, .incrementQuantity
|
||
bit 7, a ; was Down pressed?
|
||
jr nz, .decrementQuantity
|
||
jr .waitForKeyPressLoop
|
||
.incrementQuantity
|
||
ld a, [wMaxItemQuantity]
|
||
inc a
|
||
ld b, a
|
||
ld hl, wItemQuantity ; current quantity
|
||
inc [hl]
|
||
ld a, [hl]
|
||
cp b
|
||
jr nz, .handleNewQuantity
|
||
; wrap to 1 if the player goes above the max quantity
|
||
ld a, 1
|
||
ld [hl], a
|
||
jr .handleNewQuantity
|
||
.decrementQuantity
|
||
ld hl, wItemQuantity ; current quantity
|
||
dec [hl]
|
||
jr nz, .handleNewQuantity
|
||
; wrap to the max quantity if the player goes below 1
|
||
ld a, [wMaxItemQuantity]
|
||
ld [hl], a
|
||
.handleNewQuantity
|
||
coord hl, 17, 10
|
||
ld a, [wListMenuID]
|
||
cp PRICEDITEMLISTMENU
|
||
jr nz, .printQuantity
|
||
.printPrice
|
||
ld c, $03
|
||
ld a, [wItemQuantity]
|
||
ld b, a
|
||
ld hl, hMoney ; total price
|
||
; initialize total price to 0
|
||
xor a
|
||
ld [hli], a
|
||
ld [hli], a
|
||
ld [hl], a
|
||
.addLoop ; loop to multiply the individual price by the quantity to get the total price
|
||
ld de, hMoney + 2
|
||
ld hl, hItemPrice + 2
|
||
push bc
|
||
predef AddBCDPredef ; add the individual price to the current sum
|
||
pop bc
|
||
dec b
|
||
jr nz, .addLoop
|
||
ld a, [hHalveItemPrices]
|
||
and a ; should the price be halved (for selling items)?
|
||
jr z, .skipHalvingPrice
|
||
xor a
|
||
ld [hDivideBCDDivisor], a
|
||
ld [hDivideBCDDivisor + 1], a
|
||
ld a, $02
|
||
ld [hDivideBCDDivisor + 2], a
|
||
predef DivideBCDPredef3 ; halves the price
|
||
; store the halved price
|
||
ld a, [hDivideBCDQuotient]
|
||
ld [hMoney], a
|
||
ld a, [hDivideBCDQuotient + 1]
|
||
ld [hMoney + 1], a
|
||
ld a, [hDivideBCDQuotient + 2]
|
||
ld [hMoney + 2], a
|
||
.skipHalvingPrice
|
||
coord hl, 12, 10
|
||
ld de, SpacesBetweenQuantityAndPriceText
|
||
call PlaceString
|
||
ld de, hMoney ; total price
|
||
ld c, $a3
|
||
call PrintBCDNumber
|
||
coord hl, 9, 10
|
||
.printQuantity
|
||
ld de, wItemQuantity ; current quantity
|
||
lb bc, LEADING_ZEROES | 1, 2 ; 1 byte, 2 digits
|
||
call PrintNumber
|
||
jp .waitForKeyPressLoop
|
||
.buttonAPressed ; the player chose to make the transaction
|
||
xor a
|
||
ld [wMenuItemToSwap], a ; 0 means no item is currently being swapped
|
||
ret
|
||
.buttonBPressed ; the player chose to cancel the transaction
|
||
xor a
|
||
ld [wMenuItemToSwap], a ; 0 means no item is currently being swapped
|
||
ld a, $ff
|
||
ret
|
||
|
||
InitialQuantityText:: ; 2d28 (0:2d28)
|
||
db "×01@"
|
||
|
||
SpacesBetweenQuantityAndPriceText:: ; 2d2c (0:2d2c)
|
||
db " @"
|
||
|
||
ExitListMenu:: ; 2d33 (0:2d33)
|
||
ld a, [wCurrentMenuItem]
|
||
ld [wChosenMenuItem], a
|
||
ld a, CANCELLED_MENU
|
||
ld [wMenuExitMethod], a
|
||
ld [wMenuWatchMovingOutOfBounds], a
|
||
xor a
|
||
ld [hJoy7], a
|
||
ld hl, wd730
|
||
res 6, [hl]
|
||
call BankswitchBack
|
||
xor a
|
||
ld [wMenuItemToSwap], a ; 0 means no item is currently being swapped
|
||
scf
|
||
ret
|
||
|
||
PrintListMenuEntries:: ; 2d52 (0:2d52)
|
||
coord hl, 5, 3
|
||
lb bc, 9, 14
|
||
call ClearScreenArea
|
||
ld a, [wListPointer]
|
||
ld e, a
|
||
ld a, [wListPointer + 1]
|
||
ld d, a
|
||
inc de ; de = beginning of list entries
|
||
ld a, [wListScrollOffset]
|
||
ld c, a
|
||
ld a, [wListMenuID]
|
||
cp ITEMLISTMENU
|
||
ld a, c
|
||
jr nz, .skipMultiplying
|
||
; if it's an item menu
|
||
; item entries are 2 bytes long, so multiply by 2
|
||
add a
|
||
sla c
|
||
.skipMultiplying
|
||
add e
|
||
ld e, a
|
||
jr nc, .noCarry
|
||
inc d
|
||
.noCarry
|
||
coord hl, 6, 4 ; coordinates of first list entry name
|
||
ld b, 4 ; print 4 names
|
||
.loop
|
||
ld a, b
|
||
ld [wWhichPokemon], a
|
||
ld a, [de]
|
||
ld [wd11e], a
|
||
cp $ff
|
||
jp z, .printCancelMenuItem
|
||
push bc
|
||
push de
|
||
push hl
|
||
push hl
|
||
push de
|
||
ld a, [wListMenuID]
|
||
and a
|
||
jr z, .pokemonPCMenu
|
||
cp $01
|
||
jr z, .movesMenu
|
||
.itemMenu
|
||
call GetItemName
|
||
jr .placeNameString
|
||
.pokemonPCMenu
|
||
push hl
|
||
ld hl, wPartyCount
|
||
ld a, [wListPointer]
|
||
cp l ; is it a list of party pokemon or box pokemon?
|
||
ld hl, wPartyMonNicks
|
||
jr z, .getPokemonName
|
||
ld hl, wBoxMonNicks ; box pokemon names
|
||
.getPokemonName
|
||
ld a, [wWhichPokemon]
|
||
ld b, a
|
||
ld a, 4
|
||
sub b
|
||
ld b, a
|
||
ld a, [wListScrollOffset]
|
||
add b
|
||
call GetPartyMonName
|
||
pop hl
|
||
jr .placeNameString
|
||
.movesMenu
|
||
call GetMoveName
|
||
.placeNameString
|
||
call PlaceString
|
||
pop de
|
||
pop hl
|
||
ld a, [wPrintItemPrices]
|
||
and a ; should prices be printed?
|
||
jr z, .skipPrintingItemPrice
|
||
.printItemPrice
|
||
push hl
|
||
ld a, [de]
|
||
ld de, ItemPrices
|
||
ld [wcf91], a
|
||
call GetItemPrice ; get price
|
||
pop hl
|
||
ld bc, SCREEN_WIDTH + 5 ; 1 row down and 5 columns right
|
||
add hl, bc
|
||
ld c, $a3 ; no leading zeroes, right-aligned, print currency symbol, 3 bytes
|
||
call PrintBCDNumber
|
||
.skipPrintingItemPrice
|
||
ld a, [wListMenuID]
|
||
and a
|
||
jr nz, .skipPrintingPokemonLevel
|
||
.printPokemonLevel
|
||
ld a, [wd11e]
|
||
push af
|
||
push hl
|
||
ld hl, wPartyCount
|
||
ld a, [wListPointer]
|
||
cp l ; is it a list of party pokemon or box pokemon?
|
||
ld a, PLAYER_PARTY_DATA
|
||
jr z, .next
|
||
ld a, BOX_DATA
|
||
.next
|
||
ld [wMonDataLocation], a
|
||
ld hl, wWhichPokemon
|
||
ld a, [hl]
|
||
ld b, a
|
||
ld a, $04
|
||
sub b
|
||
ld b, a
|
||
ld a, [wListScrollOffset]
|
||
add b
|
||
ld [hl], a
|
||
call LoadMonData
|
||
ld a, [wMonDataLocation]
|
||
and a ; is it a list of party pokemon or box pokemon?
|
||
jr z, .skipCopyingLevel
|
||
.copyLevel
|
||
ld a, [wLoadedMonBoxLevel]
|
||
ld [wLoadedMonLevel], a
|
||
.skipCopyingLevel
|
||
pop hl
|
||
ld bc, $001c
|
||
add hl, bc
|
||
call PrintLevel
|
||
pop af
|
||
ld [wd11e], a
|
||
.skipPrintingPokemonLevel
|
||
pop hl
|
||
pop de
|
||
inc de
|
||
ld a, [wListMenuID]
|
||
cp ITEMLISTMENU
|
||
jr nz, .nextListEntry
|
||
.printItemQuantity
|
||
ld a, [wd11e]
|
||
ld [wcf91], a
|
||
call IsKeyItem ; check if item is unsellable
|
||
ld a, [wIsKeyItem]
|
||
and a ; is the item unsellable?
|
||
jr nz, .skipPrintingItemQuantity ; if so, don't print the quantity
|
||
push hl
|
||
ld bc, SCREEN_WIDTH + 8 ; 1 row down and 8 columns right
|
||
add hl, bc
|
||
ld a, "×"
|
||
ld [hli], a
|
||
ld a, [wd11e]
|
||
push af
|
||
ld a, [de]
|
||
ld [wMaxItemQuantity], a
|
||
push de
|
||
ld de, wd11e
|
||
ld [de], a
|
||
lb bc, 1, 2
|
||
call PrintNumber
|
||
pop de
|
||
pop af
|
||
ld [wd11e], a
|
||
pop hl
|
||
.skipPrintingItemQuantity
|
||
inc de
|
||
pop bc
|
||
inc c
|
||
push bc
|
||
inc c
|
||
ld a, [wMenuItemToSwap] ; ID of item chosen for swapping (counts from 1)
|
||
and a ; is an item being swapped?
|
||
jr z, .nextListEntry
|
||
add a
|
||
cp c ; is it this item?
|
||
jr nz, .nextListEntry
|
||
dec hl
|
||
ld a, $ec ; unfilled right arrow menu cursor to indicate an item being swapped
|
||
ld [hli], a
|
||
.nextListEntry
|
||
ld bc, 2 * SCREEN_WIDTH ; 2 rows
|
||
add hl, bc
|
||
pop bc
|
||
inc c
|
||
dec b
|
||
jp nz, .loop
|
||
ld bc, -8
|
||
add hl, bc
|
||
ld a, $ee ; down arrow
|
||
ld [hl], a
|
||
ret
|
||
.printCancelMenuItem
|
||
ld de, ListMenuCancelText
|
||
jp PlaceString
|
||
|
||
ListMenuCancelText:: ; 2e8c (0:2e8c)
|
||
db "CANCEL@"
|
||
|
||
GetMonName:: ; 2e93 (0:2e93)
|
||
push hl
|
||
ld a, [H_LOADEDROMBANK]
|
||
push af
|
||
ld a, BANK(MonsterNames) ; 3a
|
||
ld [H_LOADEDROMBANK], a
|
||
ld [MBC1RomBank], a
|
||
ld a, [wd11e]
|
||
dec a
|
||
ld hl, MonsterNames ; 4000
|
||
ld c, 10
|
||
ld b, 0
|
||
call AddNTimes
|
||
ld de, wcd6d
|
||
push de
|
||
ld bc, 10
|
||
call CopyData
|
||
ld hl, wcd6d + 10
|
||
ld [hl], "@"
|
||
pop de
|
||
pop af
|
||
ld [H_LOADEDROMBANK], a
|
||
ld [MBC1RomBank], a
|
||
pop hl
|
||
ret
|
||
|
||
GetItemName:: ; 2ec4 (0:2ec4)
|
||
; given an item ID at [wd11e], store the name of the item into a string
|
||
; starting at wcd6d
|
||
push hl
|
||
push bc
|
||
ld a, [wd11e]
|
||
cp HM_01 ; is this a TM/HM?
|
||
jr nc, .Machine
|
||
|
||
ld [wd0b5], a
|
||
ld a, ITEM_NAME
|
||
ld [wNameListType], a
|
||
ld a, BANK(ItemNames)
|
||
ld [wPredefBank], a
|
||
call GetName
|
||
jr .Finish
|
||
|
||
.Machine
|
||
call GetMachineName
|
||
.Finish
|
||
ld de, wcd6d ; pointer to where item name is stored in RAM
|
||
pop bc
|
||
pop hl
|
||
ret
|
||
|
||
GetMachineName:: ; 2ee8 (0:2ee8)
|
||
; copies the name of the TM/HM in [wd11e] to wcd6d
|
||
push hl
|
||
push de
|
||
push bc
|
||
ld a, [wd11e]
|
||
push af
|
||
cp TM_01 ; is this a TM? [not HM]
|
||
jr nc, .WriteTM
|
||
; if HM, then write "HM" and add 5 to the item ID, so we can reuse the
|
||
; TM printing code
|
||
add 5
|
||
ld [wd11e], a
|
||
ld hl, HiddenPrefix ; points to "HM"
|
||
ld bc, 2
|
||
jr .WriteMachinePrefix
|
||
.WriteTM
|
||
ld hl, TechnicalPrefix ; points to "TM"
|
||
ld bc, 2
|
||
.WriteMachinePrefix
|
||
ld de, wcd6d
|
||
call CopyData
|
||
|
||
; now get the machine number and convert it to text
|
||
ld a, [wd11e]
|
||
sub TM_01 - 1
|
||
ld b, "0"
|
||
.FirstDigit
|
||
sub 10
|
||
jr c, .SecondDigit
|
||
inc b
|
||
jr .FirstDigit
|
||
.SecondDigit
|
||
add 10
|
||
push af
|
||
ld a, b
|
||
ld [de], a
|
||
inc de
|
||
pop af
|
||
ld b, "0"
|
||
add b
|
||
ld [de], a
|
||
inc de
|
||
ld a, "@"
|
||
ld [de], a
|
||
pop af
|
||
ld [wd11e], a
|
||
pop bc
|
||
pop de
|
||
pop hl
|
||
ret
|
||
|
||
TechnicalPrefix:: ; 2f31 (0:2f31)
|
||
db "TM"
|
||
HiddenPrefix:: ; 2f33 (0:2f33)
|
||
db "HM"
|
||
|
||
; sets carry if item is HM, clears carry if item is not HM
|
||
; Input: a = item ID
|
||
IsItemHM:: ; 2f35 (0:2f35)
|
||
cp HM_01
|
||
jr c, .notHM
|
||
cp TM_01
|
||
ret
|
||
.notHM
|
||
and a
|
||
ret
|
||
|
||
; sets carry if move is an HM, clears carry if move is not an HM
|
||
; Input: a = move ID
|
||
IsMoveHM:: ; 2f3e (0:2f3e)
|
||
ld hl, HMMoves
|
||
ld de, 1
|
||
jp IsInArray
|
||
|
||
HMMoves:: ; 2f47 (0:2f47)
|
||
db CUT, FLY, SURF, STRENGTH, FLASH
|
||
db $ff ; terminator
|
||
|
||
GetMoveName:: ; 2f4d (0:2f4d)
|
||
push hl
|
||
ld a, MOVE_NAME
|
||
ld [wNameListType], a
|
||
ld a, [wd11e]
|
||
ld [wd0b5], a
|
||
ld a, BANK(MoveNames)
|
||
ld [wPredefBank], a
|
||
call GetName
|
||
ld de, wcd6d ; pointer to where move name is stored in RAM
|
||
pop hl
|
||
ret
|
||
|
||
; reloads text box tile patterns, current map view, and tileset tile patterns
|
||
ReloadMapData:: ; 2f66 (0:2f66)
|
||
ld a, [H_LOADEDROMBANK]
|
||
push af
|
||
ld a, [wCurMap]
|
||
call SwitchToMapRomBank
|
||
call DisableLCD
|
||
call LoadTextBoxTilePatterns
|
||
call LoadCurrentMapView
|
||
call LoadTilesetTilePatternData
|
||
call EnableLCD
|
||
pop af
|
||
call BankswitchCommon
|
||
ret
|
||
|
||
; reloads tileset tile patterns
|
||
ReloadTilesetTilePatterns:: ; 2f83 (0:2f83)
|
||
ld a, [H_LOADEDROMBANK]
|
||
push af
|
||
ld a, [wCurMap]
|
||
call SwitchToMapRomBank
|
||
call DisableLCD
|
||
call LoadTilesetTilePatternData
|
||
call EnableLCD
|
||
pop af
|
||
call BankswitchCommon
|
||
ret
|
||
|
||
; shows the town map and lets the player choose a destination to fly to
|
||
ChooseFlyDestination:: ; 2f9a (0:2f9a)
|
||
ld hl, wd72e
|
||
res 4, [hl]
|
||
jpba LoadTownMap_Fly
|
||
|
||
Func_2fa7:: ; 2fa7 (0:2fa7)
|
||
homecall Func_e8a5e
|
||
ret
|
||
|
||
SerialFunction:: ; 2fb7 (0:2fb7)
|
||
ld a, [wUnknownSerialFlag_d49a]
|
||
bit 0, a
|
||
ret z
|
||
ld a, [wUnknownSerialFlag_d49b]
|
||
and a
|
||
ret nz
|
||
ld hl, wOverworldMap+650
|
||
inc [hl]
|
||
ld a, [hl]
|
||
cp $6
|
||
ret c
|
||
xor a
|
||
ld [hl], a
|
||
ld a, $0c
|
||
ld [wUnknownSerialFlag_d49b], a
|
||
ld a, $88
|
||
ld [rSB], a
|
||
ld a, $1
|
||
ld [rSC], a
|
||
ld a, START_TRANSFER_INTERNAL_CLOCK
|
||
ld [rSC], a
|
||
ret
|
||
|
||
; causes the text box to close without waiting for a button press after displaying text
|
||
DisableWaitingAfterTextDisplay:: ; 2fde (0:2fde)
|
||
ld a, $01
|
||
ld [wDoNotWaitForButtonPressAfterDisplayingText], a
|
||
ret
|
||
|
||
; uses an item
|
||
; UseItem is used with dummy items to perform certain other functions as well
|
||
; INPUT:
|
||
; [wcf91] = item ID
|
||
; OUTPUT:
|
||
; [wActionResultOrTookBattleTurn] = success
|
||
; 00: unsucessful
|
||
; 01: successful
|
||
; 02: not able to be used right now, no extra menu displayed (only certain items use this)
|
||
UseItem:: ; 2fe4 (0:2fe4)
|
||
jpba UseItem_
|
||
|
||
; confirms the item toss and then tosses the item
|
||
; INPUT:
|
||
; hl = address of inventory (either wNumBagItems or wNumBoxItems)
|
||
; [wcf91] = item ID
|
||
; [wWhichPokemon] = index of item within inventory
|
||
; [wItemQuantity] = quantity to toss
|
||
; OUTPUT:
|
||
; clears carry flag if the item is tossed, sets carry flag if not
|
||
TossItem:: ; 2fec (0:2fec)
|
||
ld a, [H_LOADEDROMBANK]
|
||
push af
|
||
ld a, BANK(TossItem_)
|
||
ld [H_LOADEDROMBANK], a
|
||
ld [MBC1RomBank], a
|
||
call TossItem_
|
||
pop de
|
||
ld a, d
|
||
ld [H_LOADEDROMBANK], a
|
||
ld [MBC1RomBank], a
|
||
ret
|
||
|
||
; checks if an item is a key item
|
||
; INPUT:
|
||
; [wcf91] = item ID
|
||
; OUTPUT:
|
||
; [wIsKeyItem] = result
|
||
; 00: item is not key item
|
||
; 01: item is key item
|
||
IsKeyItem:: ; 3000 (0:3000)
|
||
push hl
|
||
push de
|
||
push bc
|
||
callba IsKeyItem_
|
||
pop bc
|
||
pop de
|
||
pop hl
|
||
ret
|
||
|
||
; function to draw various text boxes
|
||
; INPUT:
|
||
; [wTextBoxID] = text box ID
|
||
DisplayTextBoxID:: ; 3010 (0:3010)
|
||
homecall_sf DisplayTextBoxID_
|
||
ret
|
||
|
||
UpdateGBCPal_BGP:: ; 3021 (0:3021)
|
||
push af
|
||
ld a, [hGBC]
|
||
and a
|
||
jr z, .notGBC
|
||
push bc
|
||
push de
|
||
push hl
|
||
ld a, [rBGP]
|
||
ld b, a
|
||
ld a, [wLastBGP]
|
||
cp b
|
||
jr z, .noChangeInBGP
|
||
callba _UpdateGBCPal_BGP
|
||
.noChangeInBGP
|
||
pop hl
|
||
pop de
|
||
pop bc
|
||
.notGBC
|
||
pop af
|
||
ret
|
||
|
||
UpdateGBCPal_OBP0:: ; 3040 (0:3040)
|
||
push af
|
||
ld a, [hGBC]
|
||
and a
|
||
jr z, .notGBC
|
||
push bc
|
||
push de
|
||
push hl
|
||
ld a, [rOBP0]
|
||
ld b, a
|
||
ld a, [wLastOBP0]
|
||
cp b
|
||
jr z, .noChangeInOBP0
|
||
ld b, BANK(_UpdateGBCPal_OBP)
|
||
ld hl, _UpdateGBCPal_OBP
|
||
ld c, CONVERT_OBP0
|
||
call Bankswitch
|
||
.noChangeInOBP0
|
||
pop hl
|
||
pop de
|
||
pop bc
|
||
.notGBC
|
||
pop af
|
||
ret
|
||
|
||
UpdateGBCPal_OBP1:: ; 3061 (0:3061)
|
||
push af
|
||
ld a, [hGBC]
|
||
and a
|
||
jr z, .notGBC
|
||
push bc
|
||
push de
|
||
push hl
|
||
ld a, [rOBP1]
|
||
ld b, a
|
||
ld a, [wLastOBP1]
|
||
cp b
|
||
jr z, .noChangeInOBP1
|
||
ld b, BANK(_UpdateGBCPal_OBP)
|
||
ld hl, _UpdateGBCPal_OBP
|
||
ld c, CONVERT_OBP1
|
||
call Bankswitch
|
||
.noChangeInOBP1
|
||
pop hl
|
||
pop de
|
||
pop bc
|
||
.notGBC
|
||
pop af
|
||
ret
|
||
|
||
Func_3082:: ; 3082 (0:3082)
|
||
ld a, [H_LOADEDROMBANK]
|
||
push af
|
||
call FadeOutAudio
|
||
callbs Music_DoLowHealthAlarm
|
||
callbs Audio1_UpdateMusic
|
||
pop af
|
||
call BankswitchCommon
|
||
ret
|
||
|
||
; not zero if an NPC movement script is running, the player character is
|
||
; automatically stepping down from a door, or joypad states are being simulated
|
||
IsPlayerCharacterBeingControlledByGame:: ; 309d (0:309d)
|
||
ld a, [wNPCMovementScriptPointerTableNum]
|
||
and a
|
||
ret nz
|
||
ld a, [wd736]
|
||
bit 1, a ; currently stepping down from door bit
|
||
ret nz
|
||
ld a, [wd730]
|
||
and $80
|
||
ret
|
||
|
||
RunNPCMovementScript:: ; 30ae (0:30ae)
|
||
ld hl, wd736
|
||
bit 0, [hl]
|
||
res 0, [hl]
|
||
jr nz, .playerStepOutFromDoor
|
||
ld a, [wNPCMovementScriptPointerTableNum]
|
||
and a
|
||
ret z
|
||
dec a
|
||
add a
|
||
ld d, 0
|
||
ld e, a
|
||
ld hl, .NPCMovementScriptPointerTables
|
||
add hl, de
|
||
ld a, [hli]
|
||
ld h, [hl]
|
||
ld l, a
|
||
ld a, [H_LOADEDROMBANK]
|
||
push af
|
||
ld a, [wNPCMovementScriptBank]
|
||
call BankswitchCommon
|
||
ld a, [wNPCMovementScriptFunctionNum]
|
||
call JumpTable
|
||
pop af
|
||
call BankswitchCommon
|
||
ret
|
||
|
||
.NPCMovementScriptPointerTables
|
||
dw PalletMovementScriptPointerTable
|
||
dw PewterMuseumGuyMovementScriptPointerTable
|
||
dw PewterGymGuyMovementScriptPointerTable
|
||
.playerStepOutFromDoor
|
||
jpba PlayerStepOutFromDoor
|
||
|
||
EndNPCMovementScript:: ; 30ea (0:30ea)
|
||
jpba _EndNPCMovementScript
|
||
|
||
EmptyFunc2:: ; 30f2 (0:30f2)
|
||
ret
|
||
|
||
; stores hl in [wTrainerHeaderPtr]
|
||
StoreTrainerHeaderPointer:: ; 30f3 (0:30f3)
|
||
ld a, h
|
||
ld [wTrainerHeaderPtr], a
|
||
ld a, l
|
||
ld [wTrainerHeaderPtr+1], a
|
||
ret
|
||
|
||
; executes the current map script from the function pointer array provided in hl.
|
||
; a: map script index to execute (unless overridden by [wd733] bit 4)
|
||
ExecuteCurMapScriptInTable:: ; 30fc (0:30fc)
|
||
push af
|
||
push de
|
||
call StoreTrainerHeaderPointer
|
||
pop hl
|
||
pop af
|
||
push hl
|
||
ld hl, wFlags_D733
|
||
bit 4, [hl]
|
||
res 4, [hl]
|
||
jr z, .useProvidedIndex ; test if map script index was overridden manually
|
||
ld a, [W_CURMAPSCRIPT]
|
||
.useProvidedIndex
|
||
pop hl
|
||
ld [W_CURMAPSCRIPT], a
|
||
call JumpTable
|
||
ld a, [W_CURMAPSCRIPT]
|
||
ret
|
||
|
||
LoadGymLeaderAndCityName:: ; 311b (0:311b)
|
||
push de
|
||
ld de, wGymCityName
|
||
ld bc, $11
|
||
call CopyData ; load city name
|
||
pop hl
|
||
ld de, wGymLeaderName
|
||
ld bc, NAME_LENGTH
|
||
jp CopyData ; load gym leader name
|
||
|
||
; reads specific information from trainer header (pointed to at wTrainerHeaderPtr)
|
||
; a: offset in header data
|
||
; 0 -> flag's bit (into wTrainerHeaderFlagBit)
|
||
; 2 -> flag's byte ptr (into hl)
|
||
; 4 -> before battle text (into hl)
|
||
; 6 -> after battle text (into hl)
|
||
; 8 -> end battle text (into hl)
|
||
ReadTrainerHeaderInfo:: ; 312f (0:312f)
|
||
push de
|
||
push af
|
||
ld d, $0
|
||
ld e, a
|
||
ld hl, wTrainerHeaderPtr
|
||
ld a, [hli]
|
||
ld l, [hl]
|
||
ld h, a
|
||
add hl, de
|
||
pop af
|
||
and a
|
||
jr nz, .nonZeroOffset
|
||
ld a, [hl]
|
||
ld [wTrainerHeaderFlagBit], a ; store flag's bit
|
||
jr .done
|
||
.nonZeroOffset
|
||
cp $2
|
||
jr z, .readPointer ; read flag's byte ptr
|
||
cp $4
|
||
jr z, .readPointer ; read before battle text
|
||
cp $6
|
||
jr z, .readPointer ; read after battle text
|
||
cp $8
|
||
jr z, .readPointer ; read end battle text
|
||
cp $a
|
||
jr nz, .done
|
||
ld a, [hli] ; read end battle text (2) but override the result afterwards (XXX why, bug?)
|
||
ld d, [hl]
|
||
ld e, a
|
||
jr .done
|
||
.readPointer
|
||
ld a, [hli]
|
||
ld h, [hl]
|
||
ld l, a
|
||
.done
|
||
pop de
|
||
ret
|
||
|
||
TrainerFlagAction:: ; 3163 (0:3163)
|
||
predef_jump FlagActionPredef
|
||
|
||
TalkToTrainer:: ; 3168 (0:3168)
|
||
call StoreTrainerHeaderPointer
|
||
xor a
|
||
call ReadTrainerHeaderInfo ; read flag's bit
|
||
ld a, $2
|
||
call ReadTrainerHeaderInfo ; read flag's byte ptr
|
||
ld a, [wTrainerHeaderFlagBit]
|
||
ld c, a
|
||
ld b, FLAG_TEST
|
||
call TrainerFlagAction ; read trainer's flag
|
||
ld a, c
|
||
and a
|
||
jr z, .trainerNotYetFought ; test trainer's flag
|
||
ld a, $6
|
||
call ReadTrainerHeaderInfo ; print after battle text
|
||
jp PrintText
|
||
.trainerNotYetFought
|
||
ld a, $4
|
||
call ReadTrainerHeaderInfo ; print before battle text
|
||
call PrintText
|
||
ld a, $a
|
||
call ReadTrainerHeaderInfo ; (?) does nothing apparently (maybe bug in ReadTrainerHeaderInfo)
|
||
push de
|
||
ld a, $8
|
||
call ReadTrainerHeaderInfo ; read end battle text
|
||
pop de
|
||
call SaveEndBattleTextPointers
|
||
ld hl, wFlags_D733
|
||
set 4, [hl] ; activate map script index override (index is set below)
|
||
ld hl, wFlags_0xcd60
|
||
bit 0, [hl] ; test if player is already engaging the trainer (because the trainer saw the player)
|
||
ret nz
|
||
; if the player talked to the trainer of his own volition
|
||
call EngageMapTrainer
|
||
ld hl, W_CURMAPSCRIPT
|
||
inc [hl] ; increment map script index before StartTrainerBattle increments it again (next script function is usually EndTrainerBattle)
|
||
jp StartTrainerBattle
|
||
|
||
; checks if any trainers are seeing the player and wanting to fight
|
||
CheckFightingMapTrainers:: ; 31b5 (0:31b5)
|
||
call CheckForEngagingTrainers
|
||
ld a, [wSpriteIndex]
|
||
cp $ff
|
||
jr nz, .trainerEngaging
|
||
xor a
|
||
ld [wSpriteIndex], a
|
||
ld [wTrainerHeaderFlagBit], a
|
||
ret
|
||
.trainerEngaging
|
||
ld hl, wFlags_D733
|
||
set 3, [hl]
|
||
ld [wEmotionBubbleSpriteIndex], a
|
||
xor a ; EXCLAMATION_BUBBLE
|
||
ld [wWhichEmotionBubble], a
|
||
predef EmotionBubble
|
||
ld a, D_RIGHT | D_LEFT | D_UP | D_DOWN
|
||
ld [wJoyIgnore], a
|
||
xor a
|
||
ld [hJoyHeld], a
|
||
call TrainerWalkUpToPlayer_Bank0
|
||
ld hl, W_CURMAPSCRIPT
|
||
inc [hl] ; increment map script index (next script function is usually DisplayEnemyTrainerTextAndStartBattle)
|
||
ret
|
||
|
||
; display the before battle text after the enemy trainer has walked up to the player's sprite
|
||
DisplayEnemyTrainerTextAndStartBattle:: ; 31e8 (0:31e8)
|
||
ld a, [wd730]
|
||
and $1
|
||
ret nz ; return if the enemy trainer hasn't finished walking to the player's sprite
|
||
ld [wJoyIgnore], a
|
||
ld a, [wSpriteIndex]
|
||
ld [hSpriteIndexOrTextID], a
|
||
call DisplayTextID
|
||
; fall through
|
||
|
||
StartTrainerBattle:: ; 31f9 (0:31f9)
|
||
xor a
|
||
ld [wJoyIgnore], a
|
||
call InitBattleEnemyParameters
|
||
ld hl, wd72d
|
||
set 6, [hl]
|
||
set 7, [hl]
|
||
ld hl, wd72e
|
||
set 1, [hl]
|
||
ld hl, W_CURMAPSCRIPT
|
||
inc [hl] ; increment map script index (next script function is usually EndTrainerBattle)
|
||
ret
|
||
|
||
EndTrainerBattle:: ; 3211 (0:3211)
|
||
ld hl, wd126
|
||
set 5, [hl]
|
||
set 6, [hl]
|
||
ld hl, wd72d
|
||
res 7, [hl]
|
||
ld hl, wFlags_0xcd60
|
||
res 0, [hl] ; player is no longer engaged by any trainer
|
||
ld a, [wIsInBattle]
|
||
cp $ff
|
||
jp z, ResetButtonPressedAndMapScript
|
||
ld a, $2
|
||
call ReadTrainerHeaderInfo
|
||
ld a, [wTrainerHeaderFlagBit]
|
||
ld c, a
|
||
ld b, FLAG_SET
|
||
call TrainerFlagAction ; flag trainer as fought
|
||
ld a, [W_ENEMYMONORTRAINERCLASS]
|
||
cp 200
|
||
jr nc, .skipRemoveSprite ; test if trainer was fought (in that case skip removing the corresponding sprite)
|
||
ld hl, wMissableObjectList
|
||
ld de, $2
|
||
ld a, [wSpriteIndex]
|
||
call IsInArray ; search for sprite ID
|
||
inc hl
|
||
ld a, [hl]
|
||
ld [wMissableObjectIndex], a ; load corresponding missable object index and remove it
|
||
predef HideObject
|
||
.skipRemoveSprite
|
||
ld hl, wd730
|
||
bit 4, [hl]
|
||
res 4, [hl]
|
||
ret nz
|
||
|
||
ResetButtonPressedAndMapScript:: ; 325d (0:325d)
|
||
xor a
|
||
ld [wJoyIgnore], a
|
||
ld [hJoyHeld], a
|
||
ld [hJoyPressed], a
|
||
ld [hJoyReleased], a
|
||
ld [W_CURMAPSCRIPT], a ; reset battle status
|
||
ret
|
||
|
||
; calls TrainerWalkUpToPlayer
|
||
TrainerWalkUpToPlayer_Bank0:: ; 326b (0:326b)
|
||
jpba TrainerWalkUpToPlayer
|
||
|
||
; sets opponent type and mon set/lvl based on the engaging trainer data
|
||
InitBattleEnemyParameters:: ; 3273 (0:3273)
|
||
ld a, [wEngagedTrainerClass]
|
||
ld [wCurOpponent], a
|
||
ld [W_ENEMYMONORTRAINERCLASS], a
|
||
cp 200
|
||
ld a, [wEngagedTrainerSet]
|
||
jr c, .noTrainer
|
||
ld [wTrainerNo], a
|
||
ret
|
||
.noTrainer
|
||
ld [wCurEnemyLVL], a
|
||
ret
|
||
|
||
GetSpritePosition1:: ; 328b (0:328b)
|
||
ld hl, _GetSpritePosition1
|
||
jr SpritePositionBankswitch
|
||
|
||
GetSpritePosition2:: ; 3290 (0:3290)
|
||
ld hl, _GetSpritePosition2
|
||
jr SpritePositionBankswitch
|
||
|
||
SetSpritePosition1:: ; 3295 (0:3295)
|
||
ld hl, _SetSpritePosition1
|
||
jr SpritePositionBankswitch
|
||
|
||
SetSpritePosition2:: ; 329a (0:329a)
|
||
ld hl, _SetSpritePosition2
|
||
SpritePositionBankswitch:: ; 329d (0:329d)
|
||
ld b, BANK(_GetSpritePosition1) ; BANK(_GetSpritePosition2), BANK(_SetSpritePosition1), BANK(_SetSpritePosition2)
|
||
jp Bankswitch ; indirect jump to one of the four functions
|
||
|
||
CheckForEngagingTrainers:: ; 32a2 (0:32a2)
|
||
xor a
|
||
call ReadTrainerHeaderInfo ; read trainer flag's bit (unused)
|
||
ld d, h ; store trainer header address in de
|
||
ld e, l
|
||
.trainerLoop
|
||
call StoreTrainerHeaderPointer ; set trainer header pointer to current trainer
|
||
ld a, [de]
|
||
ld [wSpriteIndex], a ; store trainer flag's bit
|
||
ld [wTrainerHeaderFlagBit], a
|
||
cp $ff
|
||
ret z
|
||
ld a, $2
|
||
call ReadTrainerHeaderInfo ; read trainer flag's byte ptr
|
||
ld b, FLAG_TEST
|
||
ld a, [wTrainerHeaderFlagBit]
|
||
ld c, a
|
||
call TrainerFlagAction ; read trainer flag
|
||
ld a, c
|
||
and a ; has the trainer already been defeated?
|
||
jr nz, .continue
|
||
push hl
|
||
push de
|
||
push hl
|
||
xor a
|
||
call ReadTrainerHeaderInfo ; get trainer header pointer
|
||
inc hl
|
||
ld a, [hl] ; read trainer engage distance
|
||
pop hl
|
||
ld [wTrainerEngageDistance], a
|
||
ld a, [wSpriteIndex]
|
||
swap a
|
||
ld [wTrainerSpriteOffset], a
|
||
predef TrainerEngage
|
||
pop de
|
||
pop hl
|
||
ld a, [wTrainerSpriteOffset]
|
||
and a
|
||
ret nz ; break if the trainer is engaging
|
||
.continue
|
||
ld hl, $c
|
||
add hl, de
|
||
ld d, h
|
||
ld e, l
|
||
jr .trainerLoop
|
||
|
||
; hl = text if the player wins
|
||
; de = text if the player loses
|
||
SaveEndBattleTextPointers:: ; 32f0 (0:32f0)
|
||
ld a, [H_LOADEDROMBANK]
|
||
ld [wEndBattleTextRomBank], a
|
||
ld a, h
|
||
ld [wEndBattleWinTextPointer], a
|
||
ld a, l
|
||
ld [wEndBattleWinTextPointer + 1], a
|
||
ld a, d
|
||
ld [wEndBattleLoseTextPointer], a
|
||
ld a, e
|
||
ld [wEndBattleLoseTextPointer + 1], a
|
||
ret
|
||
|
||
; loads data of some trainer on the current map and plays pre-battle music
|
||
; [wSpriteIndex]: sprite ID of trainer who is engaged
|
||
EngageMapTrainer:: ; 3306 (0:3306)
|
||
ld hl, wMapSpriteExtraData
|
||
ld d, $0
|
||
ld a, [wSpriteIndex]
|
||
dec a
|
||
add a
|
||
ld e, a
|
||
add hl, de ; seek to engaged trainer data
|
||
ld a, [hli] ; load trainer class
|
||
ld [wEngagedTrainerClass], a
|
||
ld a, [hl] ; load trainer mon set
|
||
ld [wEnemyMonAttackMod], a
|
||
jp PlayTrainerMusic
|
||
|
||
PrintEndBattleText:: ; 331d (0:331d)
|
||
push hl
|
||
ld hl, wd72d
|
||
bit 7, [hl]
|
||
res 7, [hl]
|
||
pop hl
|
||
ret z
|
||
ld a, [H_LOADEDROMBANK]
|
||
push af
|
||
ld a, [wEndBattleTextRomBank]
|
||
ld [H_LOADEDROMBANK], a
|
||
ld [MBC1RomBank], a
|
||
push hl
|
||
callba SaveTrainerName
|
||
ld hl, TrainerEndBattleText
|
||
call PrintText
|
||
pop hl
|
||
pop af
|
||
ld [H_LOADEDROMBANK], a
|
||
ld [MBC1RomBank], a
|
||
callba FreezeEnemyTrainerSprite
|
||
jp WaitForSoundToFinish
|
||
|
||
GetSavedEndBattleTextPointer:: ; 3353 (0:3353)
|
||
ld a, [wBattleResult]
|
||
and a
|
||
; won battle
|
||
jr nz, .lostBattle
|
||
ld a, [wEndBattleWinTextPointer]
|
||
ld h, a
|
||
ld a, [wEndBattleWinTextPointer + 1]
|
||
ld l, a
|
||
ret
|
||
.lostBattle
|
||
ld a, [wEndBattleLoseTextPointer]
|
||
ld h, a
|
||
ld a, [wEndBattleLoseTextPointer + 1]
|
||
ld l, a
|
||
ret
|
||
|
||
TrainerEndBattleText:: ; 336b (0:336b)
|
||
TX_FAR _TrainerNameText
|
||
TX_ASM
|
||
call GetSavedEndBattleTextPointer
|
||
call TextCommandProcessor
|
||
jp TextScriptEnd
|
||
|
||
PlayTrainerMusic:: ; 3379 (0:3379)
|
||
ld a, [wEngagedTrainerClass]
|
||
cp OPP_SONY1
|
||
ret z
|
||
cp OPP_SONY2
|
||
ret z
|
||
cp OPP_SONY3
|
||
ret z
|
||
ld a, [wGymLeaderNo]
|
||
and a
|
||
ret nz
|
||
xor a
|
||
ld [wAudioFadeOutControl], a
|
||
call StopAllMusic ; stop music
|
||
ld a, BANK(Music_MeetEvilTrainer)
|
||
ld [wAudioROMBank], a
|
||
ld [wAudioSavedROMBank], a
|
||
ld a, [wEngagedTrainerClass]
|
||
ld b, a
|
||
ld hl, EvilTrainerList
|
||
.evilTrainerListLoop
|
||
ld a, [hli]
|
||
cp $ff
|
||
jr z, .noEvilTrainer
|
||
cp b
|
||
jr nz, .evilTrainerListLoop
|
||
ld a, MUSIC_MEET_EVIL_TRAINER
|
||
jr .PlaySound
|
||
.noEvilTrainer
|
||
ld hl, FemaleTrainerList
|
||
.femaleTrainerListLoop
|
||
ld a, [hli]
|
||
cp $ff
|
||
jr z, .maleTrainer
|
||
cp b
|
||
jr nz, .femaleTrainerListLoop
|
||
ld a, MUSIC_MEET_FEMALE_TRAINER
|
||
jr .PlaySound
|
||
.maleTrainer
|
||
ld a, MUSIC_MEET_MALE_TRAINER
|
||
.PlaySound
|
||
ld [wNewSoundID], a
|
||
jp PlaySound
|
||
|
||
INCLUDE "data/trainer_types.asm"
|
||
|
||
; checks if the player's coordinates match an arrow movement tile's coordinates
|
||
; and if so, decodes the RLE movement data
|
||
; b = player Y
|
||
; c = player X
|
||
DecodeArrowMovementRLE:: ; 3442 (0:3442)
|
||
ld a, [hli]
|
||
cp $ff
|
||
ret z ; no match in the list
|
||
cp b
|
||
jr nz, .nextArrowMovementTileEntry1
|
||
ld a, [hli]
|
||
cp c
|
||
jr nz, .nextArrowMovementTileEntry2
|
||
ld a, [hli]
|
||
ld d, [hl]
|
||
ld e, a
|
||
ld hl, wSimulatedJoypadStatesEnd
|
||
call DecodeRLEList
|
||
dec a
|
||
ld [wSimulatedJoypadStatesIndex], a
|
||
ret
|
||
.nextArrowMovementTileEntry1
|
||
inc hl
|
||
.nextArrowMovementTileEntry2
|
||
inc hl
|
||
inc hl
|
||
jr DecodeArrowMovementRLE
|
||
|
||
FuncTX_ItemStoragePC:: ; 33ef (0:33ef)
|
||
call SaveScreenTilesToBuffer2
|
||
ld b, BANK(PlayerPC)
|
||
ld hl, PlayerPC
|
||
jr bankswitchAndContinue
|
||
|
||
FuncTX_BillsPC:: ; 33f9 (0:33f9)
|
||
call SaveScreenTilesToBuffer2
|
||
ld b, BANK(BillsPC_)
|
||
ld hl, BillsPC_
|
||
jr bankswitchAndContinue
|
||
|
||
FuncTX_GameCornerPrizeMenu:: ; 3403 (0:3403)
|
||
; XXX find a better name for this function
|
||
; special_F7
|
||
ld b, BANK(CeladonPrizeMenu)
|
||
ld hl, CeladonPrizeMenu
|
||
bankswitchAndContinue:: ; 3408 (0:3408)
|
||
call Bankswitch
|
||
jp HoldTextDisplayOpen ; continue to main text-engine function
|
||
|
||
FuncTX_PokemonCenterPC:: ; 340e (0:340e)
|
||
ld b, BANK(ActivatePC)
|
||
ld hl, ActivatePC
|
||
jr bankswitchAndContinue
|
||
|
||
StartSimulatingJoypadStates:: ; 3415 (0:3415)
|
||
xor a
|
||
ld [wOverrideSimulatedJoypadStatesMask], a
|
||
ld [wSpriteStateData2 + $06], a ; player's sprite movement byte 1
|
||
ld hl, wd730
|
||
set 7, [hl]
|
||
ret
|
||
|
||
IsItemInBag:: ; 3422 (0:3422)
|
||
; given an item_id in b
|
||
; set zero flag if item isn't in player's bag
|
||
; else reset zero flag
|
||
; related to Pokémon Tower and ghosts
|
||
predef GetQuantityOfItemInBag
|
||
ld a, b
|
||
and a
|
||
ret
|
||
|
||
IsSurfingPikachuInParty:: ; 342a (0:342a)
|
||
; set bit 6 of wd472 if true
|
||
; also calls Func_3467, which is a bankswitch to IsStarterPikachuInOurParty
|
||
ld a, [wd472]
|
||
and $3f
|
||
ld [wd472], a
|
||
ld hl, wPartyMon1
|
||
ld c, PARTY_LENGTH
|
||
ld b, SURF
|
||
.loop
|
||
ld a, [hl]
|
||
cp PIKACHU
|
||
jr nz, .notPikachu
|
||
push hl
|
||
ld de, $8
|
||
add hl, de
|
||
ld a, [hli]
|
||
cp b ; does pikachu have surf as one of its moves
|
||
jr z, .hasSurf
|
||
ld a, [hli]
|
||
cp b
|
||
jr z, .hasSurf
|
||
ld a, [hli]
|
||
cp b
|
||
jr z, .hasSurf
|
||
ld a, [hli]
|
||
cp b
|
||
jr nz, .noSurf
|
||
.hasSurf
|
||
ld a, [wd472]
|
||
set 6, a
|
||
ld [wd472], a
|
||
.noSurf
|
||
pop hl
|
||
.notPikachu
|
||
ld de, wPartyMon2 - wPartyMon1
|
||
add hl, de
|
||
dec c
|
||
jr nz, .loop
|
||
call Func_3467
|
||
ret
|
||
|
||
Func_3467:: ; 3467 (0:3467)
|
||
push hl
|
||
push bc
|
||
callab IsStarterPikachuInOurParty
|
||
pop bc
|
||
pop hl
|
||
ret nc
|
||
ld a, [wd472]
|
||
set 7, a
|
||
ld [wd472], a
|
||
ret
|
||
|
||
DisplayPokedex:: ; 347d (0:347d)
|
||
ld [wd11e], a
|
||
jpba _DisplayPokedex
|
||
|
||
SetSpriteFacingDirectionAndDelay:: ; 3488 (0:3488)
|
||
call SetSpriteFacingDirection
|
||
ld c, 6
|
||
jp DelayFrames
|
||
|
||
SetSpriteFacingDirection:: ; 3490 (0:3490)
|
||
ld a, $9
|
||
ld [H_SPRITEDATAOFFSET], a
|
||
call GetPointerWithinSpriteStateData1
|
||
ld a, [hSpriteFacingDirection]
|
||
ld [hl], a
|
||
ret
|
||
|
||
SetSpriteImageIndexAfterSettingFacingDirection:: ; 349b (0:349b)
|
||
ld de, -7
|
||
add hl, de
|
||
ld [hl], a
|
||
ret
|
||
|
||
SpriteFunc_34a1:: ; 34a1 (0:34a1)
|
||
ld a, [H_SPRITEINDEX]
|
||
swap a
|
||
add $e
|
||
ld l, a
|
||
ld h, $c2
|
||
ld c, [hl]
|
||
dec c
|
||
swap c
|
||
ld a, [$ff8d]
|
||
add c
|
||
ld c, a
|
||
ld a, [$ff8c]
|
||
swap a
|
||
add $2
|
||
ld l, a
|
||
dec h
|
||
ld [hl], c
|
||
ret
|
||
|
||
; tests if the player's coordinates are in a specified array
|
||
; INPUT:
|
||
; hl = address of array
|
||
; OUTPUT:
|
||
; [wCoordIndex] = if there is match, the matching array index
|
||
; sets carry if the coordinates are in the array, clears carry if not
|
||
ArePlayerCoordsInArray:: ; 34bc (0:34bc)
|
||
ld a, [wYCoord]
|
||
ld b, a
|
||
ld a, [wXCoord]
|
||
ld c, a
|
||
; fallthrough
|
||
|
||
CheckCoords:: ; 34c4 (0:34c4)
|
||
xor a
|
||
ld [wCoordIndex], a
|
||
.loop
|
||
ld a, [hli]
|
||
cp $ff ; reached terminator?
|
||
jr z, .notInArray
|
||
push hl
|
||
ld hl, wCoordIndex
|
||
inc [hl]
|
||
pop hl
|
||
.compareYCoord
|
||
cp b
|
||
jr z, .compareXCoord
|
||
inc hl
|
||
jr .loop
|
||
.compareXCoord
|
||
ld a, [hli]
|
||
cp c
|
||
jr nz, .loop
|
||
.inArray
|
||
scf
|
||
ret
|
||
.notInArray
|
||
and a
|
||
ret
|
||
|
||
; tests if a boulder's coordinates are in a specified array
|
||
; INPUT:
|
||
; hl = address of array
|
||
; [H_SPRITEINDEX] = index of boulder sprite
|
||
; OUTPUT:
|
||
; [wCoordIndex] = if there is match, the matching array index
|
||
; sets carry if the coordinates are in the array, clears carry if not
|
||
CheckBoulderCoords:: ; 34e1 (0:34e1)
|
||
push hl
|
||
ld hl, wSpriteStateData2 + $04
|
||
ld a, [H_SPRITEINDEX]
|
||
swap a
|
||
ld d, $0
|
||
ld e, a
|
||
add hl, de
|
||
ld a, [hli]
|
||
sub $4 ; because sprite coordinates are offset by 4
|
||
ld b, a
|
||
ld a, [hl]
|
||
sub $4 ; because sprite coordinates are offset by 4
|
||
ld c, a
|
||
pop hl
|
||
jp CheckCoords
|
||
|
||
GetPointerWithinSpriteStateData1:: ; 34f9 (0:34f9)
|
||
ld h, $c1
|
||
jr _GetPointerWithinSpriteStateData
|
||
|
||
GetPointerWithinSpriteStateData2:: ; 34fd (0:34fd)
|
||
ld h, $c2
|
||
|
||
_GetPointerWithinSpriteStateData: ; 34ff (0:34ff)
|
||
ld a, [H_SPRITEDATAOFFSET]
|
||
ld b, a
|
||
ld a, [H_SPRITEINDEX]
|
||
swap a
|
||
add b
|
||
ld l, a
|
||
ret
|
||
|
||
; decodes a $ff-terminated RLEncoded list
|
||
; each entry is a pair of bytes <byte value> <repetitions>
|
||
; the final $ff will be replicated in the output list and a contains the number of bytes written
|
||
; de: input list
|
||
; hl: output list
|
||
DecodeRLEList:: ; 3509 (0:3509)
|
||
xor a
|
||
ld [wRLEByteCount], a ; count written bytes here
|
||
.listLoop
|
||
ld a, [de]
|
||
cp $ff
|
||
jr z, .endOfList
|
||
ld [hRLEByteValue], a ; store byte value to be written
|
||
inc de
|
||
ld a, [de]
|
||
ld b, $0
|
||
ld c, a ; number of bytes to be written
|
||
ld a, [wRLEByteCount]
|
||
add c
|
||
ld [wRLEByteCount], a ; update total number of written bytes
|
||
ld a, [hRLEByteValue]
|
||
call FillMemory ; write a c-times to output
|
||
inc de
|
||
jr .listLoop
|
||
.endOfList
|
||
ld a, $ff
|
||
ld [hl], a ; write final $ff
|
||
ld a, [wRLEByteCount]
|
||
inc a ; include sentinel in counting
|
||
ret
|
||
|
||
; sets movement byte 1 for sprite [H_SPRITEINDEX] to $FE and byte 2 to [hSpriteMovementByte2]
|
||
SetSpriteMovementBytesToFE:: ; 3530 (0:3530)
|
||
push hl
|
||
call GetSpriteMovementByte1Pointer
|
||
ld [hl], $fe
|
||
call GetSpriteMovementByte2Pointer
|
||
ld a, [hSpriteMovementByte2]
|
||
ld [hl], a
|
||
pop hl
|
||
ret
|
||
|
||
; sets both movement bytes for sprite [H_SPRITEINDEX] to $FF
|
||
SetSpriteMovementBytesToFF:: ; 353f (0:353f)
|
||
push hl
|
||
call GetSpriteMovementByte1Pointer
|
||
ld [hl], $FF
|
||
call GetSpriteMovementByte2Pointer
|
||
ld [hl], $FF ; prevent person from walking?
|
||
pop hl
|
||
ret
|
||
|
||
; returns the sprite movement byte 1 pointer for sprite [H_SPRITEINDEX] in hl
|
||
GetSpriteMovementByte1Pointer:: ; 354b (0:354b)
|
||
ld h, $C2
|
||
ld a, [H_SPRITEINDEX]
|
||
swap a
|
||
add 6
|
||
ld l, a
|
||
ret
|
||
|
||
; returns the sprite movement byte 2 pointer for sprite [H_SPRITEINDEX] in hl
|
||
GetSpriteMovementByte2Pointer:: ; 3555 (0:3555)
|
||
push de
|
||
ld hl, wMapSpriteData
|
||
ld a, [H_SPRITEINDEX]
|
||
dec a
|
||
add a
|
||
ld e, a
|
||
ld d, 0
|
||
add hl, de
|
||
pop de
|
||
ret
|
||
|
||
GetTrainerInformation:: ; 3563 (0:3563)
|
||
call GetTrainerName
|
||
ld a, [wLinkState]
|
||
and a
|
||
jr nz, .linkBattle
|
||
ld a, BANK(TrainerPicAndMoneyPointers)
|
||
call BankswitchHome
|
||
ld a, [wTrainerClass]
|
||
dec a
|
||
ld hl, TrainerPicAndMoneyPointers
|
||
ld bc, $5
|
||
call AddNTimes
|
||
ld de, wTrainerPicPointer
|
||
ld a, [hli]
|
||
ld [de], a
|
||
inc de
|
||
ld a, [hli]
|
||
ld [de], a
|
||
ld de, wTrainerBaseMoney
|
||
ld a, [hli]
|
||
ld [de], a
|
||
inc de
|
||
ld a, [hli]
|
||
ld [de], a
|
||
call IsFightingJessieJames
|
||
jp BankswitchBack
|
||
.linkBattle
|
||
ld hl, wTrainerPicPointer
|
||
ld de, RedPicFront
|
||
ld [hl], e
|
||
inc hl
|
||
ld [hl], d
|
||
ret
|
||
|
||
IsFightingJessieJames:: ; 359e (0:359e)
|
||
ld a, [wTrainerClass]
|
||
cp ROCKET
|
||
ret nz
|
||
ld a, [wTrainerNo]
|
||
cp $2a
|
||
ret c
|
||
ld de, JessieJamesPic
|
||
cp $2e
|
||
jr c, .dummy
|
||
ld de, JessieJamesPic ; possibly meant to add another pic
|
||
.dummy
|
||
ld hl, wTrainerPicPointer
|
||
ld a, e
|
||
ld [hli], a
|
||
ld [hl], d
|
||
ret
|
||
|
||
GetTrainerName:: ; 35bb (0:35bb)
|
||
jpba GetTrainerName_
|
||
|
||
HasEnoughMoney:: ; 35c3 (0:35c3)
|
||
; Check if the player has at least as much
|
||
; money as the 3-byte BCD value at hMoney.
|
||
ld de, wPlayerMoney
|
||
ld hl, hMoney
|
||
ld c, 3
|
||
jp StringCmp
|
||
|
||
HasEnoughCoins:: ; 35ce (0:35ce)
|
||
; Check if the player has at least as many
|
||
; coins as the 2-byte BCD value at hCoins.
|
||
ld de, wPlayerCoins
|
||
ld hl, hCoins
|
||
ld c, 2
|
||
jp StringCmp
|
||
|
||
|
||
BankswitchHome:: ; 35d9 (0:35d9)
|
||
; switches to bank # in a
|
||
; Only use this when in the home bank!
|
||
ld [wBankswitchHomeTemp], a
|
||
ld a, [H_LOADEDROMBANK]
|
||
ld [wBankswitchHomeSavedROMBank], a
|
||
ld a, [wBankswitchHomeTemp]
|
||
call BankswitchCommon
|
||
ret
|
||
|
||
BankswitchBack:: ; 35e8 (0:35e8)
|
||
; returns from BankswitchHome
|
||
ld a, [wBankswitchHomeSavedROMBank]
|
||
call BankswitchCommon
|
||
ret
|
||
|
||
; displays yes/no choice
|
||
; yes -> set carry
|
||
YesNoChoice:: ; 35ef (0:35ef)
|
||
call SaveScreenTilesToBuffer1
|
||
call InitYesNoTextBoxParameters
|
||
jr DisplayYesNoChoice
|
||
|
||
Func_35f7:: ; 35f7 (0:35f7)
|
||
ld a, TWO_OPTION_MENU
|
||
ld [wTextBoxID], a
|
||
call InitYesNoTextBoxParameters
|
||
jp DisplayTextBoxID
|
||
|
||
InitYesNoTextBoxParameters:: ; 3602 (0:3602)
|
||
xor a ; YES_NO_MENU
|
||
ld [wTwoOptionMenuID], a
|
||
coord hl, 14, 7
|
||
ld bc, $80f
|
||
ret
|
||
|
||
YesNoChoicePokeCenter:: ; 360d (0:360d)
|
||
call SaveScreenTilesToBuffer1
|
||
ld a, HEAL_CANCEL_MENU
|
||
ld [wTwoOptionMenuID], a
|
||
coord hl, 11, 6
|
||
lb bc, 8, 12
|
||
jr DisplayYesNoChoice
|
||
|
||
Func_361d:: ; 361d (0:361d)
|
||
call SaveScreenTilesToBuffer1
|
||
ld a, WIDE_YES_NO_MENU
|
||
ld [wTwoOptionMenuID], a
|
||
coord hl, 12, 7
|
||
lb bc, 8, 13
|
||
DisplayYesNoChoice:: ; 362b (0:362b)
|
||
ld a, TWO_OPTION_MENU
|
||
ld [wTextBoxID], a
|
||
call DisplayTextBoxID
|
||
jp LoadScreenTilesFromBuffer1
|
||
|
||
; calculates the difference |a-b|, setting carry flag if a<b
|
||
CalcDifference:: ; 3636 (0:3636)
|
||
sub b
|
||
ret nc
|
||
cpl
|
||
add $1
|
||
scf
|
||
ret
|
||
|
||
MoveSprite:: ; 363d (0:363d)
|
||
; move the sprite [H_SPRITEINDEX] with the movement pointed to by de
|
||
; actually only copies the movement data to wNPCMovementDirections for later
|
||
call SetSpriteMovementBytesToFF
|
||
MoveSprite_:: ; 3640 (0:3640)
|
||
push hl
|
||
push bc
|
||
call GetSpriteMovementByte1Pointer
|
||
xor a
|
||
ld [hl], a
|
||
ld hl, wNPCMovementDirections
|
||
ld c, 0
|
||
|
||
.loop
|
||
ld a, [de]
|
||
ld [hli], a
|
||
inc de
|
||
inc c
|
||
cp $FF ; have we reached the end of the movement data?
|
||
jr nz, .loop
|
||
|
||
ld a, c
|
||
ld [wNPCNumScriptedSteps], a ; number of steps taken
|
||
|
||
pop bc
|
||
ld hl, wd730
|
||
set 0, [hl]
|
||
pop hl
|
||
xor a
|
||
ld [wOverrideSimulatedJoypadStatesMask], a
|
||
ld [wSimulatedJoypadStatesEnd], a
|
||
dec a
|
||
ld [wJoyIgnore], a
|
||
ld [wWastedByteCD3A], a
|
||
ret
|
||
|
||
; divides [hDividend2] by [hDivisor2] and stores the quotient in [hQuotient2]
|
||
DivideBytes:: ; 366e (0:366e)
|
||
push hl
|
||
ld hl, hQuotient2
|
||
xor a
|
||
ld [hld], a
|
||
ld a, [hld]
|
||
and a
|
||
jr z, .done
|
||
ld a, [hli]
|
||
.loop
|
||
sub [hl]
|
||
jr c, .done
|
||
inc hl
|
||
inc [hl]
|
||
dec hl
|
||
jr .loop
|
||
.done
|
||
pop hl
|
||
ret
|
||
|
||
|
||
LoadFontTilePatterns:: ; 3683 (0:3683)
|
||
ld a, [rLCDC]
|
||
bit 7, a ; is the LCD enabled?
|
||
jr nz, .on
|
||
.off
|
||
ld hl, FontGraphics
|
||
ld de, vFont
|
||
ld bc, FontGraphicsEnd - FontGraphics
|
||
ld a, BANK(FontGraphics)
|
||
jp FarCopyDataDouble ; if LCD is off, transfer all at once
|
||
.on
|
||
ld de, FontGraphics
|
||
ld hl, vFont
|
||
lb bc, BANK(FontGraphics), (FontGraphicsEnd - FontGraphics) / $8
|
||
jp CopyVideoDataDouble ; if LCD is on, transfer during V-blank
|
||
|
||
LoadTextBoxTilePatterns:: ; 36a3 (0:36a3)
|
||
ld a, [rLCDC]
|
||
bit 7, a ; is the LCD enabled?
|
||
jr nz, .on
|
||
.off
|
||
ld hl, TextBoxGraphics
|
||
ld de, vChars2 + $600
|
||
ld bc, TextBoxGraphicsEnd - TextBoxGraphics
|
||
ld a, BANK(TextBoxGraphics)
|
||
jp FarCopyData ; if LCD is off, transfer all at once
|
||
.on
|
||
ld de, TextBoxGraphics
|
||
ld hl, vChars2 + $600
|
||
lb bc, BANK(TextBoxGraphics), (TextBoxGraphicsEnd - TextBoxGraphics) / $10
|
||
jp CopyVideoData ; if LCD is on, transfer during V-blank
|
||
|
||
LoadHpBarAndStatusTilePatterns:: ; 36c3 (0:36c3)
|
||
ld a, [rLCDC]
|
||
bit 7, a ; is the LCD enabled?
|
||
jr nz, .on
|
||
.off
|
||
ld hl, HpBarAndStatusGraphics
|
||
ld de, vChars2 + $620
|
||
ld bc, HpBarAndStatusGraphicsEnd - HpBarAndStatusGraphics
|
||
ld a, BANK(HpBarAndStatusGraphics)
|
||
jp FarCopyData ; if LCD is off, transfer all at once
|
||
.on
|
||
ld de, HpBarAndStatusGraphics
|
||
ld hl, vChars2 + $620
|
||
lb bc, BANK(HpBarAndStatusGraphics), (HpBarAndStatusGraphicsEnd - HpBarAndStatusGraphics) / $10
|
||
jp CopyVideoData ; if LCD is on, transfer during V-blank
|
||
|
||
UncompressSpriteFromDE:: ; 36e3 (0:36e3)
|
||
; Decompress pic at a:de.
|
||
ld hl, W_SPRITEINPUTPTR
|
||
ld [hl], e
|
||
inc hl
|
||
ld [hl], d
|
||
jp UncompressSpriteData
|
||
|
||
SaveScreenTilesToBuffer2:: ; 36ec (0:36ec)
|
||
coord hl, 0, 0
|
||
ld de, wTileMapBackup2
|
||
ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
|
||
jp CopyData
|
||
|
||
LoadScreenTilesFromBuffer2:: ; 36f8 (0:36f8)
|
||
call LoadScreenTilesFromBuffer2DisableBGTransfer
|
||
ld a, $1
|
||
ld [H_AUTOBGTRANSFERENABLED], a
|
||
ret
|
||
|
||
; loads screen tiles stored in wTileMapBackup2 but leaves H_AUTOBGTRANSFERENABLED disabled
|
||
LoadScreenTilesFromBuffer2DisableBGTransfer:: ; 3700 (0:3700)
|
||
xor a
|
||
ld [H_AUTOBGTRANSFERENABLED], a
|
||
ld hl, wTileMapBackup2
|
||
coord de, 0, 0
|
||
ld bc, $168
|
||
jp CopyData
|
||
|
||
SaveScreenTilesToBuffer1:: ; 370f (0:370f)
|
||
coord hl, 0, 0
|
||
ld de, wTileMapBackup
|
||
ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
|
||
jp CopyData
|
||
|
||
LoadScreenTilesFromBuffer1:: ; 371b (0:371b)
|
||
xor a
|
||
ld [H_AUTOBGTRANSFERENABLED], a
|
||
ld hl, wTileMapBackup
|
||
coord de, 0, 0
|
||
ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
|
||
call CopyData
|
||
ld a, $1
|
||
ld [H_AUTOBGTRANSFERENABLED], a
|
||
ret
|
||
|
||
DelayFrames:: ; 372f (0:372f)
|
||
; wait c frames
|
||
call DelayFrame
|
||
dec c
|
||
jr nz, DelayFrames
|
||
ret
|
||
|
||
PlaySoundWaitForCurrent:: ; 3736 (0:3736)
|
||
push af
|
||
call WaitForSoundToFinish
|
||
pop af
|
||
jp PlaySound
|
||
|
||
; Wait for sound to finish playing
|
||
WaitForSoundToFinish:: ; 373e (0:373e)
|
||
ld a, [wLowHealthAlarm]
|
||
and $80
|
||
ret nz
|
||
push hl
|
||
.waitLoop
|
||
ld hl, wChannelSoundIDs + CH4
|
||
xor a
|
||
or [hl]
|
||
inc hl
|
||
or [hl]
|
||
inc hl
|
||
inc hl
|
||
or [hl]
|
||
and a
|
||
jr nz, .waitLoop
|
||
pop hl
|
||
ret
|
||
|
||
NamePointers:: ; 3754 (0:3754)
|
||
dw MonsterNames
|
||
dw MoveNames
|
||
dw UnusedNames
|
||
dw ItemNames
|
||
dw wPartyMonOT ; player's OT names list
|
||
dw wEnemyMonOT ; enemy's OT names list
|
||
dw TrainerNames
|
||
|
||
GetName:: ; 3762 (0:3762)
|
||
; arguments:
|
||
; [wd0b5] = which name
|
||
; [wNameListType] = which list
|
||
; [wPredefBank] = bank of list
|
||
;
|
||
; returns pointer to name in de
|
||
ld a, [wd0b5]
|
||
ld [wd11e], a
|
||
|
||
; TM names are separate from item names.
|
||
; BUG: This applies to all names instead of just items.
|
||
cp HM_01
|
||
jp nc, GetMachineName
|
||
|
||
ld a, [H_LOADEDROMBANK]
|
||
push af
|
||
push hl
|
||
push bc
|
||
push de
|
||
ld a, [wNameListType] ;List3759_entrySelector
|
||
dec a
|
||
jr nz, .otherEntries
|
||
;1 = MON_NAMES
|
||
call GetMonName
|
||
ld hl, NAME_LENGTH
|
||
add hl, de
|
||
ld e, l
|
||
ld d, h
|
||
jr .gotPtr
|
||
.otherEntries
|
||
;2-7 = OTHER ENTRIES
|
||
ld a, [wPredefBank]
|
||
call BankswitchCommon
|
||
ld a, [wNameListType] ;VariousNames' entryID
|
||
dec a
|
||
add a
|
||
ld d, 0
|
||
ld e, a
|
||
jr nc, .skip
|
||
inc d
|
||
.skip
|
||
ld hl, NamePointers
|
||
add hl, de
|
||
ld a, [hli]
|
||
ld [$ff96], a
|
||
ld a, [hl]
|
||
ld [$ff95], a
|
||
ld a, [$ff95]
|
||
ld h, a
|
||
ld a, [$ff96]
|
||
ld l, a
|
||
ld a, [wd0b5]
|
||
ld b, a
|
||
ld c, 0
|
||
.nextName
|
||
ld d, h
|
||
ld e, l
|
||
.nextChar
|
||
ld a, [hli]
|
||
cp "@"
|
||
jr nz, .nextChar
|
||
inc c ;entry counter
|
||
ld a, b ;wanted entry
|
||
cp c
|
||
jr nz, .nextName
|
||
ld h, d
|
||
ld l, e
|
||
ld de, wcd6d
|
||
ld bc, $0014
|
||
call CopyData
|
||
.gotPtr
|
||
ld a, e
|
||
ld [wUnusedCF8D], a
|
||
ld a, d
|
||
ld [wUnusedCF8D + 1], a
|
||
pop de
|
||
pop bc
|
||
pop hl
|
||
pop af
|
||
call BankswitchCommon
|
||
ret
|
||
|
||
GetItemPrice:: ; 37d2 (0:37d2)
|
||
; Stores item's price as BCD at hItemPrice (3 bytes)
|
||
; Input: [wcf91] = item id
|
||
ld a, [H_LOADEDROMBANK]
|
||
push af
|
||
ld a, [wListMenuID]
|
||
cp MOVESLISTMENU
|
||
ld a, BANK(ItemPrices)
|
||
jr nz, .asm_37e0
|
||
ld a, $f ; hardcoded Bank
|
||
.asm_37e0
|
||
call BankswitchCommon
|
||
ld hl, wItemPrices
|
||
ld a, [hli]
|
||
ld h, [hl]
|
||
ld l, a
|
||
ld a, [wcf91] ; a contains item id
|
||
cp HM_01
|
||
jr nc, .getTMPrice
|
||
ld bc, $3
|
||
.asm_37f3
|
||
add hl, bc
|
||
dec a
|
||
jr nz, .asm_37f3
|
||
dec hl
|
||
ld a, [hld]
|
||
ld [hItemPrice + 2], a
|
||
ld a, [hld]
|
||
ld [hItemPrice + 1], a
|
||
ld a, [hl]
|
||
ld [hItemPrice], a
|
||
jr .asm_380b
|
||
.getTMPrice
|
||
callbs GetMachinePrice
|
||
.asm_380b
|
||
ld de, hItemPrice
|
||
pop af
|
||
call BankswitchCommon
|
||
ret
|
||
|
||
; copies a string from [de] to [wcf4b]
|
||
CopyStringToCF4B:: ; 3813 (0:3813)
|
||
ld hl, wcf4b
|
||
; fall through
|
||
|
||
; copies a string from [de] to [hl]
|
||
CopyString:: ; 3816 (0:3816)
|
||
ld a, [de]
|
||
inc de
|
||
ld [hli], a
|
||
cp "@"
|
||
jr nz, CopyString
|
||
ret
|
||
|
||
; this function is used when lower button sensitivity is wanted (e.g. menus)
|
||
; OUTPUT: [hJoy5] = pressed buttons in usual format
|
||
; there are two flags that control its functionality, [hJoy6] and [hJoy7]
|
||
; there are esentially three modes of operation
|
||
; 1. Get newly pressed buttons only
|
||
; ([hJoy7] == 0, [hJoy6] == any)
|
||
; Just copies [hJoyPressed] to [hJoy5].
|
||
; 2. Get currently pressed buttons at low sample rate with delay
|
||
; ([hJoy7] == 1, [hJoy6] != 0)
|
||
; If the user holds down buttons for more than half a second,
|
||
; report buttons as being pressed up to 12 times per second thereafter.
|
||
; If the user holds down buttons for less than half a second,
|
||
; report only one button press.
|
||
; 3. Same as 2, but report no buttons as pressed if A or B is held down.
|
||
; ([hJoy7] == 1, [hJoy6] == 0)
|
||
JoypadLowSensitivity:: ; 381e (0:381e)
|
||
call Joypad
|
||
ld a, [hJoy7] ; flag
|
||
and a ; get all currently pressed buttons or only newly pressed buttons?
|
||
ld a, [hJoyPressed] ; newly pressed buttons
|
||
jr z, .storeButtonState
|
||
ld a, [hJoyHeld] ; all currently pressed buttons
|
||
.storeButtonState
|
||
ld [hJoy5], a
|
||
ld a, [hJoyPressed] ; newly pressed buttons
|
||
and a ; have any buttons been newly pressed since last check?
|
||
jr z, .noNewlyPressedButtons
|
||
.newlyPressedButtons
|
||
ld a, 30 ; half a second delay
|
||
ld [H_FRAMECOUNTER], a
|
||
ret
|
||
.noNewlyPressedButtons
|
||
ld a, [H_FRAMECOUNTER]
|
||
and a ; is the delay over?
|
||
jr z, .delayOver
|
||
.delayNotOver
|
||
xor a
|
||
ld [hJoy5], a ; report no buttons as pressed
|
||
ret
|
||
.delayOver
|
||
; if [hJoy6] = 0 and A or B is pressed, report no buttons as pressed
|
||
ld a, [hJoyHeld]
|
||
and A_BUTTON | B_BUTTON
|
||
jr z, .setShortDelay
|
||
ld a, [hJoy6] ; flag
|
||
and a
|
||
jr nz, .setShortDelay
|
||
xor a
|
||
ld [hJoy5], a
|
||
.setShortDelay
|
||
ld a, 5 ; 1/12 of a second delay
|
||
ld [H_FRAMECOUNTER], a
|
||
ret
|
||
|
||
WaitForTextScrollButtonPress:: ; 3852 (0:3852)
|
||
ld a, [H_DOWNARROWBLINKCNT1]
|
||
push af
|
||
ld a, [H_DOWNARROWBLINKCNT2]
|
||
push af
|
||
xor a
|
||
ld [H_DOWNARROWBLINKCNT1], a
|
||
ld a, $6
|
||
ld [H_DOWNARROWBLINKCNT2], a
|
||
.loop
|
||
push hl
|
||
ld a, [wTownMapSpriteBlinkingEnabled]
|
||
and a
|
||
jr z, .skipAnimation
|
||
push de
|
||
push bc
|
||
callab TownMapSpriteBlinkingAnimation ; 1c:5753
|
||
pop bc
|
||
pop de
|
||
.skipAnimation
|
||
coord hl, 18, 16
|
||
call HandleDownArrowBlinkTiming
|
||
pop hl
|
||
call JoypadLowSensitivity
|
||
predef CableClub_Run
|
||
ld a, [hJoy5]
|
||
and A_BUTTON | B_BUTTON
|
||
jr z, .loop
|
||
pop af
|
||
ld [H_DOWNARROWBLINKCNT2], a
|
||
pop af
|
||
ld [H_DOWNARROWBLINKCNT1], a
|
||
ret
|
||
|
||
; (unless in link battle) waits for A or B being pressed and outputs the scrolling sound effect
|
||
ManualTextScroll:: ; 388e (0:388e)
|
||
ld a, [wLinkState]
|
||
cp LINK_STATE_BATTLING
|
||
jr z, .inLinkBattle
|
||
call WaitForTextScrollButtonPress
|
||
call WaitForSoundToFinish
|
||
ld a, $90 ; SFX_PRESS_AB
|
||
jp PlaySound
|
||
.inLinkBattle
|
||
ld c, 65
|
||
jp DelayFrames
|
||
|
||
; function to do multiplication
|
||
; all values are big endian
|
||
; INPUT
|
||
; FF96-FF98 = multiplicand
|
||
; FF99 = multiplier
|
||
; OUTPUT
|
||
; FF95-FF98 = product
|
||
Multiply:: ; 38a5 (0:38a5)
|
||
push hl
|
||
push bc
|
||
callab _Multiply ; 3d:660e
|
||
pop bc
|
||
pop hl
|
||
ret
|
||
|
||
; function to do division
|
||
; all values are big endian
|
||
; INPUT
|
||
; FF95-FF98 = dividend
|
||
; FF99 = divisor
|
||
; b = number of bytes in the dividend (starting from FF95)
|
||
; OUTPUT
|
||
; FF95-FF98 = quotient
|
||
; FF99 = remainder
|
||
Divide:: ; 38b2 (0:38b2)
|
||
push hl
|
||
push de
|
||
push bc
|
||
homecall _Divide
|
||
pop bc
|
||
pop de
|
||
pop hl
|
||
ret
|
||
|
||
; This function is used to wait a short period after printing a letter to the
|
||
; screen unless the player presses the A/B button or the delay is turned off
|
||
; through the [wd730] or [wLetterPrintingDelayFlags] flags.
|
||
PrintLetterDelay:: ; 38c8 (0:38c8)
|
||
ld a, [wd730]
|
||
bit 6, a
|
||
ret nz
|
||
ld a, [wLetterPrintingDelayFlags]
|
||
bit 1, a
|
||
ret z
|
||
push hl
|
||
push de
|
||
push bc
|
||
ld a, [wLetterPrintingDelayFlags]
|
||
bit 0, a
|
||
jr z, .waitOneFrame
|
||
ld a, [wOptions]
|
||
and $f
|
||
ld [H_FRAMECOUNTER], a
|
||
jr .checkButtons
|
||
.waitOneFrame
|
||
ld a, 1
|
||
ld [H_FRAMECOUNTER], a
|
||
.checkButtons
|
||
call Joypad
|
||
ld a, [hJoyHeld]
|
||
.checkAButton
|
||
bit 0, a ; is the A button pressed?
|
||
jr z, .checkBButton
|
||
jr .endWait
|
||
.checkBButton
|
||
bit 1, a ; is the B button pressed?
|
||
jr z, .buttonsNotPressed
|
||
.endWait
|
||
call DelayFrame
|
||
jr .done
|
||
.buttonsNotPressed ; if neither A nor B is pressed
|
||
ld a, [H_FRAMECOUNTER]
|
||
and a
|
||
jr nz, .checkButtons
|
||
.done
|
||
pop bc
|
||
pop de
|
||
pop hl
|
||
ret
|
||
|
||
; Copies [hl, bc) to [de, bc - hl).
|
||
; In other words, the source data is from hl up to but not including bc,
|
||
; and the destination is de.
|
||
CopyDataUntil:: ; 3908 (0:3908)
|
||
ld a, [hli]
|
||
ld [de], a
|
||
inc de
|
||
ld a, h
|
||
cp b
|
||
jr nz, CopyDataUntil
|
||
ld a, l
|
||
cp c
|
||
jr nz, CopyDataUntil
|
||
ret
|
||
|
||
; Function to remove a pokemon from the party or the current box.
|
||
; wWhichPokemon determines the pokemon.
|
||
; [wRemoveMonFromBox] == 0 specifies the party.
|
||
; [wRemoveMonFromBox] != 0 specifies the current box.
|
||
RemovePokemon:: ; 3914 (0:3914)
|
||
jpab _RemovePokemon
|
||
|
||
AddPartyMon:: ; 391c (0:391c)
|
||
push hl
|
||
push de
|
||
push bc
|
||
callba _AddPartyMon
|
||
pop bc
|
||
pop de
|
||
pop hl
|
||
ret
|
||
|
||
; calculates all 5 stats of current mon and writes them to [de]
|
||
CalcStats:: ; 392b (0:392b)
|
||
ld c, $0
|
||
.statsLoop
|
||
inc c
|
||
call CalcStat
|
||
ld a, [H_MULTIPLICAND+1]
|
||
ld [de], a
|
||
inc de
|
||
ld a, [H_MULTIPLICAND+2]
|
||
ld [de], a
|
||
inc de
|
||
ld a, c
|
||
cp NUM_STATS
|
||
jr nz, .statsLoop
|
||
ret
|
||
|
||
; calculates stat c of current mon
|
||
; c: stat to calc (HP=1, Atk=2, Def=3, Spd=4, Spc=5)
|
||
; b: consider stat exp?
|
||
; hl: base ptr to stat exp values ([hl + 2*c - 1] and [hl + 2*c])
|
||
CalcStat:: ; 393f (0:393f)
|
||
push hl
|
||
push de
|
||
push bc
|
||
ld a, b
|
||
ld d, a
|
||
push hl
|
||
ld hl, wMonHeader
|
||
ld b, $0
|
||
add hl, bc
|
||
ld a, [hl] ; read base value of stat
|
||
ld e, a
|
||
pop hl
|
||
push hl
|
||
sla c
|
||
ld a, d
|
||
and a
|
||
jr z, .statExpDone ; consider stat exp?
|
||
add hl, bc ; skip to corresponding stat exp value
|
||
.statExpLoop ; calculates ceil(Sqrt(stat exp)) in b
|
||
xor a
|
||
ld [H_MULTIPLICAND], a
|
||
ld [H_MULTIPLICAND+1], a
|
||
inc b ; increment current stat exp bonus
|
||
ld a, b
|
||
cp $ff
|
||
jr z, .statExpDone
|
||
ld [H_MULTIPLICAND+2], a
|
||
ld [H_MULTIPLIER], a
|
||
call Multiply
|
||
ld a, [hld]
|
||
ld d, a
|
||
ld a, [$ff98]
|
||
sub d
|
||
ld a, [hli]
|
||
ld d, a
|
||
ld a, [$ff97]
|
||
sbc d ; test if (current stat exp bonus)^2 < stat exp
|
||
jr c, .statExpLoop
|
||
.statExpDone
|
||
srl c
|
||
pop hl
|
||
push bc
|
||
ld bc, wPartyMon1DVs - (wPartyMon1HPExp - 1) ; also wEnemyMonDVs - wEnemyMonHP
|
||
add hl, bc
|
||
pop bc
|
||
ld a, c
|
||
cp $2
|
||
jr z, .getAttackIV
|
||
cp $3
|
||
jr z, .getDefenseIV
|
||
cp $4
|
||
jr z, .getSpeedIV
|
||
cp $5
|
||
jr z, .getSpecialIV
|
||
.getHpIV
|
||
push bc
|
||
ld a, [hl] ; Atk IV
|
||
swap a
|
||
and $1
|
||
sla a
|
||
sla a
|
||
sla a
|
||
ld b, a
|
||
ld a, [hli] ; Def IV
|
||
and $1
|
||
sla a
|
||
sla a
|
||
add b
|
||
ld b, a
|
||
ld a, [hl] ; Spd IV
|
||
swap a
|
||
and $1
|
||
sla a
|
||
add b
|
||
ld b, a
|
||
ld a, [hl] ; Spc IV
|
||
and $1
|
||
add b ; HP IV: LSB of the other 4 IVs
|
||
pop bc
|
||
jr .calcStatFromIV
|
||
.getAttackIV
|
||
ld a, [hl]
|
||
swap a
|
||
and $f
|
||
jr .calcStatFromIV
|
||
.getDefenseIV
|
||
ld a, [hl]
|
||
and $f
|
||
jr .calcStatFromIV
|
||
.getSpeedIV
|
||
inc hl
|
||
ld a, [hl]
|
||
swap a
|
||
and $f
|
||
jr .calcStatFromIV
|
||
.getSpecialIV
|
||
inc hl
|
||
ld a, [hl]
|
||
and $f
|
||
.calcStatFromIV
|
||
ld d, $0
|
||
add e
|
||
ld e, a
|
||
jr nc, .noCarry
|
||
inc d ; de = Base + IV
|
||
.noCarry
|
||
sla e
|
||
rl d ; de = (Base + IV) * 2
|
||
srl b
|
||
srl b ; b = ceil(Sqrt(stat exp)) / 4
|
||
ld a, b
|
||
add e
|
||
jr nc, .noCarry2
|
||
inc d ; da = (Base + IV) * 2 + ceil(Sqrt(stat exp)) / 4
|
||
.noCarry2
|
||
ld [H_MULTIPLICAND+2], a
|
||
ld a, d
|
||
ld [H_MULTIPLICAND+1], a
|
||
xor a
|
||
ld [H_MULTIPLICAND], a
|
||
ld a, [wCurEnemyLVL]
|
||
ld [H_MULTIPLIER], a
|
||
call Multiply ; ((Base + IV) * 2 + ceil(Sqrt(stat exp)) / 4) * Level
|
||
ld a, [H_MULTIPLICAND]
|
||
ld [H_DIVIDEND], a
|
||
ld a, [H_MULTIPLICAND+1]
|
||
ld [H_DIVIDEND+1], a
|
||
ld a, [H_MULTIPLICAND+2]
|
||
ld [H_DIVIDEND+2], a
|
||
ld a, $64
|
||
ld [H_DIVISOR], a
|
||
ld a, $3
|
||
ld b, a
|
||
call Divide ; (((Base + IV) * 2 + ceil(Sqrt(stat exp)) / 4) * Level) / 100
|
||
ld a, c
|
||
cp $1
|
||
ld a, 5 ; + 5 for non-HP stat
|
||
jr nz, .notHPStat
|
||
ld a, [wCurEnemyLVL]
|
||
ld b, a
|
||
ld a, [H_MULTIPLICAND+2]
|
||
add b
|
||
ld [H_MULTIPLICAND+2], a
|
||
jr nc, .noCarry3
|
||
ld a, [H_MULTIPLICAND+1]
|
||
inc a
|
||
ld [H_MULTIPLICAND+1], a ; HP: (((Base + IV) * 2 + ceil(Sqrt(stat exp)) / 4) * Level) / 100 + Level
|
||
.noCarry3
|
||
ld a, 10 ; +10 for HP stat
|
||
.notHPStat
|
||
ld b, a
|
||
ld a, [H_MULTIPLICAND+2]
|
||
add b
|
||
ld [H_MULTIPLICAND+2], a
|
||
jr nc, .noCarry4
|
||
ld a, [H_MULTIPLICAND+1]
|
||
inc a ; non-HP: (((Base + IV) * 2 + ceil(Sqrt(stat exp)) / 4) * Level) / 100 + 5
|
||
ld [H_MULTIPLICAND+1], a ; HP: (((Base + IV) * 2 + ceil(Sqrt(stat exp)) / 4) * Level) / 100 + Level + 10
|
||
.noCarry4
|
||
ld a, [H_MULTIPLICAND+1] ; check for overflow (>999)
|
||
cp 999 / $100 + 1
|
||
jr nc, .overflow
|
||
cp 999 / $100
|
||
jr c, .noOverflow
|
||
ld a, [H_MULTIPLICAND+2]
|
||
cp 999 % $100 + 1
|
||
jr c, .noOverflow
|
||
.overflow
|
||
ld a, 999 / $100 ; overflow: cap at 999
|
||
ld [H_MULTIPLICAND+1], a
|
||
ld a, 999 % $100
|
||
ld [H_MULTIPLICAND+2], a
|
||
.noOverflow
|
||
pop bc
|
||
pop de
|
||
pop hl
|
||
ret
|
||
|
||
AddEnemyMonToPlayerParty:: ; 3a48 (0:3a48)
|
||
homecall_sf _AddEnemyMonToPlayerParty
|
||
ret
|
||
|
||
MoveMon:: ; 3a59 (0:3a59)
|
||
homecall_sf _MoveMon
|
||
ret
|
||
|
||
; skips a text entries, each of size NAME_LENGTH (like trainer name, OT name, rival name, ...)
|
||
; hl: base pointer, will be incremented by NAME_LENGTH * a
|
||
SkipFixedLengthTextEntries:: ; 3a6a (0:3a6a)
|
||
and a
|
||
ret z
|
||
ld bc, NAME_LENGTH
|
||
.skipLoop
|
||
add hl, bc
|
||
dec a
|
||
jr nz, .skipLoop
|
||
ret
|
||
|
||
AddNTimes:: ; 3a74 (0:3a74)
|
||
; add bc to hl a times
|
||
and a
|
||
ret z
|
||
.loop
|
||
add hl, bc
|
||
dec a
|
||
jr nz, .loop
|
||
ret
|
||
|
||
; Compare strings, c bytes in length, at de and hl.
|
||
; Often used to compare big endian numbers in battle calculations.
|
||
StringCmp:: ; 3a7b (0:3a7b)
|
||
ld a, [de]
|
||
cp [hl]
|
||
ret nz
|
||
inc de
|
||
inc hl
|
||
dec c
|
||
jr nz, StringCmp
|
||
ret
|
||
|
||
; INPUT:
|
||
; a = oam block index (each block is 4 oam entries)
|
||
; b = Y coordinate of upper left corner of sprite
|
||
; c = X coordinate of upper left corner of sprite
|
||
; de = base address of 4 tile number and attribute pairs
|
||
WriteOAMBlock:: ; 3a84 (0:3a84)
|
||
ld h, wOAMBuffer / $100
|
||
swap a ; multiply by 16
|
||
ld l, a
|
||
call .writeOneEntry ; upper left
|
||
push bc
|
||
ld a, 8
|
||
add c
|
||
ld c, a
|
||
call .writeOneEntry ; upper right
|
||
pop bc
|
||
ld a, 8
|
||
add b
|
||
ld b, a
|
||
call .writeOneEntry ; lower left
|
||
ld a, 8
|
||
add c
|
||
ld c, a
|
||
; lower right
|
||
.writeOneEntry ; 3aa0 (0:3aa0)
|
||
ld [hl], b ; Y coordinate
|
||
inc hl
|
||
ld [hl], c ; X coordinate
|
||
inc hl
|
||
ld a, [de] ; tile number
|
||
inc de
|
||
ld [hli], a
|
||
ld a, [de] ; attribute
|
||
inc de
|
||
ld [hli], a
|
||
ret
|
||
|
||
HandleMenuInput:: ; 3aab (0:3aab)
|
||
xor a
|
||
ld [wPartyMenuAnimMonEnabled], a
|
||
|
||
HandleMenuInputPokemonSelection:: ; 3aaf (0:3aaf)
|
||
ld a, [H_DOWNARROWBLINKCNT1]
|
||
push af
|
||
ld a, [H_DOWNARROWBLINKCNT2]
|
||
push af ; save existing values on stack
|
||
xor a
|
||
ld [H_DOWNARROWBLINKCNT1], a ; blinking down arrow timing value 1
|
||
ld a, 6
|
||
ld [H_DOWNARROWBLINKCNT2], a ; blinking down arrow timing value 2
|
||
.loop1
|
||
xor a
|
||
ld [wAnimCounter], a ; counter for pokemon shaking animation
|
||
call PlaceMenuCursor
|
||
call Delay3
|
||
.loop2
|
||
push hl
|
||
ld a, [wPartyMenuAnimMonEnabled]
|
||
and a ; is it a pokemon selection menu?
|
||
jr z, .getJoypadState
|
||
callba AnimatePartyMon ; shake mini sprite of selected pokemon (1c:578c)
|
||
.getJoypadState
|
||
pop hl
|
||
call JoypadLowSensitivity
|
||
ld a, [hJoy5]
|
||
and a ; was a key pressed?
|
||
jr nz, .keyPressed
|
||
push hl
|
||
coord hl, 18, 11 ; coordinates of blinking down arrow in some menus
|
||
call HandleDownArrowBlinkTiming ; blink down arrow (if any)
|
||
pop hl
|
||
ld a, [wMenuJoypadPollCount]
|
||
dec a
|
||
jr z, .giveUpWaiting
|
||
jr .loop2
|
||
.giveUpWaiting
|
||
; if a key wasn't pressed within the specified number of checks
|
||
pop af
|
||
ld [H_DOWNARROWBLINKCNT2], a
|
||
pop af
|
||
ld [H_DOWNARROWBLINKCNT1], a ; restore previous values
|
||
xor a
|
||
ld [wMenuWrappingEnabled], a ; disable menu wrapping
|
||
ret
|
||
.keyPressed
|
||
xor a
|
||
ld [wCheckFor180DegreeTurn], a
|
||
ld a, [hJoy5]
|
||
ld b, a
|
||
bit 0, a ; pressed A key?
|
||
jr nz, .checkOtherKeys
|
||
bit 6, a ; pressed Up key?
|
||
jr z, .checkIfDownPressed
|
||
.upPressed
|
||
ld a, [wCurrentMenuItem] ; selected menu item
|
||
and a ; already at the top of the menu?
|
||
jr z, .alreadyAtTop
|
||
.notAtTop
|
||
dec a
|
||
ld [wCurrentMenuItem], a ; move selected menu item up one space
|
||
jr .checkOtherKeys
|
||
.alreadyAtTop
|
||
ld a, [wMenuWrappingEnabled]
|
||
and a ; is wrapping around enabled?
|
||
jr z, .noWrappingAround
|
||
ld a, [wMaxMenuItem]
|
||
ld [wCurrentMenuItem], a ; wrap to the bottom of the menu
|
||
jr .checkOtherKeys
|
||
.checkIfDownPressed
|
||
bit 7, a
|
||
jr z, .checkOtherKeys
|
||
.downPressed
|
||
ld a, [wCurrentMenuItem]
|
||
inc a
|
||
ld c, a
|
||
ld a, [wMaxMenuItem]
|
||
cp c
|
||
jr nc, .notAtBottom
|
||
.alreadyAtBottom
|
||
ld a, [wMenuWrappingEnabled]
|
||
and a ; is wrapping around enabled?
|
||
jr z, .noWrappingAround
|
||
ld c, $00 ; wrap from bottom to top
|
||
.notAtBottom
|
||
ld a, c
|
||
ld [wCurrentMenuItem], a
|
||
.checkOtherKeys
|
||
ld a, [wMenuWatchedKeys]
|
||
and b ; does the menu care about any of the pressed keys?
|
||
jp z, .loop1
|
||
.checkIfAButtonOrBButtonPressed
|
||
ld a, [hJoy5]
|
||
and A_BUTTON | B_BUTTON
|
||
jr z, .skipPlayingSound
|
||
.AButtonOrBButtonPressed
|
||
push hl
|
||
ld hl, wFlags_0xcd60
|
||
bit 5, [hl]
|
||
pop hl
|
||
jr nz, .skipPlayingSound
|
||
ld a, $90 ; SFX_PRESS_AB
|
||
call PlaySound ; play sound
|
||
.skipPlayingSound
|
||
pop af
|
||
ld [H_DOWNARROWBLINKCNT2], a
|
||
pop af
|
||
ld [H_DOWNARROWBLINKCNT1], a ; restore previous values
|
||
xor a
|
||
ld [wMenuWrappingEnabled], a ; disable menu wrapping
|
||
ld a, [hJoy5]
|
||
ret
|
||
.noWrappingAround
|
||
ld a, [wMenuWatchMovingOutOfBounds]
|
||
and a ; should we return if the user tried to go past the top or bottom?
|
||
jr z, .checkOtherKeys
|
||
jr .checkIfAButtonOrBButtonPressed
|
||
|
||
PlaceMenuCursor:: ; 3b6d (0:3b6d)
|
||
ld a, [wTopMenuItemY]
|
||
and a ; is the y coordinate 0?
|
||
jr z, .adjustForXCoord
|
||
coord hl, 0, 0
|
||
ld bc, SCREEN_WIDTH
|
||
.topMenuItemLoop
|
||
add hl, bc
|
||
dec a
|
||
jr nz, .topMenuItemLoop
|
||
.adjustForXCoord
|
||
ld a, [wTopMenuItemX]
|
||
ld b, 0
|
||
ld c, a
|
||
add hl, bc
|
||
push hl
|
||
ld a, [wLastMenuItem]
|
||
and a ; was the previous menu id 0?
|
||
jr z, .checkForArrow1
|
||
ld bc, 40
|
||
push af
|
||
ld a, [hFlags_0xFFFA]
|
||
bit 1, a ; is the menu double spaced?
|
||
jr z, .doubleSpaced1
|
||
ld bc, 20
|
||
.doubleSpaced1
|
||
pop af
|
||
.oldMenuItemLoop
|
||
add hl, bc
|
||
dec a
|
||
jr nz, .oldMenuItemLoop
|
||
.checkForArrow1
|
||
ld a, [hl]
|
||
cp "▶" ; was an arrow next to the previously selected menu item?
|
||
jr nz, .skipClearingArrow
|
||
.clearArrow
|
||
ld a, [wTileBehindCursor]
|
||
ld [hl], a
|
||
.skipClearingArrow
|
||
pop hl
|
||
ld a, [wCurrentMenuItem]
|
||
and a
|
||
jr z, .checkForArrow2
|
||
ld bc, 40
|
||
push af
|
||
ld a, [hFlags_0xFFFA]
|
||
bit 1, a ; is the menu double spaced?
|
||
jr z, .doubleSpaced2
|
||
ld bc, 20
|
||
.doubleSpaced2
|
||
pop af
|
||
.currentMenuItemLoop
|
||
add hl, bc
|
||
dec a
|
||
jr nz, .currentMenuItemLoop
|
||
.checkForArrow2
|
||
ld a, [hl]
|
||
cp "▶" ; has the right arrow already been placed?
|
||
jr z, .skipSavingTile ; if so, don't lose the saved tile
|
||
ld [wTileBehindCursor], a ; save tile before overwriting with right arrow
|
||
.skipSavingTile
|
||
ld a, "▶" ; place right arrow
|
||
ld [hl], a
|
||
ld a, l
|
||
ld [wMenuCursorLocation], a
|
||
ld a, h
|
||
ld [wMenuCursorLocation + 1], a
|
||
ld a, [wCurrentMenuItem]
|
||
ld [wLastMenuItem], a
|
||
ret
|
||
|
||
; This is used to mark a menu cursor other than the one currently being
|
||
; manipulated. In the case of submenus, this is used to show the location of
|
||
; the menu cursor in the parent menu. In the case of swapping items in list,
|
||
; this is used to mark the item that was first chosen to be swapped.
|
||
PlaceUnfilledArrowMenuCursor:: ; 3bd9 (0:3bd9)
|
||
ld b, a
|
||
ld a, [wMenuCursorLocation]
|
||
ld l, a
|
||
ld a, [wMenuCursorLocation + 1]
|
||
ld h, a
|
||
ld [hl], $ec ; outline of right arrow
|
||
ld a, b
|
||
ret
|
||
|
||
; Replaces the menu cursor with a blank space.
|
||
EraseMenuCursor:: ; 3be6 (0:3be6)
|
||
ld a, [wMenuCursorLocation]
|
||
ld l, a
|
||
ld a, [wMenuCursorLocation + 1]
|
||
ld h, a
|
||
ld [hl], " "
|
||
ret
|
||
|
||
; This toggles a blinking down arrow at hl on and off after a delay has passed.
|
||
; This is often called even when no blinking is occurring.
|
||
; The reason is that most functions that call this initialize H_DOWNARROWBLINKCNT1 to 0.
|
||
; The effect is that if the tile at hl is initialized with a down arrow,
|
||
; this function will toggle that down arrow on and off, but if the tile isn't
|
||
; initliazed with a down arrow, this function does nothing.
|
||
; That allows this to be called without worrying about if a down arrow should
|
||
; be blinking.
|
||
HandleDownArrowBlinkTiming:: ; 3bf1 (0:3bf1)
|
||
ld a, [hl]
|
||
ld b, a
|
||
ld a, $ee ; down arrow
|
||
cp b
|
||
jr nz, .downArrowOff
|
||
.downArrowOn
|
||
ld a, [H_DOWNARROWBLINKCNT1]
|
||
dec a
|
||
ld [H_DOWNARROWBLINKCNT1], a
|
||
ret nz
|
||
ld a, [H_DOWNARROWBLINKCNT2]
|
||
dec a
|
||
ld [H_DOWNARROWBLINKCNT2], a
|
||
ret nz
|
||
ld a, " "
|
||
ld [hl], a
|
||
ld a, $ff
|
||
ld [H_DOWNARROWBLINKCNT1], a
|
||
ld a, $06
|
||
ld [H_DOWNARROWBLINKCNT2], a
|
||
ret
|
||
.downArrowOff
|
||
ld a, [H_DOWNARROWBLINKCNT1]
|
||
and a
|
||
ret z
|
||
dec a
|
||
ld [H_DOWNARROWBLINKCNT1], a
|
||
ret nz
|
||
dec a
|
||
ld [H_DOWNARROWBLINKCNT1], a
|
||
ld a, [H_DOWNARROWBLINKCNT2]
|
||
dec a
|
||
ld [H_DOWNARROWBLINKCNT2], a
|
||
ret nz
|
||
ld a, $06
|
||
ld [H_DOWNARROWBLINKCNT2], a
|
||
ld a, $ee ; down arrow
|
||
ld [hl], a
|
||
ret
|
||
|
||
; The following code either enables or disables the automatic drawing of
|
||
; text boxes by DisplayTextID. Both functions cause DisplayTextID to wait
|
||
; for a button press after displaying text (unless [wEnteringCableClub] is set).
|
||
|
||
EnableAutoTextBoxDrawing:: ; 3c29 (0:3c29)
|
||
xor a
|
||
jr AutoTextBoxDrawingCommon
|
||
|
||
DisableAutoTextBoxDrawing:: ; 3c2c (0:3c2c)
|
||
ld a, $01
|
||
|
||
AutoTextBoxDrawingCommon:: ; 3c2e (0:3c2d)
|
||
ld [wAutoTextBoxDrawingControl], a
|
||
xor a
|
||
ld [wDoNotWaitForButtonPressAfterDisplayingText], a ; make DisplayTextID wait for button press
|
||
ret
|
||
|
||
PrintText:: ; 3c36 (0:3c36)
|
||
; Print text hl at (1, 14).
|
||
push hl
|
||
ld a, MESSAGE_BOX
|
||
ld [wTextBoxID], a
|
||
call DisplayTextBoxID
|
||
call UpdateSprites
|
||
call Delay3
|
||
pop hl
|
||
PrintText_NoCreatingTextBox:: ; 3c46 (0:3c46)
|
||
coord bc, 1, 14
|
||
jp TextCommandProcessor
|
||
|
||
FarPrintText:: ; 3c4c (0:3c4c)
|
||
; print text b:hl at (1, 14)
|
||
ld a, [H_LOADEDROMBANK]
|
||
push af
|
||
ld a, b
|
||
call BankswitchCommon
|
||
call PrintText
|
||
pop af
|
||
call BankswitchCommon
|
||
ret
|
||
|
||
PrintNumber:: ; 3c5b (0:3c5b)
|
||
; Print the c-digit, b-byte value at de.
|
||
; Allows 2 to 7 digits. For 1-digit numbers, add
|
||
; the value to char "0" instead of calling PrintNumber.
|
||
; Flags LEADING_ZEROES and LEFT_ALIGN can be given
|
||
; in bits 7 and 6 of b respectively.
|
||
push bc
|
||
xor a
|
||
ld [H_PASTLEADINGZEROES], a
|
||
ld [H_NUMTOPRINT], a
|
||
ld [H_NUMTOPRINT + 1], a
|
||
ld a, b
|
||
and $f
|
||
cp 1
|
||
jr z, .byte
|
||
cp 2
|
||
jr z, .word
|
||
.long
|
||
ld a, [de]
|
||
ld [H_NUMTOPRINT], a
|
||
inc de
|
||
ld a, [de]
|
||
ld [H_NUMTOPRINT + 1], a
|
||
inc de
|
||
ld a, [de]
|
||
ld [H_NUMTOPRINT + 2], a
|
||
jr .start
|
||
|
||
.word
|
||
ld a, [de]
|
||
ld [H_NUMTOPRINT + 1], a
|
||
inc de
|
||
ld a, [de]
|
||
ld [H_NUMTOPRINT + 2], a
|
||
jr .start
|
||
|
||
.byte
|
||
ld a, [de]
|
||
ld [H_NUMTOPRINT + 2], a
|
||
|
||
.start
|
||
push de
|
||
|
||
ld d, b
|
||
ld a, c
|
||
ld b, a
|
||
xor a
|
||
ld c, a
|
||
ld a, b
|
||
|
||
cp 2
|
||
jr z, .tens
|
||
cp 3
|
||
jr z, .hundreds
|
||
cp 4
|
||
jr z, .thousands
|
||
cp 5
|
||
jr z, .ten_thousands
|
||
cp 6
|
||
jr z, .hundred_thousands
|
||
|
||
print_digit: macro
|
||
|
||
if (\1) / $10000
|
||
ld a, \1 / $10000 % $100
|
||
else xor a
|
||
endc
|
||
ld [H_POWEROFTEN + 0], a
|
||
|
||
if (\1) / $100
|
||
ld a, \1 / $100 % $100
|
||
else xor a
|
||
endc
|
||
ld [H_POWEROFTEN + 1], a
|
||
|
||
ld a, \1 / $1 % $100
|
||
ld [H_POWEROFTEN + 2], a
|
||
|
||
call .PrintDigit
|
||
call .NextDigit
|
||
endm
|
||
|
||
.millions print_digit 1000000
|
||
.hundred_thousands print_digit 100000
|
||
.ten_thousands print_digit 10000
|
||
.thousands print_digit 1000
|
||
.hundreds print_digit 100
|
||
|
||
.tens
|
||
ld c, 0
|
||
ld a, [H_NUMTOPRINT + 2]
|
||
.mod
|
||
cp 10
|
||
jr c, .ok
|
||
sub 10
|
||
inc c
|
||
jr .mod
|
||
.ok
|
||
|
||
ld b, a
|
||
ld a, [H_PASTLEADINGZEROES]
|
||
or c
|
||
ld [H_PASTLEADINGZEROES], a
|
||
jr nz, .past
|
||
call .PrintLeadingZero
|
||
jr .next
|
||
.past
|
||
ld a, "0"
|
||
add c
|
||
ld [hl], a
|
||
.next
|
||
|
||
call .NextDigit
|
||
.ones
|
||
ld a, "0"
|
||
add b
|
||
ld [hli], a
|
||
pop de
|
||
dec de
|
||
pop bc
|
||
ret
|
||
|
||
.PrintDigit: ; 3d21 (0:3d21)
|
||
; Divide by the current decimal place.
|
||
; Print the quotient, and keep the modulus.
|
||
ld c, 0
|
||
.loop
|
||
ld a, [H_POWEROFTEN]
|
||
ld b, a
|
||
ld a, [H_NUMTOPRINT]
|
||
ld [H_SAVEDNUMTOPRINT], a
|
||
cp b
|
||
jr c, .underflow0
|
||
sub b
|
||
ld [H_NUMTOPRINT], a
|
||
ld a, [H_POWEROFTEN + 1]
|
||
ld b, a
|
||
ld a, [H_NUMTOPRINT + 1]
|
||
ld [H_SAVEDNUMTOPRINT + 1], a
|
||
cp b
|
||
jr nc, .noborrow1
|
||
|
||
ld a, [H_NUMTOPRINT]
|
||
or 0
|
||
jr z, .underflow1
|
||
dec a
|
||
ld [H_NUMTOPRINT], a
|
||
ld a, [H_NUMTOPRINT + 1]
|
||
.noborrow1
|
||
|
||
sub b
|
||
ld [H_NUMTOPRINT + 1], a
|
||
ld a, [H_POWEROFTEN + 2]
|
||
ld b, a
|
||
ld a, [H_NUMTOPRINT + 2]
|
||
ld [H_SAVEDNUMTOPRINT + 2], a
|
||
cp b
|
||
jr nc, .noborrow2
|
||
|
||
ld a, [H_NUMTOPRINT + 1]
|
||
and a
|
||
jr nz, .borrowed
|
||
|
||
ld a, [H_NUMTOPRINT]
|
||
and a
|
||
jr z, .underflow2
|
||
dec a
|
||
ld [H_NUMTOPRINT], a
|
||
xor a
|
||
.borrowed
|
||
|
||
dec a
|
||
ld [H_NUMTOPRINT + 1], a
|
||
ld a, [H_NUMTOPRINT + 2]
|
||
.noborrow2
|
||
sub b
|
||
ld [H_NUMTOPRINT + 2], a
|
||
inc c
|
||
jr .loop
|
||
|
||
.underflow2
|
||
ld a, [H_SAVEDNUMTOPRINT + 1]
|
||
ld [H_NUMTOPRINT + 1], a
|
||
.underflow1
|
||
ld a, [H_SAVEDNUMTOPRINT]
|
||
ld [H_NUMTOPRINT], a
|
||
.underflow0
|
||
ld a, [H_PASTLEADINGZEROES]
|
||
or c
|
||
jr z, .PrintLeadingZero
|
||
|
||
ld a, "0"
|
||
add c
|
||
ld [hl], a
|
||
ld [H_PASTLEADINGZEROES], a
|
||
ret
|
||
|
||
.PrintLeadingZero: ; 3d7f (0:3d7f)
|
||
bit BIT_LEADING_ZEROES, d
|
||
ret z
|
||
ld [hl], "0"
|
||
ret
|
||
|
||
.NextDigit: ; 3d85 (0:3d85)
|
||
; Increment unless the number is left-aligned,
|
||
; leading zeroes are not printed, and no digits
|
||
; have been printed yet.
|
||
bit BIT_LEADING_ZEROES, d
|
||
jr nz, .inc
|
||
bit BIT_LEFT_ALIGN, d
|
||
jr z, .inc
|
||
ld a, [H_PASTLEADINGZEROES]
|
||
and a
|
||
ret z
|
||
.inc
|
||
inc hl
|
||
ret
|
||
|
||
|
||
JumpTable:: ; 3d93 (0:3d93)
|
||
; Call function a in jumptable hl.
|
||
; de is not preserved.
|
||
push hl
|
||
push de
|
||
push bc
|
||
add a
|
||
ld d, 0
|
||
ld e, a
|
||
add hl, de
|
||
ld a, [hli]
|
||
ld h, [hl]
|
||
ld l, a
|
||
ld de, .returnAddress
|
||
push de
|
||
jp [hl]
|
||
.returnAddress
|
||
pop bc
|
||
pop de
|
||
pop hl
|
||
ret
|
||
|
||
|
||
IsInArray:: ; 3da7 (0:3da7)
|
||
; Search an array at hl for the value in a.
|
||
; Entry size is de bytes.
|
||
; Return count b and carry if found.
|
||
ld b, 0
|
||
|
||
IsInRestOfArray:: ; 3da9 (0:3da9)
|
||
ld c, a
|
||
.loop
|
||
ld a, [hl]
|
||
cp -1
|
||
jr z, .notfound
|
||
cp c
|
||
jr z, .found
|
||
inc b
|
||
add hl, de
|
||
jr .loop
|
||
|
||
.notfound
|
||
and a
|
||
ret
|
||
|
||
.found
|
||
scf
|
||
ret
|
||
|
||
InitMapSprites:: ; 3dba (0:3dba)
|
||
jpab _InitMapSprites
|
||
|
||
RestoreScreenTilesAndReloadTilePatterns:: ; 3dc2 (0:3dc2)
|
||
call ClearSprites
|
||
ld a, $1
|
||
ld [wUpdateSpritesEnabled], a
|
||
call ReloadMapSpriteTilePatterns
|
||
call LoadScreenTilesFromBuffer2
|
||
call LoadTextBoxTilePatterns
|
||
call RunDefaultPaletteCommand
|
||
jr Delay3
|
||
|
||
|
||
GBPalWhiteOutWithDelay3:: ; 3dd8 (0:3dd8)
|
||
call GBPalWhiteOut
|
||
|
||
Delay3:: ; 3ddb (0:3ddb)
|
||
; The bg map is updated each frame in thirds.
|
||
; Wait three frames to let the bg map fully update.
|
||
ld c, 3
|
||
jp DelayFrames
|
||
|
||
GBPalNormal:: ; 3de0 (0:3de0)
|
||
; Reset BGP and OBP0.
|
||
ld a, %11100100 ; 3210
|
||
ld [rBGP], a
|
||
ld a, %11010000 ; 3100
|
||
ld [rOBP0], a
|
||
call UpdateGBCPal_BGP
|
||
call UpdateGBCPal_OBP0
|
||
call UpdateGBCPal_OBP1
|
||
ret
|
||
|
||
GBPalWhiteOut:: ; 3df2 (0:3df2)
|
||
; White out all palettes.
|
||
xor a
|
||
ld [rBGP], a
|
||
ld [rOBP0], a
|
||
ld [rOBP1], a
|
||
call UpdateGBCPal_BGP
|
||
call UpdateGBCPal_OBP0
|
||
call UpdateGBCPal_OBP1
|
||
ret
|
||
|
||
|
||
RunDefaultPaletteCommand:: ; 3e03 (0:3e03)
|
||
ld b, $ff
|
||
RunPaletteCommand:: ; 3e05 (0:3e05)
|
||
ld a, [wOnSGB]
|
||
and a
|
||
ret z
|
||
predef_jump _RunPaletteCommand
|
||
|
||
GetHealthBarColor:: ; 3e0f (0:3e0f)
|
||
; Return at hl the palette of
|
||
; an HP bar e pixels long.
|
||
ld a, e
|
||
cp 27
|
||
ld d, 0 ; green
|
||
jr nc, .gotColor
|
||
cp 10
|
||
inc d ; yellow
|
||
jr nc, .gotColor
|
||
inc d ; red
|
||
.gotColor
|
||
ld [hl], d
|
||
ret
|
||
|
||
; Copy the current map's sprites' tile patterns to VRAM again after they have
|
||
; been overwritten by other tile patterns.
|
||
ReloadMapSpriteTilePatterns:: ; 3e1e (0:3e1e)
|
||
ld hl, wFontLoaded
|
||
ld a, [hl]
|
||
push af
|
||
res 0, [hl]
|
||
push hl
|
||
xor a
|
||
ld [wSpriteSetID], a
|
||
call DisableLCD
|
||
call InitMapSprites
|
||
call EnableLCD
|
||
pop hl
|
||
pop af
|
||
ld [hl], a
|
||
call LoadPlayerSpriteGraphics
|
||
call LoadFontTilePatterns
|
||
jp UpdateSprites
|
||
|
||
|
||
GiveItem:: ; 3e3f (0:3e3f)
|
||
; Give player quantity c of item b,
|
||
; and copy the item's name to wcf4b.
|
||
; Return carry on success.
|
||
ld a, b
|
||
ld [wd11e], a
|
||
ld [wcf91], a
|
||
ld a, c
|
||
ld [wItemQuantity], a
|
||
ld hl, wNumBagItems
|
||
call AddItemToInventory
|
||
ret nc
|
||
call GetItemName
|
||
call CopyStringToCF4B
|
||
scf
|
||
ret
|
||
|
||
GivePokemon:: ; 3e59 (0:3e59)
|
||
; Give the player monster b at level c.
|
||
ld a, b
|
||
ld [wcf91], a
|
||
ld a, c
|
||
ld [wCurEnemyLVL], a
|
||
xor a ; PLAYER_PARTY_DATA
|
||
ld [wMonDataLocation], a
|
||
jpba _GivePokemon ; 3d:66fa
|
||
|
||
Random:: ; 3e6d (0:3e6d)
|
||
; Return a random number in a.
|
||
; For battles, use BattleRandom.
|
||
push hl
|
||
push de
|
||
push bc
|
||
callba Random_
|
||
ld a, [hRandomAdd]
|
||
pop bc
|
||
pop de
|
||
pop hl
|
||
ret
|
||
|
||
BankswitchCommon:: ; 3e7e (0:3e7e)
|
||
ld [H_LOADEDROMBANK], a
|
||
ld [MBC1RomBank], a
|
||
ret
|
||
|
||
Bankswitch:: ; 3e84 (0:3e84)
|
||
; self-contained bankswitch, use this when not in the home bank
|
||
; switches to the bank in b
|
||
ld a, [H_LOADEDROMBANK]
|
||
push af
|
||
ld a, b
|
||
ld [H_LOADEDROMBANK], a
|
||
ld [MBC1RomBank], a
|
||
call JumpToAddress
|
||
pop bc
|
||
ld a, b
|
||
ld [H_LOADEDROMBANK], a
|
||
ld [MBC1RomBank], a
|
||
ret
|
||
JumpToAddress:: ; 3e98 (0:3e98)
|
||
jp [hl]
|
||
|
||
SwitchSRAMBankAndLatchClockData:: ; 3e99 (0:3e99)
|
||
push af
|
||
ld a, $1
|
||
ld [MBC1SRamBankingMode], a
|
||
ld a, SRAM_ENABLE
|
||
ld [MBC1SRamEnable], a
|
||
pop af
|
||
ld [MBC1SRamBank], a
|
||
ret
|
||
|
||
PrepareRTCDataAndDisableSRAM:: ; 3ea9 (0:3ea9)
|
||
push af
|
||
ld a, $0
|
||
ld [MBC1SRamBankingMode], a
|
||
ld [MBC1SRamEnable], a
|
||
pop af
|
||
ret
|
||
|
||
INCLUDE "home/predef.asm"
|
||
|
||
UpdateCinnabarGymGateTileBlocks:: ; 3ef0 (0:3ef0)
|
||
callba UpdateCinnabarGymGateTileBlocks_
|
||
ret ; again?
|
||
;jp Bankswitch
|
||
|
||
CheckForHiddenObjectOrBookshelfOrCardKeyDoor:: ; 3ef9 (0:3ef9)
|
||
ld a, [H_LOADEDROMBANK]
|
||
push af
|
||
ld a, [hJoyHeld]
|
||
bit 0, a ; A button
|
||
jr z, .nothingFound
|
||
; A button is pressed
|
||
callbs CheckForHiddenObject
|
||
ld a, [$ffee]
|
||
and a
|
||
jr nz, .hiddenObjectNotFound
|
||
xor a
|
||
ld [$ffeb], a
|
||
ld a, [wHiddenObjectFunctionRomBank]
|
||
call BankswitchCommon
|
||
call JumpToAddress
|
||
ld a, [$ffeb]
|
||
jr .done
|
||
.hiddenObjectNotFound
|
||
predef GetTileAndCoordsInFrontOfPlayer
|
||
callba PrintBookshelfText
|
||
ld a, [$ffdb]
|
||
and a
|
||
jr z, .done
|
||
.nothingFound
|
||
ld a, $ff
|
||
.done
|
||
ld [$ffeb], a
|
||
pop af
|
||
call BankswitchCommon
|
||
ret
|
||
|
||
PrintPredefTextID:: ; 3f3a (0:3f3a)
|
||
ld [hSpriteIndexOrTextID], a ; $ff8c
|
||
ld hl, TextPredefs
|
||
call SetMapTextPointer
|
||
ld hl, wTextPredefFlag
|
||
set 0, [hl]
|
||
call DisplayTextID
|
||
|
||
RestoreMapTextPointer:: ; 3f4a (0:3f4a)
|
||
ld hl, wMapTextPtr
|
||
ld a, [$ffec]
|
||
ld [hli], a
|
||
ld a, [$ffec + 1]
|
||
ld [hl], a
|
||
ret
|
||
|
||
SetMapTextPointer:: ; 3f54 (0:3f54)
|
||
ld a, [wMapTextPtr]
|
||
ld [$ffec], a
|
||
ld a, [wMapTextPtr + 1]
|
||
ld [$ffec + 1], a
|
||
ld a, l
|
||
ld [wMapTextPtr], a
|
||
ld a, h
|
||
ld [wMapTextPtr + 1], a
|
||
ret
|
||
|
||
TextPredefs:: ; 3f67 (0:3f67)
|
||
const_value = 1
|
||
|
||
add_tx_pre CardKeySuccessText ; 01
|
||
add_tx_pre CardKeyFailText ; 02
|
||
add_tx_pre RedBedroomPCText ; 03
|
||
add_tx_pre RedBedroomSNESText ; 04
|
||
add_tx_pre PushStartText ; 05
|
||
add_tx_pre SaveOptionText ; 06
|
||
add_tx_pre StrengthsAndWeaknessesText ; 07
|
||
add_tx_pre OakLabEmailText ; 08
|
||
add_tx_pre AerodactylFossilText ; 09
|
||
add_tx_pre Route15UpstairsBinocularsText ; 0A
|
||
add_tx_pre KabutopsFossilText ; 0B
|
||
add_tx_pre FanClubPicture1Text ; 0C
|
||
add_tx_pre FanClubPicture2Text ; 0D
|
||
add_tx_pre GymStatueText1 ; 0E
|
||
add_tx_pre GymStatueText2 ; 0F
|
||
add_tx_pre BookcaseText ; 10
|
||
add_tx_pre ViridianCityPokecenterBenchGuyText ; 11
|
||
add_tx_pre PewterCityPokecenterBenchGuyText ; 12
|
||
add_tx_pre CeruleanCityPokecenterBenchGuyText ; 13
|
||
add_tx_pre LavenderCityPokecenterBenchGuyText ; 14
|
||
add_tx_pre VermilionCityPokecenterBenchGuyText ; 15
|
||
add_tx_pre CeladonCityPokecenterBenchGuyText ; 16
|
||
add_tx_pre CeladonCityHotelText ; 17
|
||
add_tx_pre FuchsiaCityPokecenterBenchGuyText ; 18
|
||
add_tx_pre CinnabarIslandPokecenterBenchGuyText ; 19
|
||
add_tx_pre SaffronCityPokecenterBenchGuyText ; 1A
|
||
add_tx_pre MtMoonPokecenterBenchGuyText ; 1B
|
||
add_tx_pre RockTunnelPokecenterBenchGuyText ; 1C
|
||
add_tx_pre UnusedBenchGuyText1 ; 1D
|
||
add_tx_pre UnusedBenchGuyText2 ; 1E
|
||
add_tx_pre UnusedBenchGuyText3 ; 1F
|
||
add_tx_pre UnusedPredefText ; 20
|
||
add_tx_pre PokemonCenterPCText ; 21
|
||
add_tx_pre ViridianSchoolNotebook ; 22
|
||
add_tx_pre ViridianSchoolBlackboard ; 23
|
||
; add_tx_pre FakeTextPredef22
|
||
; add_tx_pre FakeTextPredef23
|
||
add_tx_pre JustAMomentText ; 24
|
||
add_tx_pre OpenBillsPCText ; 25
|
||
add_tx_pre FoundHiddenItemText ; 26
|
||
add_tx_pre HiddenItemBagFullText ; 27
|
||
add_tx_pre VermilionGymTrashText ; 28
|
||
add_tx_pre IndigoPlateauHQText ; 29
|
||
add_tx_pre GameCornerOutOfOrderText ; 2A
|
||
add_tx_pre GameCornerOutToLunchText ; 2B
|
||
add_tx_pre GameCornerSomeonesKeysText ; 2C
|
||
add_tx_pre FoundHiddenCoinsText ; 2D
|
||
add_tx_pre DroppedHiddenCoinsText ; 2E
|
||
add_tx_pre BillsHouseMonitorText ; 2F
|
||
add_tx_pre BillsHouseInitiatedText ; 30
|
||
add_tx_pre BillsHousePokemonList ; 31
|
||
add_tx_pre MagazinesText ; 32
|
||
add_tx_pre CinnabarGymQuiz ; 33
|
||
add_tx_pre GameCornerNoCoinsText ; 34
|
||
add_tx_pre GameCornerCoinCaseText ; 35
|
||
add_tx_pre LinkCableHelp ; 36
|
||
add_tx_pre TMNotebook ; 37
|
||
add_tx_pre FightingDojoText ; 38
|
||
add_tx_pre EnemiesOnEverySideText ; 39
|
||
add_tx_pre WhatGoesAroundComesAroundText ; 3A
|
||
add_tx_pre NewBicycleText ; 3B
|
||
add_tx_pre IndigoPlateauStatues ; 3C XXX unused
|
||
add_tx_pre VermilionGymTrashSuccesText1 ; 3D
|
||
add_tx_pre VermilionGymTrashSuccesText2 ; 3E
|
||
add_tx_pre VermilionGymTrashSuccesText3 ; 3F
|
||
add_tx_pre VermilionGymTrashFailText ; 40
|
||
add_tx_pre TownMapText ; 41
|
||
add_tx_pre BookOrSculptureText ; 42
|
||
add_tx_pre ElevatorText ; 43
|
||
add_tx_pre PokemonStuffText ; 44
|
||
|
||
; dr $3f67, $4000
|