Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pret
GitHub Repository: pret/pokered
Path: blob/master/home/overworld.asm
1270 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 CheckForHiddenObjectOrBookshelfOrCardKeyDoor
91
ldh a, [hItemAlreadyFound]
92
and a
93
jp z, OverworldLoop ; jump if a hidden object 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 ; switch to the ROM bank of the current map
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] ; destination map
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
.checkWestMap
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] ; width of connected map
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] ; map width
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
.xCoordMatched
1101
; found sign
1102
push hl
1103
push bc
1104
ld hl, wSignTextIDs
1105
ld b, 0
1106
dec c
1107
add hl, bc
1108
ld a, [hl]
1109
ldh [hTextID], a ; store sign text ID
1110
pop bc
1111
pop hl
1112
ret
1113
.retry
1114
dec b
1115
jr nz, .signLoop
1116
; 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
1117
.extendRangeOverCounter
1118
predef GetTileAndCoordsInFrontOfPlayer ; get the tile in front of the player in c
1119
ld hl, wTilesetTalkingOverTiles ; list of tiles that extend talking range (counter tiles)
1120
ld b, 3
1121
ld d, $20 ; talking range in pixels (long range)
1122
.counterTilesLoop
1123
ld a, [hli]
1124
cp c
1125
jr z, IsSpriteInFrontOfPlayer2 ; jumps if the tile in front of the player is a counter tile
1126
dec b
1127
jr nz, .counterTilesLoop
1128
1129
; part of the above function, but sometimes its called on its own, when signs are irrelevant
1130
; the caller must zero [hTextID]
1131
IsSpriteInFrontOfPlayer::
1132
ld d, $10 ; talking range in pixels (normal range)
1133
IsSpriteInFrontOfPlayer2::
1134
lb bc, $3c, $40 ; Y and X position of player sprite
1135
ld a, [wSpritePlayerStateData1FacingDirection]
1136
.checkIfPlayerFacingUp
1137
cp SPRITE_FACING_UP
1138
jr nz, .checkIfPlayerFacingDown
1139
; facing up
1140
ld a, b
1141
sub d
1142
ld b, a
1143
ld a, PLAYER_DIR_UP
1144
jr .doneCheckingDirection
1145
1146
.checkIfPlayerFacingDown
1147
cp SPRITE_FACING_DOWN
1148
jr nz, .checkIfPlayerFacingRight
1149
; facing down
1150
ld a, b
1151
add d
1152
ld b, a
1153
ld a, PLAYER_DIR_DOWN
1154
jr .doneCheckingDirection
1155
1156
.checkIfPlayerFacingRight
1157
cp SPRITE_FACING_RIGHT
1158
jr nz, .playerFacingLeft
1159
; facing right
1160
ld a, c
1161
add d
1162
ld c, a
1163
ld a, PLAYER_DIR_RIGHT
1164
jr .doneCheckingDirection
1165
1166
.playerFacingLeft
1167
; facing left
1168
ld a, c
1169
sub d
1170
ld c, a
1171
ld a, PLAYER_DIR_LEFT
1172
.doneCheckingDirection
1173
ld [wPlayerDirection], a
1174
ld a, [wNumSprites] ; number of sprites
1175
and a
1176
ret z
1177
; if there are sprites
1178
ld hl, wSprite01StateData1
1179
ld d, a
1180
ld e, $01
1181
.spriteLoop
1182
push hl
1183
ld a, [hli] ; image (0 if no sprite)
1184
and a
1185
jr z, .nextSprite
1186
inc l
1187
ld a, [hli] ; sprite visibility
1188
inc a
1189
jr z, .nextSprite
1190
inc l
1191
ld a, [hli] ; Y location
1192
cp b
1193
jr nz, .nextSprite
1194
inc l
1195
ld a, [hl] ; X location
1196
cp c
1197
jr z, .foundSpriteInFrontOfPlayer
1198
.nextSprite
1199
pop hl
1200
ld a, l
1201
add $10
1202
ld l, a
1203
inc e
1204
dec d
1205
jr nz, .spriteLoop
1206
ret
1207
.foundSpriteInFrontOfPlayer
1208
pop hl
1209
ld a, l
1210
and $f0
1211
inc a
1212
ld l, a ; hl = x#SPRITESTATEDATA1_MOVEMENTSTATUS
1213
set BIT_FACE_PLAYER, [hl]
1214
ld a, e
1215
ldh [hTextID], a
1216
ret
1217
1218
; function to check if the player will jump down a ledge and check if the tile ahead is passable (when not surfing)
1219
; sets the carry flag if there is a collision, and unsets it if there isn't a collision
1220
CollisionCheckOnLand::
1221
ld a, [wMovementFlags]
1222
bit BIT_LEDGE_OR_FISHING, a
1223
jr nz, .noCollision
1224
; if not jumping a ledge
1225
ld a, [wSimulatedJoypadStatesIndex]
1226
and a
1227
jr nz, .noCollision ; no collisions when the player's movements are being controlled by the game
1228
ld a, [wPlayerDirection] ; the direction that the player is trying to go in
1229
ld d, a
1230
ld a, [wSpritePlayerStateData1CollisionData]
1231
and d ; check if a sprite is in the direction the player is trying to go
1232
jr nz, .collision
1233
xor a
1234
ldh [hTextID], a
1235
call IsSpriteInFrontOfPlayer ; check for sprite collisions again? when does the above check fail to detect a sprite collision?
1236
ldh a, [hTextID]
1237
and a ; was there a sprite collision?
1238
jr nz, .collision
1239
; if no sprite collision
1240
ld hl, TilePairCollisionsLand
1241
call CheckForJumpingAndTilePairCollisions
1242
jr c, .collision
1243
call CheckTilePassable
1244
jr nc, .noCollision
1245
.collision
1246
ld a, [wChannelSoundIDs + CHAN5]
1247
cp SFX_COLLISION ; check if collision sound is already playing
1248
jr z, .setCarry
1249
ld a, SFX_COLLISION
1250
call PlaySound ; play collision sound (if it's not already playing)
1251
.setCarry
1252
scf
1253
ret
1254
.noCollision
1255
and a
1256
ret
1257
1258
; function that checks if the tile in front of the player is passable
1259
; clears carry if it is, sets carry if not
1260
CheckTilePassable::
1261
predef GetTileAndCoordsInFrontOfPlayer ; get tile in front of player
1262
ld a, [wTileInFrontOfPlayer] ; tile in front of player
1263
ld c, a
1264
ld hl, wTilesetCollisionPtr ; pointer to list of passable tiles
1265
ld a, [hli]
1266
ld h, [hl]
1267
ld l, a ; hl now points to passable tiles
1268
.loop
1269
ld a, [hli]
1270
cp $ff
1271
jr z, .tileNotPassable
1272
cp c
1273
ret z
1274
jr .loop
1275
.tileNotPassable
1276
scf
1277
ret
1278
1279
; check if the player is going to jump down a small ledge
1280
; and check for collisions that only occur between certain pairs of tiles
1281
; Input: hl - address of directional collision data
1282
; sets carry if there is a collision and unsets carry if not
1283
CheckForJumpingAndTilePairCollisions::
1284
push hl
1285
predef GetTileAndCoordsInFrontOfPlayer ; get the tile in front of the player
1286
push de
1287
push bc
1288
farcall HandleLedges ; check if the player is trying to jump a ledge
1289
pop bc
1290
pop de
1291
pop hl
1292
and a
1293
ld a, [wMovementFlags]
1294
bit BIT_LEDGE_OR_FISHING, a
1295
ret nz
1296
; if not jumping
1297
1298
CheckForTilePairCollisions2::
1299
lda_coord 8, 9 ; tile the player is on
1300
ld [wTilePlayerStandingOn], a
1301
1302
CheckForTilePairCollisions::
1303
ld a, [wTileInFrontOfPlayer]
1304
ld c, a
1305
.tilePairCollisionLoop
1306
ld a, [wCurMapTileset]
1307
ld b, a
1308
ld a, [hli]
1309
cp $ff
1310
jr z, .noMatch
1311
cp b
1312
jr z, .tilesetMatches
1313
inc hl
1314
.retry
1315
inc hl
1316
jr .tilePairCollisionLoop
1317
.tilesetMatches
1318
ld a, [wTilePlayerStandingOn] ; tile the player is on
1319
ld b, a
1320
ld a, [hl]
1321
cp b
1322
jr z, .currentTileMatchesFirstInPair
1323
inc hl
1324
ld a, [hl]
1325
cp b
1326
jr z, .currentTileMatchesSecondInPair
1327
jr .retry
1328
.currentTileMatchesFirstInPair
1329
inc hl
1330
ld a, [hl]
1331
cp c
1332
jr z, .foundMatch
1333
jr .tilePairCollisionLoop
1334
.currentTileMatchesSecondInPair
1335
dec hl
1336
ld a, [hli]
1337
cp c
1338
inc hl
1339
jr nz, .tilePairCollisionLoop
1340
.foundMatch
1341
scf
1342
ret
1343
.noMatch
1344
and a
1345
ret
1346
1347
INCLUDE "data/tilesets/pair_collision_tile_ids.asm"
1348
1349
; this builds a tile map from the tile block map based on the current X/Y coordinates of the player's character
1350
LoadCurrentMapView::
1351
ldh a, [hLoadedROMBank]
1352
push af
1353
ld a, [wTilesetBank] ; tile data ROM bank
1354
ldh [hLoadedROMBank], a
1355
ld [rROMB], a ; switch to ROM bank that contains tile data
1356
ld a, [wCurrentTileBlockMapViewPointer] ; address of upper left corner of current map view
1357
ld e, a
1358
ld a, [wCurrentTileBlockMapViewPointer + 1]
1359
ld d, a
1360
ld hl, wSurroundingTiles
1361
ld b, SCREEN_BLOCK_HEIGHT
1362
.rowLoop ; each loop iteration fills in one row of tile blocks
1363
push hl
1364
push de
1365
ld c, SCREEN_BLOCK_WIDTH
1366
.rowInnerLoop ; loop to draw each tile block of the current row
1367
push bc
1368
push de
1369
push hl
1370
ld a, [de]
1371
ld c, a ; tile block number
1372
call DrawTileBlock
1373
pop hl
1374
pop de
1375
pop bc
1376
inc hl
1377
inc hl
1378
inc hl
1379
inc hl
1380
inc de
1381
dec c
1382
jr nz, .rowInnerLoop
1383
; update tile block map pointer to next row's address
1384
pop de
1385
ld a, [wCurMapWidth]
1386
add MAP_BORDER * 2
1387
add e
1388
ld e, a
1389
jr nc, .noCarry
1390
inc d
1391
.noCarry
1392
; update tile map pointer to next row's address
1393
pop hl
1394
ld a, SURROUNDING_WIDTH * BLOCK_HEIGHT
1395
add l
1396
ld l, a
1397
jr nc, .noCarry2
1398
inc h
1399
.noCarry2
1400
dec b
1401
jr nz, .rowLoop
1402
ld hl, wSurroundingTiles
1403
ld bc, 0
1404
.adjustForYCoordWithinTileBlock
1405
ld a, [wYBlockCoord]
1406
and a
1407
jr z, .adjustForXCoordWithinTileBlock
1408
ld bc, SURROUNDING_WIDTH * 2
1409
add hl, bc
1410
.adjustForXCoordWithinTileBlock
1411
ld a, [wXBlockCoord]
1412
and a
1413
jr z, .copyToVisibleAreaBuffer
1414
ld bc, BLOCK_WIDTH / 2
1415
add hl, bc
1416
.copyToVisibleAreaBuffer
1417
decoord 0, 0 ; base address for the tiles that are directly transferred to VRAM during V-blank
1418
ld b, SCREEN_HEIGHT
1419
.rowLoop2
1420
ld c, SCREEN_WIDTH
1421
.rowInnerLoop2
1422
ld a, [hli]
1423
ld [de], a
1424
inc de
1425
dec c
1426
jr nz, .rowInnerLoop2
1427
ld a, SURROUNDING_WIDTH - SCREEN_WIDTH
1428
add l
1429
ld l, a
1430
jr nc, .noCarry3
1431
inc h
1432
.noCarry3
1433
dec b
1434
jr nz, .rowLoop2
1435
pop af
1436
ldh [hLoadedROMBank], a
1437
ld [rROMB], a ; restore previous ROM bank
1438
ret
1439
1440
AdvancePlayerSprite::
1441
ld a, [wSpritePlayerStateData1YStepVector]
1442
ld b, a
1443
ld a, [wSpritePlayerStateData1XStepVector]
1444
ld c, a
1445
ld hl, wWalkCounter ; walking animation counter
1446
dec [hl]
1447
jr nz, .afterUpdateMapCoords
1448
; if it's the end of the animation, update the player's map coordinates
1449
ld a, [wYCoord]
1450
add b
1451
ld [wYCoord], a
1452
ld a, [wXCoord]
1453
add c
1454
ld [wXCoord], a
1455
.afterUpdateMapCoords
1456
ld a, [wWalkCounter] ; walking animation counter
1457
cp $07
1458
jp nz, .scrollBackgroundAndSprites
1459
; if this is the first iteration of the animation
1460
ld a, c
1461
cp $01
1462
jr nz, .checkIfMovingWest
1463
; moving east
1464
ld a, [wMapViewVRAMPointer]
1465
ld e, a
1466
and $e0
1467
ld d, a
1468
ld a, e
1469
add $02
1470
and $1f
1471
or d
1472
ld [wMapViewVRAMPointer], a
1473
jr .adjustXCoordWithinBlock
1474
.checkIfMovingWest
1475
cp $ff
1476
jr nz, .checkIfMovingSouth
1477
; moving west
1478
ld a, [wMapViewVRAMPointer]
1479
ld e, a
1480
and $e0
1481
ld d, a
1482
ld a, e
1483
sub $02
1484
and $1f
1485
or d
1486
ld [wMapViewVRAMPointer], a
1487
jr .adjustXCoordWithinBlock
1488
.checkIfMovingSouth
1489
ld a, b
1490
cp $01
1491
jr nz, .checkIfMovingNorth
1492
; moving south
1493
ld a, [wMapViewVRAMPointer]
1494
add $40
1495
ld [wMapViewVRAMPointer], a
1496
jr nc, .adjustXCoordWithinBlock
1497
ld a, [wMapViewVRAMPointer + 1]
1498
inc a
1499
and $03
1500
or $98
1501
ld [wMapViewVRAMPointer + 1], a
1502
jr .adjustXCoordWithinBlock
1503
.checkIfMovingNorth
1504
cp $ff
1505
jr nz, .adjustXCoordWithinBlock
1506
; moving north
1507
ld a, [wMapViewVRAMPointer]
1508
sub $40
1509
ld [wMapViewVRAMPointer], a
1510
jr nc, .adjustXCoordWithinBlock
1511
ld a, [wMapViewVRAMPointer + 1]
1512
dec a
1513
and $03
1514
or $98
1515
ld [wMapViewVRAMPointer + 1], a
1516
.adjustXCoordWithinBlock
1517
ld a, c
1518
and a
1519
jr z, .pointlessJump ; mistake?
1520
.pointlessJump
1521
ld hl, wXBlockCoord
1522
ld a, [hl]
1523
add c
1524
ld [hl], a
1525
cp $02
1526
jr nz, .checkForMoveToWestBlock
1527
; moved into the tile block to the east
1528
xor a
1529
ld [hl], a
1530
ld hl, wXOffsetSinceLastSpecialWarp
1531
inc [hl]
1532
ld de, wCurrentTileBlockMapViewPointer
1533
call MoveTileBlockMapPointerEast
1534
jr .updateMapView
1535
.checkForMoveToWestBlock
1536
cp $ff
1537
jr nz, .adjustYCoordWithinBlock
1538
; moved into the tile block to the west
1539
ld a, $01
1540
ld [hl], a
1541
ld hl, wXOffsetSinceLastSpecialWarp
1542
dec [hl]
1543
ld de, wCurrentTileBlockMapViewPointer
1544
call MoveTileBlockMapPointerWest
1545
jr .updateMapView
1546
.adjustYCoordWithinBlock
1547
ld hl, wYBlockCoord
1548
ld a, [hl]
1549
add b
1550
ld [hl], a
1551
cp $02
1552
jr nz, .checkForMoveToNorthBlock
1553
; moved into the tile block to the south
1554
xor a
1555
ld [hl], a
1556
ld hl, wYOffsetSinceLastSpecialWarp
1557
inc [hl]
1558
ld de, wCurrentTileBlockMapViewPointer
1559
ld a, [wCurMapWidth]
1560
call MoveTileBlockMapPointerSouth
1561
jr .updateMapView
1562
.checkForMoveToNorthBlock
1563
cp $ff
1564
jr nz, .updateMapView
1565
; moved into the tile block to the north
1566
ld a, $01
1567
ld [hl], a
1568
ld hl, wYOffsetSinceLastSpecialWarp
1569
dec [hl]
1570
ld de, wCurrentTileBlockMapViewPointer
1571
ld a, [wCurMapWidth]
1572
call MoveTileBlockMapPointerNorth
1573
.updateMapView
1574
call LoadCurrentMapView
1575
ld a, [wSpritePlayerStateData1YStepVector]
1576
cp $01
1577
jr nz, .checkIfMovingNorth2
1578
; if moving south
1579
call ScheduleSouthRowRedraw
1580
jr .scrollBackgroundAndSprites
1581
.checkIfMovingNorth2
1582
cp $ff
1583
jr nz, .checkIfMovingEast2
1584
; if moving north
1585
call ScheduleNorthRowRedraw
1586
jr .scrollBackgroundAndSprites
1587
.checkIfMovingEast2
1588
ld a, [wSpritePlayerStateData1XStepVector]
1589
cp $01
1590
jr nz, .checkIfMovingWest2
1591
; if moving east
1592
call ScheduleEastColumnRedraw
1593
jr .scrollBackgroundAndSprites
1594
.checkIfMovingWest2
1595
cp $ff
1596
jr nz, .scrollBackgroundAndSprites
1597
; if moving west
1598
call ScheduleWestColumnRedraw
1599
.scrollBackgroundAndSprites
1600
ld a, [wSpritePlayerStateData1YStepVector]
1601
ld b, a
1602
ld a, [wSpritePlayerStateData1XStepVector]
1603
ld c, a
1604
sla b
1605
sla c
1606
ldh a, [hSCY]
1607
add b
1608
ldh [hSCY], a ; update background scroll Y
1609
ldh a, [hSCX]
1610
add c
1611
ldh [hSCX], a ; update background scroll X
1612
; shift all the sprites in the direction opposite of the player's motion
1613
; so that the player appears to move relative to them
1614
ld hl, wSprite01StateData1YPixels
1615
ld a, [wNumSprites] ; number of sprites
1616
and a ; are there any sprites?
1617
jr z, .done
1618
ld e, a
1619
.spriteShiftLoop
1620
ld a, [hl]
1621
sub b
1622
ld [hli], a
1623
inc l
1624
ld a, [hl]
1625
sub c
1626
ld [hl], a
1627
ld a, $0e
1628
add l
1629
ld l, a
1630
dec e
1631
jr nz, .spriteShiftLoop
1632
.done
1633
ret
1634
1635
; the following four functions are used to move the pointer to the upper left
1636
; corner of the tile block map in the direction of motion
1637
1638
MoveTileBlockMapPointerEast::
1639
ld a, [de]
1640
add $01
1641
ld [de], a
1642
ret nc
1643
inc de
1644
ld a, [de]
1645
inc a
1646
ld [de], a
1647
ret
1648
1649
MoveTileBlockMapPointerWest::
1650
ld a, [de]
1651
sub $01
1652
ld [de], a
1653
ret nc
1654
inc de
1655
ld a, [de]
1656
dec a
1657
ld [de], a
1658
ret
1659
1660
MoveTileBlockMapPointerSouth::
1661
add MAP_BORDER * 2
1662
ld b, a
1663
ld a, [de]
1664
add b
1665
ld [de], a
1666
ret nc
1667
inc de
1668
ld a, [de]
1669
inc a
1670
ld [de], a
1671
ret
1672
1673
MoveTileBlockMapPointerNorth::
1674
add MAP_BORDER * 2
1675
ld b, a
1676
ld a, [de]
1677
sub b
1678
ld [de], a
1679
ret nc
1680
inc de
1681
ld a, [de]
1682
dec a
1683
ld [de], a
1684
ret
1685
1686
; the following 6 functions are used to tell the V-blank handler to redraw
1687
; the portion of the map that was newly exposed due to the player's movement
1688
1689
ScheduleNorthRowRedraw::
1690
hlcoord 0, 0
1691
call CopyToRedrawRowOrColumnSrcTiles
1692
ld a, [wMapViewVRAMPointer]
1693
ldh [hRedrawRowOrColumnDest], a
1694
ld a, [wMapViewVRAMPointer + 1]
1695
ldh [hRedrawRowOrColumnDest + 1], a
1696
ld a, REDRAW_ROW
1697
ldh [hRedrawRowOrColumnMode], a
1698
ret
1699
1700
CopyToRedrawRowOrColumnSrcTiles::
1701
ld de, wRedrawRowOrColumnSrcTiles
1702
ld c, 2 * SCREEN_WIDTH
1703
.loop
1704
ld a, [hli]
1705
ld [de], a
1706
inc de
1707
dec c
1708
jr nz, .loop
1709
ret
1710
1711
ScheduleSouthRowRedraw::
1712
hlcoord 0, 16
1713
call CopyToRedrawRowOrColumnSrcTiles
1714
ld a, [wMapViewVRAMPointer]
1715
ld l, a
1716
ld a, [wMapViewVRAMPointer + 1]
1717
ld h, a
1718
ld bc, $200
1719
add hl, bc
1720
ld a, h
1721
and $03
1722
or $98
1723
ldh [hRedrawRowOrColumnDest + 1], a
1724
ld a, l
1725
ldh [hRedrawRowOrColumnDest], a
1726
ld a, REDRAW_ROW
1727
ldh [hRedrawRowOrColumnMode], a
1728
ret
1729
1730
ScheduleEastColumnRedraw::
1731
hlcoord 18, 0
1732
call ScheduleColumnRedrawHelper
1733
ld a, [wMapViewVRAMPointer]
1734
ld c, a
1735
and $e0
1736
ld b, a
1737
ld a, c
1738
add 18
1739
and $1f
1740
or b
1741
ldh [hRedrawRowOrColumnDest], a
1742
ld a, [wMapViewVRAMPointer + 1]
1743
ldh [hRedrawRowOrColumnDest + 1], a
1744
ld a, REDRAW_COL
1745
ldh [hRedrawRowOrColumnMode], a
1746
ret
1747
1748
ScheduleColumnRedrawHelper::
1749
ld de, wRedrawRowOrColumnSrcTiles
1750
ld c, SCREEN_HEIGHT
1751
.loop
1752
ld a, [hli]
1753
ld [de], a
1754
inc de
1755
ld a, [hl]
1756
ld [de], a
1757
inc de
1758
ld a, SCREEN_WIDTH - 1
1759
add l
1760
ld l, a
1761
jr nc, .noCarry
1762
inc h
1763
.noCarry
1764
dec c
1765
jr nz, .loop
1766
ret
1767
1768
ScheduleWestColumnRedraw::
1769
hlcoord 0, 0
1770
call ScheduleColumnRedrawHelper
1771
ld a, [wMapViewVRAMPointer]
1772
ldh [hRedrawRowOrColumnDest], a
1773
ld a, [wMapViewVRAMPointer + 1]
1774
ldh [hRedrawRowOrColumnDest + 1], a
1775
ld a, REDRAW_COL
1776
ldh [hRedrawRowOrColumnMode], a
1777
ret
1778
1779
; function to write the tiles that make up a tile block to memory
1780
; Input: c = tile block ID, hl = destination address
1781
DrawTileBlock::
1782
push hl
1783
ld a, [wTilesetBlocksPtr] ; pointer to tiles
1784
ld l, a
1785
ld a, [wTilesetBlocksPtr + 1]
1786
ld h, a
1787
ld a, c
1788
swap a
1789
ld b, a
1790
and $f0
1791
ld c, a
1792
ld a, b
1793
and $0f
1794
ld b, a ; bc = tile block ID * 0x10
1795
add hl, bc
1796
ld d, h
1797
ld e, l ; de = address of the tile block's tiles
1798
pop hl
1799
ld c, BLOCK_HEIGHT ; 4 loop iterations
1800
.loop ; each loop iteration, write 4 tile numbers
1801
push bc
1802
REPT BLOCK_WIDTH - 1
1803
ld a, [de]
1804
ld [hli], a
1805
inc de
1806
ENDR
1807
ld a, [de]
1808
ld [hl], a
1809
inc de
1810
ld bc, SURROUNDING_WIDTH - (BLOCK_WIDTH - 1)
1811
add hl, bc
1812
pop bc
1813
dec c
1814
jr nz, .loop
1815
ret
1816
1817
; function to update joypad state and simulate button presses
1818
JoypadOverworld::
1819
xor a
1820
ld [wSpritePlayerStateData1YStepVector], a
1821
ld [wSpritePlayerStateData1XStepVector], a
1822
call RunMapScript
1823
call Joypad
1824
ld a, [wStatusFlags7]
1825
bit BIT_TRAINER_BATTLE, a
1826
jr nz, .notForcedDownwards
1827
ld a, [wCurMap]
1828
cp ROUTE_17 ; Cycling Road
1829
jr nz, .notForcedDownwards
1830
ldh a, [hJoyHeld]
1831
and PAD_CTRL_PAD | PAD_B | PAD_A
1832
jr nz, .notForcedDownwards
1833
ld a, PAD_DOWN
1834
ldh [hJoyHeld], a ; on the cycling road, if there isn't a trainer and the player isn't pressing buttons, simulate a down press
1835
.notForcedDownwards
1836
ld a, [wStatusFlags5]
1837
bit BIT_SCRIPTED_MOVEMENT_STATE, a
1838
ret z
1839
; if simulating button presses
1840
ldh a, [hJoyHeld]
1841
ld b, a
1842
ld a, [wOverrideSimulatedJoypadStatesMask] ; bit mask for button presses that override simulated ones
1843
and b
1844
ret nz ; return if the simulated button presses are overridden
1845
ld hl, wSimulatedJoypadStatesIndex
1846
dec [hl]
1847
ld a, [hl]
1848
cp $ff
1849
jr z, .doneSimulating ; if the end of the simulated button presses has been reached
1850
ld hl, wSimulatedJoypadStatesEnd
1851
add l
1852
ld l, a
1853
jr nc, .noCarry
1854
inc h
1855
.noCarry
1856
ld a, [hl]
1857
ldh [hJoyHeld], a ; store simulated button press in joypad state
1858
and a
1859
ret nz
1860
ldh [hJoyPressed], a
1861
ldh [hJoyReleased], a
1862
ret
1863
1864
; if done simulating button presses
1865
.doneSimulating
1866
xor a
1867
ld [wUnusedOverrideSimulatedJoypadStatesIndex], a
1868
ld [wSimulatedJoypadStatesIndex], a
1869
ld [wSimulatedJoypadStatesEnd], a
1870
ld [wJoyIgnore], a
1871
ldh [hJoyHeld], a
1872
ld hl, wMovementFlags
1873
ld a, [hl]
1874
and (1 << BIT_SPINNING) | (1 << BIT_LEDGE_OR_FISHING) | (1 << 5) | (1 << 4) | (1 << 3)
1875
ld [hl], a
1876
ld hl, wStatusFlags5
1877
res BIT_SCRIPTED_MOVEMENT_STATE, [hl]
1878
ret
1879
1880
; function to check the tile ahead to determine if the character should get on land or keep surfing
1881
; sets carry if there is a collision and clears carry otherwise
1882
; It seems that this function has a bug in it, but due to luck, it doesn't
1883
; show up. After detecting a sprite collision, it jumps to the code that
1884
; checks if the next tile is passable instead of just directly jumping to the
1885
; "collision detected" code. However, it doesn't store the next tile in c,
1886
; so the old value of c is used. 2429 is always called before this function,
1887
; and 2429 always sets c to 0xF0. There is no 0xF0 background tile, so it
1888
; is considered impassable and it is detected as a collision.
1889
CollisionCheckOnWater::
1890
ld a, [wStatusFlags5]
1891
bit BIT_SCRIPTED_MOVEMENT_STATE, a
1892
jp nz, .noCollision ; return and clear carry if button presses are being simulated
1893
ld a, [wPlayerDirection] ; the direction that the player is trying to go in
1894
ld d, a
1895
ld a, [wSpritePlayerStateData1CollisionData]
1896
and d ; check if a sprite is in the direction the player is trying to go
1897
jr nz, .checkIfNextTileIsPassable ; bug?
1898
ld hl, TilePairCollisionsWater
1899
call CheckForJumpingAndTilePairCollisions
1900
jr c, .collision
1901
predef GetTileAndCoordsInFrontOfPlayer ; get tile in front of player (puts it in c and [wTileInFrontOfPlayer])
1902
ld a, [wTileInFrontOfPlayer] ; tile in front of player
1903
cp $14 ; water tile
1904
jr z, .noCollision ; keep surfing if it's a water tile
1905
cp $32 ; either the left tile of the S.S. Anne boarding platform or the tile on eastern coastlines (depending on the current tileset)
1906
jr z, .checkIfVermilionDockTileset
1907
cp $48 ; tile on right on coast lines in Safari Zone
1908
jr z, .noCollision ; keep surfing
1909
; check if the [land] tile in front of the player is passable
1910
.checkIfNextTileIsPassable
1911
ld hl, wTilesetCollisionPtr ; pointer to list of passable tiles
1912
ld a, [hli]
1913
ld h, [hl]
1914
ld l, a
1915
.loop
1916
ld a, [hli]
1917
cp $ff
1918
jr z, .collision
1919
cp c
1920
jr z, .stopSurfing ; stop surfing if the tile is passable
1921
jr .loop
1922
.collision
1923
ld a, [wChannelSoundIDs + CHAN5]
1924
cp SFX_COLLISION ; check if collision sound is already playing
1925
jr z, .setCarry
1926
ld a, SFX_COLLISION
1927
call PlaySound ; play collision sound (if it's not already playing)
1928
.setCarry
1929
scf
1930
jr .done
1931
.noCollision
1932
and a
1933
.done
1934
ret
1935
.stopSurfing
1936
xor a
1937
ld [wWalkBikeSurfState], a
1938
call LoadPlayerSpriteGraphics
1939
call PlayDefaultMusic
1940
jr .noCollision
1941
.checkIfVermilionDockTileset
1942
ld a, [wCurMapTileset]
1943
cp SHIP_PORT ; Vermilion Dock tileset
1944
jr nz, .noCollision ; keep surfing if it's not the boarding platform tile
1945
jr .stopSurfing ; if it is the boarding platform tile, stop surfing
1946
1947
; function to run the current map's script
1948
RunMapScript::
1949
push hl
1950
push de
1951
push bc
1952
farcall TryPushingBoulder
1953
ld a, [wMiscFlags]
1954
bit BIT_BOULDER_DUST, a
1955
jr z, .afterBoulderEffect
1956
farcall DoBoulderDustAnimation
1957
.afterBoulderEffect
1958
pop bc
1959
pop de
1960
pop hl
1961
call RunNPCMovementScript
1962
ld a, [wCurMap] ; current map number
1963
call SwitchToMapRomBank ; change to the ROM bank the map's data is in
1964
ld hl, wCurMapScriptPtr
1965
ld a, [hli]
1966
ld h, [hl]
1967
ld l, a
1968
ld de, .return
1969
push de
1970
jp hl ; jump to script
1971
.return
1972
ret
1973
1974
LoadWalkingPlayerSpriteGraphics::
1975
ld de, RedSprite
1976
ld hl, vNPCSprites
1977
jr LoadPlayerSpriteGraphicsCommon
1978
1979
LoadSurfingPlayerSpriteGraphics::
1980
ld de, SeelSprite
1981
ld hl, vNPCSprites
1982
jr LoadPlayerSpriteGraphicsCommon
1983
1984
LoadBikePlayerSpriteGraphics::
1985
ld de, RedBikeSprite
1986
ld hl, vNPCSprites
1987
1988
LoadPlayerSpriteGraphicsCommon::
1989
push de
1990
push hl
1991
lb bc, BANK(RedSprite), $0c
1992
call CopyVideoData
1993
pop hl
1994
pop de
1995
ld a, $c0
1996
add e
1997
ld e, a
1998
jr nc, .noCarry
1999
inc d
2000
.noCarry
2001
set 3, h ; add $800 ($80 tiles) to hl (1 << 3 == $8)
2002
lb bc, BANK(RedSprite), $0c
2003
jp CopyVideoData
2004
2005
; function to load data from the map header
2006
LoadMapHeader::
2007
farcall MarkTownVisitedAndLoadMissableObjects
2008
ld a, [wCurMapTileset]
2009
ld [wUnusedCurMapTilesetCopy], a
2010
ld a, [wCurMap]
2011
call SwitchToMapRomBank
2012
ld a, [wCurMapTileset]
2013
ld b, a
2014
res BIT_NO_PREVIOUS_MAP, a
2015
ld [wCurMapTileset], a
2016
ldh [hPreviousTileset], a
2017
bit BIT_NO_PREVIOUS_MAP, b
2018
ret nz
2019
ld hl, MapHeaderPointers
2020
ld a, [wCurMap]
2021
sla a
2022
jr nc, .noCarry1
2023
inc h
2024
.noCarry1
2025
add l
2026
ld l, a
2027
jr nc, .noCarry2
2028
inc h
2029
.noCarry2
2030
ld a, [hli]
2031
ld h, [hl]
2032
ld l, a ; hl = base of map header
2033
ld de, wCurMapHeader
2034
ld c, wCurMapHeaderEnd - wCurMapHeader
2035
.copyFixedHeaderLoop
2036
ld a, [hli]
2037
ld [de], a
2038
inc de
2039
dec c
2040
jr nz, .copyFixedHeaderLoop
2041
; initialize all the connected maps to disabled at first, before loading the actual values
2042
ld a, $ff
2043
ld [wNorthConnectedMap], a
2044
ld [wSouthConnectedMap], a
2045
ld [wWestConnectedMap], a
2046
ld [wEastConnectedMap], a
2047
; copy connection data (if any) to WRAM
2048
ld a, [wCurMapConnections]
2049
ld b, a
2050
.checkNorth
2051
bit NORTH_F, b
2052
jr z, .checkSouth
2053
ld de, wNorthConnectionHeader
2054
call CopyMapConnectionHeader
2055
.checkSouth
2056
bit SOUTH_F, b
2057
jr z, .checkWest
2058
ld de, wSouthConnectionHeader
2059
call CopyMapConnectionHeader
2060
.checkWest
2061
bit WEST_F, b
2062
jr z, .checkEast
2063
ld de, wWestConnectionHeader
2064
call CopyMapConnectionHeader
2065
.checkEast
2066
bit EAST_F, b
2067
jr z, .getObjectDataPointer
2068
ld de, wEastConnectionHeader
2069
call CopyMapConnectionHeader
2070
.getObjectDataPointer
2071
ld a, [hli]
2072
ld [wObjectDataPointerTemp], a
2073
ld a, [hli]
2074
ld [wObjectDataPointerTemp + 1], a
2075
push hl
2076
ld a, [wObjectDataPointerTemp]
2077
ld l, a
2078
ld a, [wObjectDataPointerTemp + 1]
2079
ld h, a ; hl = base of object data
2080
ld de, wMapBackgroundTile
2081
ld a, [hli]
2082
ld [de], a
2083
.loadWarpData
2084
ld a, [hli]
2085
ld [wNumberOfWarps], a
2086
and a
2087
jr z, .loadSignData
2088
ld c, a
2089
ld de, wWarpEntries
2090
.warpLoop ; one warp per loop iteration
2091
ld b, 4
2092
.warpInnerLoop
2093
ld a, [hli]
2094
ld [de], a
2095
inc de
2096
dec b
2097
jr nz, .warpInnerLoop
2098
dec c
2099
jr nz, .warpLoop
2100
.loadSignData
2101
ld a, [hli] ; number of signs
2102
ld [wNumSigns], a
2103
and a ; are there any signs?
2104
jr z, .loadSpriteData ; if not, skip this
2105
ld c, a
2106
ld de, wSignTextIDs
2107
ld a, d
2108
ldh [hSignCoordPointer], a
2109
ld a, e
2110
ldh [hSignCoordPointer + 1], a
2111
ld de, wSignCoords
2112
.signLoop
2113
ld a, [hli]
2114
ld [de], a
2115
inc de
2116
ld a, [hli]
2117
ld [de], a
2118
inc de
2119
push de
2120
ldh a, [hSignCoordPointer]
2121
ld d, a
2122
ldh a, [hSignCoordPointer + 1]
2123
ld e, a
2124
ld a, [hli]
2125
ld [de], a
2126
inc de
2127
ld a, d
2128
ldh [hSignCoordPointer], a
2129
ld a, e
2130
ldh [hSignCoordPointer + 1], a
2131
pop de
2132
dec c
2133
jr nz, .signLoop
2134
.loadSpriteData
2135
ld a, [wStatusFlags4]
2136
bit BIT_BATTLE_OVER_OR_BLACKOUT, a
2137
jp nz, .finishUp ; if so, skip this because battles don't destroy this data
2138
ld a, [hli]
2139
ld [wNumSprites], a ; save the number of sprites
2140
push hl
2141
; zero out sprite state data for sprites 01-15
2142
ld hl, wSprite01StateData1
2143
ld de, wSprite01StateData2
2144
xor a
2145
ld b, $f0
2146
.zeroSpriteDataLoop
2147
ld [hli], a
2148
ld [de], a
2149
inc e
2150
dec b
2151
jr nz, .zeroSpriteDataLoop
2152
; disable SPRITESTATEDATA1_IMAGEINDEX (set to $ff) for sprites 01-15
2153
ld hl, wSprite01StateData1ImageIndex
2154
ld de, $10
2155
ld c, $0f
2156
.disableSpriteEntriesLoop
2157
ld [hl], $ff
2158
add hl, de
2159
dec c
2160
jr nz, .disableSpriteEntriesLoop
2161
pop hl
2162
ld de, wSprite01StateData1
2163
ld a, [wNumSprites] ; number of sprites
2164
and a ; are there any sprites?
2165
jp z, .finishUp ; if there are no sprites, skip the rest
2166
ld b, a
2167
ld c, $00
2168
.loadSpriteLoop
2169
ld a, [hli]
2170
ld [de], a ; x#SPRITESTATEDATA1_PICTUREID
2171
inc d
2172
ld a, $04
2173
add e
2174
ld e, a
2175
ld a, [hli]
2176
ld [de], a ; x#SPRITESTATEDATA2_MAPY
2177
inc e
2178
ld a, [hli]
2179
ld [de], a ; x#SPRITESTATEDATA2_MAPX
2180
inc e
2181
ld a, [hli]
2182
ld [de], a ; x#SPRITESTATEDATA2_MOVEMENTBYTE1
2183
ld a, [hli]
2184
ldh [hLoadSpriteTemp1], a ; save movement byte 2
2185
ld a, [hli]
2186
ldh [hLoadSpriteTemp2], a ; save text ID and flags byte
2187
push bc
2188
push hl
2189
ld b, $00
2190
ld hl, wMapSpriteData
2191
add hl, bc
2192
ldh a, [hLoadSpriteTemp1]
2193
ld [hli], a ; store movement byte 2 in byte 0 of sprite entry
2194
ldh a, [hLoadSpriteTemp2]
2195
ld [hl], a ; this appears pointless, since the value is overwritten immediately after
2196
ldh a, [hLoadSpriteTemp2]
2197
ldh [hLoadSpriteTemp1], a
2198
and $3f
2199
ld [hl], a ; store text ID in byte 1 of sprite entry
2200
pop hl
2201
ldh a, [hLoadSpriteTemp1]
2202
bit BIT_TRAINER, a
2203
jr nz, .trainerSprite
2204
bit BIT_ITEM, a
2205
jr nz, .itemBallSprite
2206
jr .regularSprite
2207
.trainerSprite
2208
ld a, [hli]
2209
ldh [hLoadSpriteTemp1], a ; save trainer class
2210
ld a, [hli]
2211
ldh [hLoadSpriteTemp2], a ; save trainer number (within class)
2212
push hl
2213
ld hl, wMapSpriteExtraData
2214
add hl, bc
2215
ldh a, [hLoadSpriteTemp1]
2216
ld [hli], a ; store trainer class in byte 0 of the entry
2217
ldh a, [hLoadSpriteTemp2]
2218
ld [hl], a ; store trainer number in byte 1 of the entry
2219
pop hl
2220
jr .nextSprite
2221
.itemBallSprite
2222
ld a, [hli]
2223
ldh [hLoadSpriteTemp1], a ; save item number
2224
push hl
2225
ld hl, wMapSpriteExtraData
2226
add hl, bc
2227
ldh a, [hLoadSpriteTemp1]
2228
ld [hli], a ; store item number in byte 0 of the entry
2229
xor a
2230
ld [hl], a ; zero byte 1, since it is not used
2231
pop hl
2232
jr .nextSprite
2233
.regularSprite
2234
push hl
2235
ld hl, wMapSpriteExtraData
2236
add hl, bc
2237
; zero both bytes, since regular sprites don't use this extra space
2238
xor a
2239
ld [hli], a
2240
ld [hl], a
2241
pop hl
2242
.nextSprite
2243
pop bc
2244
dec d
2245
ld a, $0a
2246
add e
2247
ld e, a
2248
inc c
2249
inc c
2250
dec b
2251
jp nz, .loadSpriteLoop
2252
.finishUp
2253
predef LoadTilesetHeader
2254
callfar LoadWildData
2255
pop hl ; restore hl from before going to the warp/sign/sprite data (this value was saved for seemingly no purpose)
2256
ld a, [wCurMapHeight] ; map height in 4x4 tile blocks
2257
add a ; double it
2258
ld [wCurrentMapHeight2], a ; store map height in 2x2 tile blocks
2259
ld a, [wCurMapWidth] ; map width in 4x4 tile blocks
2260
add a ; double it
2261
ld [wCurrentMapWidth2], a ; map width in 2x2 tile blocks
2262
ld a, [wCurMap]
2263
ld c, a
2264
ld b, $00
2265
ldh a, [hLoadedROMBank]
2266
push af
2267
ld a, BANK(MapSongBanks)
2268
ldh [hLoadedROMBank], a
2269
ld [rROMB], a
2270
ld hl, MapSongBanks
2271
add hl, bc
2272
add hl, bc
2273
ld a, [hli]
2274
ld [wMapMusicSoundID], a ; music 1
2275
ld a, [hl]
2276
ld [wMapMusicROMBank], a ; music 2
2277
pop af
2278
ldh [hLoadedROMBank], a
2279
ld [rROMB], a
2280
ret
2281
2282
; function to copy map connection data from ROM to WRAM
2283
; Input: hl = source, de = destination
2284
CopyMapConnectionHeader::
2285
ld c, $0b
2286
.loop
2287
ld a, [hli]
2288
ld [de], a
2289
inc de
2290
dec c
2291
jr nz, .loop
2292
ret
2293
2294
; function to load map data
2295
LoadMapData::
2296
ldh a, [hLoadedROMBank]
2297
push af
2298
call DisableLCD
2299
ld a, $98
2300
ld [wMapViewVRAMPointer + 1], a
2301
xor a
2302
ld [wMapViewVRAMPointer], a
2303
ldh [hSCY], a
2304
ldh [hSCX], a
2305
ld [wWalkCounter], a
2306
ld [wUnusedCurMapTilesetCopy], a
2307
ld [wWalkBikeSurfStateCopy], a
2308
ld [wSpriteSetID], a
2309
call LoadTextBoxTilePatterns
2310
call LoadMapHeader
2311
farcall InitMapSprites ; load tile pattern data for sprites
2312
call LoadTileBlockMap
2313
call LoadTilesetTilePatternData
2314
call LoadCurrentMapView
2315
; copy current map view to VRAM
2316
hlcoord 0, 0
2317
ld de, vBGMap0
2318
ld b, SCREEN_HEIGHT
2319
.vramCopyLoop
2320
ld c, SCREEN_WIDTH
2321
.vramCopyInnerLoop
2322
ld a, [hli]
2323
ld [de], a
2324
inc e
2325
dec c
2326
jr nz, .vramCopyInnerLoop
2327
ld a, TILEMAP_WIDTH - SCREEN_WIDTH
2328
add e
2329
ld e, a
2330
jr nc, .noCarry
2331
inc d
2332
.noCarry
2333
dec b
2334
jr nz, .vramCopyLoop
2335
ld a, $01
2336
ld [wUpdateSpritesEnabled], a
2337
call EnableLCD
2338
ld b, SET_PAL_OVERWORLD
2339
call RunPaletteCommand
2340
call LoadPlayerSpriteGraphics
2341
ld a, [wStatusFlags6]
2342
and (1 << BIT_FLY_WARP) | (1 << BIT_DUNGEON_WARP)
2343
jr nz, .restoreRomBank
2344
ld a, [wStatusFlags7]
2345
bit BIT_NO_MAP_MUSIC, a
2346
jr nz, .restoreRomBank
2347
call UpdateMusic6Times
2348
call PlayDefaultMusicFadeOutCurrent
2349
.restoreRomBank
2350
pop af
2351
ldh [hLoadedROMBank], a
2352
ld [rROMB], a
2353
ret
2354
2355
; function to switch to the ROM bank that a map is stored in
2356
; Input: a = map number
2357
SwitchToMapRomBank::
2358
push hl
2359
push bc
2360
ld c, a
2361
ld b, $00
2362
ld a, BANK(MapHeaderBanks)
2363
call BankswitchHome
2364
ld hl, MapHeaderBanks
2365
add hl, bc
2366
ld a, [hl]
2367
ldh [hMapROMBank], a
2368
call BankswitchBack
2369
ldh a, [hMapROMBank]
2370
ldh [hLoadedROMBank], a
2371
ld [rROMB], a
2372
pop bc
2373
pop hl
2374
ret
2375
2376
IgnoreInputForHalfSecond:
2377
ld a, 30
2378
ld [wIgnoreInputCounter], a
2379
ld hl, wStatusFlags5
2380
ld a, [hl]
2381
or (1 << BIT_DISABLE_JOYPAD) | (1 << BIT_UNKNOWN_5_2) | (1 << BIT_UNKNOWN_5_1)
2382
ld [hl], a ; set ignore input bit
2383
ret
2384
2385
ResetUsingStrengthOutOfBattleBit:
2386
ld hl, wStatusFlags1
2387
res BIT_STRENGTH_ACTIVE, [hl]
2388
ret
2389
2390
ForceBikeOrSurf::
2391
ld b, BANK(RedSprite)
2392
ld hl, LoadPlayerSpriteGraphics ; in bank 0
2393
call Bankswitch
2394
jp PlayDefaultMusic ; update map/player state?
2395
2396
CheckForUserInterruption::
2397
; Return carry if Up+Select+B, Start or A are pressed in c frames.
2398
; Used only in the intro and title screen.
2399
call DelayFrame
2400
2401
push bc
2402
call JoypadLowSensitivity
2403
pop bc
2404
2405
ldh a, [hJoyHeld]
2406
cp PAD_UP + PAD_SELECT + PAD_B
2407
jr z, .input
2408
2409
ldh a, [hJoy5]
2410
IF DEF(_DEBUG)
2411
and PAD_START | PAD_SELECT | PAD_A
2412
ELSE
2413
and PAD_START | PAD_A
2414
ENDC
2415
jr nz, .input
2416
2417
dec c
2418
jr nz, CheckForUserInterruption
2419
2420
and a
2421
ret
2422
2423
.input
2424
scf
2425
ret
2426
2427
; function to load position data for destination warp when switching maps
2428
; INPUT:
2429
; a = ID of destination warp within destination map
2430
LoadDestinationWarpPosition::
2431
ld b, a
2432
ldh a, [hLoadedROMBank]
2433
push af
2434
ld a, [wPredefParentBank]
2435
ldh [hLoadedROMBank], a
2436
ld [rROMB], a
2437
ld a, b
2438
add a
2439
add a
2440
ld c, a
2441
ld b, 0
2442
add hl, bc
2443
ld bc, 4
2444
ld de, wCurrentTileBlockMapViewPointer
2445
call CopyData
2446
pop af
2447
ldh [hLoadedROMBank], a
2448
ld [rROMB], a
2449
ret
2450
2451