Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pret
GitHub Repository: pret/pokered
Path: blob/master/home/overworld.asm
2023 views
1
HandleMidJump::
2
; Handle the player jumping down
3
; a ledge in the overworld.
4
farjp _HandleMidJump
5
6
EnterMap::
7
; Load a new map.
8
ld a, PAD_BUTTONS | PAD_CTRL_PAD
9
ld [wJoyIgnore], a
10
call LoadMapData
11
farcall ClearVariablesOnEnterMap
12
ld hl, wStatusFlags2
13
bit BIT_WILD_ENCOUNTER_COOLDOWN, [hl]
14
jr z, .skipGivingThreeStepsOfNoRandomBattles
15
ld a, 3 ; minimum number of steps between battles
16
ld [wNumberOfNoRandomBattleStepsLeft], a
17
.skipGivingThreeStepsOfNoRandomBattles
18
ld hl, wStatusFlags4
19
bit BIT_BATTLE_OVER_OR_BLACKOUT, [hl]
20
res BIT_BATTLE_OVER_OR_BLACKOUT, [hl]
21
call z, ResetUsingStrengthOutOfBattleBit
22
call nz, MapEntryAfterBattle
23
ld hl, wStatusFlags6
24
ld a, [hl]
25
and (1 << BIT_FLY_WARP) | (1 << BIT_DUNGEON_WARP)
26
jr z, .didNotEnterUsingFlyWarpOrDungeonWarp
27
res BIT_FLY_WARP, [hl]
28
farcall EnterMapAnim
29
call UpdateSprites
30
.didNotEnterUsingFlyWarpOrDungeonWarp
31
farcall CheckForceBikeOrSurf ; handle currents in SF islands and forced bike riding in cycling road
32
ld hl, wStatusFlags3
33
res BIT_NO_NPC_FACE_PLAYER, [hl]
34
call UpdateSprites
35
ld hl, wCurrentMapScriptFlags
36
set BIT_CUR_MAP_LOADED_1, [hl]
37
set BIT_CUR_MAP_LOADED_2, [hl]
38
xor a
39
ld [wJoyIgnore], a
40
41
OverworldLoop::
42
call DelayFrame
43
OverworldLoopLessDelay::
44
call DelayFrame
45
call LoadGBPal
46
ld a, [wMovementFlags]
47
bit BIT_LEDGE_OR_FISHING, a
48
call nz, HandleMidJump
49
ld a, [wWalkCounter]
50
and a
51
jp nz, .moveAhead ; if the player sprite has not yet completed the walking animation
52
call JoypadOverworld ; get joypad state (which is possibly simulated)
53
farcall SafariZoneCheck
54
ld a, [wSafariZoneGameOver]
55
and a
56
jp nz, WarpFound2
57
ld hl, wStatusFlags3
58
bit BIT_WARP_FROM_CUR_SCRIPT, [hl]
59
res BIT_WARP_FROM_CUR_SCRIPT, [hl]
60
jp nz, WarpFound2
61
ld a, [wStatusFlags6]
62
and (1 << BIT_FLY_WARP) | (1 << BIT_DUNGEON_WARP)
63
jp nz, HandleFlyWarpOrDungeonWarp
64
ld a, [wCurOpponent]
65
and a
66
jp nz, .newBattle
67
ld a, [wStatusFlags5]
68
bit BIT_SCRIPTED_MOVEMENT_STATE, a
69
jr z, .notSimulating
70
ldh a, [hJoyHeld]
71
jr .checkIfStartIsPressed
72
.notSimulating
73
ldh a, [hJoyPressed]
74
.checkIfStartIsPressed
75
bit B_PAD_START, a
76
jr z, .startButtonNotPressed
77
; if START is pressed
78
xor a ; TEXT_START_MENU
79
ldh [hTextID], a
80
jp .displayDialogue
81
.startButtonNotPressed
82
bit B_PAD_A, a
83
jp z, .checkIfDownButtonIsPressed
84
; if A is pressed
85
ld a, [wStatusFlags5]
86
bit BIT_UNKNOWN_5_2, a
87
jp nz, .noDirectionButtonsPressed
88
call IsPlayerCharacterBeingControlledByGame
89
jr nz, .checkForOpponent
90
call CheckForHiddenEventOrBookshelfOrCardKeyDoor
91
ldh a, [hItemAlreadyFound]
92
and a
93
jp z, OverworldLoop ; jump if a hidden event or bookshelf was found, but not if a card key door was found
94
call IsSpriteOrSignInFrontOfPlayer
95
ldh a, [hTextID]
96
and a
97
jp z, OverworldLoop
98
.displayDialogue
99
predef GetTileAndCoordsInFrontOfPlayer
100
call UpdateSprites
101
ld a, [wMiscFlags]
102
bit BIT_TURNING, a
103
jr nz, .checkForOpponent
104
bit BIT_SEEN_BY_TRAINER, a
105
jr nz, .checkForOpponent
106
lda_coord 8, 9
107
ld [wTilePlayerStandingOn], a ; checked when using Surf for forbidden tile pairs
108
call DisplayTextID ; display either the start menu or the NPC/sign text
109
ld a, [wEnteringCableClub]
110
and a
111
jr z, .checkForOpponent
112
dec a
113
ld a, 0
114
ld [wEnteringCableClub], a
115
jr z, .changeMap
116
; XXX can this code be reached?
117
predef TryLoadSaveFile
118
ld a, [wCurMap]
119
ld [wDestinationMap], a
120
call PrepareForSpecialWarp
121
ld a, [wCurMap]
122
call SwitchToMapRomBank
123
ld hl, wCurMapTileset
124
set BIT_NO_PREVIOUS_MAP, [hl]
125
.changeMap
126
jp EnterMap
127
.checkForOpponent
128
ld a, [wCurOpponent]
129
and a
130
jp nz, .newBattle
131
jp OverworldLoop
132
.noDirectionButtonsPressed
133
ld hl, wMiscFlags
134
res BIT_TURNING, [hl]
135
call UpdateSprites
136
ld a, 1
137
ld [wCheckFor180DegreeTurn], a
138
ld a, [wPlayerMovingDirection] ; the direction that was pressed last time
139
and a
140
jp z, OverworldLoop
141
; if a direction was pressed last time
142
ld [wPlayerLastStopDirection], a ; save the last direction
143
xor a
144
ld [wPlayerMovingDirection], a ; zero the direction
145
jp OverworldLoop
146
147
.checkIfDownButtonIsPressed
148
ldh a, [hJoyHeld] ; current joypad state
149
bit B_PAD_DOWN, a
150
jr z, .checkIfUpButtonIsPressed
151
ld a, 1
152
ld [wSpritePlayerStateData1YStepVector], a
153
ld a, PLAYER_DIR_DOWN
154
jr .handleDirectionButtonPress
155
156
.checkIfUpButtonIsPressed
157
bit B_PAD_UP, a
158
jr z, .checkIfLeftButtonIsPressed
159
ld a, -1
160
ld [wSpritePlayerStateData1YStepVector], a
161
ld a, PLAYER_DIR_UP
162
jr .handleDirectionButtonPress
163
164
.checkIfLeftButtonIsPressed
165
bit B_PAD_LEFT, a
166
jr z, .checkIfRightButtonIsPressed
167
ld a, -1
168
ld [wSpritePlayerStateData1XStepVector], a
169
ld a, PLAYER_DIR_LEFT
170
jr .handleDirectionButtonPress
171
172
.checkIfRightButtonIsPressed
173
bit B_PAD_RIGHT, a
174
jr z, .noDirectionButtonsPressed
175
ld a, 1
176
ld [wSpritePlayerStateData1XStepVector], a
177
178
179
.handleDirectionButtonPress
180
ld [wPlayerDirection], a ; new direction
181
ld a, [wStatusFlags5]
182
bit BIT_SCRIPTED_MOVEMENT_STATE, a
183
jr nz, .noDirectionChange ; ignore direction changes if we are
184
ld a, [wCheckFor180DegreeTurn]
185
and a
186
jr z, .noDirectionChange
187
ld a, [wPlayerDirection] ; new direction
188
ld b, a
189
ld a, [wPlayerLastStopDirection] ; old direction
190
cp b
191
jr z, .noDirectionChange
192
; Check whether the player did a 180-degree turn.
193
; It appears that this code was supposed to show the player rotate by having
194
; the player's sprite face an intermediate direction before facing the opposite
195
; direction (instead of doing an instantaneous about-face), but the intermediate
196
; direction is only set for a short period of time. It is unlikely for it to
197
; ever be visible because DelayFrame is called at the start of OverworldLoop and
198
; normally not enough cycles would be executed between then and the time the
199
; direction is set for V-blank to occur while the direction is still set.
200
swap a ; put old direction in upper half
201
or b ; put new direction in lower half
202
cp (PLAYER_DIR_DOWN << 4) | PLAYER_DIR_UP ; change dir from down to up
203
jr nz, .notDownToUp
204
ld a, PLAYER_DIR_LEFT
205
ld [wPlayerMovingDirection], a
206
jr .holdIntermediateDirectionLoop
207
.notDownToUp
208
cp (PLAYER_DIR_UP << 4) | PLAYER_DIR_DOWN ; change dir from up to down
209
jr nz, .notUpToDown
210
ld a, PLAYER_DIR_RIGHT
211
ld [wPlayerMovingDirection], a
212
jr .holdIntermediateDirectionLoop
213
.notUpToDown
214
cp (PLAYER_DIR_RIGHT << 4) | PLAYER_DIR_LEFT ; change dir from right to left
215
jr nz, .notRightToLeft
216
ld a, PLAYER_DIR_DOWN
217
ld [wPlayerMovingDirection], a
218
jr .holdIntermediateDirectionLoop
219
.notRightToLeft
220
cp (PLAYER_DIR_LEFT << 4) | PLAYER_DIR_RIGHT ; change dir from left to right
221
jr nz, .holdIntermediateDirectionLoop
222
ld a, PLAYER_DIR_UP
223
ld [wPlayerMovingDirection], a
224
.holdIntermediateDirectionLoop
225
ld hl, wMiscFlags
226
set BIT_TURNING, [hl]
227
ld hl, wCheckFor180DegreeTurn
228
dec [hl]
229
jr nz, .holdIntermediateDirectionLoop
230
ld a, [wPlayerDirection]
231
ld [wPlayerMovingDirection], a
232
call NewBattle
233
jp c, .battleOccurred
234
jp OverworldLoop
235
236
.noDirectionChange
237
ld a, [wPlayerDirection] ; current direction
238
ld [wPlayerMovingDirection], a ; save direction
239
call UpdateSprites
240
ld a, [wWalkBikeSurfState]
241
cp $02 ; surfing
242
jr z, .surfing
243
; not surfing
244
call CollisionCheckOnLand
245
jr nc, .noCollision
246
; collision occurred
247
push hl
248
ld hl, wMovementFlags
249
bit BIT_STANDING_ON_WARP, [hl]
250
pop hl
251
jp z, OverworldLoop
252
; collision occurred while standing on a warp
253
push hl
254
call ExtraWarpCheck ; sets carry if there is a potential to warp
255
pop hl
256
jp c, CheckWarpsCollision
257
jp OverworldLoop
258
259
.surfing
260
call CollisionCheckOnWater
261
jp c, OverworldLoop
262
263
.noCollision
264
ld a, $08
265
ld [wWalkCounter], a
266
jr .moveAhead2
267
268
.moveAhead
269
ld a, [wMovementFlags]
270
bit BIT_SPINNING, a
271
jr z, .noSpinning
272
farcall LoadSpinnerArrowTiles
273
.noSpinning
274
call UpdateSprites
275
276
.moveAhead2
277
ld hl, wMiscFlags
278
res BIT_TURNING, [hl]
279
ld a, [wWalkBikeSurfState]
280
dec a ; riding a bike?
281
jr nz, .normalPlayerSpriteAdvancement
282
ld a, [wMovementFlags]
283
bit BIT_LEDGE_OR_FISHING, a
284
jr nz, .normalPlayerSpriteAdvancement
285
call DoBikeSpeedup
286
.normalPlayerSpriteAdvancement
287
call AdvancePlayerSprite
288
ld a, [wWalkCounter]
289
and a
290
jp nz, CheckMapConnections ; it seems like this check will never succeed (the other place where CheckMapConnections is run works)
291
; walking animation finished
292
ld a, [wStatusFlags5]
293
bit BIT_SCRIPTED_MOVEMENT_STATE, a
294
jr nz, .doneStepCounting ; if button presses are being simulated, don't count steps
295
; step counting
296
ld hl, wStepCounter
297
dec [hl]
298
ld a, [wStatusFlags2]
299
bit BIT_WILD_ENCOUNTER_COOLDOWN, a
300
jr z, .doneStepCounting
301
ld hl, wNumberOfNoRandomBattleStepsLeft
302
dec [hl]
303
jr nz, .doneStepCounting
304
ld hl, wStatusFlags2
305
res BIT_WILD_ENCOUNTER_COOLDOWN, [hl]
306
.doneStepCounting
307
CheckEvent EVENT_IN_SAFARI_ZONE
308
jr z, .notSafariZone
309
farcall SafariZoneCheckSteps
310
ld a, [wSafariZoneGameOver]
311
and a
312
jp nz, WarpFound2
313
.notSafariZone
314
ld a, [wIsInBattle]
315
and a
316
jp nz, CheckWarpsNoCollision
317
predef ApplyOutOfBattlePoisonDamage ; also increment daycare mon exp
318
ld a, [wOutOfBattleBlackout]
319
and a
320
jp nz, HandleBlackOut ; if all pokemon fainted
321
.newBattle
322
call NewBattle
323
ld hl, wMovementFlags
324
res BIT_STANDING_ON_WARP, [hl]
325
jp nc, CheckWarpsNoCollision ; check for warps if there was no battle
326
.battleOccurred
327
ld hl, wStatusFlags3
328
res BIT_TALKED_TO_TRAINER, [hl]
329
ld hl, wStatusFlags7
330
res BIT_TRAINER_BATTLE, [hl]
331
ld hl, wCurrentMapScriptFlags
332
set BIT_CUR_MAP_LOADED_1, [hl]
333
set BIT_CUR_MAP_LOADED_2, [hl]
334
xor a
335
ldh [hJoyHeld], a
336
ld a, [wCurMap]
337
cp CINNABAR_GYM
338
jr nz, .notCinnabarGym
339
SetEvent EVENT_2A7
340
.notCinnabarGym
341
ld hl, wStatusFlags4
342
set BIT_BATTLE_OVER_OR_BLACKOUT, [hl]
343
ld a, [wCurMap]
344
cp OAKS_LAB
345
jp z, .noFaintCheck ; no blacking out if the player lost to the rival in Oak's lab
346
callfar AnyPartyAlive
347
ld a, d
348
and a
349
jr z, .allPokemonFainted
350
.noFaintCheck
351
ld c, 10
352
call DelayFrames
353
jp EnterMap
354
.allPokemonFainted
355
ld a, $ff
356
ld [wIsInBattle], a
357
call RunMapScript
358
jp HandleBlackOut
359
360
; function to determine if there will be a battle and execute it (either a trainer battle or wild battle)
361
; sets carry if a battle occurred and unsets carry if not
362
NewBattle::
363
ld a, [wStatusFlags3]
364
bit BIT_ON_DUNGEON_WARP, a
365
jr nz, .noBattle
366
call IsPlayerCharacterBeingControlledByGame
367
jr nz, .noBattle ; no battle if the player character is under the game's control
368
ld a, [wStatusFlags4]
369
bit BIT_NO_BATTLES, a
370
jr nz, .noBattle
371
farjp InitBattle
372
.noBattle
373
and a
374
ret
375
376
; function to make bikes twice as fast as walking
377
DoBikeSpeedup::
378
ld a, [wNPCMovementScriptPointerTableNum]
379
and a
380
ret nz
381
ld a, [wCurMap]
382
cp ROUTE_17 ; Cycling Road
383
jr nz, .goFaster
384
ldh a, [hJoyHeld]
385
and PAD_UP | PAD_LEFT | PAD_RIGHT
386
ret nz
387
.goFaster
388
jp AdvancePlayerSprite
389
390
; check if the player has stepped onto a warp after having not collided
391
CheckWarpsNoCollision::
392
ld a, [wNumberOfWarps]
393
and a
394
jp z, CheckMapConnections
395
ld a, [wNumberOfWarps]
396
ld b, 0
397
ld c, a
398
ld a, [wYCoord]
399
ld d, a
400
ld a, [wXCoord]
401
ld e, a
402
ld hl, wWarpEntries
403
CheckWarpsNoCollisionLoop::
404
ld a, [hli] ; check if the warp's Y position matches
405
cp d
406
jr nz, CheckWarpsNoCollisionRetry1
407
ld a, [hli] ; check if the warp's X position matches
408
cp e
409
jr nz, CheckWarpsNoCollisionRetry2
410
; if a match was found
411
push hl
412
push bc
413
ld hl, wMovementFlags
414
set BIT_STANDING_ON_WARP, [hl]
415
farcall IsPlayerStandingOnDoorTileOrWarpTile
416
pop bc
417
pop hl
418
jr c, WarpFound1 ; jump if standing on door or warp
419
push hl
420
push bc
421
call ExtraWarpCheck
422
pop bc
423
pop hl
424
jr nc, CheckWarpsNoCollisionRetry2
425
; if the extra check passed
426
ld a, [wStatusFlags7]
427
bit BIT_FORCED_WARP, a
428
jr nz, WarpFound1
429
push de
430
push bc
431
call Joypad
432
pop bc
433
pop de
434
ldh a, [hJoyHeld]
435
and PAD_CTRL_PAD
436
jr z, CheckWarpsNoCollisionRetry2 ; if directional buttons aren't being pressed, do not pass through the warp
437
jr WarpFound1
438
439
; check if the player has stepped onto a warp after having collided
440
CheckWarpsCollision::
441
ld a, [wNumberOfWarps]
442
ld c, a
443
ld hl, wWarpEntries
444
.loop
445
ld a, [hli] ; Y coordinate of warp
446
ld b, a
447
ld a, [wYCoord]
448
cp b
449
jr nz, .retry1
450
ld a, [hli] ; X coordinate of warp
451
ld b, a
452
ld a, [wXCoord]
453
cp b
454
jr nz, .retry2
455
ld a, [hli]
456
ld [wDestinationWarpID], a
457
ld a, [hl]
458
ldh [hWarpDestinationMap], a
459
jr WarpFound2
460
.retry1
461
inc hl
462
.retry2
463
inc hl
464
inc hl
465
dec c
466
jr nz, .loop
467
jp OverworldLoop
468
469
CheckWarpsNoCollisionRetry1::
470
inc hl
471
CheckWarpsNoCollisionRetry2::
472
inc hl
473
inc hl
474
jp ContinueCheckWarpsNoCollisionLoop
475
476
WarpFound1::
477
ld a, [hli]
478
ld [wDestinationWarpID], a
479
ld a, [hli]
480
ldh [hWarpDestinationMap], a
481
482
WarpFound2::
483
ld a, [wNumberOfWarps]
484
sub c
485
ld [wWarpedFromWhichWarp], a ; save ID of used warp
486
ld a, [wCurMap]
487
ld [wWarpedFromWhichMap], a
488
call CheckIfInOutsideMap
489
jr nz, .indoorMaps
490
; this is for handling "outside" maps that can't have the 0xFF destination map
491
ld a, [wCurMap]
492
ld [wLastMap], a
493
ld a, [wCurMapWidth]
494
ld [wUnusedLastMapWidth], a
495
ldh a, [hWarpDestinationMap]
496
ld [wCurMap], a
497
cp ROCK_TUNNEL_1F
498
jr nz, .notRockTunnel
499
ld a, $06
500
ld [wMapPalOffset], a
501
call GBFadeOutToBlack
502
.notRockTunnel
503
call PlayMapChangeSound
504
jr .done
505
506
; for maps that can have the 0xFF destination map, which means to return to the outside map
507
; not all these maps are necessarily indoors, though
508
.indoorMaps
509
ldh a, [hWarpDestinationMap]
510
cp LAST_MAP
511
jr z, .goBackOutside
512
; if not going back to the previous map
513
ld [wCurMap], a
514
farcall IsPlayerStandingOnWarpPadOrHole
515
ld a, [wStandingOnWarpPadOrHole]
516
dec a ; is the player on a warp pad?
517
jr nz, .notWarpPad
518
; if the player is on a warp pad
519
ld hl, wStatusFlags6
520
set BIT_FLY_WARP, [hl]
521
call LeaveMapAnim
522
jr .skipMapChangeSound
523
.notWarpPad
524
call PlayMapChangeSound
525
.skipMapChangeSound
526
ld hl, wMovementFlags
527
res BIT_STANDING_ON_DOOR, [hl]
528
res BIT_EXITING_DOOR, [hl]
529
jr .done
530
.goBackOutside
531
ld a, [wLastMap]
532
ld [wCurMap], a
533
call PlayMapChangeSound
534
xor a
535
ld [wMapPalOffset], a
536
.done
537
ld hl, wMovementFlags
538
set BIT_STANDING_ON_DOOR, [hl] ; have the player's sprite step out from the door (if there is one)
539
call IgnoreInputForHalfSecond
540
jp EnterMap
541
542
ContinueCheckWarpsNoCollisionLoop::
543
inc b ; increment warp number
544
dec c ; decrement number of warps
545
jp nz, CheckWarpsNoCollisionLoop
546
547
; if no matching warp was found
548
CheckMapConnections::
549
; check west map
550
ld a, [wXCoord]
551
cp $ff
552
jr nz, .checkEastMap
553
ld a, [wWestConnectedMap]
554
ld [wCurMap], a
555
ld a, [wWestConnectedMapXAlignment] ; new X coordinate upon entering west map
556
ld [wXCoord], a
557
ld a, [wYCoord]
558
ld c, a
559
ld a, [wWestConnectedMapYAlignment] ; Y adjustment upon entering west map
560
add c
561
ld c, a
562
ld [wYCoord], a
563
ld a, [wWestConnectedMapViewPointer] ; pointer to upper left corner of map without adjustment for Y position
564
ld l, a
565
ld a, [wWestConnectedMapViewPointer + 1]
566
ld h, a
567
srl c
568
jr z, .savePointer1
569
.pointerAdjustmentLoop1
570
ld a, [wWestConnectedMapWidth]
571
add MAP_BORDER * 2
572
ld e, a
573
ld d, 0
574
ld b, 0
575
add hl, de
576
dec c
577
jr nz, .pointerAdjustmentLoop1
578
.savePointer1
579
ld a, l
580
ld [wCurrentTileBlockMapViewPointer], a ; pointer to upper left corner of current tile block map section
581
ld a, h
582
ld [wCurrentTileBlockMapViewPointer + 1], a
583
jp .loadNewMap
584
585
.checkEastMap
586
ld b, a
587
ld a, [wCurrentMapWidth2]
588
cp b
589
jr nz, .checkNorthMap
590
ld a, [wEastConnectedMap]
591
ld [wCurMap], a
592
ld a, [wEastConnectedMapXAlignment] ; new X coordinate upon entering east map
593
ld [wXCoord], a
594
ld a, [wYCoord]
595
ld c, a
596
ld a, [wEastConnectedMapYAlignment] ; Y adjustment upon entering east map
597
add c
598
ld c, a
599
ld [wYCoord], a
600
ld a, [wEastConnectedMapViewPointer] ; pointer to upper left corner of map without adjustment for Y position
601
ld l, a
602
ld a, [wEastConnectedMapViewPointer + 1]
603
ld h, a
604
srl c
605
jr z, .savePointer2
606
.pointerAdjustmentLoop2
607
ld a, [wEastConnectedMapWidth]
608
add MAP_BORDER * 2
609
ld e, a
610
ld d, 0
611
ld b, 0
612
add hl, de
613
dec c
614
jr nz, .pointerAdjustmentLoop2
615
.savePointer2
616
ld a, l
617
ld [wCurrentTileBlockMapViewPointer], a ; pointer to upper left corner of current tile block map section
618
ld a, h
619
ld [wCurrentTileBlockMapViewPointer + 1], a
620
jp .loadNewMap
621
622
.checkNorthMap
623
ld a, [wYCoord]
624
cp $ff
625
jr nz, .checkSouthMap
626
ld a, [wNorthConnectedMap]
627
ld [wCurMap], a
628
ld a, [wNorthConnectedMapYAlignment] ; new Y coordinate upon entering north map
629
ld [wYCoord], a
630
ld a, [wXCoord]
631
ld c, a
632
ld a, [wNorthConnectedMapXAlignment] ; X adjustment upon entering north map
633
add c
634
ld c, a
635
ld [wXCoord], a
636
ld a, [wNorthConnectedMapViewPointer] ; pointer to upper left corner of map without adjustment for X position
637
ld l, a
638
ld a, [wNorthConnectedMapViewPointer + 1]
639
ld h, a
640
ld b, 0
641
srl c
642
add hl, bc
643
ld a, l
644
ld [wCurrentTileBlockMapViewPointer], a ; pointer to upper left corner of current tile block map section
645
ld a, h
646
ld [wCurrentTileBlockMapViewPointer + 1], a
647
jp .loadNewMap
648
649
.checkSouthMap
650
ld b, a
651
ld a, [wCurrentMapHeight2]
652
cp b
653
jr nz, .didNotEnterConnectedMap
654
ld a, [wSouthConnectedMap]
655
ld [wCurMap], a
656
ld a, [wSouthConnectedMapYAlignment] ; new Y coordinate upon entering south map
657
ld [wYCoord], a
658
ld a, [wXCoord]
659
ld c, a
660
ld a, [wSouthConnectedMapXAlignment] ; X adjustment upon entering south map
661
add c
662
ld c, a
663
ld [wXCoord], a
664
ld a, [wSouthConnectedMapViewPointer] ; pointer to upper left corner of map without adjustment for X position
665
ld l, a
666
ld a, [wSouthConnectedMapViewPointer + 1]
667
ld h, a
668
ld b, 0
669
srl c
670
add hl, bc
671
ld a, l
672
ld [wCurrentTileBlockMapViewPointer], a ; pointer to upper left corner of current tile block map section
673
ld a, h
674
ld [wCurrentTileBlockMapViewPointer + 1], a
675
.loadNewMap ; load the connected map that was entered
676
call LoadMapHeader
677
call PlayDefaultMusicFadeOutCurrent
678
ld b, SET_PAL_OVERWORLD
679
call RunPaletteCommand
680
; Since the sprite set shouldn't change, this will just update VRAM slots at
681
; x#SPRITESTATEDATA2_IMAGEBASEOFFSET without loading any tile patterns.
682
farcall InitMapSprites
683
call LoadTileBlockMap
684
jp OverworldLoopLessDelay
685
686
.didNotEnterConnectedMap
687
jp OverworldLoop
688
689
; function to play a sound when changing maps
690
PlayMapChangeSound::
691
lda_coord 8, 8 ; upper left tile of the 4x4 square the player's sprite is standing on
692
cp $0b ; door tile in tileset 0
693
jr nz, .didNotGoThroughDoor
694
ld a, SFX_GO_INSIDE
695
jr .playSound
696
.didNotGoThroughDoor
697
ld a, SFX_GO_OUTSIDE
698
.playSound
699
call PlaySound
700
ld a, [wMapPalOffset]
701
and a
702
ret nz
703
jp GBFadeOutToBlack
704
705
CheckIfInOutsideMap::
706
; If the player is in an outside map (a town or route), set the z flag
707
ld a, [wCurMapTileset]
708
and a ; most towns/routes have tileset 0 (OVERWORLD)
709
ret z
710
cp PLATEAU ; Route 23 / Indigo Plateau
711
ret
712
713
; this function is an extra check that sometimes has to pass in order to warp, beyond just standing on a warp
714
; the "sometimes" qualification is necessary because of CheckWarpsNoCollision's behavior
715
; depending on the map, either "function 1" or "function 2" is used for the check
716
; "function 1" passes when the player is at the edge of the map and is facing towards the outside of the map
717
; "function 2" passes when the the tile in front of the player is among a certain set
718
; sets carry if the check passes, otherwise clears carry
719
ExtraWarpCheck::
720
ld a, [wCurMap]
721
cp SS_ANNE_3F
722
jr z, .useFunction1
723
cp ROCKET_HIDEOUT_B1F
724
jr z, .useFunction2
725
cp ROCKET_HIDEOUT_B2F
726
jr z, .useFunction2
727
cp ROCKET_HIDEOUT_B4F
728
jr z, .useFunction2
729
cp ROCK_TUNNEL_1F
730
jr z, .useFunction2
731
ld a, [wCurMapTileset]
732
and a ; outside tileset (OVERWORLD)
733
jr z, .useFunction2
734
cp SHIP ; S.S. Anne tileset
735
jr z, .useFunction2
736
cp SHIP_PORT ; Vermilion Port tileset
737
jr z, .useFunction2
738
cp PLATEAU ; Indigo Plateau tileset
739
jr z, .useFunction2
740
.useFunction1
741
ld hl, IsPlayerFacingEdgeOfMap
742
jr .doBankswitch
743
.useFunction2
744
ld hl, IsWarpTileInFrontOfPlayer
745
.doBankswitch
746
ld b, BANK(IsWarpTileInFrontOfPlayer)
747
jp Bankswitch
748
749
MapEntryAfterBattle::
750
farcall IsPlayerStandingOnWarp ; for enabling warp testing after collisions
751
ld a, [wMapPalOffset]
752
and a
753
jp z, GBFadeInFromWhite
754
jp LoadGBPal
755
756
HandleBlackOut::
757
; For when all the player's pokemon faint.
758
; Does not print the "blacked out" message.
759
call GBFadeOutToBlack
760
ld a, $08
761
call StopMusic
762
ld hl, wStatusFlags4
763
res BIT_BATTLE_OVER_OR_BLACKOUT, [hl]
764
ld a, BANK(ResetStatusAndHalveMoneyOnBlackout) ; also BANK(PrepareForSpecialWarp) and BANK(SpecialEnterMap)
765
ldh [hLoadedROMBank], a
766
ld [rROMB], a
767
call ResetStatusAndHalveMoneyOnBlackout
768
call PrepareForSpecialWarp
769
call PlayDefaultMusicFadeOutCurrent
770
jp SpecialEnterMap
771
772
StopMusic::
773
ld [wAudioFadeOutControl], a
774
ld a, SFX_STOP_ALL_MUSIC
775
ld [wNewSoundID], a
776
call PlaySound
777
.wait
778
ld a, [wAudioFadeOutControl]
779
and a
780
jr nz, .wait
781
jp StopAllSounds
782
783
HandleFlyWarpOrDungeonWarp::
784
call UpdateSprites
785
call Delay3
786
xor a
787
ld [wBattleResult], a
788
ld [wWalkBikeSurfState], a
789
ld [wIsInBattle], a
790
ld [wMapPalOffset], a
791
ld hl, wStatusFlags6
792
set BIT_FLY_OR_DUNGEON_WARP, [hl]
793
res BIT_ALWAYS_ON_BIKE, [hl]
794
call LeaveMapAnim
795
ld a, BANK(PrepareForSpecialWarp)
796
ldh [hLoadedROMBank], a
797
ld [rROMB], a
798
call PrepareForSpecialWarp
799
jp SpecialEnterMap
800
801
LeaveMapAnim::
802
farjp _LeaveMapAnim
803
804
LoadPlayerSpriteGraphics::
805
; Load sprite graphics based on whether the player is standing, biking, or surfing.
806
807
; 0: standing
808
; 1: biking
809
; 2: surfing
810
811
ld a, [wWalkBikeSurfState]
812
dec a
813
jr z, .ridingBike
814
815
ldh a, [hTileAnimations]
816
and a
817
jr nz, .determineGraphics
818
jr .startWalking
819
820
.ridingBike
821
; If the bike can't be used,
822
; start walking instead.
823
call IsBikeRidingAllowed
824
jr c, .determineGraphics
825
826
.startWalking
827
xor a
828
ld [wWalkBikeSurfState], a
829
ld [wWalkBikeSurfStateCopy], a
830
jp LoadWalkingPlayerSpriteGraphics
831
832
.determineGraphics
833
ld a, [wWalkBikeSurfState]
834
and a
835
jp z, LoadWalkingPlayerSpriteGraphics
836
dec a
837
jp z, LoadBikePlayerSpriteGraphics
838
dec a
839
jp z, LoadSurfingPlayerSpriteGraphics
840
jp LoadWalkingPlayerSpriteGraphics
841
842
IsBikeRidingAllowed::
843
; The bike can be used on Route 23 and Indigo Plateau,
844
; or maps with tilesets in BikeRidingTilesets.
845
; Return carry if biking is allowed.
846
847
ld a, [wCurMap]
848
cp ROUTE_23
849
jr z, .allowed
850
cp INDIGO_PLATEAU
851
jr z, .allowed
852
853
ld a, [wCurMapTileset]
854
ld b, a
855
ld hl, BikeRidingTilesets
856
.loop
857
ld a, [hli]
858
cp b
859
jr z, .allowed
860
inc a
861
jr nz, .loop
862
and a
863
ret
864
865
.allowed
866
scf
867
ret
868
869
INCLUDE "data/tilesets/bike_riding_tilesets.asm"
870
871
; load the tile pattern data of the current tileset into VRAM
872
LoadTilesetTilePatternData::
873
ld a, [wTilesetGfxPtr]
874
ld l, a
875
ld a, [wTilesetGfxPtr + 1]
876
ld h, a
877
ld de, vTileset
878
ld bc, $600
879
ld a, [wTilesetBank]
880
jp FarCopyData2
881
882
; this loads the current map's complete tile map (which references blocks, not individual tiles) to wOverworldMap
883
; it can also load partial tile maps of connected maps into a border of length 3 around the current map
884
LoadTileBlockMap::
885
; fill wOverworldMap-wOverworldMapEnd with the background tile
886
ld hl, wOverworldMap
887
ld a, [wMapBackgroundTile]
888
ld d, a
889
ld bc, wOverworldMapEnd - wOverworldMap
890
.backgroundTileLoop
891
ld a, d
892
ld [hli], a
893
dec bc
894
ld a, c
895
or b
896
jr nz, .backgroundTileLoop
897
; load tile map of current map (made of tile block IDs)
898
; a 3-byte border at the edges of the map is kept so that there is space for map connections
899
ld hl, wOverworldMap
900
ld a, [wCurMapWidth]
901
ldh [hMapWidth], a
902
add MAP_BORDER * 2 ; east and west
903
ldh [hMapStride], a ; map width + border
904
ld b, 0
905
ld c, a
906
; make space for north border (next 3 lines)
907
add hl, bc
908
add hl, bc
909
add hl, bc
910
ld c, MAP_BORDER
911
add hl, bc ; this puts us past the (west) border
912
ld a, [wCurMapDataPtr] ; tile map pointer
913
ld e, a
914
ld a, [wCurMapDataPtr + 1]
915
ld d, a ; de = tile map pointer
916
ld a, [wCurMapHeight]
917
ld b, a
918
.rowLoop ; copy one row each iteration
919
push hl
920
ldh a, [hMapWidth] ; map width (without border)
921
ld c, a
922
.rowInnerLoop
923
ld a, [de]
924
inc de
925
ld [hli], a
926
dec c
927
jr nz, .rowInnerLoop
928
; add the map width plus the border to the base address of the current row to get the next row's address
929
pop hl
930
ldh a, [hMapStride] ; map width + border
931
add l
932
ld l, a
933
jr nc, .noCarry
934
inc h
935
.noCarry
936
dec b
937
jr nz, .rowLoop
938
.northConnection
939
ld a, [wNorthConnectedMap]
940
cp $ff
941
jr z, .southConnection
942
call SwitchToMapRomBank
943
ld a, [wNorthConnectionStripSrc]
944
ld l, a
945
ld a, [wNorthConnectionStripSrc + 1]
946
ld h, a
947
ld a, [wNorthConnectionStripDest]
948
ld e, a
949
ld a, [wNorthConnectionStripDest + 1]
950
ld d, a
951
ld a, [wNorthConnectionStripLength]
952
ldh [hNorthSouthConnectionStripWidth], a
953
ld a, [wNorthConnectedMapWidth]
954
ldh [hNorthSouthConnectedMapWidth], a
955
call LoadNorthSouthConnectionsTileMap
956
.southConnection
957
ld a, [wSouthConnectedMap]
958
cp $ff
959
jr z, .westConnection
960
call SwitchToMapRomBank
961
ld a, [wSouthConnectionStripSrc]
962
ld l, a
963
ld a, [wSouthConnectionStripSrc + 1]
964
ld h, a
965
ld a, [wSouthConnectionStripDest]
966
ld e, a
967
ld a, [wSouthConnectionStripDest + 1]
968
ld d, a
969
ld a, [wSouthConnectionStripLength]
970
ldh [hNorthSouthConnectionStripWidth], a
971
ld a, [wSouthConnectedMapWidth]
972
ldh [hNorthSouthConnectedMapWidth], a
973
call LoadNorthSouthConnectionsTileMap
974
.westConnection
975
ld a, [wWestConnectedMap]
976
cp $ff
977
jr z, .eastConnection
978
call SwitchToMapRomBank
979
ld a, [wWestConnectionStripSrc]
980
ld l, a
981
ld a, [wWestConnectionStripSrc + 1]
982
ld h, a
983
ld a, [wWestConnectionStripDest]
984
ld e, a
985
ld a, [wWestConnectionStripDest + 1]
986
ld d, a
987
ld a, [wWestConnectionStripLength]
988
ld b, a
989
ld a, [wWestConnectedMapWidth]
990
ldh [hEastWestConnectedMapWidth], a
991
call LoadEastWestConnectionsTileMap
992
.eastConnection
993
ld a, [wEastConnectedMap]
994
cp $ff
995
jr z, .done
996
call SwitchToMapRomBank
997
ld a, [wEastConnectionStripSrc]
998
ld l, a
999
ld a, [wEastConnectionStripSrc + 1]
1000
ld h, a
1001
ld a, [wEastConnectionStripDest]
1002
ld e, a
1003
ld a, [wEastConnectionStripDest + 1]
1004
ld d, a
1005
ld a, [wEastConnectionStripLength]
1006
ld b, a
1007
ld a, [wEastConnectedMapWidth]
1008
ldh [hEastWestConnectedMapWidth], a
1009
call LoadEastWestConnectionsTileMap
1010
.done
1011
ret
1012
1013
LoadNorthSouthConnectionsTileMap::
1014
ld c, MAP_BORDER
1015
.loop
1016
push de
1017
push hl
1018
ldh a, [hNorthSouthConnectionStripWidth]
1019
ld b, a
1020
.innerLoop
1021
ld a, [hli]
1022
ld [de], a
1023
inc de
1024
dec b
1025
jr nz, .innerLoop
1026
pop hl
1027
pop de
1028
ldh a, [hNorthSouthConnectedMapWidth]
1029
add l
1030
ld l, a
1031
jr nc, .noCarry1
1032
inc h
1033
.noCarry1
1034
ld a, [wCurMapWidth]
1035
add MAP_BORDER * 2
1036
add e
1037
ld e, a
1038
jr nc, .noCarry2
1039
inc d
1040
.noCarry2
1041
dec c
1042
jr nz, .loop
1043
ret
1044
1045
LoadEastWestConnectionsTileMap::
1046
push hl
1047
push de
1048
ld c, MAP_BORDER
1049
.innerLoop
1050
ld a, [hli]
1051
ld [de], a
1052
inc de
1053
dec c
1054
jr nz, .innerLoop
1055
pop de
1056
pop hl
1057
ldh a, [hEastWestConnectedMapWidth]
1058
add l
1059
ld l, a
1060
jr nc, .noCarry1
1061
inc h
1062
.noCarry1
1063
ld a, [wCurMapWidth]
1064
add MAP_BORDER * 2
1065
add e
1066
ld e, a
1067
jr nc, .noCarry2
1068
inc d
1069
.noCarry2
1070
dec b
1071
jr nz, LoadEastWestConnectionsTileMap
1072
ret
1073
1074
; function to check if there is a sign or sprite in front of the player
1075
; if so, it is stored in [hTextID]
1076
; if not, [hTextID] is set to 0
1077
IsSpriteOrSignInFrontOfPlayer::
1078
xor a
1079
ldh [hTextID], a
1080
ld a, [wNumSigns]
1081
and a
1082
jr z, .extendRangeOverCounter
1083
; if there are signs
1084
predef GetTileAndCoordsInFrontOfPlayer ; get the coordinates in front of the player in de
1085
ld hl, wSignCoords
1086
ld a, [wNumSigns]
1087
ld b, a
1088
ld c, 0
1089
.signLoop
1090
inc c
1091
ld a, [hli] ; sign Y
1092
cp d
1093
jr z, .yCoordMatched
1094
inc hl
1095
jr .retry
1096
.yCoordMatched
1097
ld a, [hli] ; sign X
1098
cp e
1099
jr nz, .retry
1100
; X coord matched: found sign
1101
push hl
1102
push bc
1103
ld hl, wSignTextIDs
1104
ld b, 0
1105
dec c
1106
add hl, bc
1107
ld a, [hl]
1108
ldh [hTextID], a ; store sign text ID
1109
pop bc
1110
pop hl
1111
ret
1112
.retry
1113
dec b
1114
jr nz, .signLoop
1115
; check if the player is front of a counter in a pokemon center, pokemart, etc. and if so, extend the range at which he can talk to the NPC
1116
.extendRangeOverCounter
1117
predef GetTileAndCoordsInFrontOfPlayer ; get the tile in front of the player in c
1118
ld hl, wTilesetTalkingOverTiles ; list of tiles that extend talking range (counter tiles)
1119
ld b, 3
1120
ld d, $20 ; talking range in pixels (long range)
1121
.counterTilesLoop
1122
ld a, [hli]
1123
cp c
1124
jr z, IsSpriteInFrontOfPlayer2 ; jumps if the tile in front of the player is a counter tile
1125
dec b
1126
jr nz, .counterTilesLoop
1127
1128
; part of the above function, but sometimes its called on its own, when signs are irrelevant
1129
; the caller must zero [hTextID]
1130
IsSpriteInFrontOfPlayer::
1131
ld d, $10 ; talking range in pixels (normal range)
1132
IsSpriteInFrontOfPlayer2::
1133
lb bc, $3c, $40 ; Y and X position of player sprite
1134
ld a, [wSpritePlayerStateData1FacingDirection]
1135
.checkIfPlayerFacingUp
1136
cp SPRITE_FACING_UP
1137
jr nz, .checkIfPlayerFacingDown
1138
; facing up
1139
ld a, b
1140
sub d
1141
ld b, a
1142
ld a, PLAYER_DIR_UP
1143
jr .doneCheckingDirection
1144
1145
.checkIfPlayerFacingDown
1146
cp SPRITE_FACING_DOWN
1147
jr nz, .checkIfPlayerFacingRight
1148
; facing down
1149
ld a, b
1150
add d
1151
ld b, a
1152
ld a, PLAYER_DIR_DOWN
1153
jr .doneCheckingDirection
1154
1155
.checkIfPlayerFacingRight
1156
cp SPRITE_FACING_RIGHT
1157
jr nz, .playerFacingLeft
1158
; facing right
1159
ld a, c
1160
add d
1161
ld c, a
1162
ld a, PLAYER_DIR_RIGHT
1163
jr .doneCheckingDirection
1164
1165
.playerFacingLeft
1166
; facing left
1167
ld a, c
1168
sub d
1169
ld c, a
1170
ld a, PLAYER_DIR_LEFT
1171
.doneCheckingDirection
1172
ld [wPlayerDirection], a
1173
ld a, [wNumSprites]
1174
and a
1175
ret z
1176
; if there are sprites
1177
ld hl, wSprite01StateData1
1178
ld d, a
1179
ld e, $01
1180
.spriteLoop
1181
push hl
1182
ld a, [hli] ; image (0 if no sprite)
1183
and a
1184
jr z, .nextSprite
1185
inc l
1186
ld a, [hli] ; sprite visibility
1187
inc a
1188
jr z, .nextSprite
1189
inc l
1190
ld a, [hli] ; Y location
1191
cp b
1192
jr nz, .nextSprite
1193
inc l
1194
ld a, [hl] ; X location
1195
cp c
1196
jr z, .foundSpriteInFrontOfPlayer
1197
.nextSprite
1198
pop hl
1199
ld a, l
1200
add SPRITESTATEDATA1_LENGTH
1201
ld l, a
1202
inc e
1203
dec d
1204
jr nz, .spriteLoop
1205
ret
1206
.foundSpriteInFrontOfPlayer
1207
pop hl
1208
ld a, l
1209
and $f0
1210
inc a
1211
ld l, a ; hl = x#SPRITESTATEDATA1_MOVEMENTSTATUS
1212
set BIT_FACE_PLAYER, [hl]
1213
ld a, e
1214
ldh [hTextID], a
1215
ret
1216
1217
; function to check if the player will jump down a ledge and check if the tile ahead is passable (when not surfing)
1218
; sets the carry flag if there is a collision, and unsets it if there isn't a collision
1219
CollisionCheckOnLand::
1220
ld a, [wMovementFlags]
1221
bit BIT_LEDGE_OR_FISHING, a
1222
jr nz, .noCollision
1223
; if not jumping a ledge
1224
ld a, [wSimulatedJoypadStatesIndex]
1225
and a
1226
jr nz, .noCollision ; no collisions when the player's movements are being controlled by the game
1227
ld a, [wPlayerDirection] ; the direction that the player is trying to go in
1228
ld d, a
1229
ld a, [wSpritePlayerStateData1CollisionData]
1230
and d ; check if a sprite is in the direction the player is trying to go
1231
jr nz, .collision
1232
xor a
1233
ldh [hTextID], a
1234
call IsSpriteInFrontOfPlayer ; check for sprite collisions again? when does the above check fail to detect a sprite collision?
1235
ldh a, [hTextID]
1236
and a ; was there a sprite collision?
1237
jr nz, .collision
1238
; if no sprite collision
1239
ld hl, TilePairCollisionsLand
1240
call CheckForJumpingAndTilePairCollisions
1241
jr c, .collision
1242
call CheckTilePassable
1243
jr nc, .noCollision
1244
.collision
1245
ld a, [wChannelSoundIDs + CHAN5]
1246
cp SFX_COLLISION ; check if collision sound is already playing
1247
jr z, .setCarry
1248
ld a, SFX_COLLISION
1249
call PlaySound ; play collision sound (if it's not already playing)
1250
.setCarry
1251
scf
1252
ret
1253
.noCollision
1254
and a
1255
ret
1256
1257
; function that checks if the tile in front of the player is passable
1258
; clears carry if it is, sets carry if not
1259
CheckTilePassable::
1260
predef GetTileAndCoordsInFrontOfPlayer
1261
ld a, [wTileInFrontOfPlayer]
1262
ld c, a
1263
ld hl, wTilesetCollisionPtr ; pointer to list of passable tiles
1264
ld a, [hli]
1265
ld h, [hl]
1266
ld l, a ; hl now points to passable tiles
1267
.loop
1268
ld a, [hli]
1269
cp $ff
1270
jr z, .tileNotPassable
1271
cp c
1272
ret z
1273
jr .loop
1274
.tileNotPassable
1275
scf
1276
ret
1277
1278
; check if the player is going to jump down a small ledge
1279
; and check for collisions that only occur between certain pairs of tiles
1280
; Input: hl - address of directional collision data
1281
; sets carry if there is a collision and unsets carry if not
1282
CheckForJumpingAndTilePairCollisions::
1283
push hl
1284
predef GetTileAndCoordsInFrontOfPlayer
1285
push de
1286
push bc
1287
farcall HandleLedges ; check if the player is trying to jump a ledge
1288
pop bc
1289
pop de
1290
pop hl
1291
and a
1292
ld a, [wMovementFlags]
1293
bit BIT_LEDGE_OR_FISHING, a
1294
ret nz
1295
; if not jumping
1296
1297
CheckForTilePairCollisions2::
1298
lda_coord 8, 9 ; tile the player is on
1299
ld [wTilePlayerStandingOn], a
1300
1301
CheckForTilePairCollisions::
1302
ld a, [wTileInFrontOfPlayer]
1303
ld c, a
1304
.tilePairCollisionLoop
1305
ld a, [wCurMapTileset]
1306
ld b, a
1307
ld a, [hli]
1308
cp $ff
1309
jr z, .noMatch
1310
cp b
1311
jr z, .tilesetMatches
1312
inc hl
1313
.retry
1314
inc hl
1315
jr .tilePairCollisionLoop
1316
.tilesetMatches
1317
ld a, [wTilePlayerStandingOn]
1318
ld b, a
1319
ld a, [hl]
1320
cp b
1321
jr z, .currentTileMatchesFirstInPair
1322
inc hl
1323
ld a, [hl]
1324
cp b
1325
jr z, .currentTileMatchesSecondInPair
1326
jr .retry
1327
.currentTileMatchesFirstInPair
1328
inc hl
1329
ld a, [hl]
1330
cp c
1331
jr z, .foundMatch
1332
jr .tilePairCollisionLoop
1333
.currentTileMatchesSecondInPair
1334
dec hl
1335
ld a, [hli]
1336
cp c
1337
inc hl
1338
jr nz, .tilePairCollisionLoop
1339
.foundMatch
1340
scf
1341
ret
1342
.noMatch
1343
and a
1344
ret
1345
1346
INCLUDE "data/tilesets/pair_collision_tile_ids.asm"
1347
1348
; this builds a tile map from the tile block map based on the current X/Y coordinates of the player's character
1349
LoadCurrentMapView::
1350
ldh a, [hLoadedROMBank]
1351
push af
1352
ld a, [wTilesetBank]
1353
ldh [hLoadedROMBank], a
1354
ld [rROMB], a
1355
ld a, [wCurrentTileBlockMapViewPointer] ; address of upper left corner of current map view
1356
ld e, a
1357
ld a, [wCurrentTileBlockMapViewPointer + 1]
1358
ld d, a
1359
ld hl, wSurroundingTiles
1360
ld b, SCREEN_BLOCK_HEIGHT
1361
.rowLoop ; each loop iteration fills in one row of tile blocks
1362
push hl
1363
push de
1364
ld c, SCREEN_BLOCK_WIDTH
1365
.rowInnerLoop ; loop to draw each tile block of the current row
1366
push bc
1367
push de
1368
push hl
1369
ld a, [de]
1370
ld c, a ; tile block number
1371
call DrawTileBlock
1372
pop hl
1373
pop de
1374
pop bc
1375
inc hl
1376
inc hl
1377
inc hl
1378
inc hl
1379
inc de
1380
dec c
1381
jr nz, .rowInnerLoop
1382
; update tile block map pointer to next row's address
1383
pop de
1384
ld a, [wCurMapWidth]
1385
add MAP_BORDER * 2
1386
add e
1387
ld e, a
1388
jr nc, .noCarry
1389
inc d
1390
.noCarry
1391
; update tile map pointer to next row's address
1392
pop hl
1393
ld a, SURROUNDING_WIDTH * BLOCK_HEIGHT
1394
add l
1395
ld l, a
1396
jr nc, .noCarry2
1397
inc h
1398
.noCarry2
1399
dec b
1400
jr nz, .rowLoop
1401
ld hl, wSurroundingTiles
1402
ld bc, 0
1403
.adjustForYCoordWithinTileBlock
1404
ld a, [wYBlockCoord]
1405
and a
1406
jr z, .adjustForXCoordWithinTileBlock
1407
ld bc, SURROUNDING_WIDTH * 2
1408
add hl, bc
1409
.adjustForXCoordWithinTileBlock
1410
ld a, [wXBlockCoord]
1411
and a
1412
jr z, .copyToVisibleAreaBuffer
1413
ld bc, BLOCK_WIDTH / 2
1414
add hl, bc
1415
.copyToVisibleAreaBuffer
1416
decoord 0, 0 ; base address for the tiles that are directly transferred to VRAM during V-blank
1417
ld b, SCREEN_HEIGHT
1418
.rowLoop2
1419
ld c, SCREEN_WIDTH
1420
.rowInnerLoop2
1421
ld a, [hli]
1422
ld [de], a
1423
inc de
1424
dec c
1425
jr nz, .rowInnerLoop2
1426
ld a, SURROUNDING_WIDTH - SCREEN_WIDTH
1427
add l
1428
ld l, a
1429
jr nc, .noCarry3
1430
inc h
1431
.noCarry3
1432
dec b
1433
jr nz, .rowLoop2
1434
pop af
1435
ldh [hLoadedROMBank], a
1436
ld [rROMB], a
1437
ret
1438
1439
AdvancePlayerSprite::
1440
ld a, [wSpritePlayerStateData1YStepVector]
1441
ld b, a
1442
ld a, [wSpritePlayerStateData1XStepVector]
1443
ld c, a
1444
ld hl, wWalkCounter
1445
dec [hl]
1446
jr nz, .afterUpdateMapCoords
1447
; if it's the end of the animation, update the player's map coordinates
1448
ld a, [wYCoord]
1449
add b
1450
ld [wYCoord], a
1451
ld a, [wXCoord]
1452
add c
1453
ld [wXCoord], a
1454
.afterUpdateMapCoords
1455
ld a, [wWalkCounter]
1456
cp $07
1457
jp nz, .scrollBackgroundAndSprites
1458
; if this is the first iteration of the animation
1459
ld a, c
1460
cp $01
1461
jr nz, .checkIfMovingWest
1462
; moving east
1463
ld a, [wMapViewVRAMPointer]
1464
ld e, a
1465
and $e0
1466
ld d, a
1467
ld a, e
1468
add $02
1469
and $1f
1470
or d
1471
ld [wMapViewVRAMPointer], a
1472
jr .adjustXCoordWithinBlock
1473
.checkIfMovingWest
1474
cp $ff
1475
jr nz, .checkIfMovingSouth
1476
; moving west
1477
ld a, [wMapViewVRAMPointer]
1478
ld e, a
1479
and $e0
1480
ld d, a
1481
ld a, e
1482
sub $02
1483
and $1f
1484
or d
1485
ld [wMapViewVRAMPointer], a
1486
jr .adjustXCoordWithinBlock
1487
.checkIfMovingSouth
1488
ld a, b
1489
cp $01
1490
jr nz, .checkIfMovingNorth
1491
; moving south
1492
ld a, [wMapViewVRAMPointer]
1493
add $40
1494
ld [wMapViewVRAMPointer], a
1495
jr nc, .adjustXCoordWithinBlock
1496
ld a, [wMapViewVRAMPointer + 1]
1497
inc a
1498
and $03
1499
or $98
1500
ld [wMapViewVRAMPointer + 1], a
1501
jr .adjustXCoordWithinBlock
1502
.checkIfMovingNorth
1503
cp $ff
1504
jr nz, .adjustXCoordWithinBlock
1505
; moving north
1506
ld a, [wMapViewVRAMPointer]
1507
sub $40
1508
ld [wMapViewVRAMPointer], a
1509
jr nc, .adjustXCoordWithinBlock
1510
ld a, [wMapViewVRAMPointer + 1]
1511
dec a
1512
and $03
1513
or $98
1514
ld [wMapViewVRAMPointer + 1], a
1515
.adjustXCoordWithinBlock
1516
ld a, c
1517
and a
1518
jr z, .pointlessJump ; mistake?
1519
.pointlessJump
1520
ld hl, wXBlockCoord
1521
ld a, [hl]
1522
add c
1523
ld [hl], a
1524
cp $02
1525
jr nz, .checkForMoveToWestBlock
1526
; moved into the tile block to the east
1527
xor a
1528
ld [hl], a
1529
ld hl, wXOffsetSinceLastSpecialWarp
1530
inc [hl]
1531
ld de, wCurrentTileBlockMapViewPointer
1532
call MoveTileBlockMapPointerEast
1533
jr .updateMapView
1534
.checkForMoveToWestBlock
1535
cp $ff
1536
jr nz, .adjustYCoordWithinBlock
1537
; moved into the tile block to the west
1538
ld a, $01
1539
ld [hl], a
1540
ld hl, wXOffsetSinceLastSpecialWarp
1541
dec [hl]
1542
ld de, wCurrentTileBlockMapViewPointer
1543
call MoveTileBlockMapPointerWest
1544
jr .updateMapView
1545
.adjustYCoordWithinBlock
1546
ld hl, wYBlockCoord
1547
ld a, [hl]
1548
add b
1549
ld [hl], a
1550
cp $02
1551
jr nz, .checkForMoveToNorthBlock
1552
; moved into the tile block to the south
1553
xor a
1554
ld [hl], a
1555
ld hl, wYOffsetSinceLastSpecialWarp
1556
inc [hl]
1557
ld de, wCurrentTileBlockMapViewPointer
1558
ld a, [wCurMapWidth]
1559
call MoveTileBlockMapPointerSouth
1560
jr .updateMapView
1561
.checkForMoveToNorthBlock
1562
cp $ff
1563
jr nz, .updateMapView
1564
; moved into the tile block to the north
1565
ld a, $01
1566
ld [hl], a
1567
ld hl, wYOffsetSinceLastSpecialWarp
1568
dec [hl]
1569
ld de, wCurrentTileBlockMapViewPointer
1570
ld a, [wCurMapWidth]
1571
call MoveTileBlockMapPointerNorth
1572
.updateMapView
1573
call LoadCurrentMapView
1574
ld a, [wSpritePlayerStateData1YStepVector]
1575
cp $01
1576
jr nz, .checkIfMovingNorth2
1577
; if moving south
1578
call ScheduleSouthRowRedraw
1579
jr .scrollBackgroundAndSprites
1580
.checkIfMovingNorth2
1581
cp $ff
1582
jr nz, .checkIfMovingEast2
1583
; if moving north
1584
call ScheduleNorthRowRedraw
1585
jr .scrollBackgroundAndSprites
1586
.checkIfMovingEast2
1587
ld a, [wSpritePlayerStateData1XStepVector]
1588
cp $01
1589
jr nz, .checkIfMovingWest2
1590
; if moving east
1591
call ScheduleEastColumnRedraw
1592
jr .scrollBackgroundAndSprites
1593
.checkIfMovingWest2
1594
cp $ff
1595
jr nz, .scrollBackgroundAndSprites
1596
; if moving west
1597
call ScheduleWestColumnRedraw
1598
.scrollBackgroundAndSprites
1599
ld a, [wSpritePlayerStateData1YStepVector]
1600
ld b, a
1601
ld a, [wSpritePlayerStateData1XStepVector]
1602
ld c, a
1603
sla b
1604
sla c
1605
ldh a, [hSCY]
1606
add b
1607
ldh [hSCY], a ; update background scroll Y
1608
ldh a, [hSCX]
1609
add c
1610
ldh [hSCX], a ; update background scroll X
1611
; shift all the sprites in the direction opposite of the player's motion
1612
; so that the player appears to move relative to them
1613
ld hl, wSprite01StateData1YPixels
1614
ld a, [wNumSprites]
1615
and a ; are there any sprites?
1616
jr z, .done
1617
ld e, a
1618
.spriteShiftLoop
1619
ld a, [hl]
1620
sub b
1621
ld [hli], a
1622
inc l
1623
ld a, [hl]
1624
sub c
1625
ld [hl], a
1626
ld a, $0e
1627
add l
1628
ld l, a
1629
dec e
1630
jr nz, .spriteShiftLoop
1631
.done
1632
ret
1633
1634
; the following four functions are used to move the pointer to the upper left
1635
; corner of the tile block map in the direction of motion
1636
1637
MoveTileBlockMapPointerEast::
1638
ld a, [de]
1639
add $01
1640
ld [de], a
1641
ret nc
1642
inc de
1643
ld a, [de]
1644
inc a
1645
ld [de], a
1646
ret
1647
1648
MoveTileBlockMapPointerWest::
1649
ld a, [de]
1650
sub $01
1651
ld [de], a
1652
ret nc
1653
inc de
1654
ld a, [de]
1655
dec a
1656
ld [de], a
1657
ret
1658
1659
MoveTileBlockMapPointerSouth::
1660
add MAP_BORDER * 2
1661
ld b, a
1662
ld a, [de]
1663
add b
1664
ld [de], a
1665
ret nc
1666
inc de
1667
ld a, [de]
1668
inc a
1669
ld [de], a
1670
ret
1671
1672
MoveTileBlockMapPointerNorth::
1673
add MAP_BORDER * 2
1674
ld b, a
1675
ld a, [de]
1676
sub b
1677
ld [de], a
1678
ret nc
1679
inc de
1680
ld a, [de]
1681
dec a
1682
ld [de], a
1683
ret
1684
1685
; the following 6 functions are used to tell the V-blank handler to redraw
1686
; the portion of the map that was newly exposed due to the player's movement
1687
1688
ScheduleNorthRowRedraw::
1689
hlcoord 0, 0
1690
call CopyToRedrawRowOrColumnSrcTiles
1691
ld a, [wMapViewVRAMPointer]
1692
ldh [hRedrawRowOrColumnDest], a
1693
ld a, [wMapViewVRAMPointer + 1]
1694
ldh [hRedrawRowOrColumnDest + 1], a
1695
ld a, REDRAW_ROW
1696
ldh [hRedrawRowOrColumnMode], a
1697
ret
1698
1699
CopyToRedrawRowOrColumnSrcTiles::
1700
ld de, wRedrawRowOrColumnSrcTiles
1701
ld c, 2 * SCREEN_WIDTH
1702
.loop
1703
ld a, [hli]
1704
ld [de], a
1705
inc de
1706
dec c
1707
jr nz, .loop
1708
ret
1709
1710
ScheduleSouthRowRedraw::
1711
hlcoord 0, 16
1712
call CopyToRedrawRowOrColumnSrcTiles
1713
ld a, [wMapViewVRAMPointer]
1714
ld l, a
1715
ld a, [wMapViewVRAMPointer + 1]
1716
ld h, a
1717
ld bc, $200
1718
add hl, bc
1719
ld a, h
1720
and $03
1721
or $98
1722
ldh [hRedrawRowOrColumnDest + 1], a
1723
ld a, l
1724
ldh [hRedrawRowOrColumnDest], a
1725
ld a, REDRAW_ROW
1726
ldh [hRedrawRowOrColumnMode], a
1727
ret
1728
1729
ScheduleEastColumnRedraw::
1730
hlcoord 18, 0
1731
call ScheduleColumnRedrawHelper
1732
ld a, [wMapViewVRAMPointer]
1733
ld c, a
1734
and $e0
1735
ld b, a
1736
ld a, c
1737
add 18
1738
and $1f
1739
or b
1740
ldh [hRedrawRowOrColumnDest], a
1741
ld a, [wMapViewVRAMPointer + 1]
1742
ldh [hRedrawRowOrColumnDest + 1], a
1743
ld a, REDRAW_COL
1744
ldh [hRedrawRowOrColumnMode], a
1745
ret
1746
1747
ScheduleColumnRedrawHelper::
1748
ld de, wRedrawRowOrColumnSrcTiles
1749
ld c, SCREEN_HEIGHT
1750
.loop
1751
ld a, [hli]
1752
ld [de], a
1753
inc de
1754
ld a, [hl]
1755
ld [de], a
1756
inc de
1757
ld a, SCREEN_WIDTH - 1
1758
add l
1759
ld l, a
1760
jr nc, .noCarry
1761
inc h
1762
.noCarry
1763
dec c
1764
jr nz, .loop
1765
ret
1766
1767
ScheduleWestColumnRedraw::
1768
hlcoord 0, 0
1769
call ScheduleColumnRedrawHelper
1770
ld a, [wMapViewVRAMPointer]
1771
ldh [hRedrawRowOrColumnDest], a
1772
ld a, [wMapViewVRAMPointer + 1]
1773
ldh [hRedrawRowOrColumnDest + 1], a
1774
ld a, REDRAW_COL
1775
ldh [hRedrawRowOrColumnMode], a
1776
ret
1777
1778
; function to write the tiles that make up a tile block to memory
1779
; Input: c = tile block ID, hl = destination address
1780
DrawTileBlock::
1781
push hl
1782
ld a, [wTilesetBlocksPtr] ; pointer to tiles
1783
ld l, a
1784
ld a, [wTilesetBlocksPtr + 1]
1785
ld h, a
1786
ld a, c
1787
swap a
1788
ld b, a
1789
and $f0
1790
ld c, a
1791
ld a, b
1792
and $0f
1793
ld b, a ; bc = tile block ID * 0x10
1794
add hl, bc
1795
ld d, h
1796
ld e, l ; de = address of the tile block's tiles
1797
pop hl
1798
ld c, BLOCK_HEIGHT ; 4 loop iterations
1799
.loop ; each loop iteration, write 4 tile numbers
1800
push bc
1801
REPT BLOCK_WIDTH - 1
1802
ld a, [de]
1803
ld [hli], a
1804
inc de
1805
ENDR
1806
ld a, [de]
1807
ld [hl], a
1808
inc de
1809
ld bc, SURROUNDING_WIDTH - (BLOCK_WIDTH - 1)
1810
add hl, bc
1811
pop bc
1812
dec c
1813
jr nz, .loop
1814
ret
1815
1816
; function to update joypad state and simulate button presses
1817
JoypadOverworld::
1818
xor a
1819
ld [wSpritePlayerStateData1YStepVector], a
1820
ld [wSpritePlayerStateData1XStepVector], a
1821
call RunMapScript
1822
call Joypad
1823
ld a, [wStatusFlags7]
1824
bit BIT_TRAINER_BATTLE, a
1825
jr nz, .notForcedDownwards
1826
ld a, [wCurMap]
1827
cp ROUTE_17 ; Cycling Road
1828
jr nz, .notForcedDownwards
1829
ldh a, [hJoyHeld]
1830
and PAD_CTRL_PAD | PAD_B | PAD_A
1831
jr nz, .notForcedDownwards
1832
ld a, PAD_DOWN
1833
ldh [hJoyHeld], a ; on the cycling road, if there isn't a trainer and the player isn't pressing buttons, simulate a down press
1834
.notForcedDownwards
1835
ld a, [wStatusFlags5]
1836
bit BIT_SCRIPTED_MOVEMENT_STATE, a
1837
ret z
1838
; if simulating button presses
1839
ldh a, [hJoyHeld]
1840
ld b, a
1841
ld a, [wOverrideSimulatedJoypadStatesMask] ; bit mask for button presses that override simulated ones
1842
and b
1843
ret nz ; return if the simulated button presses are overridden
1844
ld hl, wSimulatedJoypadStatesIndex
1845
dec [hl]
1846
ld a, [hl]
1847
cp $ff
1848
jr z, .doneSimulating ; if the end of the simulated button presses has been reached
1849
ld hl, wSimulatedJoypadStatesEnd
1850
add l
1851
ld l, a
1852
jr nc, .noCarry
1853
inc h
1854
.noCarry
1855
ld a, [hl]
1856
ldh [hJoyHeld], a ; store simulated button press in joypad state
1857
and a
1858
ret nz
1859
ldh [hJoyPressed], a
1860
ldh [hJoyReleased], a
1861
ret
1862
1863
; if done simulating button presses
1864
.doneSimulating
1865
xor a
1866
ld [wUnusedOverrideSimulatedJoypadStatesIndex], a
1867
ld [wSimulatedJoypadStatesIndex], a
1868
ld [wSimulatedJoypadStatesEnd], a
1869
ld [wJoyIgnore], a
1870
ldh [hJoyHeld], a
1871
ld hl, wMovementFlags
1872
ld a, [hl]
1873
and (1 << BIT_SPINNING) | (1 << BIT_LEDGE_OR_FISHING) | (1 << 5) | (1 << 4) | (1 << 3)
1874
ld [hl], a
1875
ld hl, wStatusFlags5
1876
res BIT_SCRIPTED_MOVEMENT_STATE, [hl]
1877
ret
1878
1879
; function to check the tile ahead to determine if the character should get on land or keep surfing
1880
; sets carry if there is a collision and clears carry otherwise
1881
; It seems that this function has a bug in it, but due to luck, it doesn't
1882
; show up. After detecting a sprite collision, it jumps to the code that
1883
; checks if the next tile is passable instead of just directly jumping to the
1884
; "collision detected" code. However, it doesn't store the next tile in c,
1885
; so the old value of c is used. 2429 is always called before this function,
1886
; and 2429 always sets c to 0xF0. There is no 0xF0 background tile, so it
1887
; is considered impassable and it is detected as a collision.
1888
CollisionCheckOnWater::
1889
ld a, [wStatusFlags5]
1890
bit BIT_SCRIPTED_MOVEMENT_STATE, a
1891
jp nz, .noCollision ; return and clear carry if button presses are being simulated
1892
ld a, [wPlayerDirection] ; the direction that the player is trying to go in
1893
ld d, a
1894
ld a, [wSpritePlayerStateData1CollisionData]
1895
and d ; check if a sprite is in the direction the player is trying to go
1896
jr nz, .checkIfNextTileIsPassable ; bug?
1897
ld hl, TilePairCollisionsWater
1898
call CheckForJumpingAndTilePairCollisions
1899
jr c, .collision
1900
predef GetTileAndCoordsInFrontOfPlayer ; get tile in front of player (puts it in c and [wTileInFrontOfPlayer])
1901
ld a, [wTileInFrontOfPlayer] ; tile in front of player
1902
cp $14 ; water tile
1903
jr z, .noCollision ; keep surfing if it's a water tile
1904
cp $32 ; either the left tile of the S.S. Anne boarding platform or the tile on eastern coastlines (depending on the current tileset)
1905
jr z, .checkIfVermilionDockTileset
1906
cp $48 ; tile on right on coast lines in Safari Zone
1907
jr z, .noCollision ; keep surfing
1908
; check if the [land] tile in front of the player is passable
1909
.checkIfNextTileIsPassable
1910
ld hl, wTilesetCollisionPtr ; pointer to list of passable tiles
1911
ld a, [hli]
1912
ld h, [hl]
1913
ld l, a
1914
.loop
1915
ld a, [hli]
1916
cp $ff
1917
jr z, .collision
1918
cp c
1919
jr z, .stopSurfing ; stop surfing if the tile is passable
1920
jr .loop
1921
.collision
1922
ld a, [wChannelSoundIDs + CHAN5]
1923
cp SFX_COLLISION ; check if collision sound is already playing
1924
jr z, .setCarry
1925
ld a, SFX_COLLISION
1926
call PlaySound ; play collision sound (if it's not already playing)
1927
.setCarry
1928
scf
1929
jr .done
1930
.noCollision
1931
and a
1932
.done
1933
ret
1934
.stopSurfing
1935
xor a
1936
ld [wWalkBikeSurfState], a
1937
call LoadPlayerSpriteGraphics
1938
call PlayDefaultMusic
1939
jr .noCollision
1940
.checkIfVermilionDockTileset
1941
ld a, [wCurMapTileset]
1942
cp SHIP_PORT ; Vermilion Dock tileset
1943
jr nz, .noCollision ; keep surfing if it's not the boarding platform tile
1944
jr .stopSurfing ; if it is the boarding platform tile, stop surfing
1945
1946
; function to run the current map's script
1947
RunMapScript::
1948
push hl
1949
push de
1950
push bc
1951
farcall TryPushingBoulder
1952
ld a, [wMiscFlags]
1953
bit BIT_BOULDER_DUST, a
1954
jr z, .afterBoulderEffect
1955
farcall DoBoulderDustAnimation
1956
.afterBoulderEffect
1957
pop bc
1958
pop de
1959
pop hl
1960
call RunNPCMovementScript
1961
ld a, [wCurMap] ; current map number
1962
call SwitchToMapRomBank ; change to the ROM bank the map's data is in
1963
ld hl, wCurMapScriptPtr
1964
ld a, [hli]
1965
ld h, [hl]
1966
ld l, a
1967
ld de, .return
1968
push de
1969
jp hl ; jump to script
1970
.return
1971
ret
1972
1973
LoadWalkingPlayerSpriteGraphics::
1974
ld de, RedSprite
1975
ld hl, vNPCSprites
1976
jr LoadPlayerSpriteGraphicsCommon
1977
1978
LoadSurfingPlayerSpriteGraphics::
1979
ld de, SeelSprite
1980
ld hl, vNPCSprites
1981
jr LoadPlayerSpriteGraphicsCommon
1982
1983
LoadBikePlayerSpriteGraphics::
1984
ld de, RedBikeSprite
1985
ld hl, vNPCSprites
1986
1987
LoadPlayerSpriteGraphicsCommon::
1988
push de
1989
push hl
1990
lb bc, BANK(RedSprite), $0c
1991
call CopyVideoData
1992
pop hl
1993
pop de
1994
ld a, $c0
1995
add e
1996
ld e, a
1997
jr nc, .noCarry
1998
inc d
1999
.noCarry
2000
set 3, h ; add $800 ($80 tiles) to hl (1 << 3 == $8)
2001
lb bc, BANK(RedSprite), $0c
2002
jp CopyVideoData
2003
2004
; function to load data from the map header
2005
LoadMapHeader::
2006
farcall MarkTownVisitedAndLoadToggleableObjects
2007
ld a, [wCurMapTileset]
2008
ld [wUnusedCurMapTilesetCopy], a
2009
ld a, [wCurMap]
2010
call SwitchToMapRomBank
2011
ld a, [wCurMapTileset]
2012
ld b, a
2013
res BIT_NO_PREVIOUS_MAP, a
2014
ld [wCurMapTileset], a
2015
ldh [hPreviousTileset], a
2016
bit BIT_NO_PREVIOUS_MAP, b
2017
ret nz
2018
ld hl, MapHeaderPointers
2019
ld a, [wCurMap]
2020
sla a
2021
jr nc, .noCarry1
2022
inc h
2023
.noCarry1
2024
add l
2025
ld l, a
2026
jr nc, .noCarry2
2027
inc h
2028
.noCarry2
2029
ld a, [hli]
2030
ld h, [hl]
2031
ld l, a ; hl = base of map header
2032
ld de, wCurMapHeader
2033
ld c, wCurMapHeaderEnd - wCurMapHeader
2034
.copyFixedHeaderLoop
2035
ld a, [hli]
2036
ld [de], a
2037
inc de
2038
dec c
2039
jr nz, .copyFixedHeaderLoop
2040
; initialize all the connected maps to disabled at first, before loading the actual values
2041
ld a, $ff
2042
ld [wNorthConnectedMap], a
2043
ld [wSouthConnectedMap], a
2044
ld [wWestConnectedMap], a
2045
ld [wEastConnectedMap], a
2046
; copy connection data (if any) to WRAM
2047
ld a, [wCurMapConnections]
2048
ld b, a
2049
; check north
2050
bit NORTH_F, b
2051
jr z, .checkSouth
2052
ld de, wNorthConnectionHeader
2053
call CopyMapConnectionHeader
2054
.checkSouth
2055
bit SOUTH_F, b
2056
jr z, .checkWest
2057
ld de, wSouthConnectionHeader
2058
call CopyMapConnectionHeader
2059
.checkWest
2060
bit WEST_F, b
2061
jr z, .checkEast
2062
ld de, wWestConnectionHeader
2063
call CopyMapConnectionHeader
2064
.checkEast
2065
bit EAST_F, b
2066
jr z, .getObjectDataPointer
2067
ld de, wEastConnectionHeader
2068
call CopyMapConnectionHeader
2069
.getObjectDataPointer
2070
ld a, [hli]
2071
ld [wObjectDataPointerTemp], a
2072
ld a, [hli]
2073
ld [wObjectDataPointerTemp + 1], a
2074
push hl
2075
ld a, [wObjectDataPointerTemp]
2076
ld l, a
2077
ld a, [wObjectDataPointerTemp + 1]
2078
ld h, a ; hl = base of object data
2079
ld de, wMapBackgroundTile
2080
ld a, [hli]
2081
ld [de], a
2082
; load warp data
2083
ld a, [hli]
2084
ld [wNumberOfWarps], a
2085
and a
2086
jr z, .loadSignData
2087
ld c, a
2088
ld de, wWarpEntries
2089
.warpLoop ; one warp per loop iteration
2090
ld b, 4
2091
.warpInnerLoop
2092
ld a, [hli]
2093
ld [de], a
2094
inc de
2095
dec b
2096
jr nz, .warpInnerLoop
2097
dec c
2098
jr nz, .warpLoop
2099
.loadSignData
2100
ld a, [hli] ; number of signs
2101
ld [wNumSigns], a
2102
and a ; are there any signs?
2103
jr z, .loadSpriteData ; if not, skip this
2104
ld c, a
2105
ld de, wSignTextIDs
2106
ld a, d
2107
ldh [hSignCoordPointer], a
2108
ld a, e
2109
ldh [hSignCoordPointer + 1], a
2110
ld de, wSignCoords
2111
.signLoop
2112
ld a, [hli]
2113
ld [de], a
2114
inc de
2115
ld a, [hli]
2116
ld [de], a
2117
inc de
2118
push de
2119
ldh a, [hSignCoordPointer]
2120
ld d, a
2121
ldh a, [hSignCoordPointer + 1]
2122
ld e, a
2123
ld a, [hli]
2124
ld [de], a
2125
inc de
2126
ld a, d
2127
ldh [hSignCoordPointer], a
2128
ld a, e
2129
ldh [hSignCoordPointer + 1], a
2130
pop de
2131
dec c
2132
jr nz, .signLoop
2133
.loadSpriteData
2134
ld a, [wStatusFlags4]
2135
bit BIT_BATTLE_OVER_OR_BLACKOUT, a
2136
jp nz, .finishUp ; if so, skip this because battles don't destroy this data
2137
ld a, [hli]
2138
ld [wNumSprites], a ; save the number of sprites
2139
push hl
2140
; zero out sprite state data for sprites 01-15
2141
ld hl, wSprite01StateData1
2142
ld de, wSprite01StateData2
2143
xor a
2144
ld b, $f0
2145
.zeroSpriteDataLoop
2146
ld [hli], a
2147
ld [de], a
2148
inc e
2149
dec b
2150
jr nz, .zeroSpriteDataLoop
2151
; disable SPRITESTATEDATA1_IMAGEINDEX (set to $ff) for sprites 01-15
2152
ld hl, wSprite01StateData1ImageIndex
2153
ld de, SPRITESTATEDATA1_LENGTH
2154
ld c, NUM_SPRITESTATEDATA_STRUCTS - 1
2155
.disableSpriteEntriesLoop
2156
ld [hl], $ff
2157
add hl, de
2158
dec c
2159
jr nz, .disableSpriteEntriesLoop
2160
pop hl
2161
ld de, wSprite01StateData1
2162
ld a, [wNumSprites] ; number of sprites
2163
and a ; are there any sprites?
2164
jp z, .finishUp ; if there are no sprites, skip the rest
2165
ld b, a
2166
ld c, $00
2167
.loadSpriteLoop
2168
ld a, [hli]
2169
ld [de], a ; x#SPRITESTATEDATA1_PICTUREID
2170
inc d
2171
ld a, $04
2172
add e
2173
ld e, a
2174
ld a, [hli]
2175
ld [de], a ; x#SPRITESTATEDATA2_MAPY
2176
inc e
2177
ld a, [hli]
2178
ld [de], a ; x#SPRITESTATEDATA2_MAPX
2179
inc e
2180
ld a, [hli]
2181
ld [de], a ; x#SPRITESTATEDATA2_MOVEMENTBYTE1
2182
ld a, [hli]
2183
ldh [hLoadSpriteTemp1], a ; save movement byte 2
2184
ld a, [hli]
2185
ldh [hLoadSpriteTemp2], a ; save text ID and flags byte
2186
push bc
2187
push hl
2188
ld b, $00
2189
ld hl, wMapSpriteData
2190
add hl, bc
2191
ldh a, [hLoadSpriteTemp1]
2192
ld [hli], a ; store movement byte 2 in byte 0 of sprite entry
2193
ldh a, [hLoadSpriteTemp2]
2194
ld [hl], a ; this appears pointless, since the value is overwritten immediately after
2195
ldh a, [hLoadSpriteTemp2]
2196
ldh [hLoadSpriteTemp1], a
2197
and $3f
2198
ld [hl], a ; store text ID in byte 1 of sprite entry
2199
pop hl
2200
ldh a, [hLoadSpriteTemp1]
2201
bit BIT_TRAINER, a
2202
jr nz, .trainerSprite
2203
bit BIT_ITEM, a
2204
jr nz, .itemBallSprite
2205
jr .regularSprite
2206
.trainerSprite
2207
ld a, [hli]
2208
ldh [hLoadSpriteTemp1], a ; save trainer class
2209
ld a, [hli]
2210
ldh [hLoadSpriteTemp2], a ; save trainer number (within class)
2211
push hl
2212
ld hl, wMapSpriteExtraData
2213
add hl, bc
2214
ldh a, [hLoadSpriteTemp1]
2215
ld [hli], a ; store trainer class in byte 0 of the entry
2216
ldh a, [hLoadSpriteTemp2]
2217
ld [hl], a ; store trainer number in byte 1 of the entry
2218
pop hl
2219
jr .nextSprite
2220
.itemBallSprite
2221
ld a, [hli]
2222
ldh [hLoadSpriteTemp1], a ; save item number
2223
push hl
2224
ld hl, wMapSpriteExtraData
2225
add hl, bc
2226
ldh a, [hLoadSpriteTemp1]
2227
ld [hli], a ; store item number in byte 0 of the entry
2228
xor a
2229
ld [hl], a ; zero byte 1, since it is not used
2230
pop hl
2231
jr .nextSprite
2232
.regularSprite
2233
push hl
2234
ld hl, wMapSpriteExtraData
2235
add hl, bc
2236
; zero both bytes, since regular sprites don't use this extra space
2237
xor a
2238
ld [hli], a
2239
ld [hl], a
2240
pop hl
2241
.nextSprite
2242
pop bc
2243
dec d
2244
ld a, $0a
2245
add e
2246
ld e, a
2247
inc c
2248
inc c
2249
dec b
2250
jp nz, .loadSpriteLoop
2251
.finishUp
2252
predef LoadTilesetHeader
2253
callfar LoadWildData
2254
pop hl ; restore hl from before going to the warp/sign/sprite data (this value was saved for seemingly no purpose)
2255
ld a, [wCurMapHeight] ; map height in 4x4 tile blocks
2256
add a ; double it
2257
ld [wCurrentMapHeight2], a ; store map height in 2x2 tile blocks
2258
ld a, [wCurMapWidth] ; map width in 4x4 tile blocks
2259
add a ; double it
2260
ld [wCurrentMapWidth2], a ; map width in 2x2 tile blocks
2261
ld a, [wCurMap]
2262
ld c, a
2263
ld b, $00
2264
ldh a, [hLoadedROMBank]
2265
push af
2266
ld a, BANK(MapSongBanks)
2267
ldh [hLoadedROMBank], a
2268
ld [rROMB], a
2269
ld hl, MapSongBanks
2270
add hl, bc
2271
add hl, bc
2272
ld a, [hli]
2273
ld [wMapMusicSoundID], a ; music 1
2274
ld a, [hl]
2275
ld [wMapMusicROMBank], a ; music 2
2276
pop af
2277
ldh [hLoadedROMBank], a
2278
ld [rROMB], a
2279
ret
2280
2281
; function to copy map connection data from ROM to WRAM
2282
; Input: hl = source, de = destination
2283
CopyMapConnectionHeader::
2284
ld c, $0b
2285
.loop
2286
ld a, [hli]
2287
ld [de], a
2288
inc de
2289
dec c
2290
jr nz, .loop
2291
ret
2292
2293
; function to load map data
2294
LoadMapData::
2295
ldh a, [hLoadedROMBank]
2296
push af
2297
call DisableLCD
2298
ld a, HIGH(vBGMap0)
2299
ld [wMapViewVRAMPointer + 1], a
2300
xor a
2301
ld [wMapViewVRAMPointer], a
2302
ldh [hSCY], a
2303
ldh [hSCX], a
2304
ld [wWalkCounter], a
2305
ld [wUnusedCurMapTilesetCopy], a
2306
ld [wWalkBikeSurfStateCopy], a
2307
ld [wSpriteSetID], a
2308
call LoadTextBoxTilePatterns
2309
call LoadMapHeader
2310
farcall InitMapSprites ; load tile pattern data for sprites
2311
call LoadTileBlockMap
2312
call LoadTilesetTilePatternData
2313
call LoadCurrentMapView
2314
; copy current map view to VRAM
2315
hlcoord 0, 0
2316
ld de, vBGMap0
2317
ld b, SCREEN_HEIGHT
2318
.vramCopyLoop
2319
ld c, SCREEN_WIDTH
2320
.vramCopyInnerLoop
2321
ld a, [hli]
2322
ld [de], a
2323
inc e
2324
dec c
2325
jr nz, .vramCopyInnerLoop
2326
ld a, TILEMAP_WIDTH - SCREEN_WIDTH
2327
add e
2328
ld e, a
2329
jr nc, .noCarry
2330
inc d
2331
.noCarry
2332
dec b
2333
jr nz, .vramCopyLoop
2334
ld a, $01
2335
ld [wUpdateSpritesEnabled], a
2336
call EnableLCD
2337
ld b, SET_PAL_OVERWORLD
2338
call RunPaletteCommand
2339
call LoadPlayerSpriteGraphics
2340
ld a, [wStatusFlags6]
2341
and (1 << BIT_FLY_WARP) | (1 << BIT_DUNGEON_WARP)
2342
jr nz, .restoreRomBank
2343
ld a, [wStatusFlags7]
2344
bit BIT_NO_MAP_MUSIC, a
2345
jr nz, .restoreRomBank
2346
call UpdateMusic6Times
2347
call PlayDefaultMusicFadeOutCurrent
2348
.restoreRomBank
2349
pop af
2350
ldh [hLoadedROMBank], a
2351
ld [rROMB], a
2352
ret
2353
2354
; function to switch to the ROM bank that a map is stored in
2355
; Input: a = map number
2356
SwitchToMapRomBank::
2357
push hl
2358
push bc
2359
ld c, a
2360
ld b, $00
2361
ld a, BANK(MapHeaderBanks)
2362
call BankswitchHome
2363
ld hl, MapHeaderBanks
2364
add hl, bc
2365
ld a, [hl]
2366
ldh [hMapROMBank], a
2367
call BankswitchBack
2368
ldh a, [hMapROMBank]
2369
ldh [hLoadedROMBank], a
2370
ld [rROMB], a
2371
pop bc
2372
pop hl
2373
ret
2374
2375
IgnoreInputForHalfSecond:
2376
ld a, 30
2377
ld [wIgnoreInputCounter], a
2378
ld hl, wStatusFlags5
2379
ld a, [hl]
2380
or (1 << BIT_DISABLE_JOYPAD) | (1 << BIT_UNKNOWN_5_2) | (1 << BIT_UNKNOWN_5_1)
2381
ld [hl], a ; set ignore input bit
2382
ret
2383
2384
ResetUsingStrengthOutOfBattleBit:
2385
ld hl, wStatusFlags1
2386
res BIT_STRENGTH_ACTIVE, [hl]
2387
ret
2388
2389
ForceBikeOrSurf::
2390
ld b, BANK(RedSprite)
2391
ld hl, LoadPlayerSpriteGraphics ; in bank 0
2392
call Bankswitch
2393
jp PlayDefaultMusic ; update map/player state?
2394
2395
CheckForUserInterruption::
2396
; Return carry if Up+Select+B, Start or A are pressed in c frames.
2397
; Used only in the intro and title screen.
2398
call DelayFrame
2399
2400
push bc
2401
call JoypadLowSensitivity
2402
pop bc
2403
2404
ldh a, [hJoyHeld]
2405
cp PAD_UP + PAD_SELECT + PAD_B
2406
jr z, .input
2407
2408
ldh a, [hJoy5]
2409
IF DEF(_DEBUG)
2410
and PAD_START | PAD_SELECT | PAD_A
2411
ELSE
2412
and PAD_START | PAD_A
2413
ENDC
2414
jr nz, .input
2415
2416
dec c
2417
jr nz, CheckForUserInterruption
2418
2419
and a
2420
ret
2421
2422
.input
2423
scf
2424
ret
2425
2426
; function to load position data for destination warp when switching maps
2427
; INPUT:
2428
; a = ID of destination warp within destination map
2429
LoadDestinationWarpPosition::
2430
ld b, a
2431
ldh a, [hLoadedROMBank]
2432
push af
2433
ld a, [wPredefParentBank]
2434
ldh [hLoadedROMBank], a
2435
ld [rROMB], a
2436
ld a, b
2437
add a
2438
add a
2439
ld c, a
2440
ld b, 0
2441
add hl, bc
2442
ld bc, 4
2443
ld de, wCurrentTileBlockMapViewPointer
2444
call CopyData
2445
pop af
2446
ldh [hLoadedROMBank], a
2447
ld [rROMB], a
2448
ret
2449
2450