summaryrefslogtreecommitdiff
path: root/engine/pokegear
diff options
context:
space:
mode:
authormid-kid <esteve.varela@gmail.com>2018-03-13 13:07:16 +0100
committermid-kid <esteve.varela@gmail.com>2018-03-13 13:21:40 +0100
commitbaa0dc5a963a79843b37888bcfe1d2dfe833ade9 (patch)
tree968c86105bd67a3121d8f3f20018bfc59191f4c9 /engine/pokegear
parent12070ca50067d3abe36a730190f88ee43f2cace9 (diff)
Organize the engine/ directory
This is an informed attempt at reorganizing the engine/ directory by creating categorized subdirectories, in order to make it easier to navigate and find things. The directories created are as follows: * engine/game: Contains all "minigames", things like the unown puzzle and slot machine. * engine/gfx: Contains all handling of graphics. From loading palettes to playing animations. * engine/link: Contains all multiplayer functionality. * engine/menu: Contains all generic/misc. menus and menu code. Other, more specialized menus are in their own subdirectories (pokedex, pokegear, party menu, etc). * engine/overworld: Contains all handling of the overworld. From loading and connecting maps to wild encounters and the scripting engine. * engine/pokegear: In the same vein as engine/pokedex, except it could use some more splitting up. * engine/pokemon: Contains everything related to manipulating pokemon data. From the pokemon storage system to evolution and mail. * engine/printer: Contains everything related to printing things as well as the printer communication. * engine/title: Contains intro sequences, title screens and credits.
Diffstat (limited to 'engine/pokegear')
-rwxr-xr-xengine/pokegear/pokegear.asm3097
-rw-r--r--engine/pokegear/radio.asm1932
2 files changed, 5029 insertions, 0 deletions
diff --git a/engine/pokegear/pokegear.asm b/engine/pokegear/pokegear.asm
new file mode 100755
index 000000000..f04276b2d
--- /dev/null
+++ b/engine/pokegear/pokegear.asm
@@ -0,0 +1,3097 @@
+; Pokégear cards
+ const_def
+ const POKEGEARCARD_CLOCK ; 0
+ const POKEGEARCARD_MAP ; 1
+ const POKEGEARCARD_PHONE ; 2
+ const POKEGEARCARD_RADIO ; 3
+NUM_POKEGEAR_CARDS EQU const_value
+
+; PokegearJumptable.Jumptable indexes
+ const_def
+ const POKEGEARSTATE_CLOCKINIT ; 0
+ const POKEGEARSTATE_CLOCKJOYPAD ; 1
+ const POKEGEARSTATE_MAPCHECKREGION ; 2
+ const POKEGEARSTATE_JOHTOMAPINIT ; 3
+ const POKEGEARSTATE_JOHTOMAPJOYPAD ; 4
+ const POKEGEARSTATE_KANTOMAPINIT ; 5
+ const POKEGEARSTATE_KANTOMAPJOYPAD ; 6
+ const POKEGEARSTATE_PHONEINIT ; 7
+ const POKEGEARSTATE_PHONEJOYPAD ; 8
+ const POKEGEARSTATE_MAKEPHONECALL ; 9
+ const POKEGEARSTATE_FINISHPHONECALL ; a
+ const POKEGEARSTATE_RADIOINIT ; b
+ const POKEGEARSTATE_RADIOJOYPAD ; c
+
+PokeGear: ; 90b8d (24:4b8d)
+ ld hl, wOptions
+ ld a, [hl]
+ push af
+ set NO_TEXT_SCROLL, [hl]
+ ld a, [hInMenu]
+ push af
+ ld a, $1
+ ld [hInMenu], a
+ ld a, [wVramState]
+ push af
+ xor a
+ ld [wVramState], a
+ call .InitTilemap
+ call DelayFrame
+.loop
+ call UpdateTime
+ call JoyTextDelay
+ ld a, [wJumptableIndex]
+ bit 7, a
+ jr nz, .done
+ call PokegearJumptable
+ farcall PlaySpriteAnimations
+ call DelayFrame
+ jr .loop
+
+.done
+ ld de, SFX_READ_TEXT_2
+ call PlaySFX
+ call WaitSFX
+ pop af
+ ld [wVramState], a
+ pop af
+ ld [hInMenu], a
+ pop af
+ ld [wOptions], a
+ call ClearBGPalettes
+ xor a ; LOW(vBGMap0)
+ ld [hBGMapAddress], a
+ ld a, HIGH(vBGMap0)
+ ld [hBGMapAddress + 1], a
+ ld a, $90
+ ld [hWY], a
+ call ExitPokegearRadio_HandleMusic
+ ret
+
+.InitTilemap: ; 90bea (24:4bea)
+ call ClearBGPalettes
+ call ClearTileMap
+ call ClearSprites
+ call DisableLCD
+ xor a
+ ld [hSCY], a
+ ld [hSCX], a
+ ld a, $7
+ ld [hWX], a
+ call Pokegear_LoadGFX
+ farcall ClearSpriteAnims
+ call InitPokegearModeIndicatorArrow
+ ld a, 8
+ call SkipMusic
+ ld a, LCDC_DEFAULT
+ ld [rLCDC], a
+ call TownMap_InitCursorAndPlayerIconPositions
+ xor a
+ ld [wJumptableIndex], a ; POKEGEARSTATE_CLOCKINIT
+ ld [wPokegearCard], a ; POKEGEARCARD_CLOCK
+ ld [wPokegearMapRegion], a ; JOHTO_REGION
+ ld [wcf66], a
+ ld [wPokegearPhoneScrollPosition], a
+ ld [wPokegearPhoneCursorPosition], a
+ ld [wPokegearPhoneSelectedPerson], a
+ ld [wPokegearRadioChannelBank], a
+ ld [wPokegearRadioChannelAddr], a
+ ld [wPokegearRadioChannelAddr + 1], a
+ call Pokegear_InitJumptableIndices
+ call InitPokegearTilemap
+ ld b, SCGB_POKEGEAR_PALS
+ call GetSGBLayout
+ call SetPalettes
+ ld a, [hCGB]
+ and a
+ ret z
+ ld a, %11100100
+ call DmgToCgbObjPal0
+ ret
+
+Pokegear_LoadGFX: ; 90c4e
+ call ClearVBank1
+ ld hl, TownMapGFX
+ ld de, vTiles2
+ ld a, BANK(TownMapGFX)
+ call FarDecompress
+ ld hl, PokegearGFX
+ ld de, vTiles2 tile $30
+ ld a, BANK(PokegearGFX)
+ call FarDecompress
+ ld hl, PokegearSpritesGFX
+ ld de, vTiles0
+ ld a, BANK(PokegearSpritesGFX)
+ call Decompress
+ ld a, [wMapGroup]
+ ld b, a
+ ld a, [wMapNumber]
+ ld c, a
+ call GetWorldMapLocation
+ cp FAST_SHIP
+ jr z, .ssaqua
+ farcall GetPlayerIcon
+ push de
+ ld h, d
+ ld l, e
+ ld a, b
+ ; standing sprite
+ push af
+ ld de, vTiles0 tile $10
+ ld bc, 4 tiles
+ call FarCopyBytes
+ pop af
+ pop hl
+ ; walking sprite
+ ld de, 12 tiles
+ add hl, de
+ ld de, vTiles0 tile $14
+ ld bc, 4 tiles
+ call FarCopyBytes
+ ret
+
+.ssaqua
+ ld hl, FastShipGFX
+ ld de, vTiles0 tile $10
+ ld bc, 8 tiles
+ call CopyBytes
+ ret
+
+; 90cb2
+
+FastShipGFX: ; 90cb2
+INCBIN "gfx/pokegear/fast_ship.2bpp"
+; 90d32
+
+InitPokegearModeIndicatorArrow: ; 90d32 (24:4d32)
+ depixel 4, 2, 4, 0
+ ld a, SPRITE_ANIM_INDEX_POKEGEAR_ARROW
+ call _InitSpriteAnimStruct
+ ld hl, SPRITEANIMSTRUCT_TILE_ID
+ add hl, bc
+ ld [hl], $0
+ ret
+
+AnimatePokegearModeIndicatorArrow: ; 90d41 (24:4d41)
+ ld hl, wPokegearCard
+ ld e, [hl]
+ ld d, 0
+ ld hl, .XCoords
+ add hl, de
+ ld a, [hl]
+ ld hl, SPRITEANIMSTRUCT_XOFFSET
+ add hl, bc
+ ld [hl], a
+ ret
+
+; 90d52 (24:4d52)
+
+.XCoords: ; 90d52
+ db $00 ; POKEGEARCARD_CLOCK
+ db $10 ; POKEGEARCARD_MAP
+ db $20 ; POKEGEARCARD_PHONE
+ db $30 ; POKEGEARCARD_RADIO
+; 90d56
+
+TownMap_GetCurrentLandmark: ; 90d56
+ ld a, [wMapGroup]
+ ld b, a
+ ld a, [wMapNumber]
+ ld c, a
+ call GetWorldMapLocation
+ cp SPECIAL_MAP
+ ret nz
+ ld a, [wBackupMapGroup]
+ ld b, a
+ ld a, [wBackupMapNumber]
+ ld c, a
+ call GetWorldMapLocation
+ ret
+
+; 90d70
+
+TownMap_InitCursorAndPlayerIconPositions: ; 90d70 (24:4d70)
+ ld a, [wMapGroup]
+ ld b, a
+ ld a, [wMapNumber]
+ ld c, a
+ call GetWorldMapLocation
+ cp FAST_SHIP
+ jr z, .FastShip
+ cp SPECIAL_MAP
+ jr nz, .LoadLandmark
+ ld a, [wBackupMapGroup]
+ ld b, a
+ ld a, [wBackupMapNumber]
+ ld c, a
+ call GetWorldMapLocation
+.LoadLandmark:
+ ld [wPokegearMapPlayerIconLandmark], a
+ ld [wPokegearMapCursorLandmark], a
+ ret
+
+.FastShip:
+ ld [wPokegearMapPlayerIconLandmark], a
+ ld a, NEW_BARK_TOWN
+ ld [wPokegearMapCursorLandmark], a
+ ret
+
+Pokegear_InitJumptableIndices: ; 90d9e (24:4d9e)
+ ld a, POKEGEARSTATE_CLOCKINIT
+ ld [wJumptableIndex], a
+ xor a ; POKEGEARCARD_CLOCK
+ ld [wPokegearCard], a
+ ret
+
+InitPokegearTilemap: ; 90da8 (24:4da8)
+ xor a
+ ld [hBGMapMode], a
+ hlcoord 0, 0
+ ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+ ld a, $4f
+ call ByteFill
+ ld a, [wPokegearCard]
+ maskbits NUM_POKEGEAR_CARDS
+ add a
+ ld e, a
+ ld d, 0
+ ld hl, .Jumptable
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld de, .return_from_jumptable
+ push de
+ jp hl
+
+.return_from_jumptable
+ call Pokegear_FinishTilemap
+ farcall TownMapPals
+ ld a, [wPokegearMapRegion]
+ and a
+ jr nz, .kanto_0
+ xor a ; LOW(vBGMap0)
+ ld [hBGMapAddress], a
+ ld a, HIGH(vBGMap0)
+ ld [hBGMapAddress + 1], a
+ call .UpdateBGMap
+ ld a, $90
+ jr .finish
+
+.kanto_0
+ xor a ; LOW(vBGMap1)
+ ld [hBGMapAddress], a
+ ld a, HIGH(vBGMap1)
+ ld [hBGMapAddress + 1], a
+ call .UpdateBGMap
+ xor a
+.finish
+ ld [hWY], a
+ ; swap region maps
+ ld a, [wPokegearMapRegion]
+ maskbits NUM_REGIONS
+ xor 1
+ ld [wPokegearMapRegion], a
+ ret
+
+.UpdateBGMap: ; 90e00 (24:4e00)
+ ld a, [hCGB]
+ and a
+ jr z, .dmg
+ ld a, $2
+ ld [hBGMapMode], a
+ ld c, 3
+ call DelayFrames
+.dmg
+ call WaitBGMap
+ ret
+
+; 90e12 (24:4e12)
+
+.Jumptable: ; 90e12
+; entries correspond to POKEGEARCARD_* constants
+ dw .Clock
+ dw .Map
+ dw .Phone
+ dw .Radio
+; 90e1a
+
+.Clock: ; 90e1a
+ ld de, ClockTilemapRLE
+ call Pokegear_LoadTilemapRLE
+ hlcoord 12, 1
+ ld de, .switch
+ call PlaceString
+ hlcoord 0, 12
+ lb bc, 4, 18
+ call TextBox
+ call Pokegear_UpdateClock
+ ret
+
+; 90e36 (24:4e36)
+
+.switch
+ db " SWITCH▶@"
+; 90e3f
+
+.Map: ; 90e3f
+ ld a, [wPokegearMapPlayerIconLandmark]
+ cp FAST_SHIP
+ jr z, .johto
+ cp KANTO_LANDMARK
+ jr nc, .kanto
+.johto
+ ld e, 0
+ jr .ok
+
+.kanto
+ ld e, 1
+.ok
+ farcall PokegearMap
+ ld a, $07
+ ld bc, $12
+ hlcoord 1, 2
+ call ByteFill
+ hlcoord 0, 2
+ ld [hl], $06
+ hlcoord 19, 2
+ ld [hl], $17
+ ld a, [wPokegearMapCursorLandmark]
+ call PokegearMap_UpdateLandmarkName
+ ret
+
+; 90e72
+
+.Radio: ; 90e72
+ ld de, RadioTilemapRLE
+ call Pokegear_LoadTilemapRLE
+ hlcoord 0, 12
+ lb bc, 4, 18
+ call TextBox
+ ret
+
+; 90e82
+
+.Phone: ; 90e82
+ ld de, PhoneTilemapRLE
+ call Pokegear_LoadTilemapRLE
+ hlcoord 0, 12
+ lb bc, 4, 18
+ call TextBox
+ call .PlacePhoneBars
+ call PokegearPhone_UpdateDisplayList
+ ret
+
+; 90e98
+
+.PlacePhoneBars: ; 90e98 (24:4e98)
+ hlcoord 17, 1
+ ld a, $3c
+ ld [hli], a
+ inc a
+ ld [hl], a
+ hlcoord 17, 2
+ inc a
+ ld [hli], a
+ call GetMapPhoneService
+ and a
+ ret nz
+ hlcoord 18, 2
+ ld [hl], $3f
+ ret
+
+Pokegear_FinishTilemap: ; 90eb0 (24:4eb0)
+ hlcoord 0, 0
+ ld bc, $8
+ ld a, $4f
+ call ByteFill
+ hlcoord 0, 1
+ ld bc, $8
+ ld a, $4f
+ call ByteFill
+ ld de, wPokegearFlags
+ ld a, [de]
+ bit POKEGEAR_MAP_CARD_F, a
+ call nz, .PlaceMapIcon
+ ld a, [de]
+ bit POKEGEAR_PHONE_CARD_F, a
+ call nz, .PlacePhoneIcon
+ ld a, [de]
+ bit POKEGEAR_RADIO_CARD_F, a
+ call nz, .PlaceRadioIcon
+ hlcoord 0, 0
+ ld a, $46
+ call .PlacePokegearCardIcon
+ ret
+
+.PlaceMapIcon: ; 90ee4 (24:4ee4)
+ hlcoord 2, 0
+ ld a, $40
+ jr .PlacePokegearCardIcon
+
+.PlacePhoneIcon: ; 90eeb (24:4eeb)
+ hlcoord 4, 0
+ ld a, $44
+ jr .PlacePokegearCardIcon
+
+.PlaceRadioIcon: ; 90ef2 (24:4ef2)
+ hlcoord 6, 0
+ ld a, $42
+.PlacePokegearCardIcon: ; 90ef7 (24:4ef7)
+ ld [hli], a
+ inc a
+ ld [hld], a
+ ld bc, $14
+ add hl, bc
+ add $f
+ ld [hli], a
+ inc a
+ ld [hld], a
+ ret
+
+PokegearJumptable: ; 90f04 (24:4f04)
+ ld a, [wJumptableIndex]
+ ld e, a
+ ld d, 0
+ ld hl, .Jumptable
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp hl
+
+.Jumptable: ; 90f13 (24:4f13)
+; entries correspond to POKEGEARSTATE_* constants
+ dw PokegearClock_Init
+ dw PokegearClock_Joypad
+ dw PokegearMap_CheckRegion
+ dw PokegearMap_Init
+ dw PokegearMap_JohtoMap
+ dw PokegearMap_Init
+ dw PokegearMap_KantoMap
+ dw PokegearPhone_Init
+ dw PokegearPhone_Joypad
+ dw PokegearPhone_MakePhoneCall
+ dw PokegearPhone_FinishPhoneCall
+ dw PokegearRadio_Init
+ dw PokegearRadio_Joypad
+
+PokegearClock_Init: ; 90f2d (24:4f2d)
+ call InitPokegearTilemap
+ ld hl, PokegearText_PressAnyButtonToExit
+ call PrintText
+ ld hl, wJumptableIndex
+ inc [hl]
+ call ExitPokegearRadio_HandleMusic
+ ret
+
+PokegearClock_Joypad: ; 90f3e (24:4f3e)
+ call .UpdateClock
+ ld hl, hJoyLast
+ ld a, [hl]
+ and A_BUTTON | B_BUTTON | START | SELECT
+ jr nz, .quit
+ ld a, [hl]
+ and D_RIGHT
+ ret z
+ ld a, [wPokegearFlags]
+ bit POKEGEAR_MAP_CARD_F, a
+ jr z, .no_map_card
+ ld c, POKEGEARSTATE_MAPCHECKREGION
+ ld b, POKEGEARCARD_MAP
+ jr .done
+
+.no_map_card
+ ld a, [wPokegearFlags]
+ bit POKEGEAR_PHONE_CARD_F, a
+ jr z, .no_phone_card
+ ld c, POKEGEARSTATE_PHONEINIT
+ ld b, POKEGEARCARD_PHONE
+ jr .done
+
+.no_phone_card
+ ld a, [wPokegearFlags]
+ bit POKEGEAR_RADIO_CARD_F, a
+ ret z
+ ld c, POKEGEARSTATE_RADIOINIT
+ ld b, POKEGEARCARD_RADIO
+.done
+ call Pokegear_SwitchPage
+ ret
+
+.quit
+ ld hl, wJumptableIndex
+ set 7, [hl]
+ ret
+
+.UpdateClock: ; 90f7b (24:4f7b)
+ xor a
+ ld [hBGMapMode], a
+ call Pokegear_UpdateClock
+ ld a, $1
+ ld [hBGMapMode], a
+ ret
+
+Pokegear_UpdateClock: ; 90f86 (24:4f86)
+ hlcoord 3, 5
+ lb bc, 5, 14
+ call ClearBox
+ ld a, [hHours]
+ ld b, a
+ ld a, [hMinutes]
+ ld c, a
+ decoord 6, 8
+ farcall PrintHoursMins
+ ld hl, .DayText
+ bccoord 6, 6
+ call PlaceHLTextAtBC
+ ret
+
+; 90fa8 (24:4fa8)
+ db "ごぜん@"
+ db "ごご@"
+
+.DayText: ; 0x90faf
+ text_jump UnknownText_0x1c5821
+ db "@"
+
+; 0x90fb4
+
+PokegearMap_CheckRegion: ; 90fb4 (24:4fb4)
+ ld a, [wPokegearMapPlayerIconLandmark]
+ cp FAST_SHIP
+ jr z, .johto
+ cp KANTO_LANDMARK
+ jr nc, .kanto
+.johto
+ ld a, POKEGEARSTATE_JOHTOMAPINIT
+ jr .done
+ ret
+
+.kanto
+ ld a, POKEGEARSTATE_KANTOMAPINIT
+.done
+ ld [wJumptableIndex], a
+ call ExitPokegearRadio_HandleMusic
+ ret
+
+PokegearMap_Init: ; 90fcd (24:4fcd)
+ call InitPokegearTilemap
+ ld a, [wPokegearMapPlayerIconLandmark]
+ call PokegearMap_InitPlayerIcon
+ ld a, [wPokegearMapCursorLandmark]
+ call PokegearMap_InitCursor
+ ld a, c
+ ld [wPokegearMapCursorObjectPointer], a
+ ld a, b
+ ld [wPokegearMapCursorObjectPointer + 1], a
+ ld hl, wJumptableIndex
+ inc [hl]
+ ret
+
+PokegearMap_KantoMap: ; 90fe9 (24:4fe9)
+ call TownMap_GetKantoLandmarkLimits
+ jr PokegearMap_ContinueMap
+
+PokegearMap_JohtoMap: ; 90fee (24:4fee)
+ ld d, SILVER_CAVE
+ ld e, NEW_BARK_TOWN
+PokegearMap_ContinueMap: ; 90ff2 (24:4ff2)
+ ld hl, hJoyLast
+ ld a, [hl]
+ and B_BUTTON
+ jr nz, .cancel
+ ld a, [hl]
+ and D_RIGHT
+ jr nz, .right
+ ld a, [hl]
+ and D_LEFT
+ jr nz, .left
+ call .DPad
+ ret
+
+.right
+ ld a, [wPokegearFlags]
+ bit POKEGEAR_PHONE_CARD_F, a
+ jr z, .no_phone
+ ld c, POKEGEARSTATE_PHONEINIT
+ ld b, POKEGEARCARD_PHONE
+ jr .done
+
+.no_phone
+ ld a, [wPokegearFlags]
+ bit POKEGEAR_RADIO_CARD_F, a
+ ret z
+ ld c, POKEGEARSTATE_RADIOINIT
+ ld b, POKEGEARCARD_RADIO
+ jr .done
+
+.left
+ ld c, POKEGEARSTATE_CLOCKINIT
+ ld b, POKEGEARCARD_CLOCK
+.done
+ call Pokegear_SwitchPage
+ ret
+
+.cancel
+ ld hl, wJumptableIndex
+ set 7, [hl]
+ ret
+
+.DPad: ; 9102f (24:502f)
+ ld hl, hJoyLast
+ ld a, [hl]
+ and D_UP
+ jr nz, .up
+ ld a, [hl]
+ and D_DOWN
+ jr nz, .down
+ ret
+
+.up
+ ld hl, wPokegearMapCursorLandmark
+ ld a, [hl]
+ cp d
+ jr c, .wrap_around_up
+ ld a, e
+ dec a
+ ld [hl], a
+.wrap_around_up
+ inc [hl]
+ jr .done_dpad
+
+.down
+ ld hl, wPokegearMapCursorLandmark
+ ld a, [hl]
+ cp e
+ jr nz, .wrap_around_down
+ ld a, d
+ inc a
+ ld [hl], a
+.wrap_around_down
+ dec [hl]
+.done_dpad
+ ld a, [wPokegearMapCursorLandmark]
+ call PokegearMap_UpdateLandmarkName
+ ld a, [wPokegearMapCursorObjectPointer]
+ ld c, a
+ ld a, [wPokegearMapCursorObjectPointer + 1]
+ ld b, a
+ ld a, [wPokegearMapCursorLandmark]
+ call PokegearMap_UpdateCursorPosition
+ ret
+
+PokegearMap_InitPlayerIcon: ; 9106a
+ push af
+ depixel 0, 0
+ ld b, SPRITE_ANIM_INDEX_RED_WALK
+ ld a, [wPlayerGender]
+ bit PLAYERGENDER_FEMALE_F, a
+ jr z, .got_gender
+ ld b, SPRITE_ANIM_INDEX_BLUE_WALK
+.got_gender
+ ld a, b
+ call _InitSpriteAnimStruct
+ ld hl, SPRITEANIMSTRUCT_TILE_ID
+ add hl, bc
+ ld [hl], $10
+ pop af
+ ld e, a
+ push bc
+ farcall GetLandmarkCoords
+ pop bc
+ ld hl, SPRITEANIMSTRUCT_XCOORD
+ add hl, bc
+ ld [hl], e
+ ld hl, SPRITEANIMSTRUCT_YCOORD
+ add hl, bc
+ ld [hl], d
+ ret
+
+; 91098
+
+PokegearMap_InitCursor: ; 91098
+ push af
+ depixel 0, 0
+ ld a, SPRITE_ANIM_INDEX_POKEGEAR_ARROW
+ call _InitSpriteAnimStruct
+ ld hl, SPRITEANIMSTRUCT_TILE_ID
+ add hl, bc
+ ld [hl], $04
+ ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
+ add hl, bc
+ ld [hl], SPRITE_ANIM_SEQ_NULL
+ pop af
+ push bc
+ call PokegearMap_UpdateCursorPosition
+ pop bc
+ ret
+
+; 910b4
+
+PokegearMap_UpdateLandmarkName: ; 910b4
+ push af
+ hlcoord 8, 0
+ lb bc, 2, 12
+ call ClearBox
+ pop af
+ ld e, a
+ push de
+ farcall GetLandmarkName
+ pop de
+ farcall TownMap_ConvertLineBreakCharacters
+ hlcoord 8, 0
+ ld [hl], $34
+ ret
+
+; 910d4
+
+PokegearMap_UpdateCursorPosition: ; 910d4
+ push bc
+ ld e, a
+ farcall GetLandmarkCoords
+ pop bc
+ ld hl, SPRITEANIMSTRUCT_XCOORD
+ add hl, bc
+ ld [hl], e
+ ld hl, SPRITEANIMSTRUCT_YCOORD
+ add hl, bc
+ ld [hl], d
+ ret
+
+; 910e8
+
+TownMap_GetKantoLandmarkLimits: ; 910e8
+ ld a, [wStatusFlags]
+ bit STATUSFLAGS_HALL_OF_FAME_F, a
+ jr z, .not_hof
+ ld d, ROUTE_28
+ ld e, PALLET_TOWN
+ ret
+
+.not_hof
+ ld d, ROUTE_28
+ ld e, VICTORY_ROAD
+ ret
+
+; 910f9
+
+PokegearRadio_Init: ; 910f9 (24:50f9)
+ call InitPokegearTilemap
+ depixel 4, 10, 4, 4
+ ld a, SPRITE_ANIM_INDEX_RADIO_TUNING_KNOB
+ call _InitSpriteAnimStruct
+ ld hl, SPRITEANIMSTRUCT_TILE_ID
+ add hl, bc
+ ld [hl], $08
+ call _UpdateRadioStation
+ ld hl, wJumptableIndex
+ inc [hl]
+ ret
+
+PokegearRadio_Joypad: ; 91112 (24:5112)
+ ld hl, hJoyLast
+ ld a, [hl]
+ and B_BUTTON
+ jr nz, .cancel
+ ld a, [hl]
+ and D_LEFT
+ jr nz, .left
+ ld a, [wPokegearRadioChannelAddr]
+ ld l, a
+ ld a, [wPokegearRadioChannelAddr + 1]
+ ld h, a
+ ld a, [wPokegearRadioChannelBank]
+ and a
+ ret z
+ rst FarCall
+ ret
+
+.left
+ ld a, [wPokegearFlags]
+ bit POKEGEAR_PHONE_CARD_F, a
+ jr z, .no_phone
+ ld c, POKEGEARSTATE_PHONEINIT
+ ld b, POKEGEARCARD_PHONE
+ jr .switch_page
+
+.no_phone
+ ld a, [wPokegearFlags]
+ bit POKEGEAR_MAP_CARD_F, a
+ jr z, .no_map
+ ld c, POKEGEARSTATE_MAPCHECKREGION
+ ld b, POKEGEARCARD_MAP
+ jr .switch_page
+
+.no_map
+ ld c, POKEGEARSTATE_CLOCKINIT
+ ld b, POKEGEARCARD_CLOCK
+.switch_page
+ call Pokegear_SwitchPage
+ ret
+
+.cancel
+ ld hl, wJumptableIndex
+ set 7, [hl]
+ ret
+
+PokegearPhone_Init: ; 91156 (24:5156)
+ ld hl, wJumptableIndex
+ inc [hl]
+ xor a
+ ld [wPokegearPhoneScrollPosition], a
+ ld [wPokegearPhoneCursorPosition], a
+ ld [wPokegearPhoneSelectedPerson], a
+ call InitPokegearTilemap
+ call ExitPokegearRadio_HandleMusic
+ ld hl, PokegearText_WhomToCall
+ call PrintText
+ ret
+
+PokegearPhone_Joypad: ; 91171 (24:5171)
+ ld hl, hJoyPressed
+ ld a, [hl]
+ and B_BUTTON
+ jr nz, .b
+ ld a, [hl]
+ and A_BUTTON
+ jr nz, .a
+ ld hl, hJoyLast
+ ld a, [hl]
+ and D_LEFT
+ jr nz, .left
+ ld a, [hl]
+ and D_RIGHT
+ jr nz, .right
+ call PokegearPhone_GetDPad
+ ret
+
+.left
+ ld a, [wPokegearFlags]
+ bit POKEGEAR_MAP_CARD_F, a
+ jr z, .no_map
+ ld c, POKEGEARSTATE_MAPCHECKREGION
+ ld b, POKEGEARCARD_MAP
+ jr .switch_page
+
+.no_map
+ ld c, POKEGEARSTATE_CLOCKINIT
+ ld b, POKEGEARCARD_CLOCK
+ jr .switch_page
+
+.right
+ ld a, [wPokegearFlags]
+ bit POKEGEAR_RADIO_CARD_F, a
+ ret z
+ ld c, POKEGEARSTATE_RADIOINIT
+ ld b, POKEGEARCARD_RADIO
+.switch_page
+ call Pokegear_SwitchPage
+ ret
+
+.b
+ ld hl, wJumptableIndex
+ set 7, [hl]
+ ret
+
+.a
+ ld hl, wPhoneList
+ ld a, [wPokegearPhoneScrollPosition]
+ ld e, a
+ ld d, 0
+ add hl, de
+ ld a, [wPokegearPhoneCursorPosition]
+ ld e, a
+ ld d, 0
+ add hl, de
+ ld a, [hl]
+ and a
+ ret z
+ ld [wPokegearPhoneSelectedPerson], a
+ hlcoord 1, 4
+ ld a, [wPokegearPhoneCursorPosition]
+ ld bc, 20 * 2
+ call AddNTimes
+ ld [hl], "▷"
+ call PokegearPhoneContactSubmenu
+ jr c, .quit_submenu
+ ld hl, wJumptableIndex
+ inc [hl]
+ ret
+
+.quit_submenu
+ ld a, POKEGEARSTATE_PHONEJOYPAD
+ ld [wJumptableIndex], a
+ ret
+
+PokegearPhone_MakePhoneCall: ; 911eb (24:51eb)
+ call GetMapPhoneService
+ and a
+ jr nz, .no_service
+ ld hl, wOptions
+ res NO_TEXT_SCROLL, [hl]
+ xor a
+ ld [hInMenu], a
+ ld de, SFX_CALL
+ call PlaySFX
+ ld hl, .dotdotdot
+ call PrintText
+ call WaitSFX
+ ld de, SFX_CALL
+ call PlaySFX
+ ld hl, .dotdotdot
+ call PrintText
+ call WaitSFX
+ ld a, [wPokegearPhoneSelectedPerson]
+ ld b, a
+ call Function90199
+ ld c, 10
+ call DelayFrames
+ ld hl, wOptions
+ set NO_TEXT_SCROLL, [hl]
+ ld a, $1
+ ld [hInMenu], a
+ call PokegearPhone_UpdateCursor
+ ld hl, wJumptableIndex
+ inc [hl]
+ ret
+
+.no_service
+ farcall Phone_NoSignal
+ ld hl, .OutOfServiceArea
+ call PrintText
+ ld a, POKEGEARSTATE_PHONEJOYPAD
+ ld [wJumptableIndex], a
+ ld hl, PokegearText_WhomToCall
+ call PrintText
+ ret
+
+; 9124c (24:524c)
+
+.dotdotdot ; 0x9124c
+ ;
+ text_jump UnknownText_0x1c5824
+ db "@"
+
+; 0x91251
+
+.OutOfServiceArea: ; 0x91251
+ ; You're out of the service area.
+ text_jump UnknownText_0x1c5827
+ db "@"
+
+; 0x91256
+
+PokegearPhone_FinishPhoneCall: ; 91256 (24:5256)
+ ld a, [hJoyPressed]
+ and A_BUTTON | B_BUTTON
+ ret z
+ farcall HangUp
+ ld a, POKEGEARSTATE_PHONEJOYPAD
+ ld [wJumptableIndex], a
+ ld hl, PokegearText_WhomToCall
+ call PrintText
+ ret
+
+PokegearPhone_GetDPad: ; 9126d (24:526d)
+ ld hl, hJoyLast
+ ld a, [hl]
+ and D_UP
+ jr nz, .up
+ ld a, [hl]
+ and D_DOWN
+ jr nz, .down
+ ret
+
+.up
+ ld hl, wPokegearPhoneCursorPosition
+ ld a, [hl]
+ and a
+ jr z, .scroll_page_up
+ dec [hl]
+ jr .done_joypad_same_page
+
+.scroll_page_up
+ ld hl, wPokegearPhoneScrollPosition
+ ld a, [hl]
+ and a
+ ret z
+ dec [hl]
+ jr .done_joypad_update_page
+
+.down
+ ld hl, wPokegearPhoneCursorPosition
+ ld a, [hl]
+ cp 3
+ jr nc, .scroll_page_down
+ inc [hl]
+ jr .done_joypad_same_page
+
+.scroll_page_down
+ ld hl, wPokegearPhoneScrollPosition
+ ld a, [hl]
+ cp 6
+ ret nc
+ inc [hl]
+ jr .done_joypad_update_page
+
+.done_joypad_same_page
+ xor a
+ ld [hBGMapMode], a
+ call PokegearPhone_UpdateCursor
+ call WaitBGMap
+ ret
+
+.done_joypad_update_page
+ xor a
+ ld [hBGMapMode], a
+ call PokegearPhone_UpdateDisplayList
+ call WaitBGMap
+ ret
+
+PokegearPhone_UpdateCursor: ; 912b7 (24:52b7)
+ ld a, " "
+ hlcoord 1, 4
+ ld [hl], a
+ hlcoord 1, 6
+ ld [hl], a
+ hlcoord 1, 8
+ ld [hl], a
+ hlcoord 1, 10
+ ld [hl], a
+ hlcoord 1, 4
+ ld a, [wPokegearPhoneCursorPosition]
+ ld bc, 2 * SCREEN_WIDTH
+ call AddNTimes
+ ld [hl], "▶"
+ ret
+
+PokegearPhone_UpdateDisplayList: ; 912d8 (24:52d8)
+ hlcoord 1, 3
+ ld b, 9
+ ld a, " "
+.row
+ ld c, 18
+.col
+ ld [hli], a
+ dec c
+ jr nz, .col
+ inc hl
+ inc hl
+ dec b
+ jr nz, .row
+ ld a, [wPokegearPhoneScrollPosition]
+ ld e, a
+ ld d, $0
+ ld hl, wPhoneList
+ add hl, de
+ xor a
+ ld [wPokegearPhoneLoadNameBuffer], a
+.loop
+ ld a, [hli]
+ push hl
+ push af
+ hlcoord 2, 4
+ ld a, [wPokegearPhoneLoadNameBuffer]
+ ld bc, 2 * SCREEN_WIDTH
+ call AddNTimes
+ ld d, h
+ ld e, l
+ pop af
+ ld b, a
+ call Function90380
+ pop hl
+ ld a, [wPokegearPhoneLoadNameBuffer]
+ inc a
+ ld [wPokegearPhoneLoadNameBuffer], a
+ cp 4
+ jr c, .loop
+ call PokegearPhone_UpdateCursor
+ ret
+
+; 9131e (24:531e)
+
+PokegearPhone_DeletePhoneNumber: ; 9131e
+ ld hl, wPhoneList
+ ld a, [wPokegearPhoneScrollPosition]
+ ld e, a
+ ld d, 0
+ add hl, de
+ ld a, [wPokegearPhoneCursorPosition]
+ ld e, a
+ ld d, 0
+ add hl, de
+ ld [hl], 0
+ ld hl, wPhoneList
+ ld c, CONTACT_LIST_SIZE
+.loop
+ ld a, [hli]
+ and a
+ jr nz, .skip
+ ld a, [hld]
+ ld [hli], a
+ ld [hl], 0
+.skip
+ dec c
+ jr nz, .loop
+ ret
+
+; 91342
+
+PokegearPhoneContactSubmenu: ; 91342 (24:5342)
+ ld hl, wPhoneList
+ ld a, [wPokegearPhoneScrollPosition]
+ ld e, a
+ ld d, 0
+ add hl, de
+ ld a, [wPokegearPhoneCursorPosition]
+ ld e, a
+ ld d, 0
+ add hl, de
+ ld c, [hl]
+ farcall CheckCanDeletePhoneNumber
+ ld a, c
+ and a
+ jr z, .cant_delete
+ ld hl, .CallDeleteCancelJumptable
+ ld de, .CallDeleteCancelStrings
+ jr .got_menu_data
+
+.cant_delete
+ ld hl, .CallCancelJumptable
+ ld de, .CallCancelStrings
+.got_menu_data
+ xor a
+ ld [hBGMapMode], a
+ push hl
+ push de
+ ld a, [de]
+ ld l, a
+ inc de
+ ld a, [de]
+ ld h, a
+ inc de
+ push hl
+ ld bc, hBGMapAddress + 1
+ add hl, bc
+ ld a, [de]
+ inc de
+ sla a
+ ld b, a
+ ld c, 8
+ push de
+ call TextBox
+ pop de
+ pop hl
+ inc hl
+ call PlaceString
+ pop de
+ xor a
+ ld [wPokegearPhoneSubmenuCursor], a
+ call .UpdateCursor
+ call WaitBGMap
+.loop
+ push de
+ call JoyTextDelay
+ pop de
+ ld hl, hJoyPressed
+ ld a, [hl]
+ and D_UP
+ jr nz, .d_up
+ ld a, [hl]
+ and D_DOWN
+ jr nz, .d_down
+ ld a, [hl]
+ and A_BUTTON | B_BUTTON
+ jr nz, .a_b
+ call DelayFrame
+ jr .loop
+
+.d_up
+ ld hl, wPokegearPhoneSubmenuCursor
+ ld a, [hl]
+ and a
+ jr z, .loop
+ dec [hl]
+ call .UpdateCursor
+ jr .loop
+
+.d_down
+ ld hl, 2
+ add hl, de
+ ld a, [wPokegearPhoneSubmenuCursor]
+ inc a
+ cp [hl]
+ jr nc, .loop
+ ld [wPokegearPhoneSubmenuCursor], a
+ call .UpdateCursor
+ jr .loop
+
+.a_b
+ xor a
+ ld [hBGMapMode], a
+ call PokegearPhone_UpdateDisplayList
+ ld a, $1
+ ld [hBGMapMode], a
+ pop hl
+ ld a, [hJoyPressed]
+ and B_BUTTON
+ jr nz, .Cancel
+ ld a, [wPokegearPhoneSubmenuCursor]
+ ld e, a
+ ld d, 0
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp hl
+
+.Cancel: ; 913f1
+ ld hl, PokegearText_WhomToCall
+ call PrintText
+ scf
+ ret
+
+; 913f9 (24:53f9)
+
+.Delete: ; 913f9
+ ld hl, PokegearText_DeleteStoredNumber
+ call MenuTextBox
+ call YesNoBox
+ call ExitMenu
+ jr c, .CancelDelete
+ call PokegearPhone_DeletePhoneNumber
+ xor a
+ ld [hBGMapMode], a
+ call PokegearPhone_UpdateDisplayList
+ ld hl, PokegearText_WhomToCall
+ call PrintText
+ call WaitBGMap
+.CancelDelete:
+ scf
+ ret
+
+; 9141b
+
+.Call: ; 9141b
+ and a
+ ret
+
+; 9141d
+
+.UpdateCursor: ; 9141d (24:541d)
+ push de
+ ld a, [de]
+ inc de
+ ld l, a
+ ld a, [de]
+ inc de
+ ld h, a
+ ld a, [de]
+ ld c, a
+ push hl
+ ld a, " "
+ ld de, SCREEN_WIDTH * 2
+.clear_column
+ ld [hl], a
+ add hl, de
+ dec c
+ jr nz, .clear_column
+ pop hl
+ ld a, [wPokegearPhoneSubmenuCursor]
+ ld bc, SCREEN_WIDTH * 2
+ call AddNTimes
+ ld [hl], "▶"
+ pop de
+ ret
+
+; 9143f (24:543f)
+
+.CallDeleteCancelStrings: ; 9143f
+ dwcoord 10, 6
+ db 3
+ db "CALL"
+ next "DELETE"
+ next "CANCEL"
+ db "@"
+; 91455
+
+.CallDeleteCancelJumptable: ; 91455
+ dw .Call
+ dw .Delete
+ dw .Cancel
+
+; 9145b
+
+.CallCancelStrings: ; 9145b
+ dwcoord 10, 8
+ db 2
+ db "CALL"
+ next "CANCEL"
+ db "@"
+; 9146a
+
+.CallCancelJumptable: ; 9146a
+ dw .Call
+ dw .Cancel
+
+; 9146e
+
+; unused
+ ld a, [hHours]
+ cp 12
+ jr c, .am
+ sub 12
+ ld [wd265], a
+ scf
+ ret
+
+.am
+ ld [wd265], a
+ and a
+ ret
+
+; 91480
+
+Pokegear_SwitchPage: ; 91480 (24:5480)
+ ld de, SFX_READ_TEXT_2
+ call PlaySFX
+ ld a, c
+ ld [wJumptableIndex], a
+ ld a, b
+ ld [wPokegearCard], a
+ call DeleteSpriteAnimStruct2ToEnd
+ ret
+
+ExitPokegearRadio_HandleMusic: ; 91492
+ ld a, [wPokegearRadioMusicPlaying]
+ cp RESTART_MAP_MUSIC
+ jr z, .restart_map_music
+ cp ENTER_MAP_MUSIC
+ call z, EnterMapMusic
+ xor a
+ ld [wPokegearRadioMusicPlaying], a
+ ret
+
+.restart_map_music
+ call RestartMapMusic
+ xor a
+ ld [wPokegearRadioMusicPlaying], a
+ ret
+
+; 914ab
+
+DeleteSpriteAnimStruct2ToEnd: ; 914ab (24:54ab)
+ ld hl, wSpriteAnim2
+ ld bc, wSpriteAnimationStructsEnd - wSpriteAnim2
+ xor a
+ call ByteFill
+ ld a, 2
+ ld [wSpriteAnimCount], a
+ ret
+
+Pokegear_LoadTilemapRLE: ; 914bb (24:54bb)
+ ; Format: repeat count, tile ID
+ ; Terminated with -1
+ hlcoord 0, 0
+.loop
+ ld a, [de]
+ cp -1
+ ret z
+ ld b, a
+ inc de
+ ld a, [de]
+ ld c, a
+ inc de
+ ld a, b
+.load
+ ld [hli], a
+ dec c
+ jr nz, .load
+ jr .loop
+
+; 914ce (24:54ce)
+
+PokegearText_WhomToCall: ; 0x914ce
+ ; Whom do you want to call?
+ text_jump UnknownText_0x1c5847
+ db "@"
+
+; 0x914d3
+
+PokegearText_PressAnyButtonToExit: ; 0x914d3
+ ; Press any button to exit.
+ text_jump UnknownText_0x1c5862
+ db "@"
+
+; 0x914d8
+
+PokegearText_DeleteStoredNumber: ; 0x914d8
+ ; Delete this stored phone number?
+ text_jump UnknownText_0x1c587d
+ db "@"
+
+; 0x914dd
+
+PokegearSpritesGFX: ; 914dd
+INCBIN "gfx/pokegear/pokegear_sprites.2bpp.lz"
+; 9150d
+
+RadioTilemapRLE: ; 9150d
+INCBIN "gfx/pokegear/radio.tilemap.rle"
+PhoneTilemapRLE: ; 9158a
+INCBIN "gfx/pokegear/phone.tilemap.rle"
+ClockTilemapRLE: ; 915db
+INCBIN "gfx/pokegear/clock.tilemap.rle"
+; 9163e
+
+_UpdateRadioStation: ; 9163e (24:563e)
+ jr UpdateRadioStation
+
+; called from engine/sprite_anims.asm
+
+AnimateTuningKnob: ; 91640 (24:5640)
+ push bc
+ call .TuningKnob
+ pop bc
+ ld a, [wRadioTuningKnob]
+ ld hl, SPRITEANIMSTRUCT_XOFFSET
+ add hl, bc
+ ld [hl], a
+ ret
+
+.TuningKnob: ; 9164e (24:564e)
+ ld hl, hJoyLast
+ ld a, [hl]
+ and D_DOWN
+ jr nz, .down
+ ld a, [hl]
+ and D_UP
+ jr nz, .up
+ ret
+
+.down
+ ld hl, wRadioTuningKnob
+ ld a, [hl]
+ and a
+ ret z
+ dec [hl]
+ dec [hl]
+ jr .update
+
+.up
+ ld hl, wRadioTuningKnob
+ ld a, [hl]
+ cp 80
+ ret nc
+ inc [hl]
+ inc [hl]
+.update
+UpdateRadioStation: ; 9166f (24:566f)
+ ld hl, wRadioTuningKnob
+ ld d, [hl]
+ ld hl, RadioChannels
+.loop
+ ld a, [hli]
+ cp -1
+ jr z, .nostation
+ cp d
+ jr z, .foundstation
+ inc hl
+ inc hl
+ jr .loop
+
+.nostation
+ call NoRadioStation
+ ret
+
+.foundstation
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld de, .returnafterstation
+ push de
+ jp hl
+
+.returnafterstation
+ ld a, [wPokegearRadioChannelBank]
+ and a
+ ret z
+ xor a
+ ld [hBGMapMode], a
+ hlcoord 2, 9
+ call PlaceString
+ ld a, $1
+ ld [hBGMapMode], a
+ ret
+
+; 916a1 (24:56a1)
+
+; unused
+ ld [wPokegearRadioChannelBank], a
+ ld a, [hli]
+ ld [wPokegearRadioChannelAddr], a
+ ld a, [hli]
+ ld [wPokegearRadioChannelAddr + 1], a
+ ret
+
+; 916ad
+
+RadioChannels:
+; entries correspond to constants/radio_constants.asm
+
+; frequency value given here = 4 × ingame_frequency − 2
+ dbw 16, .PKMNTalkAndPokedexShow
+ dbw 28, .PokemonMusic
+ dbw 32, .LuckyChannel
+ dbw 40, .BuenasPassword
+ dbw 52, .RuinsOfAlphRadio
+ dbw 64, .PlacesAndPeople
+ dbw 72, .LetsAllSing
+ dbw 78, .PokeFluteRadio
+ dbw 80, .EvolutionRadio
+ db -1
+
+.PKMNTalkAndPokedexShow:
+; Pokédex Show in the morning
+
+; Oak's Pokémon Talk in the afternoon and evening
+ call .InJohto
+ jr nc, .NoSignal
+ ld a, [wTimeOfDay]
+ and a
+ jp z, LoadStation_PokedexShow
+ jp LoadStation_OaksPokemonTalk
+
+.PokemonMusic:
+ call .InJohto
+ jr nc, .NoSignal
+ jp LoadStation_PokemonMusic
+
+.LuckyChannel:
+ call .InJohto
+ jr nc, .NoSignal
+ jp LoadStation_LuckyChannel
+
+.BuenasPassword:
+ call .InJohto
+ jr nc, .NoSignal
+ jp LoadStation_BuenasPassword
+
+.RuinsOfAlphRadio:
+ ld a, [wPokegearMapPlayerIconLandmark]
+ cp RUINS_OF_ALPH
+ jr nz, .NoSignal
+ jp LoadStation_UnownRadio
+
+.PlacesAndPeople:
+ call .InJohto
+ jr c, .NoSignal
+ ld a, [wPokegearFlags]
+ bit POKEGEAR_EXPN_CARD_F, a
+ jr z, .NoSignal
+ jp LoadStation_PlacesAndPeople
+
+.LetsAllSing:
+ call .InJohto
+ jr c, .NoSignal
+ ld a, [wPokegearFlags]
+ bit POKEGEAR_EXPN_CARD_F, a
+ jr z, .NoSignal
+ jp LoadStation_LetsAllSing
+
+.PokeFluteRadio:
+ call .InJohto
+ jr c, .NoSignal
+ ld a, [wPokegearFlags]
+ bit POKEGEAR_EXPN_CARD_F, a
+ jr z, .NoSignal
+ jp LoadStation_PokeFluteRadio
+
+.EvolutionRadio:
+; This station airs in the Lake of Rage area when Rocket are still in Mahogany.
+ ld a, [wStatusFlags]
+ bit STATUSFLAGS_ROCKET_SIGNAL_F, a
+ jr z, .NoSignal
+ ld a, [wPokegearMapPlayerIconLandmark]
+ cp MAHOGANY_TOWN
+ jr z, .ok
+ cp ROUTE_43
+ jr z, .ok
+ cp LAKE_OF_RAGE
+ jr nz, .NoSignal
+.ok
+ jp LoadStation_EvolutionRadio
+
+.NoSignal:
+ call NoRadioStation
+ ret
+
+.InJohto:
+; if in Johto or on the S.S. Aqua, set carry
+
+; otherwise clear carry
+ ld a, [wPokegearMapPlayerIconLandmark]
+ cp FAST_SHIP
+ jr z, .johto
+ cp KANTO_LANDMARK
+ jr c, .johto
+.kanto
+ and a
+ ret
+
+.johto
+ scf
+ ret
+
+LoadStation_OaksPokemonTalk: ; 91753 (24:5753)
+ xor a ; OAKS_POKEMON_TALK
+ ld [wCurrentRadioLine], a
+ ld [wNumRadioLinesPrinted], a
+ ld a, BANK(PlayRadioShow)
+ ld hl, PlayRadioShow
+ call Radio_BackUpFarCallParams
+ ld de, OaksPKMNTalkName
+ ret
+
+LoadStation_PokedexShow: ; 91766 (24:5766)
+ ld a, POKEDEX_SHOW
+ ld [wCurrentRadioLine], a
+ xor a
+ ld [wNumRadioLinesPrinted], a
+ ld a, BANK(PlayRadioShow)
+ ld hl, PlayRadioShow
+ call Radio_BackUpFarCallParams
+ ld de, PokedexShowName
+ ret
+
+LoadStation_PokemonMusic: ; 9177b (24:577b)
+ ld a, POKEMON_MUSIC
+ ld [wCurrentRadioLine], a
+ xor a
+ ld [wNumRadioLinesPrinted], a
+ ld a, BANK(PlayRadioShow)
+ ld hl, PlayRadioShow
+ call Radio_BackUpFarCallParams
+ ld de, PokemonMusicName
+ ret
+
+LoadStation_LuckyChannel: ; 91790 (24:5790)
+ ld a, LUCKY_CHANNEL
+ ld [wCurrentRadioLine], a
+ xor a
+ ld [wNumRadioLinesPrinted], a
+ ld a, BANK(PlayRadioShow)
+ ld hl, PlayRadioShow
+ call Radio_BackUpFarCallParams
+ ld de, LuckyChannelName
+ ret
+
+LoadStation_BuenasPassword: ; 917a5 (24:57a5)
+ ld a, BUENAS_PASSWORD
+ ld [wCurrentRadioLine], a
+ xor a
+ ld [wNumRadioLinesPrinted], a
+ ld a, BANK(PlayRadioShow)
+ ld hl, PlayRadioShow
+ call Radio_BackUpFarCallParams
+ ld de, NotBuenasPasswordName
+ ld a, [wStatusFlags2]
+ bit STATUSFLAGS2_ROCKETS_IN_RADIO_TOWER_F, a
+ ret z
+ ld de, BuenasPasswordName
+ ret
+
+; 917c3 (24:57c3)
+
+BuenasPasswordName: db "BUENA'S PASSWORD@"
+NotBuenasPasswordName: db "@"
+
+LoadStation_UnownRadio: ; 917d5 (24:57d5)
+ ld a, UNOWN_RADIO
+ ld [wCurrentRadioLine], a
+ xor a
+ ld [wNumRadioLinesPrinted], a
+ ld a, BANK(PlayRadioShow)
+ ld hl, PlayRadioShow
+ call Radio_BackUpFarCallParams
+ ld de, UnownStationName
+ ret
+
+LoadStation_PlacesAndPeople: ; 917ea (24:57ea)
+ ld a, PLACES_AND_PEOPLE
+ ld [wCurrentRadioLine], a
+ xor a
+ ld [wNumRadioLinesPrinted], a
+ ld a, BANK(PlayRadioShow)
+ ld hl, PlayRadioShow
+ call Radio_BackUpFarCallParams
+ ld de, PlacesAndPeopleName
+ ret
+
+LoadStation_LetsAllSing: ; 917ff (24:57ff)
+ ld a, LETS_ALL_SING
+ ld [wCurrentRadioLine], a
+ xor a
+ ld [wNumRadioLinesPrinted], a
+ ld a, BANK(PlayRadioShow)
+ ld hl, PlayRadioShow
+ call Radio_BackUpFarCallParams
+ ld de, LetsAllSingName
+ ret
+
+; 91814 (24:5814)
+
+LoadStation_RocketRadio: ; 91814
+ ld a, ROCKET_RADIO
+ ld [wCurrentRadioLine], a
+ xor a
+ ld [wNumRadioLinesPrinted], a
+ ld a, BANK(PlayRadioShow)
+ ld hl, PlayRadioShow
+ call Radio_BackUpFarCallParams
+ ld de, LetsAllSingName
+ ret
+
+; 91829
+
+LoadStation_PokeFluteRadio: ; 91829 (24:5829)
+ ld a, POKE_FLUTE_RADIO
+ ld [wCurrentRadioLine], a
+ xor a
+ ld [wNumRadioLinesPrinted], a
+ ld a, BANK(PlayRadioShow)
+ ld hl, PlayRadioShow
+ call Radio_BackUpFarCallParams
+ ld de, PokeFluteStationName
+ ret
+
+LoadStation_EvolutionRadio: ; 9183e (24:583e)
+ ld a, EVOLUTION_RADIO
+ ld [wCurrentRadioLine], a
+ xor a
+ ld [wNumRadioLinesPrinted], a
+ ld a, BANK(PlayRadioShow)
+ ld hl, PlayRadioShow
+ call Radio_BackUpFarCallParams
+ ld de, UnownStationName
+ ret
+
+; 91853 (24:5853)
+
+Unreferenced_LoadStation: ; 91853
+ ret
+
+RadioMusicRestartDE: ; 91854 (24:5854)
+ push de
+ ld a, e
+ ld [wPokegearRadioMusicPlaying], a
+ ld de, MUSIC_NONE
+ call PlayMusic
+ pop de
+ ld a, e
+ ld [wMapMusic], a
+ call PlayMusic
+ ret
+
+RadioMusicRestartPokemonChannel: ; 91868 (24:5868)
+ push de
+ ld a, RESTART_MAP_MUSIC
+ ld [wPokegearRadioMusicPlaying], a
+ ld de, MUSIC_NONE
+ call PlayMusic
+ pop de
+ ld de, MUSIC_POKEMON_CHANNEL
+ call PlayMusic
+ ret
+
+Radio_BackUpFarCallParams: ; 9187c (24:587c)
+ ld [wPokegearRadioChannelBank], a
+ ld a, l
+ ld [wPokegearRadioChannelAddr], a
+ ld a, h
+ ld [wPokegearRadioChannelAddr + 1], a
+ ret
+
+NoRadioStation: ; 91888 (24:5888)
+ call NoRadioMusic
+ call NoRadioName
+ xor a
+ ld [wPokegearRadioChannelBank], a
+ ld [wPokegearRadioChannelAddr], a
+ ld [wPokegearRadioChannelAddr + 1], a
+ ld a, $1
+ ld [hBGMapMode], a
+ ret
+
+NoRadioMusic: ; 9189d (24:589d)
+ ld de, MUSIC_NONE
+ call PlayMusic
+ ld a, ENTER_MAP_MUSIC
+ ld [wPokegearRadioMusicPlaying], a
+ ret
+
+NoRadioName: ; 918a9 (24:58a9)
+ xor a
+ ld [hBGMapMode], a
+ hlcoord 1, 8
+ lb bc, 3, 18
+ call ClearBox
+ hlcoord 0, 12
+ lb bc, 4, 18
+ call TextBox
+ ret
+
+; 918bf
+
+OaksPKMNTalkName: db "OAK's <PK><MN> Talk@"
+PokedexShowName: db "#DEX Show@"
+PokemonMusicName: db "#MON Music@"
+LuckyChannelName: db "Lucky Channel@"
+UnownStationName: db "?????@"
+
+PlacesAndPeopleName: db "Places & People@"
+LetsAllSingName: db "Let's All Sing!@"
+PokeFluteStationName: db "# FLUTE@"
+; 9191c
+
+_TownMap: ; 9191c
+ ld hl, wOptions
+ ld a, [hl]
+ push af
+ set NO_TEXT_SCROLL, [hl]
+
+ ld a, [hInMenu]
+ push af
+ ld a, $1
+ ld [hInMenu], a
+
+ ld a, [wVramState]
+ push af
+ xor a
+ ld [wVramState], a
+
+ call ClearBGPalettes
+ call ClearTileMap
+ call ClearSprites
+ call DisableLCD
+ call Pokegear_LoadGFX
+ farcall ClearSpriteAnims
+ ld a, 8
+ call SkipMusic
+ ld a, LCDC_DEFAULT
+ ld [rLCDC], a
+ call TownMap_GetCurrentLandmark
+ ld [wTownMapPlayerIconLandmark], a
+ ld [wTownMapCursorLandmark], a
+ xor a
+ ld [hBGMapMode], a
+ call .InitTilemap
+ call WaitBGMap2
+ ld a, [wTownMapPlayerIconLandmark]
+ call PokegearMap_InitPlayerIcon
+ ld a, [wTownMapCursorLandmark]
+ call PokegearMap_InitCursor
+ ld a, c
+ ld [wTownMapCursorObjectPointer], a
+ ld a, b
+ ld [wTownMapCursorObjectPointer + 1], a
+ ld b, SCGB_POKEGEAR_PALS
+ call GetSGBLayout
+ call SetPalettes
+ ld a, [hCGB]
+ and a
+ jr z, .dmg
+ ld a, %11100100
+ call DmgToCgbObjPal0
+ call DelayFrame
+
+.dmg
+ ld a, [wTownMapPlayerIconLandmark]
+ cp KANTO_LANDMARK
+ jr nc, .kanto
+ ld d, KANTO_LANDMARK - 1
+ ld e, 1
+ call .loop
+ jr .resume
+
+.kanto
+ call TownMap_GetKantoLandmarkLimits
+ call .loop
+
+.resume
+ pop af
+ ld [wVramState], a
+ pop af
+ ld [hInMenu], a
+ pop af
+ ld [wOptions], a
+ call ClearBGPalettes
+ ret
+
+.loop
+ call JoyTextDelay
+ ld hl, hJoyPressed
+ ld a, [hl]
+ and B_BUTTON
+ ret nz
+
+ ld hl, hJoyLast
+ ld a, [hl]
+ and D_UP
+ jr nz, .pressed_up
+
+ ld a, [hl]
+ and D_DOWN
+ jr nz, .pressed_down
+.loop2
+ push de
+ farcall PlaySpriteAnimations
+ pop de
+ call DelayFrame
+ jr .loop
+
+.pressed_up
+ ld hl, wTownMapCursorLandmark
+ ld a, [hl]
+ cp d
+ jr c, .okay
+ ld a, e
+ dec a
+ ld [hl], a
+
+.okay
+ inc [hl]
+ jr .next
+
+.pressed_down
+ ld hl, wTownMapCursorLandmark
+ ld a, [hl]
+ cp e
+ jr nz, .okay2
+ ld a, d
+ inc a
+ ld [hl], a
+
+.okay2
+ dec [hl]
+
+.next
+ push de
+ ld a, [wTownMapCursorLandmark]
+ call PokegearMap_UpdateLandmarkName
+ ld a, [wTownMapCursorObjectPointer]
+ ld c, a
+ ld a, [wTownMapCursorObjectPointer + 1]
+ ld b, a
+ ld a, [wTownMapCursorLandmark]
+ call PokegearMap_UpdateCursorPosition
+ pop de
+ jr .loop2
+; 91a04
+
+.InitTilemap: ; 91a04
+ ld a, [wTownMapPlayerIconLandmark]
+ cp KANTO_LANDMARK
+ jr nc, .kanto2
+ ld e, JOHTO_REGION
+ jr .okay_tilemap
+
+.kanto2
+ ld e, KANTO_REGION
+.okay_tilemap
+ farcall PokegearMap
+ ld a, $07
+ ld bc, 6
+ hlcoord 1, 0
+ call ByteFill
+ hlcoord 0, 0
+ ld [hl], $06
+ hlcoord 7, 0
+ ld [hl], $17
+ hlcoord 7, 1
+ ld [hl], $16
+ hlcoord 7, 2
+ ld [hl], $26
+ ld a, $07
+ ld bc, NAME_LENGTH
+ hlcoord 8, 2
+ call ByteFill
+ hlcoord 19, 2
+ ld [hl], $17
+ ld a, [wTownMapCursorLandmark]
+ call PokegearMap_UpdateLandmarkName
+ farcall TownMapPals
+ ret
+; 91a53
+
+PlayRadio: ; 91a53
+ ld hl, wOptions
+ ld a, [hl]
+ push af
+ set NO_TEXT_SCROLL, [hl]
+ call .PlayStation
+ ld c, 100
+ call DelayFrames
+.loop
+ call JoyTextDelay
+ ld a, [hJoyPressed]
+ and A_BUTTON | B_BUTTON
+ jr nz, .stop
+ ld a, [wPokegearRadioChannelAddr]
+ ld l, a
+ ld a, [wPokegearRadioChannelAddr + 1]
+ ld h, a
+ ld a, [wPokegearRadioChannelBank]
+ and a
+ jr z, .zero
+ rst FarCall
+.zero
+ call DelayFrame
+ jr .loop
+
+.stop
+ pop af
+ ld [wOptions], a
+ call ExitPokegearRadio_HandleMusic
+ ret
+
+; 91a87
+
+.PlayStation: ; 91a87
+ ld a, ENTER_MAP_MUSIC
+ ld [wPokegearRadioMusicPlaying], a
+ ld hl, .StationPointers
+ ld d, 0
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld de, .jump_return
+ push de
+ jp hl
+
+.jump_return
+ push de
+ hlcoord 0, 12
+ lb bc, 4, 18
+ call TextBox
+ hlcoord 1, 14
+ ld [hl], $72
+ pop de
+ hlcoord 2, 14
+ call PlaceString
+ ld h, b
+ ld l, c
+ ld [hl], $73
+ call WaitBGMap
+ ret
+
+; 91ab9
+
+.StationPointers: ; 91ab9
+; entries correspond to MAPRADIO_* constants
+ dw .OakOrPnP
+ dw LoadStation_OaksPokemonTalk
+ dw LoadStation_PokedexShow
+ dw LoadStation_PokemonMusic
+ dw LoadStation_LuckyChannel
+ dw LoadStation_UnownRadio
+ dw LoadStation_PlacesAndPeople
+ dw LoadStation_LetsAllSing
+ dw LoadStation_RocketRadio
+
+; 91acb
+
+.OakOrPnP: ; 91acb
+ call IsInJohto
+ and a
+ jr nz, .kanto
+ call UpdateTime
+ ld a, [wTimeOfDay]
+ and a
+ jp z, LoadStation_PokedexShow
+ jp LoadStation_OaksPokemonTalk
+
+.kanto
+ jp LoadStation_PlacesAndPeople
+
+; 91ae1
+
+PokegearMap: ; 91ae1
+ ld a, e
+ and a
+ jr nz, .kanto
+ call LoadTownMapGFX
+ call FillJohtoMap
+ ret
+
+.kanto
+ call LoadTownMapGFX
+ call FillKantoMap
+ ret
+
+; 91af3
+
+_FlyMap: ; 91af3
+ call ClearBGPalettes
+ call ClearTileMap
+ call ClearSprites
+ ld hl, hInMenu
+ ld a, [hl]
+ push af
+ ld [hl], $1
+ xor a
+ ld [hBGMapMode], a
+ farcall ClearSpriteAnims
+ call LoadTownMapGFX
+ ld de, FlyMapLabelBorderGFX
+ ld hl, vTiles2 tile $30
+ lb bc, BANK(FlyMapLabelBorderGFX), 6
+ call Request1bpp
+ call FlyMap
+ call ret_91c8f
+ ld b, SCGB_POKEGEAR_PALS
+ call GetSGBLayout
+ call SetPalettes
+.loop
+ call JoyTextDelay
+ ld hl, hJoyPressed
+ ld a, [hl]
+ and B_BUTTON
+ jr nz, .pressedB
+ ld a, [hl]
+ and A_BUTTON
+ jr nz, .pressedA
+ call FlyMapScroll
+ call GetMapCursorCoordinates
+ farcall PlaySpriteAnimations
+ call DelayFrame
+ jr .loop
+
+.pressedB
+ ld a, -1
+ jr .exit
+
+.pressedA
+ ld a, [wTownMapPlayerIconLandmark]
+ ld l, a
+ ld h, 0
+ add hl, hl
+ ld de, Flypoints + 1
+ add hl, de
+ ld a, [hl]
+.exit
+ ld [wTownMapPlayerIconLandmark], a
+ pop af
+ ld [hInMenu], a
+ call ClearBGPalettes
+ ld a, $90
+ ld [hWY], a
+ xor a ; LOW(vBGMap0)
+ ld [hBGMapAddress], a
+ ld a, HIGH(vBGMap0)
+ ld [hBGMapAddress + 1], a
+ ld a, [wTownMapPlayerIconLandmark]
+ ld e, a
+ ret
+
+; 91b73
+
+FlyMapScroll: ; 91b73
+ ld a, [wStartFlypoint]
+ ld e, a
+ ld a, [wEndFlypoint]
+ ld d, a
+ ld hl, hJoyLast
+ ld a, [hl]
+ and D_UP
+ jr nz, .ScrollNext
+ ld a, [hl]
+ and D_DOWN
+ jr nz, .ScrollPrev
+ ret
+
+.ScrollNext:
+ ld hl, wTownMapPlayerIconLandmark
+ ld a, [hl]
+ cp d
+ jr nz, .NotAtEndYet
+ ld a, e
+ dec a
+ ld [hl], a
+.NotAtEndYet:
+ inc [hl]
+ call CheckIfVisitedFlypoint
+ jr z, .ScrollNext
+ jr .Finally
+
+.ScrollPrev:
+ ld hl, wTownMapPlayerIconLandmark
+ ld a, [hl]
+ cp e
+ jr nz, .NotAtStartYet
+ ld a, d
+ inc a
+ ld [hl], a
+.NotAtStartYet:
+ dec [hl]
+ call CheckIfVisitedFlypoint
+ jr z, .ScrollPrev
+.Finally:
+ call TownMapBubble
+ call WaitBGMap
+ xor a
+ ld [hBGMapMode], a
+ ret
+
+; 91bb5
+
+TownMapBubble: ; 91bb5
+; Draw the bubble containing the location text in the town map HUD
+
+; Top-left corner
+ hlcoord 1, 0
+ ld a, $30
+ ld [hli], a
+; Top row
+ ld bc, 16
+ ld a, " "
+ call ByteFill
+; Top-right corner
+ ld a, $31
+ ld [hl], a
+ hlcoord 1, 1
+
+; Middle row
+ ld bc, 18
+ ld a, " "
+ call ByteFill
+
+; Bottom-left corner
+ hlcoord 1, 2
+ ld a, $32
+ ld [hli], a
+; Bottom row
+ ld bc, 16
+ ld a, " "
+ call ByteFill
+; Bottom-right corner
+ ld a, $33
+ ld [hl], a
+
+; Print "Where?"
+ hlcoord 2, 0
+ ld de, .Where
+ call PlaceString
+; Print the name of the default flypoint
+ call .Name
+; Up/down arrows
+ hlcoord 18, 1
+ ld [hl], $34
+ ret
+
+.Where:
+ db "Where?@"
+
+.Name:
+; We need the map location of the default flypoint
+ ld a, [wTownMapPlayerIconLandmark]
+ ld l, a
+ ld h, 0
+ add hl, hl ; two bytes per flypoint
+ ld de, Flypoints
+ add hl, de
+ ld e, [hl]
+ farcall GetLandmarkName
+ hlcoord 2, 1
+ ld de, wStringBuffer1
+ call PlaceString
+ ret
+
+; 91c17
+
+GetMapCursorCoordinates: ; 91c17
+ ld a, [wTownMapPlayerIconLandmark]
+ ld l, a
+ ld h, 0
+ add hl, hl
+ ld de, Flypoints
+ add hl, de
+ ld e, [hl]
+ farcall GetLandmarkCoords
+ ld a, [wTownMapCursorCoordinates]
+ ld c, a
+ ld a, [wTownMapCursorCoordinates + 1]
+ ld b, a
+ ld hl, 4
+ add hl, bc
+ ld [hl], e
+ ld hl, 5
+ add hl, bc
+ ld [hl], d
+ ret
+
+; 91c3c
+
+CheckIfVisitedFlypoint: ; 91c3c
+; Check if the flypoint loaded in [hl] has been visited yet.
+ push bc
+ push de
+ push hl
+ ld l, [hl]
+ ld h, 0
+ add hl, hl
+ ld de, Flypoints + 1
+ add hl, de
+ ld c, [hl]
+ call HasVisitedSpawn
+ pop hl
+ pop de
+ pop bc
+ and a
+ ret
+
+; 91c50
+
+HasVisitedSpawn: ; 91c50
+; Check if spawn point c has been visited.
+ ld hl, wVisitedSpawns
+ ld b, CHECK_FLAG
+ ld d, 0
+ predef SmallFarFlagAction
+ ld a, c
+ ret
+
+; 91c5e
+
+INCLUDE "data/maps/flypoints.asm"
+
+ret_91c8f: ; 91c8f
+ ret
+
+; 91c90
+
+FlyMap: ; 91c90
+ ld a, [wMapGroup]
+ ld b, a
+ ld a, [wMapNumber]
+ ld c, a
+ call GetWorldMapLocation
+; If we're not in a valid location, i.e. Pokecenter floor 2F,
+; the backup map information is used.
+ cp SPECIAL_MAP
+ jr nz, .CheckRegion
+ ld a, [wBackupMapGroup]
+ ld b, a
+ ld a, [wBackupMapNumber]
+ ld c, a
+ call GetWorldMapLocation
+.CheckRegion:
+; The first 46 locations are part of Johto. The rest are in Kanto.
+ cp KANTO_LANDMARK
+ jr nc, .KantoFlyMap
+.JohtoFlyMap:
+; Note that .NoKanto should be modified in tandem with this branch
+ push af
+; Start from New Bark Town
+ ld a, FLY_NEW_BARK
+ ld [wTownMapPlayerIconLandmark], a
+; Flypoints begin at New Bark Town...
+ ld [wStartFlypoint], a
+; ..and end at Silver Cave.
+ ld a, FLY_MT_SILVER
+ ld [wEndFlypoint], a
+; Fill out the map
+ call FillJohtoMap
+ call .MapHud
+ pop af
+ call TownMapPlayerIcon
+ ret
+
+.KantoFlyMap:
+; The event that there are no flypoints enabled in a map is not
+; accounted for. As a result, if you attempt to select a flypoint
+; when there are none enabled, the game will crash. Additionally,
+; the flypoint selection has a default starting point that
+; can be flown to even if none are enabled.
+; To prevent both of these things from happening when the player
+; enters Kanto, fly access is restricted until Indigo Plateau is
+; visited and its flypoint enabled.
+ push af
+ ld c, SPAWN_INDIGO
+ call HasVisitedSpawn
+ and a
+ jr z, .NoKanto
+; Kanto's map is only loaded if we've visited Indigo Plateau
+
+; Flypoints begin at Pallet Town...
+ ld a, FLY_PALLET
+ ld [wStartFlypoint], a
+; ...and end at Indigo Plateau
+ ld a, FLY_INDIGO
+ ld [wEndFlypoint], a
+; Because Indigo Plateau is the first flypoint the player
+; visits, it's made the default flypoint.
+ ld [wTownMapPlayerIconLandmark], a
+; Fill out the map
+ call FillKantoMap
+ call .MapHud
+ pop af
+ call TownMapPlayerIcon
+ ret
+
+.NoKanto:
+; If Indigo Plateau hasn't been visited, we use Johto's map instead
+
+; Start from New Bark Town
+ ld a, FLY_NEW_BARK
+ ld [wTownMapPlayerIconLandmark], a
+; Flypoints begin at New Bark Town...
+ ld [wStartFlypoint], a
+; ..and end at Silver Cave
+ ld a, FLY_MT_SILVER
+ ld [wEndFlypoint], a
+ call FillJohtoMap
+ pop af
+.MapHud:
+ call TownMapBubble
+ call TownMapPals
+ hlbgcoord 0, 0 ; BG Map 0
+ call TownMapBGUpdate
+ call TownMapMon
+ ld a, c
+ ld [wTownMapCursorCoordinates], a
+ ld a, b
+ ld [wTownMapCursorCoordinates + 1], a
+ ret
+
+; 91d11
+
+Pokedex_GetArea: ; 91d11
+; e: Current landmark
+ ld a, [wTownMapPlayerIconLandmark]
+ push af
+ ld a, [wTownMapCursorLandmark]
+ push af
+ ld a, e
+ ld [wTownMapPlayerIconLandmark], a
+ call ClearSprites
+ xor a
+ ld [hBGMapMode], a
+ ld a, $1
+ ld [hInMenu], a
+ ld de, PokedexNestIconGFX
+ ld hl, vTiles0 tile $7f
+ lb bc, BANK(PokedexNestIconGFX), 1
+ call Request2bpp
+ call .GetPlayerOrFastShipIcon
+ ld hl, vTiles0 tile $78
+ ld c, 4
+ call Request2bpp
+ call LoadTownMapGFX
+ call FillKantoMap
+ call .PlaceString_MonsNest
+ call TownMapPals
+ hlbgcoord 0, 0, vBGMap1
+ call TownMapBGUpdate
+ call FillJohtoMap
+ call .PlaceString_MonsNest
+ call TownMapPals
+ hlbgcoord 0, 0
+ call TownMapBGUpdate
+ ld b, SCGB_POKEGEAR_PALS
+ call GetSGBLayout
+ call SetPalettes
+ xor a
+ ld [hBGMapMode], a
+ xor a ; JOHTO_REGION
+ call .GetAndPlaceNest
+.loop
+ call JoyTextDelay
+ ld hl, hJoyPressed
+ ld a, [hl]
+ and A_BUTTON | B_BUTTON
+ jr nz, .a_b
+ ld a, [hJoypadDown]
+ and SELECT
+ jr nz, .select
+ call .LeftRightInput
+ call .BlinkNestIcons
+ jr .next
+
+.select
+ call .HideNestsShowPlayer
+.next
+ call DelayFrame
+ jr .loop
+
+.a_b
+ call ClearSprites
+ pop af
+ ld [wTownMapCursorLandmark], a
+ pop af
+ ld [wTownMapPlayerIconLandmark], a
+ ret
+
+; 91d9b
+
+.LeftRightInput: ; 91d9b
+ ld a, [hl]
+ and D_LEFT
+ jr nz, .left
+ ld a, [hl]
+ and D_RIGHT
+ jr nz, .right
+ ret
+
+.left
+ ld a, [hWY]
+ cp $90
+ ret z
+ call ClearSprites
+ ld a, $90
+ ld [hWY], a
+ xor a ; JOHTO_REGION
+ call .GetAndPlaceNest
+ ret
+
+.right
+ ld a, [wStatusFlags]
+ bit STATUSFLAGS_HALL_OF_FAME_F, a
+ ret z
+ ld a, [hWY]
+ and a
+ ret z
+ call ClearSprites
+ xor a
+ ld [hWY], a
+ ld a, KANTO_REGION
+ call .GetAndPlaceNest
+ ret
+
+; 91dcd
+
+.BlinkNestIcons: ; 91dcd
+ ld a, [hVBlankCounter]
+ ld e, a
+ and $f
+ ret nz
+ ld a, e
+ and $10
+ jr nz, .copy_sprites
+ call ClearSprites
+ ret
+
+.copy_sprites
+ hlcoord 0, 0
+ ld de, wVirtualOAM
+ ld bc, wVirtualOAMEnd - wVirtualOAM
+ call CopyBytes
+ ret
+
+; 91de9
+
+.PlaceString_MonsNest: ; 91de9
+ hlcoord 0, 0
+ ld bc, SCREEN_WIDTH
+ ld a, " "
+ call ByteFill
+ hlcoord 0, 1
+ ld a, $6
+ ld [hli], a
+ ld bc, SCREEN_WIDTH - 2
+ ld a, $7
+ call ByteFill
+ ld [hl], $17
+ call GetPokemonName
+ hlcoord 2, 0
+ call PlaceString
+ ld h, b
+ ld l, c
+ ld de, .String_SNest
+ call PlaceString
+ ret
+
+; 91e16
+
+.String_SNest:
+ db "'S NEST@"
+; 91e1e
+
+.GetAndPlaceNest: ; 91e1e
+ ld [wTownMapCursorLandmark], a
+ ld e, a
+ farcall FindNest ; load nest landmarks into wTileMap[0,0]
+ decoord 0, 0
+ ld hl, wVirtualOAMSprite00
+.nestloop
+ ld a, [de]
+ and a
+ jr z, .done_nest
+ push de
+ ld e, a
+ push hl
+ farcall GetLandmarkCoords
+ pop hl
+ ; load into OAM
+ ld a, d
+ sub 4
+ ld [hli], a ; y
+ ld a, e
+ sub 4
+ ld [hli], a ; x
+ ld a, $7f ; nest icon
+ ld [hli], a ; tile id
+ xor a
+ ld [hli], a ; attributes
+ ; next
+ pop de
+ inc de
+ jr .nestloop
+
+.done_nest
+ ld hl, wVirtualOAM
+ decoord 0, 0
+ ld bc, wVirtualOAMEnd - wVirtualOAM
+ call CopyBytes
+ ret
+
+; 91e5a
+
+.HideNestsShowPlayer: ; 91e5a
+ call .CheckPlayerLocation
+ ret c
+ ld a, [wTownMapPlayerIconLandmark]
+ ld e, a
+ farcall GetLandmarkCoords
+ ld c, e
+ ld b, d
+ ld de, .PlayerOAM
+ ld hl, wVirtualOAMSprite00
+.ShowPlayerLoop:
+ ld a, [de]
+ cp $80
+ jr z, .clear_oam
+ add b
+ ld [hli], a ; y
+ inc de
+ ld a, [de]
+ add c
+ ld [hli], a ; x
+ inc de
+ ld a, [de]
+ add $78 ; where the player's sprite is loaded
+ ld [hli], a ; tile id
+ inc de
+ push bc
+ ld c, PAL_OW_RED
+ ld a, [wPlayerGender]
+ bit PLAYERGENDER_FEMALE_F, a
+ jr z, .male
+ inc c ; PAL_OW_BLUE
+.male
+ ld a, c
+ ld [hli], a ; attributes
+ pop bc
+ jr .ShowPlayerLoop
+
+.clear_oam
+ ld hl, wVirtualOAMSprite04
+ ld bc, wVirtualOAMEnd - wVirtualOAMSprite04
+ xor a
+ call ByteFill
+ ret
+
+; 91e9c
+
+.PlayerOAM: ; 91e9c
+ ; y pxl, x pxl, tile offset
+ db -1 * 8, -1 * 8, 0 ; top left
+ db -1 * 8, 0 * 8, 1 ; top right
+ db 0 * 8, -1 * 8, 2 ; bottom left
+ db 0 * 8, 0 * 8, 3 ; bottom right
+ db $80 ; terminator
+; 91ea9
+
+.CheckPlayerLocation: ; 91ea9
+; Don't show the player's sprite if you're
+; not in the same region as what's currently
+; on the screen.
+ ld a, [wTownMapPlayerIconLandmark]
+ cp FAST_SHIP
+ jr z, .johto
+ cp KANTO_LANDMARK
+ jr c, .johto
+.kanto
+ ld a, [wTownMapCursorLandmark]
+ and a
+ jr z, .clear
+ jr .ok
+
+.johto
+ ld a, [wTownMapCursorLandmark]
+ and a
+ jr nz, .clear
+.ok
+ and a
+ ret
+
+.clear
+ ld hl, wVirtualOAM
+ ld bc, wVirtualOAMEnd - wVirtualOAM
+ xor a
+ call ByteFill
+ scf
+ ret
+
+; 91ed0
+
+.GetPlayerOrFastShipIcon: ; 91ed0
+ ld a, [wTownMapPlayerIconLandmark]
+ cp FAST_SHIP
+ jr z, .FastShip
+ farcall GetPlayerIcon
+ ret
+
+.FastShip:
+ ld de, FastShipGFX
+ ld b, BANK(FastShipGFX)
+ ret
+
+; 91ee4
+
+TownMapBGUpdate: ; 91ee4
+; Update BG Map tiles and attributes
+
+; BG Map address
+ ld a, l
+ ld [hBGMapAddress], a
+ ld a, h
+ ld [hBGMapAddress + 1], a
+; Only update palettes on CGB
+ ld a, [hCGB]
+ and a
+ jr z, .tiles
+; BG Map mode 2 (palettes)
+ ld a, 2
+ ld [hBGMapMode], a
+; The BG Map is updated in thirds, so we wait
+
+; 3 frames to update the whole screen's palettes.
+ ld c, 3
+ call DelayFrames
+.tiles
+; Update BG Map tiles
+ call WaitBGMap
+; Turn off BG Map update
+ xor a
+ ld [hBGMapMode], a
+ ret
+
+; 91eff
+
+FillJohtoMap: ; 91eff
+ ld de, JohtoMap
+ jr FillTownMap
+
+FillKantoMap: ; 91f04
+ ld de, KantoMap
+FillTownMap: ; 91f07
+ hlcoord 0, 0
+.loop
+ ld a, [de]
+ cp -1
+ ret z
+ ld a, [de]
+ ld [hli], a
+ inc de
+ jr .loop
+
+; 91f13
+
+TownMapPals: ; 91f13
+; Assign palettes based on tile ids
+ hlcoord 0, 0
+ decoord 0, 0, wAttrMap
+ ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+.loop
+; Current tile
+ ld a, [hli]
+ push hl
+; The palette map covers tiles $00 to $5f; $60 and above use palette 0
+ cp $60
+ jr nc, .pal0
+
+; The palette data is condensed to nybbles, least-significant first.
+ ld hl, .PalMap
+ srl a
+ jr c, .odd
+; Even-numbered tile ids take the bottom nybble...
+ add l
+ ld l, a
+ ld a, h
+ adc 0
+ ld h, a
+ ld a, [hl]
+ and PALETTE_MASK
+ jr .update
+
+.odd
+; ...and odd ids take the top.
+ add l
+ ld l, a
+ ld a, h
+ adc 0
+ ld h, a
+ ld a, [hl]
+ swap a
+ and PALETTE_MASK
+ jr .update
+
+.pal0
+ xor a
+.update
+ pop hl
+ ld [de], a
+ inc de
+ dec bc
+ ld a, b
+ or c
+ jr nz, .loop
+ ret
+
+.PalMap:
+INCLUDE "gfx/pokegear/town_map_palette_map.asm"
+; 91f7b
+
+TownMapMon: ; 91f7b
+; Draw the FlyMon icon at town map location
+
+; Get FlyMon species
+ ld a, [wCurPartyMon]
+ ld hl, wPartySpecies
+ ld e, a
+ ld d, $0
+ add hl, de
+ ld a, [hl]
+ ld [wd265], a
+; Get FlyMon icon
+ ld e, $08 ; starting tile in VRAM
+ farcall GetSpeciesIcon
+; Animation/palette
+ depixel 0, 0
+ ld a, SPRITE_ANIM_INDEX_PARTY_MON
+ call _InitSpriteAnimStruct
+ ld hl, SPRITEANIMSTRUCT_TILE_ID
+ add hl, bc
+ ld [hl], $08
+ ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
+ add hl, bc
+ ld [hl], SPRITE_ANIM_SEQ_NULL
+ ret
+
+; 91fa6
+
+TownMapPlayerIcon: ; 91fa6
+; Draw the player icon at town map location in a
+ push af
+ farcall GetPlayerIcon
+; Standing icon
+ ld hl, vTiles0 tile $10
+ ld c, 4 ; # tiles
+ call Request2bpp
+; Walking icon
+ ld hl, $c0
+ add hl, de
+ ld d, h
+ ld e, l
+ ld hl, vTiles0 tile $14
+ ld c, 4 ; # tiles
+ ld a, BANK(ChrisSpriteGFX) ; does nothing
+ call Request2bpp
+; Animation/palette
+ depixel 0, 0
+ ld b, SPRITE_ANIM_INDEX_RED_WALK ; Male
+ ld a, [wPlayerGender]
+ bit PLAYERGENDER_FEMALE_F, a
+ jr z, .got_gender
+ ld b, SPRITE_ANIM_INDEX_BLUE_WALK ; Female
+.got_gender
+ ld a, b
+ call _InitSpriteAnimStruct
+ ld hl, SPRITEANIMSTRUCT_TILE_ID
+ add hl, bc
+ ld [hl], $10
+ pop af
+ ld e, a
+ push bc
+ farcall GetLandmarkCoords
+ pop bc
+ ld hl, SPRITEANIMSTRUCT_XCOORD
+ add hl, bc
+ ld [hl], e
+ ld hl, SPRITEANIMSTRUCT_YCOORD
+ add hl, bc
+ ld [hl], d
+ ret
+
+; 0x91ff2
+
+LoadTownMapGFX: ; 91ff2
+ ld hl, TownMapGFX
+ ld de, vTiles2
+ lb bc, BANK(TownMapGFX), 48
+ call DecompressRequest2bpp
+ ret
+
+; 91fff
+
+JohtoMap: ; 91fff
+INCBIN "gfx/pokegear/johto.bin"
+; 92168
+
+KantoMap: ; 92168
+INCBIN "gfx/pokegear/kanto.bin"
+; 922d1
+
+PokedexNestIconGFX: ; 922d1
+INCBIN "gfx/pokegear/dexmap_nest_icon.2bpp"
+FlyMapLabelBorderGFX: ; 922e1
+INCBIN "gfx/pokegear/flymap_label_border.1bpp"
+
+Unreferenced_Function92311:
+ xor a
+ ld [wTownMapPlayerIconLandmark], a
+ call ClearBGPalettes
+ call ClearTileMap
+ call ClearSprites
+ ld hl, hInMenu
+ ld a, [hl]
+ push af
+ ld [hl], $1
+ xor a
+ ld [hBGMapMode], a
+ farcall ClearSpriteAnims
+ call LoadTownMapGFX
+ ld de, FlyMapLabelBorderGFX
+ ld hl, vTiles2 tile $30
+ lb bc, BANK(FlyMapLabelBorderGFX), 6
+ call Request1bpp
+ call FillKantoMap
+ call TownMapBubble
+ call TownMapPals
+ hlbgcoord 0, 0, vBGMap1
+ call TownMapBGUpdate
+ call FillJohtoMap
+ call TownMapBubble
+ call TownMapPals
+ hlbgcoord 0, 0
+ call TownMapBGUpdate
+ call TownMapMon
+ ld a, c
+ ld [wTownMapCursorCoordinates], a
+ ld a, b
+ ld [wTownMapCursorCoordinates + 1], a
+ ld b, SCGB_POKEGEAR_PALS
+ call GetSGBLayout
+ call SetPalettes
+.loop
+ call JoyTextDelay
+ ld hl, hJoyPressed
+ ld a, [hl]
+ and B_BUTTON
+ jr nz, .pressedB
+ ld a, [hl]
+ and A_BUTTON
+ jr nz, .pressedA
+ call .HandleDPad
+ call GetMapCursorCoordinates
+ farcall PlaySpriteAnimations
+ call DelayFrame
+ jr .loop
+
+.pressedB
+ ld a, -1
+ jr .finished_a_b
+
+.pressedA
+ ld a, [wTownMapPlayerIconLandmark]
+ ld l, a
+ ld h, 0
+ add hl, hl
+ ld de, Flypoints + 1
+ add hl, de
+ ld a, [hl]
+.finished_a_b
+ ld [wTownMapPlayerIconLandmark], a
+ pop af
+ ld [hInMenu], a
+ call ClearBGPalettes
+ ld a, $90
+ ld [hWY], a
+ xor a ; LOW(vBGMap0)
+ ld [hBGMapAddress], a
+ ld a, HIGH(vBGMap0)
+ ld [hBGMapAddress + 1], a
+ ld a, [wTownMapPlayerIconLandmark]
+ ld e, a
+ ret
+
+; 923b8
+
+.HandleDPad: ; 923b8
+ ld hl, hJoyLast
+ ld a, [hl]
+ and D_DOWN | D_RIGHT
+ jr nz, .down_right
+ ld a, [hl]
+ and D_UP | D_LEFT
+ jr nz, .up_left
+ ret
+
+.down_right
+ ld hl, wTownMapPlayerIconLandmark
+ ld a, [hl]
+ cp FLY_INDIGO
+ jr c, .okay_dr
+ ld [hl], -1
+.okay_dr
+ inc [hl]
+ jr .continue
+
+.up_left
+ ld hl, wTownMapPlayerIconLandmark
+ ld a, [hl]
+ and a
+ jr nz, .okay_ul
+ ld [hl], FLY_INDIGO + 1
+.okay_ul
+ dec [hl]
+.continue
+ ld a, [wTownMapPlayerIconLandmark]
+ cp KANTO_FLYPOINT
+ jr c, .johto
+ call FillKantoMap
+ xor a
+ ld b, $9c
+ jr .finish
+
+.johto
+ call FillJohtoMap
+ ld a, $90
+ ld b, $98
+.finish
+ ld [hWY], a
+ ld a, b
+ ld [hBGMapAddress + 1], a
+ call TownMapBubble
+ call WaitBGMap
+ xor a
+ ld [hBGMapMode], a
+ ret
+
+; 92402
diff --git a/engine/pokegear/radio.asm b/engine/pokegear/radio.asm
new file mode 100644
index 000000000..ffaef80f0
--- /dev/null
+++ b/engine/pokegear/radio.asm
@@ -0,0 +1,1932 @@
+PlayRadioShow:
+; If we're already in the radio program proper, we don't need to be here.
+ ld a, [wCurrentRadioLine]
+ cp POKE_FLUTE_RADIO
+ jr nc, .ok
+; If Team Rocket is not occupying the radio tower, we don't need to be here.
+ ld a, [wStatusFlags2]
+ bit STATUSFLAGS2_ROCKETS_IN_RADIO_TOWER_F, a
+ jr z, .ok
+; If we're in Kanto, we don't need to be here.
+ call IsInJohto
+ and a
+ jr nz, .ok
+; Team Rocket broadcasts on all stations.
+ ld a, ROCKET_RADIO
+ ld [wCurrentRadioLine], a
+.ok
+; Jump to the currently loaded station. The index to which we need to jump is in wCurrentRadioLine.
+ ld a, [wCurrentRadioLine]
+ ld e, a
+ ld d, 0
+ ld hl, RadioJumptable
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp hl
+
+RadioJumptable:
+; entries correspond to constants/radio_constants.asm
+ dw OaksPKMNTalk1 ; $00
+ dw PokedexShow1 ; $01
+ dw BenMonMusic1 ; $02
+ dw LuckyNumberShow1 ; $03
+ dw BuenasPassword1 ; $04
+ dw PeoplePlaces1 ; $05
+ dw FernMonMusic1 ; $06
+ dw RocketRadio1 ; $07
+ dw PokeFluteRadio ; $08
+ dw UnownRadio ; $09
+ dw EvolutionRadio ; $0a
+; OaksPKMNTalk
+ dw OaksPKMNTalk2 ; $0b
+ dw OaksPKMNTalk3 ; $0c
+ dw OaksPKMNTalk4 ; $0d
+ dw OaksPKMNTalk5 ; $0e
+ dw OaksPKMNTalk6 ; $0f
+ dw OaksPKMNTalk7 ; $10
+ dw OaksPKMNTalk8 ; $11
+ dw OaksPKMNTalk9 ; $12
+ dw PokedexShow2 ; $13
+ dw PokedexShow3 ; $14
+ dw PokedexShow4 ; $15
+ dw PokedexShow5 ; $16
+; Ben Music
+ dw BenMonMusic2 ; $17
+ dw BenMonMusic3 ; $18
+ dw BenFernMusic4 ; $19
+ dw BenFernMusic5 ; $1a
+ dw BenFernMusic6 ; $1b
+ dw BenFernMusic7 ; $1c
+ dw FernMonMusic2 ; $1d
+; Lucky Number Show
+ dw LuckyNumberShow2 ; $1e
+ dw LuckyNumberShow3 ; $1f
+ dw LuckyNumberShow4 ; $20
+ dw LuckyNumberShow5 ; $21
+ dw LuckyNumberShow6 ; $22
+ dw LuckyNumberShow7 ; $23
+ dw LuckyNumberShow8 ; $24
+ dw LuckyNumberShow9 ; $25
+ dw LuckyNumberShow10 ; $26
+ dw LuckyNumberShow11 ; $27
+ dw LuckyNumberShow12 ; $28
+ dw LuckyNumberShow13 ; $29
+ dw LuckyNumberShow14 ; $2a
+ dw LuckyNumberShow15 ; $2b
+; People & Places
+ dw PeoplePlaces2 ; $2c
+ dw PeoplePlaces3 ; $2d
+ dw PeoplePlaces4 ; $2e
+ dw PeoplePlaces5 ; $2f
+ dw PeoplePlaces6 ; $30
+ dw PeoplePlaces7 ; $31
+; Rocket Radio
+ dw RocketRadio2 ; $32
+ dw RocketRadio3 ; $33
+ dw RocketRadio4 ; $34
+ dw RocketRadio5 ; $35
+ dw RocketRadio6 ; $36
+ dw RocketRadio7 ; $37
+ dw RocketRadio8 ; $38
+ dw RocketRadio9 ; $39
+ dw RocketRadio10 ; $3a
+; More Pokemon Channel stuff
+ dw OaksPKMNTalk10 ; $3b
+ dw OaksPKMNTalk11 ; $3c
+ dw OaksPKMNTalk12 ; $3d
+ dw OaksPKMNTalk13 ; $3e
+ dw OaksPKMNTalk14 ; $3f
+; Buenas Password
+ dw BuenasPassword2 ; $40
+ dw BuenasPassword3 ; $41
+ dw BuenasPassword4 ; $42
+ dw BuenasPassword5 ; $43
+ dw BuenasPassword6 ; $44
+ dw BuenasPassword7 ; $45
+ dw BuenasPassword8 ; $46
+ dw BuenasPassword9 ; $47
+ dw BuenasPassword10 ; $48
+ dw BuenasPassword11 ; $49
+ dw BuenasPassword12 ; $4a
+ dw BuenasPassword13 ; $4b
+ dw BuenasPassword14 ; $4c
+ dw BuenasPassword15 ; $4d
+ dw BuenasPassword16 ; $4e
+ dw BuenasPassword17 ; $4f
+ dw BuenasPassword18 ; $50
+ dw BuenasPassword19 ; $51
+ dw BuenasPassword20 ; $52
+ dw BuenasPassword21 ; $53
+ dw RadioScroll ; $54
+; More Pokemon Channel stuff
+ dw PokedexShow6 ; $55
+ dw PokedexShow7 ; $56
+ dw PokedexShow8 ; $57
+
+
+PrintRadioLine:
+ ld [wNextRadioLine], a
+ ld hl, wRadioText
+ ld a, [wNumRadioLinesPrinted]
+ cp 2
+ jr nc, .print
+ inc hl
+ ld [hl], TX_START
+ inc a
+ ld [wNumRadioLinesPrinted], a
+ cp 2
+ jr nz, .print
+ bccoord 1, 16
+ call PlaceHLTextAtBC
+ jr .skip
+.print
+ call PrintTextBoxText
+.skip
+ ld a, RADIO_SCROLL
+ ld [wCurrentRadioLine], a
+ ld a, 100
+ ld [wRadioTextDelay], a
+ ret
+
+ReplacePeriodsWithSpaces:
+ push hl
+ ld b, SCREEN_WIDTH * 2
+.loop
+ ld a, [hl]
+ cp "."
+ jr nz, .next
+ ld [hl], " "
+
+.next
+ inc hl
+ dec b
+ jr nz, .loop
+ pop hl
+ ret
+
+RadioScroll:
+ ld hl, wRadioTextDelay
+ ld a, [hl]
+ and a
+ jr z, .proceed
+ dec [hl]
+ ret
+.proceed
+ ld a, [wNextRadioLine]
+ ld [wCurrentRadioLine], a
+ ld a, [wNumRadioLinesPrinted]
+ cp 1
+ call nz, CopyBottomLineToTopLine
+ jp ClearBottomLine
+
+OaksPKMNTalk1:
+ ld a, 5
+ ld [wOaksPKMNTalkSegmentCounter], a
+ call StartRadioStation
+ ld hl, OPT_IntroText1
+ ld a, OAKS_POKEMON_TALK_2
+ jp NextRadioLine
+
+OaksPKMNTalk2:
+ ld hl, OPT_IntroText2
+ ld a, OAKS_POKEMON_TALK_3
+ jp NextRadioLine
+
+OaksPKMNTalk3:
+ ld hl, OPT_IntroText3
+ ld a, OAKS_POKEMON_TALK_4
+ jp NextRadioLine
+
+OaksPKMNTalk4:
+; Choose a random route, and a random Pokemon from that route.
+.sample
+ call Random
+ and %11111
+ cp (OaksPKMNTalkRoutes.End - OaksPKMNTalkRoutes) / 2
+ jr nc, .sample
+ ; We now have a number between 0 and 14.
+ ld hl, OaksPKMNTalkRoutes
+ ld c, a
+ ld b, 0
+ add hl, bc
+ add hl, bc
+ ld b, [hl]
+ inc hl
+ ld c, [hl]
+ ; bc now contains the chosen map's group and number indices.
+ push bc
+
+ ; Search the JohtoGrassWildMons array for the chosen map.
+ ld hl, JohtoGrassWildMons
+.loop
+ ld a, BANK(JohtoGrassWildMons)
+ call GetFarByte
+ cp -1
+ jr z, .overflow
+ inc hl
+ cp b
+ jr nz, .next
+ ld a, BANK(JohtoGrassWildMons)
+ call GetFarByte
+ cp c
+ jr z, .done
+.next
+ dec hl
+ ld de, GRASS_WILDDATA_LENGTH
+ add hl, de
+ jr .loop
+
+.done
+ ; Point hl to the list of morning Pokémon., skipping percentages
+rept 4
+ inc hl
+endr
+ ; Generate a number, either 0, 1, or 2, to choose a time of day.
+.loop2
+ call Random
+ maskbits NUM_DAYTIMES
+ cp DARKNESS_F
+ jr z, .loop2
+
+ ld bc, 2 * NUM_GRASSMON
+ call AddNTimes
+.loop3
+ ; Choose one of the middle three Pokemon.
+ call Random
+ and NUM_GRASSMON
+ cp 2
+ jr c, .loop3
+ cp 5
+ jr nc, .loop3
+ ld e, a
+ ld d, 0
+ add hl, de
+ add hl, de
+ inc hl ; skip level
+ ld a, BANK(JohtoGrassWildMons)
+ call GetFarByte
+ ld [wNamedObjectIndexBuffer], a
+ ld [wCurPartySpecies], a
+ call GetPokemonName
+ ld hl, wStringBuffer1
+ ld de, wMonOrItemNameBuffer
+ ld bc, MON_NAME_LENGTH
+ call CopyBytes
+
+ ; Now that we've chosen our wild Pokemon,
+ ; let's recover the map index info and get its name.
+ pop bc
+ call GetWorldMapLocation
+ ld e, a
+ farcall GetLandmarkName
+ ld hl, OPT_OakText1
+ call CopyRadioTextToRAM
+ ld a, OAKS_POKEMON_TALK_5
+ jp PrintRadioLine
+
+.overflow
+ pop bc
+ ld a, OAKS_POKEMON_TALK
+ jp PrintRadioLine
+
+INCLUDE "data/radio/oaks_pkmn_talk_routes.asm"
+
+OaksPKMNTalk5:
+ ld hl, OPT_OakText2
+ ld a, OAKS_POKEMON_TALK_6
+ jp NextRadioLine
+
+OaksPKMNTalk6:
+ ld hl, OPT_OakText3
+ ld a, OAKS_POKEMON_TALK_7
+ jp NextRadioLine
+
+OPT_IntroText1:
+ ; MARY: PROF.OAK'S
+ text_jump _OPT_IntroText1
+ db "@"
+
+OPT_IntroText2:
+ ; #MON TALK!
+ text_jump _OPT_IntroText2
+ db "@"
+
+OPT_IntroText3:
+ ; With me, MARY!
+ text_jump _OPT_IntroText3
+ db "@"
+
+OPT_OakText1:
+ ; OAK: @ @
+ text_jump _OPT_OakText1
+ db "@"
+
+OPT_OakText2:
+ ; may be seen around
+ text_jump _OPT_OakText2
+ db "@"
+
+OPT_OakText3:
+ ; @ .
+ text_jump _OPT_OakText3
+ db "@"
+
+OaksPKMNTalk7:
+ ld a, [wCurPartySpecies]
+ ld [wNamedObjectIndexBuffer], a
+ call GetPokemonName
+ ld hl, OPT_MaryText1
+ ld a, OAKS_POKEMON_TALK_8
+ jp NextRadioLine
+
+OPT_MaryText1:
+ ; MARY: @ 's
+ text_jump _OPT_MaryText1
+ db "@"
+
+OaksPKMNTalk8:
+ ; 0-15 are all valid indexes into .Adverbs,
+ ; so no need for a retry loop
+ call Random
+ maskbits NUM_OAKS_POKEMON_TALK_ADVERBS
+ ld e, a
+ ld d, 0
+ ld hl, .Adverbs
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, OAKS_POKEMON_TALK_9
+ jp NextRadioLine
+
+.Adverbs:
+; there are NUM_OAKS_POKEMON_TALK_ADVERBS entries
+ dw .sweetadorably
+ dw .wigglyslickly
+ dw .aptlynamed
+ dw .undeniablykindof
+ dw .unbearably
+ dw .wowimpressively
+ dw .almostpoisonously
+ dw .sensually
+ dw .mischievously
+ dw .topically
+ dw .addictively
+ dw .looksinwater
+ dw .evolutionmustbe
+ dw .provocatively
+ dw .flippedout
+ dw .heartmeltingly
+
+.sweetadorably
+ ; sweet and adorably
+ text_jump OPT_SweetAdorably
+ db "@"
+
+.wigglyslickly
+ ; wiggly and slickly
+ text_jump OPT_WigglySlickly
+ db "@"
+
+.aptlynamed
+ ; aptly named and
+ text_jump OPT_AptlyNamed
+ db "@"
+
+.undeniablykindof
+ ; undeniably kind of
+ text_jump OPT_UndeniablyKindOf
+ db "@"
+
+.unbearably
+ ; so, so unbearably
+ text_jump OPT_Unbearably
+ db "@"
+
+.wowimpressively
+ ; wow, impressively
+ text_jump OPT_WowImpressively
+ db "@"
+
+.almostpoisonously
+ ; almost poisonously
+ text_jump OPT_AlmostPoisonously
+ db "@"
+
+.sensually
+ ; ooh, so sensually
+ text_jump OPT_Sensually
+ db "@"
+
+.mischievously
+ ; so mischievously
+ text_jump OPT_Mischievously
+ db "@"
+
+.topically
+ ; so very topically
+ text_jump OPT_Topically
+ db "@"
+
+.addictively
+ ; sure addictively
+ text_jump OPT_Addictively
+ db "@"
+
+.looksinwater
+ ; looks in water is
+ text_jump OPT_LooksInWater
+ db "@"
+
+.evolutionmustbe
+ ; evolution must be
+ text_jump OPT_EvolutionMustBe
+ db "@"
+
+.provocatively
+ ; provocatively
+ text_jump OPT_Provocatively
+ db "@"
+
+.flippedout
+ ; so flipped out and
+ text_jump OPT_FlippedOut
+ db "@"
+
+.heartmeltingly
+ ; heart-meltingly
+ text_jump OPT_HeartMeltingly
+ db "@"
+
+OaksPKMNTalk9:
+ ; 0-15 are all valid indexes into .Adjectives,
+ ; so no need for a retry loop
+ call Random
+ maskbits NUM_OAKS_POKEMON_TALK_ADJECTIVES
+ ld e, a
+ ld d, 0
+ ld hl, .Adjectives
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [wOaksPKMNTalkSegmentCounter]
+ dec a
+ ld [wOaksPKMNTalkSegmentCounter], a
+ ld a, OAKS_POKEMON_TALK_4
+ jr nz, .ok
+ ld a, 5
+ ld [wOaksPKMNTalkSegmentCounter], a
+ ld a, OAKS_POKEMON_TALK_10
+.ok
+ jp NextRadioLine
+
+.Adjectives:
+; there are NUM_OAKS_POKEMON_TALK_ADJECTIVES entries
+ dw .cute
+ dw .weird
+ dw .pleasant
+ dw .boldsortof
+ dw .frightening
+ dw .suavedebonair
+ dw .powerful
+ dw .exciting
+ dw .groovy
+ dw .inspiring
+ dw .friendly
+ dw .hothothot
+ dw .stimulating
+ dw .guarded
+ dw .lovely
+ dw .speedy
+
+.cute
+ ; cute.
+ text_jump OPT_Cute
+ db "@"
+
+.weird
+ ; weird.
+ text_jump OPT_Weird
+ db "@"
+
+.pleasant
+ ; pleasant.
+ text_jump OPT_Pleasant
+ db "@"
+
+.boldsortof
+ ; bold, sort of.
+ text_jump OPT_BoldSortOf
+ db "@"
+
+.frightening
+ ; frightening.
+ text_jump OPT_Frightening
+ db "@"
+
+.suavedebonair
+ ; suave & debonair!
+ text_jump OPT_SuaveDebonair
+ db "@"
+
+.powerful
+ ; powerful.
+ text_jump OPT_Powerful
+ db "@"
+
+.exciting
+ ; exciting.
+ text_jump OPT_Exciting
+ db "@"
+
+.groovy
+ ; groovy!
+ text_jump OPT_Groovy
+ db "@"
+
+.inspiring
+ ; inspiring.
+ text_jump OPT_Inspiring
+ db "@"
+
+.friendly
+ ; friendly.
+ text_jump OPT_Friendly
+ db "@"
+
+.hothothot
+ ; hot, hot, hot!
+ text_jump OPT_HotHotHot
+ db "@"
+
+.stimulating
+ ; stimulating.
+ text_jump OPT_Stimulating
+ db "@"
+
+.guarded
+ ; guarded.
+ text_jump OPT_Guarded
+ db "@"
+
+.lovely
+ ; lovely.
+ text_jump OPT_Lovely
+ db "@"
+
+.speedy
+ ; speedy.
+ text_jump OPT_Speedy
+ db "@"
+
+OaksPKMNTalk10:
+ farcall RadioMusicRestartPokemonChannel
+ ld hl, OPT_RestartText
+ call PrintText
+ call WaitBGMap
+ ld hl, OPT_PokemonChannelText
+ call PrintText
+ ld a, OAKS_POKEMON_TALK_11
+ ld [wCurrentRadioLine], a
+ ld a, 100
+ ld [wRadioTextDelay], a
+ ret
+
+OPT_PokemonChannelText:
+ ; #MON
+ text_jump _OPT_PokemonChannelText
+ db "@"
+
+OPT_RestartText:
+ db "@"
+
+OaksPKMNTalk11:
+ ld hl, wRadioTextDelay
+ dec [hl]
+ ret nz
+ hlcoord 9, 14
+ ld de, .pokemon_string
+ ld a, OAKS_POKEMON_TALK_12
+ jp PlaceRadioString
+
+.pokemon_string
+ db "#MON@"
+
+OaksPKMNTalk12:
+ ld hl, wRadioTextDelay
+ dec [hl]
+ ret nz
+ hlcoord 1, 16
+ ld de, .pokemon_channel_string
+ ld a, OAKS_POKEMON_TALK_13
+ jp PlaceRadioString
+
+.pokemon_channel_string
+ db "#MON Channel@"
+
+OaksPKMNTalk13:
+ ld hl, wRadioTextDelay
+ dec [hl]
+ ret nz
+ hlcoord 12, 16
+ ld de, .terminator
+ ld a, OAKS_POKEMON_TALK_14
+ jp PlaceRadioString
+
+.terminator
+ db "@"
+
+OaksPKMNTalk14:
+ ld hl, wRadioTextDelay
+ dec [hl]
+ ret nz
+ ld de, MUSIC_POKEMON_TALK
+ callfar RadioMusicRestartDE
+ ld hl, .terminator
+ call PrintText
+ ld a, OAKS_POKEMON_TALK_4
+ ld [wNextRadioLine], a
+ xor a
+ ld [wNumRadioLinesPrinted], a
+ ld a, RADIO_SCROLL
+ ld [wCurrentRadioLine], a
+ ld a, 10
+ ld [wRadioTextDelay], a
+ ret
+
+.terminator
+ db "@"
+
+PlaceRadioString:
+ ld [wCurrentRadioLine], a
+ ld a, 100
+ ld [wRadioTextDelay], a
+ jp PlaceString
+
+CopyBottomLineToTopLine:
+ hlcoord 0, 15
+ decoord 0, 13
+ ld bc, SCREEN_WIDTH * 2
+ jp CopyBytes
+
+ClearBottomLine:
+ hlcoord 1, 15
+ ld bc, SCREEN_WIDTH - 2
+ ld a, " "
+ call ByteFill
+ hlcoord 1, 16
+ ld bc, SCREEN_WIDTH - 2
+ ld a, " "
+ jp ByteFill
+
+PokedexShow_GetDexEntryBank:
+ push hl
+ push de
+ ld a, [wCurPartySpecies]
+ dec a
+ rlca
+ rlca
+ maskbits NUM_DEX_ENTRY_BANKS
+ ld hl, .PokedexEntryBanks
+ ld d, 0
+ ld e, a
+ add hl, de
+ ld a, [hl]
+ pop de
+ pop hl
+ ret
+
+.PokedexEntryBanks:
+ db BANK(PokedexEntries1)
+ db BANK(PokedexEntries2)
+ db BANK(PokedexEntries3)
+ db BANK(PokedexEntries4)
+
+PokedexShow1:
+ call StartRadioStation
+.loop
+ call Random
+ cp NUM_POKEMON
+ jr nc, .loop
+ ld c, a
+ push bc
+ ld a, c
+ call CheckCaughtMon
+ pop bc
+ jr z, .loop
+ inc c
+ ld a, c
+ ld [wCurPartySpecies], a
+ ld [wNamedObjectIndexBuffer], a
+ call GetPokemonName
+ ld hl, PokedexShowText
+ ld a, POKEDEX_SHOW_2
+ jp NextRadioLine
+
+PokedexShow2:
+ ld a, [wCurPartySpecies]
+ dec a
+ ld hl, PokedexDataPointerTable
+ ld c, a
+ ld b, 0
+ add hl, bc
+ add hl, bc
+ ld a, BANK(PokedexDataPointerTable)
+ call GetFarHalfword
+ call PokedexShow_GetDexEntryBank
+ push af
+ push hl
+ call CopyDexEntryPart1
+ dec hl
+ ld [hl], "<DONE>"
+ ld hl, wPokedexShowPointerAddr
+ call CopyRadioTextToRAM
+ pop hl
+ pop af
+ call CopyDexEntryPart2
+rept 4
+ inc hl
+endr
+ ld a, l
+ ld [wPokedexShowPointerAddr], a
+ ld a, h
+ ld [wPokedexShowPointerAddr + 1], a
+ ld a, POKEDEX_SHOW_3
+ jp PrintRadioLine
+
+PokedexShow3:
+ call CopyDexEntry
+ ld a, POKEDEX_SHOW_4
+ jp PrintRadioLine
+
+PokedexShow4:
+ call CopyDexEntry
+ ld a, POKEDEX_SHOW_5
+ jp PrintRadioLine
+
+PokedexShow5:
+ call CopyDexEntry
+ ld a, POKEDEX_SHOW_6
+ jp PrintRadioLine
+
+PokedexShow6:
+ call CopyDexEntry
+ ld a, POKEDEX_SHOW_7
+ jp PrintRadioLine
+
+PokedexShow7:
+ call CopyDexEntry
+ ld a, POKEDEX_SHOW_8
+ jp PrintRadioLine
+
+PokedexShow8:
+ call CopyDexEntry
+ ld a, POKEDEX_SHOW
+ jp PrintRadioLine
+
+CopyDexEntry:
+ ld a, [wPokedexShowPointerAddr]
+ ld l, a
+ ld a, [wPokedexShowPointerAddr + 1]
+ ld h, a
+ ld a, [wPokedexShowPointerBank]
+ push af
+ push hl
+ call CopyDexEntryPart1
+ dec hl
+ ld [hl], "<DONE>"
+ ld hl, wPokedexShowPointerAddr
+ call CopyRadioTextToRAM
+ pop hl
+ pop af
+ call CopyDexEntryPart2
+ ret
+
+CopyDexEntryPart1:
+ ld de, wPokedexShowPointerBank
+ ld bc, SCREEN_WIDTH - 1
+ call FarCopyBytes
+ ld hl, wPokedexShowPointerAddr
+ ld [hl], TX_START
+ inc hl
+ ld [hl], "<LINE>"
+ inc hl
+.loop
+ ld a, [hli]
+ cp "@"
+ ret z
+ cp "<NEXT>"
+ ret z
+ cp "<DEXEND>"
+ ret z
+ jr .loop
+
+CopyDexEntryPart2:
+ ld d, a
+.loop
+ ld a, d
+ call GetFarByte
+ inc hl
+ cp "@"
+ jr z, .okay
+ cp "<NEXT>"
+ jr z, .okay
+ cp "<DEXEND>"
+ jr nz, .loop
+.okay
+ ld a, l
+ ld [wPokedexShowPointerAddr], a
+ ld a, h
+ ld [wPokedexShowPointerAddr + 1], a
+ ld a, d
+ ld [wPokedexShowPointerBank], a
+ ret
+
+PokedexShowText:
+ ; @ @
+ text_jump _PokedexShowText
+ db "@"
+
+BenMonMusic1:
+ call StartPokemonMusicChannel
+ ld hl, BenIntroText1
+ ld a, POKEMON_MUSIC_2
+ jp NextRadioLine
+
+BenMonMusic2:
+ ld hl, BenIntroText2
+ ld a, POKEMON_MUSIC_3
+ jp NextRadioLine
+
+BenMonMusic3:
+ ld hl, BenIntroText3
+ ld a, POKEMON_MUSIC_4
+ jp NextRadioLine
+
+FernMonMusic1:
+ call StartPokemonMusicChannel
+ ld hl, FernIntroText1
+ ld a, LETS_ALL_SING_2
+ jp NextRadioLine
+
+FernMonMusic2:
+ ld hl, FernIntroMusic2
+ ld a, POKEMON_MUSIC_4
+ jp NextRadioLine
+
+BenFernMusic4:
+ ld hl, BenFernText1
+ ld a, POKEMON_MUSIC_5
+ jp NextRadioLine
+
+BenFernMusic5:
+ call GetWeekday
+ and 1
+ ld hl, BenFernText2A
+ jr z, .SunTueThurSun
+ ld hl, BenFernText2B
+.SunTueThurSun:
+ ld a, POKEMON_MUSIC_6
+ jp NextRadioLine
+
+BenFernMusic6:
+ call GetWeekday
+ and 1
+ ld hl, BenFernText3A
+ jr z, .SunTueThurSun
+ ld hl, BenFernText3B
+.SunTueThurSun:
+ ld a, POKEMON_MUSIC_7
+ jp NextRadioLine
+
+BenFernMusic7:
+ ret
+
+StartPokemonMusicChannel:
+ call RadioTerminator
+ call PrintText
+ ld de, MUSIC_POKEMON_MARCH
+ call GetWeekday
+ and 1
+ jr z, .SunTueThurSun
+ ld de, MUSIC_POKEMON_LULLABY
+.SunTueThurSun:
+ callfar RadioMusicRestartDE
+ ret
+
+BenIntroText1:
+ ; BEN: #MON MUSIC
+ text_jump _BenIntroText1
+ db "@"
+
+BenIntroText2:
+ ; CHANNEL!
+ text_jump _BenIntroText2
+ db "@"
+
+BenIntroText3:
+ ; It's me, DJ BEN!
+ text_jump _BenIntroText3
+ db "@"
+
+FernIntroText1:
+ ; FERN: #MUSIC!
+ text_jump _FernIntroText1
+ db "@"
+
+FernIntroMusic2:
+ ; With DJ FERN!
+ text_jump _FernIntroText2
+ db "@"
+
+BenFernText1:
+ ; Today's @ ,
+ text_jump _BenFernText1
+ db "@"
+
+BenFernText2A:
+ ; so let us jam to
+ text_jump _BenFernText2A
+ db "@"
+
+BenFernText2B:
+ ; so chill out to
+ text_jump _BenFernText2B
+ db "@"
+
+BenFernText3A:
+ ; #MON March!
+ text_jump _BenFernText3A
+ db "@"
+
+BenFernText3B:
+ ; #MON Lullaby!
+ text_jump _BenFernText3B
+ db "@"
+
+LuckyNumberShow1:
+ call StartRadioStation
+ callfar CheckLuckyNumberShowFlag
+ jr nc, .dontreset
+ callfar ResetLuckyNumberShowFlag
+.dontreset
+ ld hl, LC_Text1
+ ld a, LUCKY_NUMBER_SHOW_2
+ jp NextRadioLine
+
+LuckyNumberShow2:
+ ld hl, LC_Text2
+ ld a, LUCKY_NUMBER_SHOW_3
+ jp NextRadioLine
+
+LuckyNumberShow3:
+ ld hl, LC_Text3
+ ld a, LUCKY_NUMBER_SHOW_4
+ jp NextRadioLine
+
+LuckyNumberShow4:
+ ld hl, LC_Text4
+ ld a, LUCKY_NUMBER_SHOW_5
+ jp NextRadioLine
+
+LuckyNumberShow5:
+ ld hl, LC_Text5
+ ld a, LUCKY_NUMBER_SHOW_6
+ jp NextRadioLine
+
+LuckyNumberShow6:
+ ld hl, LC_Text6
+ ld a, LUCKY_NUMBER_SHOW_7
+ jp NextRadioLine
+
+LuckyNumberShow7:
+ ld hl, LC_Text7
+ ld a, LUCKY_NUMBER_SHOW_8
+ jp NextRadioLine
+
+LuckyNumberShow8:
+ ld hl, wStringBuffer1
+ ld de, wLuckyIDNumber
+ lb bc, PRINTNUM_LEADINGZEROS | 2, 5
+ call PrintNum
+ ld a, "@"
+ ld [wStringBuffer1 + 5], a
+ ld hl, LC_Text8
+ ld a, LUCKY_NUMBER_SHOW_9
+ jp NextRadioLine
+
+LuckyNumberShow9:
+ ld hl, LC_Text9
+ ld a, LUCKY_NUMBER_SHOW_10
+ jp NextRadioLine
+
+LuckyNumberShow10:
+ ld hl, LC_Text7
+ ld a, LUCKY_NUMBER_SHOW_11
+ jp NextRadioLine
+
+LuckyNumberShow11:
+ ld hl, LC_Text8
+ ld a, LUCKY_NUMBER_SHOW_12
+ jp NextRadioLine
+
+LuckyNumberShow12:
+ ld hl, LC_Text10
+ ld a, LUCKY_NUMBER_SHOW_13
+ jp NextRadioLine
+
+LuckyNumberShow13:
+ ld hl, LC_Text11
+ call Random
+ and a
+ ld a, LUCKY_CHANNEL
+ jr nz, .okay
+ ld a, LUCKY_NUMBER_SHOW_14
+.okay
+ jp NextRadioLine
+
+LuckyNumberShow14:
+ ld hl, LC_DragText1
+ ld a, LUCKY_NUMBER_SHOW_15
+ jp NextRadioLine
+
+LuckyNumberShow15:
+ ld hl, LC_DragText2
+ ld a, LUCKY_CHANNEL
+ jp NextRadioLine
+
+LC_Text1:
+ ; REED: Yeehaw! How
+ text_jump _LC_Text1
+ db "@"
+
+LC_Text2:
+ ; y'all doin' now?
+ text_jump _LC_Text2
+ db "@"
+
+LC_Text3:
+ ; Whether you're up
+ text_jump _LC_Text3
+ db "@"
+
+LC_Text4:
+ ; or way down low,
+ text_jump _LC_Text4
+ db "@"
+
+LC_Text5:
+ ; don't you miss the
+ text_jump _LC_Text5
+ db "@"
+
+LC_Text6:
+ ; LUCKY NUMBER SHOW!
+ text_jump _LC_Text6
+ db "@"
+
+LC_Text7:
+ ; This week's Lucky
+ text_jump _LC_Text7
+ db "@"
+
+LC_Text8:
+ ; Number is @ !
+ text_jump _LC_Text8
+ db "@"
+
+LC_Text9:
+ ; I'll repeat that!
+ text_jump _LC_Text9
+ db "@"
+
+LC_Text10:
+ ; Match it and go to
+ text_jump _LC_Text10
+ db "@"
+
+LC_Text11:
+ ; the RADIO TOWER!
+ text_jump _LC_Text11
+ db "@"
+
+LC_DragText1:
+ ; …Repeating myself
+ text_jump _LC_DragText1
+ db "@"
+
+LC_DragText2:
+ ; gets to be a drag…
+ text_jump _LC_DragText2
+ db "@"
+
+PeoplePlaces1:
+ call StartRadioStation
+ ld hl, PnP_Text1
+ ld a, PLACES_AND_PEOPLE_2
+ jp NextRadioLine
+
+PeoplePlaces2:
+ ld hl, PnP_Text2
+ ld a, PLACES_AND_PEOPLE_3
+ jp NextRadioLine
+
+PeoplePlaces3:
+ ld hl, PnP_Text3
+ call Random
+ cp 49 percent - 1
+ ld a, PLACES_AND_PEOPLE_4 ; People
+ jr c, .ok
+ ld a, PLACES_AND_PEOPLE_6 ; Places
+.ok
+ jp NextRadioLine
+
+PnP_Text1:
+ ; PLACES AND PEOPLE!
+ text_jump _PnP_Text1
+ db "@"
+
+PnP_Text2:
+ ; Brought to you by
+ text_jump _PnP_Text2
+ db "@"
+
+PnP_Text3:
+ ; me, DJ LILY!
+ text_jump _PnP_Text3
+ db "@"
+
+PeoplePlaces4: ; People
+ call Random
+ maskbits NUM_TRAINER_CLASSES
+ inc a
+ cp NUM_TRAINER_CLASSES - 1
+ jr nc, PeoplePlaces4
+ push af
+ ld hl, PnP_HiddenPeople
+ ld a, [wStatusFlags]
+ bit STATUSFLAGS_HALL_OF_FAME_F, a
+ jr z, .ok
+ ld hl, PnP_HiddenPeople_BeatE4
+ ld a, [wKantoBadges]
+ cp %11111111 ; all badges
+ jr nz, .ok
+ ld hl, PnP_HiddenPeople_BeatKanto
+.ok
+ pop af
+ ld c, a
+ ld de, 1
+ push bc
+ call IsInArray
+ pop bc
+ jr c, PeoplePlaces4
+ push bc
+ callfar GetTrainerClassName
+ ld de, wStringBuffer1
+ call CopyName1
+ pop bc
+ ld b, 1
+ callfar GetTrainerName
+ ld hl, PnP_Text4
+ ld a, PLACES_AND_PEOPLE_5
+ jp NextRadioLine
+
+INCLUDE "data/radio/pnp_hidden_people.asm"
+
+PnP_Text4:
+ ; @ @ @
+ text_jump _PnP_Text4
+ db "@"
+
+PeoplePlaces5:
+ ; 0-15 are all valid indexes into .Adjectives,
+ ; so no need for a retry loop
+ call Random
+ maskbits NUM_PNP_PEOPLE_ADJECTIVES
+ ld e, a
+ ld d, 0
+ ld hl, .Adjectives
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ call Random
+ cp 4 percent
+ ld a, PLACES_AND_PEOPLE
+ jr c, .ok
+ call Random
+ cp 49 percent - 1
+ ld a, PLACES_AND_PEOPLE_4 ; People
+ jr c, .ok
+ ld a, PLACES_AND_PEOPLE_6 ; Places
+.ok
+ jp NextRadioLine
+
+.Adjectives:
+; there are NUM_PNP_PEOPLE_ADJECTIVES entries
+ dw PnP_cute
+ dw PnP_lazy
+ dw PnP_happy
+ dw PnP_noisy
+ dw PnP_precocious
+ dw PnP_bold
+ dw PnP_picky
+ dw PnP_sortofok
+ dw PnP_soso
+ dw PnP_great
+ dw PnP_mytype
+ dw PnP_cool
+ dw PnP_inspiring
+ dw PnP_weird
+ dw PnP_rightforme
+ dw PnP_odd
+
+PnP_cute:
+ ; is cute.
+ text_jump _PnP_cute
+ db "@"
+
+PnP_lazy:
+ ; is sort of lazy.
+ text_jump _PnP_lazy
+ db "@"
+
+PnP_happy:
+ ; is always happy.
+ text_jump _PnP_happy
+ db "@"
+
+PnP_noisy:
+ ; is quite noisy.
+ text_jump _PnP_noisy
+ db "@"
+
+PnP_precocious:
+ ; is precocious.
+ text_jump _PnP_precocious
+ db "@"
+
+PnP_bold:
+ ; is somewhat bold.
+ text_jump _PnP_bold
+ db "@"
+
+PnP_picky:
+ ; is too picky!
+ text_jump _PnP_picky
+ db "@"
+
+PnP_sortofok:
+ ; is sort of OK.
+ text_jump _PnP_sortofok
+ db "@"
+
+PnP_soso:
+ ; is just so-so.
+ text_jump _PnP_soso
+ db "@"
+
+PnP_great:
+ ; is actually great.
+ text_jump _PnP_great
+ db "@"
+
+PnP_mytype:
+ ; is just my type.
+ text_jump _PnP_mytype
+ db "@"
+
+PnP_cool:
+ ; is so cool, no?
+ text_jump _PnP_cool
+ db "@"
+
+PnP_inspiring:
+ ; is inspiring!
+ text_jump _PnP_inspiring
+ db "@"
+
+PnP_weird:
+ ; is kind of weird.
+ text_jump _PnP_weird
+ db "@"
+
+PnP_rightforme:
+ ; is right for me?
+ text_jump _PnP_rightforme
+ db "@"
+
+PnP_odd:
+ ; is definitely odd!
+ text_jump _PnP_odd
+ db "@"
+
+PeoplePlaces6: ; Places
+ call Random
+ cp (PnP_HiddenPlaces.End - PnP_HiddenPlaces) / 2
+ jr nc, PeoplePlaces6
+ ld hl, PnP_HiddenPlaces
+ ld c, a
+ ld b, 0
+ add hl, bc
+ add hl, bc
+ ld b, [hl]
+ inc hl
+ ld c, [hl]
+ call GetWorldMapLocation
+ ld e, a
+ farcall GetLandmarkName
+ ld hl, PnP_Text5
+ ld a, PLACES_AND_PEOPLE_7
+ jp NextRadioLine
+
+INCLUDE "data/radio/pnp_hidden_places.asm"
+
+PnP_Text5:
+ ; @ @
+ text_jump _PnP_Text5
+ db "@"
+
+PeoplePlaces7:
+ ; 0-15 are all valid indexes into .Adjectives,
+ ; so no need for a retry loop
+ call Random
+ maskbits NUM_PNP_PLACES_ADJECTIVES
+ ld e, a
+ ld d, 0
+ ld hl, .Adjectives
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ call CopyRadioTextToRAM
+ call Random
+ cp 4 percent
+ ld a, PLACES_AND_PEOPLE
+ jr c, .ok
+ call Random
+ cp 49 percent - 1
+ ld a, PLACES_AND_PEOPLE_4 ; People
+ jr c, .ok
+ ld a, PLACES_AND_PEOPLE_6 ; Places
+.ok
+ jp PrintRadioLine
+
+.Adjectives:
+; there are NUM_PNP_PLACES_ADJECTIVES entries
+ dw PnP_cute
+ dw PnP_lazy
+ dw PnP_happy
+ dw PnP_noisy
+ dw PnP_precocious
+ dw PnP_bold
+ dw PnP_picky
+ dw PnP_sortofok
+ dw PnP_soso
+ dw PnP_great
+ dw PnP_mytype
+ dw PnP_cool
+ dw PnP_inspiring
+ dw PnP_weird
+ dw PnP_rightforme
+ dw PnP_odd
+
+RocketRadio1:
+ call StartRadioStation
+ ld hl, RocketRadioText1
+ ld a, ROCKET_RADIO_2
+ jp NextRadioLine
+
+RocketRadio2:
+ ld hl, RocketRadioText2
+ ld a, ROCKET_RADIO_3
+ jp NextRadioLine
+
+RocketRadio3:
+ ld hl, RocketRadioText3
+ ld a, ROCKET_RADIO_4
+ jp NextRadioLine
+
+RocketRadio4:
+ ld hl, RocketRadioText4
+ ld a, ROCKET_RADIO_5
+ jp NextRadioLine
+
+RocketRadio5:
+ ld hl, RocketRadioText5
+ ld a, ROCKET_RADIO_6
+ jp NextRadioLine
+
+RocketRadio6:
+ ld hl, RocketRadioText6
+ ld a, ROCKET_RADIO_7
+ jp NextRadioLine
+
+RocketRadio7:
+ ld hl, RocketRadioText7
+ ld a, ROCKET_RADIO_8
+ jp NextRadioLine
+
+RocketRadio8:
+ ld hl, RocketRadioText8
+ ld a, ROCKET_RADIO_9
+ jp NextRadioLine
+
+RocketRadio9:
+ ld hl, RocketRadioText9
+ ld a, ROCKET_RADIO_10
+ jp NextRadioLine
+
+RocketRadio10:
+ ld hl, RocketRadioText10
+ ld a, ROCKET_RADIO
+ jp NextRadioLine
+
+RocketRadioText1:
+ ; … …Ahem, we are
+ text_jump _RocketRadioText1
+ db "@"
+
+RocketRadioText2:
+ ; TEAM ROCKET!
+ text_jump _RocketRadioText2
+ db "@"
+
+RocketRadioText3:
+ ; After three years
+ text_jump _RocketRadioText3
+ db "@"
+
+RocketRadioText4:
+ ; of preparation, we
+ text_jump _RocketRadioText4
+ db "@"
+
+RocketRadioText5:
+ ; have risen again
+ text_jump _RocketRadioText5
+ db "@"
+
+RocketRadioText6:
+ ; from the ashes!
+ text_jump _RocketRadioText6
+ db "@"
+
+RocketRadioText7:
+ ; GIOVANNI! @ Can you
+ text_jump _RocketRadioText7
+ db "@"
+
+RocketRadioText8:
+ ; hear?@ We did it!
+ text_jump _RocketRadioText8
+ db "@"
+
+RocketRadioText9:
+ ; @ Where is our boss?
+ text_jump _RocketRadioText9
+ db "@"
+
+RocketRadioText10:
+ ; @ Is he listening?
+ text_jump _RocketRadioText10
+ db "@"
+
+PokeFluteRadio:
+ call StartRadioStation
+ ld a, 1
+ ld [wNumRadioLinesPrinted], a
+ ret
+
+UnownRadio:
+ call StartRadioStation
+ ld a, 1
+ ld [wNumRadioLinesPrinted], a
+ ret
+
+EvolutionRadio:
+ call StartRadioStation
+ ld a, 1
+ ld [wNumRadioLinesPrinted], a
+ ret
+
+BuenasPassword1:
+; Determine if we need to be here
+ call BuenasPasswordCheckTime
+ jp nc, .PlayPassword
+ ld a, [wNumRadioLinesPrinted]
+ and a
+ jp z, BuenasPassword20
+ jp BuenasPassword8
+
+.PlayPassword:
+ call StartRadioStation
+ ld a, [hBGMapMode]
+ push af
+ xor a
+ ld [hBGMapMode], a
+ ld de, BuenasPasswordChannelName
+ hlcoord 2, 9
+ call PlaceString
+ pop af
+ ld [hBGMapMode], a
+ ld hl, BuenaRadioText1
+ ld a, BUENAS_PASSWORD_2
+ jp NextRadioLine
+
+BuenasPassword2:
+ ld hl, BuenaRadioText2
+ ld a, BUENAS_PASSWORD_3
+ jp NextRadioLine
+
+BuenasPassword3:
+ call BuenasPasswordCheckTime
+ ld hl, BuenaRadioText3
+ jp c, BuenasPasswordAfterMidnight
+ ld a, BUENAS_PASSWORD_4
+ jp NextRadioLine
+
+BuenasPassword4:
+ call BuenasPasswordCheckTime
+ jp c, BuenasPassword8
+ ld a, [wBuenasPassword]
+; If we already generated the password today, we don't need to generate a new one.
+ ld hl, wWeeklyFlags
+ bit WEEKLYFLAGS_BUENAS_PASSWORD_F, [hl]
+ jr nz, .AlreadyGotIt
+; There are only 11 groups to choose from.
+.greater_than_11
+ call Random
+ maskbits NUM_PASSWORD_CATEGORIES
+ cp NUM_PASSWORD_CATEGORIES
+ jr nc, .greater_than_11
+; Store it in the high nybble of e.
+ swap a
+ ld e, a
+; For each group, choose one of the three passwords.
+.greater_than_three
+ call Random
+ maskbits NUM_PASSWORDS_PER_CATEGORY
+ cp NUM_PASSWORDS_PER_CATEGORY
+ jr nc, .greater_than_three
+; The high nybble of wBuenasPassword will now contain the password group index, and the low nybble contains the actual password.
+ add e
+ ld [wBuenasPassword], a
+; Set the flag so that we don't generate a new password this week.
+ ld hl, wWeeklyFlags
+ set WEEKLYFLAGS_BUENAS_PASSWORD_F, [hl]
+.AlreadyGotIt:
+ ld c, a
+ call GetBuenasPassword
+ ld hl, BuenaRadioText4
+ ld a, BUENAS_PASSWORD_5
+ jp NextRadioLine
+
+GetBuenasPassword:
+; The password indices are held in c. High nybble contains the group index, low nybble contains the word index.
+; Load the password group pointer in hl.
+ ld a, c
+ swap a
+ and $f
+ ld hl, BuenasPasswordTable
+ ld d, 0
+ ld e, a
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+; Get the password type and store it in b.
+ ld a, [hli]
+ ld b, a
+ push hl
+ inc hl
+; Get the password index.
+ ld a, c
+ and $f
+ ld c, a
+ push hl
+ ld hl, .StringFunctionJumpTable
+ ld e, b
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ pop de ; de now contains the pointer to the value of this week's password, in Blue Card Points.
+ call _hl_
+ pop hl
+ ld c, [hl]
+ ret
+
+.StringFunctionJumpTable:
+; entries correspond to BUENA_* constants
+ dw .Mon ; BUENA_MON
+ dw .Item ; BUENA_ITEM
+ dw .Move ; BUENA_MOVE
+ dw .RawString ; BUENA_STRING
+
+.Mon:
+ call .GetTheIndex
+ call GetPokemonName
+ ret
+
+.Item:
+ call .GetTheIndex
+ call GetItemName
+ ret
+
+.Move:
+ call .GetTheIndex
+ call GetMoveName
+ ret
+
+.GetTheIndex:
+ ld h, 0
+ ld l, c
+ add hl, de
+ ld a, [hl]
+ ld [wNamedObjectIndexBuffer], a
+ ret
+
+.RawString:
+; Get the string from the table...
+ ld a, c
+ and a
+ jr z, .skip
+.read_loop
+ ld a, [de]
+ inc de
+ cp "@"
+ jr nz, .read_loop
+ dec c
+ jr nz, .read_loop
+; ... and copy it into wStringBuffer1.
+.skip
+ ld hl, wStringBuffer1
+.copy_loop
+ ld a, [de]
+ inc de
+ ld [hli], a
+ cp "@"
+ jr nz, .copy_loop
+ ld de, wStringBuffer1
+ ret
+
+INCLUDE "data/radio/buenas_passwords.asm"
+
+BuenasPassword5:
+ ld hl, BuenaRadioText5
+ ld a, BUENAS_PASSWORD_6
+ jp NextRadioLine
+
+BuenasPassword6:
+ ld hl, BuenaRadioText6
+ ld a, BUENAS_PASSWORD_7
+ jp NextRadioLine
+
+BuenasPassword7:
+ call BuenasPasswordCheckTime
+ ld hl, BuenaRadioText7
+ jr c, BuenasPasswordAfterMidnight
+ ld a, BUENAS_PASSWORD
+ jp NextRadioLine
+
+BuenasPasswordAfterMidnight:
+ push hl
+ ld hl, wWeeklyFlags
+ res WEEKLYFLAGS_BUENAS_PASSWORD_F, [hl]
+ pop hl
+ ld a, BUENAS_PASSWORD_8
+ jp NextRadioLine
+
+BuenasPassword8:
+ ld hl, wWeeklyFlags
+ res WEEKLYFLAGS_BUENAS_PASSWORD_F, [hl]
+ ld hl, BuenaRadioMidnightText10
+ ld a, BUENAS_PASSWORD_9
+ jp NextRadioLine
+
+BuenasPassword9:
+ ld hl, BuenaRadioMidnightText1
+ ld a, BUENAS_PASSWORD_10
+ jp NextRadioLine
+
+BuenasPassword10:
+ ld hl, BuenaRadioMidnightText2
+ ld a, BUENAS_PASSWORD_11
+ jp NextRadioLine
+
+BuenasPassword11:
+ ld hl, BuenaRadioMidnightText3
+ ld a, BUENAS_PASSWORD_12
+ jp NextRadioLine
+
+BuenasPassword12:
+ ld hl, BuenaRadioMidnightText4
+ ld a, BUENAS_PASSWORD_13
+ jp NextRadioLine
+
+BuenasPassword13:
+ ld hl, BuenaRadioMidnightText5
+ ld a, BUENAS_PASSWORD_14
+ jp NextRadioLine
+
+BuenasPassword14:
+ ld hl, BuenaRadioMidnightText6
+ ld a, BUENAS_PASSWORD_15
+ jp NextRadioLine
+
+BuenasPassword15:
+ ld hl, BuenaRadioMidnightText7
+ ld a, BUENAS_PASSWORD_16
+ jp NextRadioLine
+
+BuenasPassword16:
+ ld hl, BuenaRadioMidnightText8
+ ld a, BUENAS_PASSWORD_17
+ jp NextRadioLine
+
+BuenasPassword17:
+ ld hl, BuenaRadioMidnightText9
+ ld a, BUENAS_PASSWORD_18
+ jp NextRadioLine
+
+BuenasPassword18:
+ ld hl, BuenaRadioMidnightText10
+ ld a, BUENAS_PASSWORD_19
+ jp NextRadioLine
+
+BuenasPassword19:
+ ld hl, BuenaRadioMidnightText10
+ ld a, BUENAS_PASSWORD_20
+ jp NextRadioLine
+
+BuenasPassword20:
+ ld a, [hBGMapMode]
+ push af
+ farcall NoRadioMusic
+ farcall NoRadioName
+ pop af
+ ld [hBGMapMode], a
+ ld hl, wWeeklyFlags
+ res WEEKLYFLAGS_BUENAS_PASSWORD_F, [hl]
+ ld a, BUENAS_PASSWORD
+ ld [wCurrentRadioLine], a
+ xor a
+ ld [wNumRadioLinesPrinted], a
+ ld hl, BuenaOffTheAirText
+ ld a, BUENAS_PASSWORD_21
+ jp NextRadioLine
+
+BuenasPassword21:
+ ld a, BUENAS_PASSWORD
+ ld [wCurrentRadioLine], a
+ xor a
+ ld [wNumRadioLinesPrinted], a
+ call BuenasPasswordCheckTime
+ jp nc, BuenasPassword1
+ ld hl, BuenaOffTheAirText
+ ld a, BUENAS_PASSWORD_21
+ jp NextRadioLine
+
+BuenasPasswordCheckTime:
+ call UpdateTime
+ ld a, [hHours]
+ cp NITE_HOUR
+ ret
+
+BuenasPasswordChannelName:
+ db "BUENA'S PASSWORD@"
+
+BuenaRadioText1:
+ ; BUENA: BUENA here!
+ text_jump _BuenaRadioText1
+ db "@"
+
+BuenaRadioText2:
+ ; Today's password!
+ text_jump _BuenaRadioText2
+ db "@"
+
+BuenaRadioText3:
+ ; Let me think… It's
+ text_jump _BuenaRadioText3
+ db "@"
+
+BuenaRadioText4:
+ ; @ !
+ text_jump _BuenaRadioText4
+ db "@"
+
+BuenaRadioText5:
+ ; Don't forget it!
+ text_jump _BuenaRadioText5
+ db "@"
+
+BuenaRadioText6:
+ ; I'm in GOLDENROD's
+ text_jump _BuenaRadioText6
+ db "@"
+
+BuenaRadioText7:
+ ; RADIO TOWER!
+ text_jump _BuenaRadioText7
+ db "@"
+
+BuenaRadioMidnightText1:
+ ; BUENA: Oh my…
+ text_jump _BuenaRadioMidnightText1
+ db "@"
+
+BuenaRadioMidnightText2:
+ ; It's midnight! I
+ text_jump _BuenaRadioMidnightText2
+ db "@"
+
+BuenaRadioMidnightText3:
+ ; have to shut down!
+ text_jump _BuenaRadioMidnightText3
+ db "@"
+
+BuenaRadioMidnightText4:
+ ; Thanks for tuning
+ text_jump _BuenaRadioMidnightText4
+ db "@"
+
+BuenaRadioMidnightText5:
+ ; in to the end! But
+ text_jump _BuenaRadioMidnightText5
+ db "@"
+
+BuenaRadioMidnightText6:
+ ; don't stay up too
+ text_jump _BuenaRadioMidnightText6
+ db "@"
+
+BuenaRadioMidnightText7:
+ ; late! Presented to
+ text_jump _BuenaRadioMidnightText7
+ db "@"
+
+BuenaRadioMidnightText8:
+ ; you by DJ BUENA!
+ text_jump _BuenaRadioMidnightText8
+ db "@"
+
+BuenaRadioMidnightText9:
+ ; I'm outta here!
+ text_jump _BuenaRadioMidnightText9
+ db "@"
+
+BuenaRadioMidnightText10:
+ ; …
+ text_jump _BuenaRadioMidnightText10
+ db "@"
+
+BuenaOffTheAirText:
+ ;
+ text_jump _BuenaOffTheAirText
+ db "@"
+
+CopyRadioTextToRAM:
+ ld a, [hl]
+ cp TX_FAR
+ jp z, FarCopyRadioText
+ ld de, wRadioText
+ ld bc, SCREEN_WIDTH * 2
+ jp CopyBytes
+
+StartRadioStation:
+ ld a, [wNumRadioLinesPrinted]
+ and a
+ ret nz
+ call RadioTerminator
+ call PrintText
+ ld hl, RadioChannelSongs
+ ld a, [wCurrentRadioLine]
+ ld c, a
+ ld b, 0
+ add hl, bc
+ add hl, bc
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ callfar RadioMusicRestartDE
+ ret
+
+INCLUDE "data/radio/channel_music.asm"
+
+NextRadioLine:
+ push af
+ call CopyRadioTextToRAM
+ pop af
+ jp PrintRadioLine