forked from peberlein/legend_of_tilda
-
Notifications
You must be signed in to change notification settings - Fork 0
/
tilda_b0.asm
3398 lines (2745 loc) · 77.5 KB
/
tilda_b0.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
;
; Legend of Tilda
; Copyright (c) 2017 Pete Eberlein
;
; Bank 0: initialization and main loop
;
COPY 'tilda.asm'
COPY 'tilda_b6_equ.asm'
; cart starts up in bank3
; title screen and menu in bank4
; which then jumps here with save data loaded
MAIN
LI R0,>01A5 ; VDP Register 1: Blank screen
BL @VDPREG
LI R0,>07F1 ; VDP Register 7: White on Black
BL @VDPREG
LI R0,SDFLAG
LI R1,HFLAGS
LI R2,4
BL @VDPR
CLR @FLAGS
CLR @RUPEES
;LI R0,>4000
;MOV R0,@FLAGS ; set dungeon 4
RESTRT
LI R0,BANK1 ; Sprites are in bank 1
LI R1,HDREND ; First function in bank 1
CLR R2 ; load sprites
BL @BANKSW
BL @LMUSIC ; Load music for overworld/dungeon
CLR @SOUND1 ; clear all sound effects
CLR @SOUND2
CLR @SOUND3
CLR @SOUND4
LI R0,SPRLST ; Initial Sprite List Table
LI R1,SPRL0
LI R2,SPRLE-SPRL0
! MOV *R1+,*R0+
DECT R2
JNE -!
BL @SPRUPD
LI R0,~DUNLVL
SZC R0,@FLAGS ; Reset flags (except dungeon)
BL @LNKCLR ; Reset hero color and hurt counter
; store starting position for overworld or dungeon
MOV @FLAGS,R1
SRL R1,12
MOVB @DUNGSP(R1),@MAPLOC
;LI R0,>7700 ; Initial map location is 7,7 (5,3 is by fairy)(3,7 is D-1,)
;LI R0,>2100 ; Dungeons: 37, 3C, 74, 45, 0B, 22, 42, 6D, 05
;MOV R0,R1
;LI R0,MAPSAV
;BL @VDPWB
;LI R0,>3200 ; dungeon 4 room
LI R0,>3700
MOVB R0,@MAPLOC
LI R0,>0600 ; Initial HP
MOV @HFLAGS,R1
ANDI R1,REDRNG+BLURNG
JEQ !
A R0,R0 ; adjusted for blue ring
ANDI R1,REDRNG
JEQ !
A R0,R0 ; adjusted for red ring
!
MOVB R0,@HP
; TODO this shouldn't be necessary
LI R2,BOMBSA
SZC R2,@HFLAG2 ; clear bombs available
LI R0,SDBOMB
BL @VDPRB ; get bomb count
JEQ !
SOC R2,@HFLAG2 ; set bombs available
!
LI R9,32-6
LI R1,OBJECT+12 ; Clear object table, starting at sword
! CLR *R1+
DEC R9
JNE -!
BL @GETSEL ; Get currently selected item and sprite
LI R0,BANK3 ; Overworld tiles in bank 3
LI R1,MAIN ; First function in bank 1
LI R2,1 ; load overworld tiles
LI R3,DUNLVL
CZC @FLAGS,R3
JEQ !
INC R2 ; R2=2 load dungeon tiles
!
BL @BANKSW
BL @STATUS ; Draw status bar
LI R0,BANK2 ; Overworld screen is in bank 2
LI R1,MAIN ; First function in bank 1
CLR R2
BL @BANKSW
BL @WIPE ; Do wipe animation
CLR @MOVE12
LI R5,>7078 ; Link Y X position in pixels
LI R3,DIR_DN ; Initial facing down
LI R11,INFLP
B @DRAW ; Load facing sprites
* Modifies R0-R3, R12
VSYNCM
CLR R12 ; CRU Address bit 0002 - VDP INT
! TB 2 ; CRU bit 2 - VDP INT
JEQ -! ; Loop until set
MOVB @VDPSTA,R12 ; Clear interrupt flag manually since we polled CRU
LI R0,BANK6 ; play music in bank 6
LI R1,MAIN
B @BANKSW ; return after bankswitch
INFLP
;LI R0,>07FF ; VDP Register 7: White on Black
;BL @VDPREG
BL @VSYNCM ; wait for Vsync and play music
;LI R0,>07F1 ; VDP Register 7: White on Black
;BL @VDPREG
BL @SPRUPD
LI R0,BANK5
LI R1,MAIN
CLR R2 ; do moving objects
BL @BANKSW
INPUT
BL @COUNT ; increment counters and animate fire
;LI R0,>07FE ; VDP Register 7: White on Black
;BL @VDPREG
BL @DOKEYS ; read joystick and keyboard
MOV @KEY_FL, R0
SLA R0,1 ; Shift EDG_C bit into carry status
JNC MENUX
B @DOMENU ; show menu item select screen
MENUX
MOV @HEROSP,R5 ; Hero YYXX position
MOVB @HURTC,R4 ; Hurt counter
JEQ !
BL @LNKHRT
!
MOV @FLAGS,R3
ANDI R3,DIR_XX ; Get direction in R3
MOVB @SWRDOB,R0 ; Sword animation counter
JNE !
MOV @KEY_FL,R0
SLA R0,2 ; Shift EDG_B bit into carry status
JNC ITEMX
MOV @HFLAGS,R1 ; Get selected item
ANDI R1,SELITM
A R1,R1
MOV @ITEMFN(R1),R1 ; Get function for item
B *R1
ITEMX ; item done
MOV @KEY_FL,R0
SLA R0,3 ; Shift EDG_A bit into carry status
JNC !
MOV @HFLAGS,R1 ; Get sword flags
ANDI R1,ASWORD+WSWORD+MSWORD
JEQ !
LI R0,>0C00 ; Sword animation is 12 frames
MOVB R0,@SWRDOB
LI R0,SND222 ; Sword sound effect
MOV R0,@SOUND3
LI R0,SND223 ; Sword sound effect
MOV R0,@SOUND4
!
; Up/down movement has priority over left/right, unless there is an obstruction
MOVB @HURTC,R0 ; Hurt counter
CI R0,>A000 ; compare to 40<<10
JHE HURTX
MOV @KEY_FL,R0
SRC R0,3
JOC MOVEDN
MOV @KEY_FL,R0
SRC R0,2
JOC MOVEUP
HKEYS
MOV @KEY_FL,R0
SRC R0,4
JOC MOVELT
MOV @KEY_FL,R0
SRC R0,5
JOC MOVERT
HURTX
BL @SWORD ; Animate sword if needed
B @DRAW
MOVEDN
LI R3,DIR_DN
BL @SWORD
CI R5,(192-8)*256 ; Check at bottom edge of screen
JL !
B @SCRNDN ; Scroll down
!
MOV R5,R0
AI R0,>1004 ; 16 pixels down, 4 right
LI R2,VSOLID
BL @TESTCH
MOV R5,R0
AI R0,>100C ; 16 pixels down, 12 right
BL @TESTCH
MOV R5,R0 ; Make X coord 8-aligned
ANDI R0,>0007
JEQ MOVED2 ; Already aligned
MOVED0 ANDI R0,>0004
JEQ MOVEL3
JMP MOVER3
MOVEUP
LI R3,DIR_UP
BL @SWORD
CI R5,25*256 ; Check at top edge of screen
JHE !
B @SCRNUP ; Scroll up
!
MOV R5,R0
AI R0,>0704 ; 7 pixels down, 4 right
LI R2,VSOLID
BL @TESTCH
MOV R5,R0
AI R0,>070C ; 7 pixels down, 12 right
BL @TESTCH
MOVEU0
MOV R5,R0 ; Make X coord 8-aligned
ANDI R0,>0007
JEQ MOVEU2 ; Already aligned
ANDI R0,>0004
JEQ MOVEL3
JMP MOVER3
MOVERT
LI R3,DIR_RT
BL @SWORD
MOV R5,R0 ; Make Y coord 8-aligned
ANDI R0,>0700
JEQ MOVER2 ; Already aligned
ANDI R0,>0400
JEQ MOVEU2
JMP MOVED2
MOVELT
LI R3,DIR_LT
BL @SWORD
MOV R5,R0 ; Make Y coord 8-aligned
ANDI R0,>0700
JEQ MOVEL2 ; Already aligned
ANDI R0,>0400
JEQ MOVEU2
JMP MOVED2
MOVER2 MOV R5,R0 ; Check at right edge of screen
ANDI R0,>00FF
CI R0,256-16
JNE !
B @SCRNRT ; Scroll right
! LI R3,DIR_RT
MOV R5,R0
AI R0,>0810 ; 8 pixels down, 16 right
LI R2,HSOLID
BL @TESTCH
MOVER3 INC R5 ; Move X coordinate right
INV @MOVE12
JEQ ! ; Check if additional movement needed
MOV R5,R1
ANDI R1,>0007 ; Check if 8-pixel aligned
JEQ !
INC R5 ; Add additional movement if not aligned
! MOV R5, R1
SWPB R1
ANDI R1,>0800 ; Set sprite animation based on coordinate
JMP MOVE2 ; Update the sprite animation
MOVEL2 MOV R5,R0 ; Check at left edge of screen
ANDI R0,>00FF
JNE !
B @SCRNLT ; Scroll left
! LI R3,DIR_LT
MOV R5,R0
AI R0,>07FF ; 8 pixels down, 1 left
LI R2,HSOLID
BL @TESTCH
MOVEL3 DEC R5 ; Move X coordinate left
INV @MOVE12 ; Check if additional movement needed
JEQ !
MOV R5,R1
ANDI R1,>0007 ; Check if 8-pixel aligned
JEQ !
DEC R5 ; Add additional movement if not aligned
! MOV R5, R1
SWPB R1
ANDI R1,>0800 ; Set sprite animation based on coordinate
JMP MOVE2 ; Update the sprite animation
MOVED2 AI R5,>0100 ; Move Y coordinate down
INV @MOVE12 ; Check if additional movement needed
JEQ !
MOV R5,R1
ANDI R1,>0700 ; Check if 8-pixel aligned
JEQ !
AI R5,>0100 ; Add additional movement if not aligned
! MOV R5,R1
ANDI R1,>0800 ; Set sprite animation based on coordinate
MOVE2
C @DOOR,R5
JNE MOVE3
BL @GODOOR
MOV @FLAGS,R3
ANDI R3,DIR_XX
CLR R1
MOVE3
MOVB R1,@HEROSP+2 ; Set color sprite index
AI R1,>0400
MOVB R1,@HEROSP+6 ; Set outline sprite index
MOVE4 JMP DRAW
MOVEU2 AI R5,>FF00 ; Move Y coordinate up
INV @MOVE12 ; Check if additional movement needed
JEQ !
MOV R5,R1
ANDI R1,>0700 ; Check if 8-pixel aligned
JEQ !
AI R5,>FF00 ; Add additional movement if not aligned
! MOV R5,R1
ANDI R1,>0800 ; Set sprite animation based on coordinate
JMP MOVE2 ; Update the sprite animation
; Update hero sprite location and sprite patterns
; R5=YYXX
; Load sprite patterns for hero facing direction
; R3=FACE{DN,RT,LT,UP}
; Modifies R0-2,R10
DRAW
MOV R5,@HEROSP ; Update color sprite
MOV R5,@HEROSP+4 ; Update outline sprite
LNKSPR
MOV @FLAGS,R0
MOV R0,R1
ANDI R0,DIR_XX
ANDI R1,DUNLVL ; Test for dungeon (sprite masking needed at doors)
JEQ LNKSP1
LI R2,2 ; Load hero sprites
BL @MASKSP ; modifies R2 if masking is needed, R4 is count
LNKSP1 C R3,R0 ; Update facing if up/down was pressed against a wall
JEQ INFLP2
LI R0,PUSHC ; clear push counter
SZC R0,@FLAGS
LI R2,2 ; Load hero sprites
LNKSP4 LI R0,DIR_XX
SZC R0,@FLAGS
SOC R3,@FLAGS
CLR R1
BL @DOSPRT ; update hero sprite location in VDP
LNKSP2
LI R0,BANK4 ; Load the new sprites
LI R1,MAIN
BL @BANKSW
INFLP2
B @INFLP
; Draw masked sprites if going thru dungeon door
; must preserve R0,R3
MASKSP
LI R4,>28FF ; Top of screen
C R5,R4
JH !
S R5,R4
SRL R4,8
JEQ LNKSP4
LI R2,8 ; Mask top
JMP LNKSP4
!
LI R4,>A800 ; Bottom of screen
C R5,R4
JL !
S R5,R4
NEG R4
SRL R4,8
JEQ LNKSP4
LI R2,7 ; Mask bottom
JMP LNKSP4
!
SWPB R5 ; Change to XXYY
LI R4,>10FF ; Left of screen
C R5,R4
JH !
S R5,R4
SRL R4,8
JEQ LNKSP4
LI R2,5 ; Mask left
SWPB R5
JMP LNKSP4
!
LI R4,>E000 ; Left of screen
C R5,R4
JL !
S R5,R4
NEG R4
SRL R4,8
JEQ LNKSP4
LI R2,6 ; Mask right
SWPB R5
JMP LNKSP4
!
SWPB R5 ; Restore to YYXX
RT
; jumped to by TESTCH with char in R1
VSOLID
BL @SOLID ; armos touched? push block?
B @HKEYS
HSOLID
BL @SOLID ; armos touched? push block?
B @MOVE4
* Cave map, index of item group in CAVTBL
CAVMAP BYTE >00,>05,>00,>05,>10,>29,>17,>05,>00,>00,>02,>25,>17,>10,>04,>0F
BYTE >06,>00,>14,>0E,>05,>00,>06,>00,>00,>00,>11,>00,>07,>22,>05,>06
BYTE >00,>03,>26,>0B,>19,>16,>00,>10,>0E,>00,>00,>00,>08,>0E,>00,>08
BYTE >00,>00,>00,>10,>15,>00,>00,>21,>00,>1B,>00,>00,>22,>0E,>00,>18
BYTE >00,>00,>27,>1B,>16,>24,>14,>08,>0E,>0C,>16,>10,>14,>00,>0D,>00
BYTE >00,>0D,>00,>00,>00,>18,>0D,>00,>00,>00,>00,>00,>00,>00,>00,>1A
BYTE >00,>00,>0F,>05,>10,>00,>17,>0E,>05,>00,>05,>0F,>00,>28,>00,>16
BYTE >11,>0E,>00,>00,>23,>13,>06,>01,>10,>09,>00,>08,>06,>05,>00,>00
; 18: Raft ride
; 19: Power bracelet under armos
; 1A: Heart container on ground
; 1B: Fairy Pond
; 2X: indicates entrance to level X
* Dungeon starting positions
DUNGSP ; 0 1 2 3 4 5 6 7 8 9
BYTE >77,>73,>7D,>7C,>71,>76,>79,>F1,>F6,>FE
EVEN
* Go into doorway or stairs or dock(raft)
GODOOR
MOV R11,R13 ; FIXME this gets overwritten by calling ANDOOR
LI R8,SWRDSP
! CLR *R8+
CI R8,WRKSP+256 ; Clear sprite table
JNE -!
MOV R5,R0
LI R2,GODOO2
BL @TESTCH
; Either stairs or dock (dungeon stairs are >7400)
CI R1,>7C00 ; Green dock char
JEQ RAFTUP
CI R1,>1C00 ; Red dock char
JEQ RAFTUP
BL @QUIET ; Mute all sound channels
LI R9,16 ; delay 16 frames
! BL @VSYNCM
DEC R9
JNE -!
JMP GODOO3
GODOO2 ; Solid tile means Cave/Doorway
CLR R9
LI R10,3
BL @QUIET ; Mute all sound channels
LI R0,SND212 ; Stairs sound
MOV R0,@SOUND3
LI R0,SND213 ; Stairs sound
MOV R0,@SOUND4
!
BL @ANDOOR ; Animate going in the door
LI R0,BANK4
LI R1,MAIN
LI R2,7 ; Load masked sprites at bottom
LI R3,DIR_UP
INC R9
MOV R9,R4 ; R4=number of lines to mask
BL @BANKSW
AI R5,>0100 ; Move down
CI R9,16
JNE -!
BL @VSYNCM
BL @VSYNCM
BL @VSYNCM
GODOO3
MOVB @MAPLOC,R1
SRL R1,8
CLR R2
MOVB @CAVMAP(R1),R2 ; get cave entry
MOVB R2,@CAVTYP ; store it
CI R2,>2000
JL !
B @GODUNG ; entering dungeon if starting with 2X
!
LI R4,INCAVE
SOC R4,@FLAGS ; Set in cave or dungeon flag
LI R0,BANK2 ; Overworld/deungon is in bank 2
LI R1,HDREND ; First function in bank 1
CLR R2
BL @BANKSW
LI R0,DUNLVL
CZC @FLAGS,R0
JNE DCAVIN
LI R0,>B178 ; Put hero at cave entrance
MOV R0,@HEROSP ; Update color sprite
MOV R0,@HEROSP+4 ; Update outline sprite
BL @CAVEIN
GODOO5
LI R0,BANK4 ; Hero sprites in bank 4
LI R1,HDREND ; First function in bank 4
LI R2,2 ; Load hero sprites
LI R3,DIR_UP
BL @BANKSW
; TODO animate up movement
LI R9,5 ; Hero walks upward for 5 frames
! BL @VSYNCM
LI R1,->100
BL @DOSPRT
DEC R9
JNE -!
BL @VSYNCM
BL @VSYNCM
BL @VSYNCM
MOV @FLAGS,R3
ANDI R3,DIR_XX
ORI R3,DIR_UP
LI R2,2 ; Load hero sprites
B @LNKSP2
* Ride the raft upward, or return to R13 if no raft
RAFTUP
LI R0,RAFT
CZC @HFLAGS,R0
JNE !
B *R13 ; dock - no raft
!
LI R7,->0100 ; Move up
MOV R5,R8
ANDI R8,>00FF
ORI R8,>1800
RAFTGO
LI R0,SND191 ; Secret
MOV R0,@SOUND2
LI R0,SPRPAT+(>110*8) ; Raft sprite pattern
BL @READ32 ; Get the sprite pattern
LI R0,SPRPAT+(>1C*8) ; extra hero sprite pattern
BL @PUTSCR ; Save it
LI R0,RAFTSC ; Raft sprite and color
MOV R0,@SWRDSP+2
LI R1,SWRDSP+4 ; Clear remaining sprites and scratchpad
! CLR *R1+
CI R1,SPRLST+>80
JNE -!
!
A R7,R5 ; Move Y up one
MOV R5,@HEROSP ; Update color sprite
MOV R5,@HEROSP+4 ; Update outline sprite
MOV R5,R0
AI R0,>0600
MOV R0,@SWRDSP ; Use sword index for raft
BL @SPRUPD
BL @VSYNCM
C R5,R8
JNE -!
CLR @SWRDSP+2 ; hide raft
CI R7,->0100 ; going up?
JEQ SCRNUP
B @INFLP
DCAVIN
LI R0,>2830 ; Put hero at cave entrance
MOV R0,@HEROSP ; Update color sprite
MOV R0,@HEROSP+4 ; Update outline sprite
BL @CAVEIN
LI R0,DIR_XX
SZC R0,@FLAGS
LI R0,BANK4 ; Hero sprites in bank 4
LI R1,HDREND ; First function in bank 4
LI R2,2 ; Load hero sprites
LI R3,DIR_DN
SOC R0,@FLAGS
BL @BANKSW
; todo animate walking downward
MOV @FLAGS,R3
ANDI R3,DIR_XX
LI R2,2 ; Load hero sprites
B @LNKSP2
RAFTDN
MOV @HEROSP,R5
LI R7,>0100 ; Move down
MOV @DOOR,R8 ; Stop here
JMP RAFTGO
SCRNRT LI R0,>0100 ; Add 1 to MAPLOC X
LI R3,DIR_RT
BL @DOMAZE
AB R0,@MAPLOC
LI R0,BANK2
LI R1,MAIN
CLR R2
BL @BANKSW
BL @SCRLRT
B @SCRLED
SCRNLT LI R0,>FF00 ; Add -1 to MAPLOC X
LI R3,DIR_LT
BL @DOMAZE
AB R0,@MAPLOC
LI R0,BANK2
LI R1,MAIN
CLR R2
BL @BANKSW
BL @SCRLLT
B @SCRLED
SCRNUP
LI R0,INCAVE
CZC @FLAGS,R0 ; Are we leaving a cave? (dungeon)
JNE DCVOUT
LI R0,>F000 ; Add -1 to MAPLOC Y
LI R3,DIR_UP
BL @DOMAZE
AB R0,@MAPLOC
LI R0,BANK2
LI R1,MAIN
CLR R2
BL @BANKSW
BL @SCRLUP
B @SCRLED
SCRNDN LI R0,INCAVE
CZC @FLAGS,R0 ; Are we leaving a cave?
JNE CAVOUT
LI R0,DUNLVL
CZC @FLAGS,R0 ; Are we in a dungeon?
JEQ !
MOVB @MAPLOC,R0
ANDI R0,>7000
CI R0,>7000 ; Going down at bottom of dungeon map?
JEQ DUNOUT ; Exit dungout, wipe and animate exiting door
! LI R0,>1000 ; Add 1 to MAPLOC Y
LI R3,DIR_DN
BL @DOMAZE
AB R0,@MAPLOC
LI R0,BANK2
LI R1,MAIN
CLR R2
BL @BANKSW
BL @SCRLDN
MOVB @MAPLOC,R1
SRL R1,8
CLR R0
MOVB @CAVMAP(R1),R0 ; get cave entry
CI R0,>1800 ; Raft ride?
JEQ RAFTDN
B @SCRLED
DCVOUT
LI R0,BANK3
LI R1,MAIN
LI R2,5 ; Load dungeon border walls
BL @BANKSW
LI R0,INCAVE
CAVOUT ; R0=INCAVE
SZC R0,@FLAGS ; Clear in cave flag
BL @CLRCAV
LI R0,BANK2
LI R1,MAIN
CLR R2
BL @BANKSW ; Load outside screen
MOV @DOOR,R5
MOV R5,@HEROSP
MOV R5,@HEROSP+4
BL @CAVEOT ; Update the flipped screen
CAVOU2
; check what tile is under hero (doorway, stairs, or dock)
MOV @DOOR,R5 ; R5=YYXX hero
MOV R5,R0
LI R2,!
BL @TESTCH
!
CI R1,>7F00 ; doorway
JEQ !
CI R1,>D800 ; waterfall
JEQ !
; TODO test for water - ride raft down
AI R5,-8*256 ; -(17*256)-16 ; appear up and to the left
MOV R5,@HEROSP ; Update color sprite
MOV R5,@HEROSP+4 ; Update outline sprite
JMP CAVOU3
!
AI R5,>1100
LI R9,17
LI R10,3
BL @QUIET
LI R0,SND212 ; Stairs sound
MOV R0,@SOUND3
LI R0,SND213 ; Stairs sound
MOV R0,@SOUND4
!
LI R0,BANK4 ;
LI R1,MAIN
LI R2,7 ; load hero sprites masked BOTTOM (R3 = direction, R4=count)
LI R3,DIR_DN
MOV R9,R4
DEC R4
JNE !
LI R2,2 ; load hero sprites
! BL @BANKSW
AI R5,->0100 ; Move up
BL @ANDOOR ; Animate going out door
DEC R9
JNE -!!
CAVOU3
BL @LMUSIC
BL @VSYNCM
BL @VSYNCM
B @INFLP
DUNOUT
BL @QUIET ; Turn off music
LI R0,DUNLVL
SZC R0,@FLAGS ; Clear dungeon flag and level
LI R0,MAPSAV
BL @VDPRB
MOVB R1,@MAPLOC ; Restore saved overworld map location
BL @CLRSCN
LI R0,BANK3 ; Overworld tiles in bank 3
LI R1,MAIN ; First function in bank 1
LI R2,1 ; load overworld tiles
BL @BANKSW
BL @STATUS ; Update status
LI R0,BANK2
LI R1,MAIN
CLR R2
BL @BANKSW ; Load outside screen
MOV @DOOR,R5
MOV R5,@HEROSP
MOV R5,@HEROSP+4
BL @WIPE
JMP CAVOU2
GODUNG
LI R0,MAPSAV ; Save overworld map location in VDP ram
MOVB @MAPLOC,R1
BL @VDPWB
LI R0,DNENEM+VDPWM ; clear dungeon enemies counts
MOVB @R0LB,*R14
MOVB R0,*R14
LI R1,128 ; 256 nibbles
! CLR *R15
DEC R1
JNE -!
SRL R2,8
AI R2,->20 ; R2=dungeon level 1-9
MOVB @DUNGSP(R2),R1 ; dungeon starting position
MOVB R1,@MAPLOC
SLA R2,12 ; Get dungeon level in >X000
SOC R2,@FLAGS ; Store dungeon level
BL @CLRSCN ; clear screen before updating tiles
LI R0,BANK3
LI R1,MAIN
LI R2,2 ; Load dungeon tileset
BL @BANKSW
BL @STATUS ; Update status
LI R0,BANK2 ; Overworld/deungon is in bank 2
LI R1,MAIN ; First function in bank 1
CLR R2
BL @BANKSW
BL @LMUSIC
BL @WIPE
LI R0,>B178 ; Put hero at cave entrance
MOV R0,@HEROSP ; Update color sprite
MOV R0,@HEROSP+4 ; Update outline sprite
CLR R1
BL @DOSPRT ; FIXME this should draw partial sprite instead
LI R2,2 ; Load hero sprites
BL @MASKSP ; modifies R2 if masking is needed, R4 is count
B @GODOO5
SCRLED ; after scrolling, check if darkened room and try lighting up
MOV @FLAGS,R0
ANDI R0,DARKRM
JEQ !
LI R0,BANK2
LI R1,MAIN
LI R2,1 ; LITEUP function
BL @BANKSW
!
MOV @FLAGS,R0
ANDI R0,DUNLVL
JEQ !
; TODO move player before closing shutters
; TODO player moves more if in shutter doorway
LI R0,BANK2
LI R1,MAIN
LI R2,4 ; Draw shutters function
BL @BANKSW
!
MOV @FLAGS,R3
ANDI R3,DIR_XX
MOV @HEROSP,R5
B @DRAW
* Do Forest Maze or Up Up Up Mountain
* Must preserve R0 if not in maze, CLR R0 otherwise
* R3 = direction (preserve)
* Modifies R1, R2
DOMAZE
LI R1,DUNLVL
CZC @FLAGS,R1
JNE !
LI R1,>6100 ; Forest maze location
LI R2,FRSTMZ ; Forest maze directions
CB @MAPLOC,R1
JEQ INMAZE
LI R1,>1B00 ; Up up mountain location
LI R2,UPUPMT ; Up up mountain directions
CB @MAPLOC,R1
JEQ INMAZE
MAZE0 ; reset the maze state to zero
LI R1,MAZEST+VDPWM ; Maze state + VDP write mask
MOVB @R1LB,*R14
MOVB R1,*R14
CLR *R15 ; Set it to zero
! RT
INMAZE
CB *R2,R3 ; Test exit
JEQ MAZE0 ; Exit the maze
LI R1,MAZEST
MOVB @R1LB,*R14
MOVB R1,*R14
LI R1,VDPRD ; VDP read data
MOVB *R1,R1
SWPB R1
INC R1
A R1,R2
CB *R2,R3 ; Compare direction
JEQ ! ; Went the right way