-
Notifications
You must be signed in to change notification settings - Fork 14
/
bank_00.asm
14805 lines (13998 loc) · 484 KB
/
bank_00.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
ORG $008000
I_RESET:
SEI ; Disable IRQ.
STZ.W HW_NMITIMEN ; Disable IRQ, NMI and joypad reading.
STZ.W HW_HDMAEN ; Disable HDMA.
STZ.W HW_MDMAEN ; Disable DMA.
STZ.W HW_APUIO0 ;\ Clear SPC I/O ports.
STZ.W HW_APUIO1 ;|
STZ.W HW_APUIO2 ;|
STZ.W HW_APUIO3 ;/
LDA.B #!HW_DISP_FBlank ;\ Enable F-blank.
STA.W HW_INIDISP ;/
CLC ;\ Disable emulation mode.
XCE ;/
REP #$38 ; AXY->16, Disable decimal mode.
LDA.W #0 ;\ Initialize direct page to 0x0000.
TCD ;/
LDA.W #StackStart ;\ Initialize stack pointer to $01FF.
TCS ;/
LDA.W #$A9|(!OBJOffscreen<<8) ;\ "LDA #$F0"
STA.L OAMResetRoutine ;/
LDX.W #3*(!OBJCount-1) ;
LDY.W #OAMMirror+4*(!OBJCount-1)+1 ; Starting address to clear ($03FD).
- LDA.W #$008D ;\
STA.L OAMResetRoutine+2,X ;| "STA $xxxx" for each OAM slot
TYA ;|
STA.L OAMResetRoutine+3,X ;/
SEC ;\
SBC.W #4 ;|
TAY ;|
DEX #3 ;| Loop for all OAM slots.
BPL - ;/
SEP #$30 ; AXY->8
LDA.B #$6B ;\ "RTL"
STA.L OAMResetRoutine+386 ;/
JSR UploadSPCEngine ; Upload the SPC engine.
STZ.W GameMode ; Clear game mode.
STZ.W OverworldOverride ; Clear OW bypass level number.
JSR ClearMemory ; Clear out $0000-$1FFF and $7F837B/D.
JSR UploadSamples ; Upload SPC samples.
JSR WindowDMASetup ; Set up DMA for window settings.
LDA.B #(VRam_OBJTiles>>13)|!HW_OBJ_Size_8_16
STA.W HW_OBJSEL ; Set OAM character sizes to be 8x8 and 16x16.
INC.B LagFlag ;
GameLoop: ; Main game loop.
LDA.B LagFlag ;\ Wait for NMI before executing next frame.
BEQ GameLoop ;/
CLI ; Enable interrupts.
INC.B TrueFrame ; Increment global frame counter.
JSR RunGameMode ; Run the game.
STZ.B LagFlag ; Indicate that the current frame has finished.
BRA GameLoop ;
SPC700UploadLoop: ; Subroutine to upload data to the SPC chip. 24-bit pointer to data should be in $00.
PHP ;
REP #$30 ; AXY->16
LDY.W #0 ;
LDA.W #$BBAA ; Value to check for when the SPC chip is ready.
- CMP.W HW_APUIO0 ;\ Wait for the SPC to be ready.
BNE - ;/
SEP #$20 ; A->8
LDA.B #$CC ; Byte used to enable SPC block upload.
BRA SendSPCBlock ;
TransferBytes: ; Block upload loop. Entry point at $0080B3
LDA.B [_0],Y ;\
INY ;| Load first byte to upload.
XBA ;|
LDA.B #0 ;/ Validation byte for SPC.
BRA StartTransfer ;
NextByte: ; Inner byte loop for each block. Entry point below.
XBA ;\\
LDA.B [_0],Y ;|| Load next byte.
INY ;||
XBA ;|/
- CMP.W HW_APUIO0 ;|\ Wait for the SPC to respond from the previous byte.
BNE - ;|/
INC A ;| Increment validation byte.
StartTransfer: ;| Entry point for the inner byte loop.
REP #$20 ;|\ A->16
STA.W HW_APUIO0 ;|| Send byte, plus the validation byte.
SEP #$20 ;|/ A->8
DEX ;|
BNE NextByte ;/
- CMP.W HW_APUIO0 ;\ Wait for the SPC to respond from the last byte of the block.
BNE - ;/
- ADC.B #3 ;\ Add 3; if A becomes 0, add 3 once more so it's still positive.
BEQ - ;/
SendSPCBlock: ; Entry point for the SPC engine upload loop.
PHA ;
REP #$20 ; A->16
LDA.B [_0],Y ;\
INY #2 ;| Get data length.
TAX ;/
LDA.B [_0],Y ;\
INY #2 ;| Send the ARAM address to write to.
STA.W HW_APUIO2 ;/
SEP #$20 ; A->8
CPX.W #1 ;\
LDA.B #0 ;| If at the end of the data block, send #$00.
ROL A ;| Else, send #$01.
STA.W HW_APUIO1 ;/
ADC.B #$7F ; Set overflow flag if there are still bytes left to write.
PLA ;\
STA.W HW_APUIO0 ;| Send a byte to indicate the write is done,
- CMP.W HW_APUIO0 ;| then wait for the response back from the SPC chip.
BNE - ;/
BVS TransferBytes ; If the overflow flag was set earlier, jump back to upload additional blocks.
STZ.W HW_APUIO0 ;\
STZ.W HW_APUIO1 ;| Clear SPC I/O ports.
STZ.W HW_APUIO2 ;|
STZ.W HW_APUIO3 ;/
PLP ;
RTS ;
UploadSPCEngine: ; Routine to upload the music engine to the SPC700 chip.
LDA.B #SPC700Engine ;\
%BorW(STA, _0) ;|
LDA.B #SPC700Engine>>8 ;|
%BorW(STA, _1) ;| Point $00 to the SPC engine code at $0E8000.
LDA.B #SPC700Engine>>16 ;|
%BorW(STA, _2) ;/
UploadDataToSPC: ;
SEI ;\
JSR SPC700UploadLoop ;| Upload the data pointed to by $00. Make sure interrupts don't fire during the process.
CLI ;/
RTS ;
UploadSamples: ; Routine to upload music samples to the SPC700 chip.
LDA.B #MusicSamples ;\
%BorW(STA, _0) ;|
LDA.B #MusicSamples>>8 ;| Point $00 to the SPC sample data at $0F8000.
%BorW(STA, _1) ;|
LDA.B #MusicSamples>>16 ;|
%BorW(STA, _2) ;/
BRA StartMusicUpload ; Upload data.
UploadMusicBank1: ; Routine to upload overworld music data to the SPC700 chip.
LDA.B #MusicBank1 ;\
%BorW(STA, _0) ;|
LDA.B #MusicBank1>>8 ;| Point $00 to the overworld music bank at $0E98B1.
%BorW(STA, _1) ;|
LDA.B #MusicBank1>>16 ;|
%BorW(STA, _2) ;/
StartMusicUpload: ;
LDA.B #-1 ;\ Tell the SPC that music data is being sent.
STA.W HW_APUIO1 ;/
JSR UploadDataToSPC ; Upload data.
LDX.B #3 ;\
- STZ.W HW_APUIO0,X ;|
STZ.W SPCIO0,X ;|
STZ.W Empty1DFD,X ;| Clear out all SPC I/O ports and mirrors.
DEX ;|
BPL - ;/
SPCUploadReturn: ;
RTS ;
UploadLevelMusic: ; Routine to upload level music data to the SPC700 chip.
LDA.W BonusGameActivate ;\
BNE UploadOverworldMusic ;| Upload the level music bank on one of 3 conditions:
LDA.W OverworldOverride ;| 1. Going to a bonus game.
CMP.B #!MainMapLvls+!IntroCutsceneLevel ;| 2. Loading the intro level.
BEQ UploadOverworldMusic ;| 3. Going to a new level (not primary).
ORA.W SublevelCount ;| If none of these conditions are met, return.
ORA.W ShowMarioStart ;|
BNE SPCUploadReturn ;/
UploadOverworldMusic: ;
LDA.B #MusicBank2 ;\
%BorW(STA, _0) ;|
LDA.B #MusicBank2>>8 ;| Point $00 to the level music bank at $0EAED6.
%BorW(STA, _1) ;|
LDA.B #MusicBank2>>16 ;|
%BorW(STA, _2) ;/
BRA StartMusicUpload ; Upload the data.
UploadCreditsMusic: ; Routine to upload credits music data to the SPC700 chip.
LDA.B #MusicBank3 ;\
%BorW(STA, _0) ;|
LDA.B #MusicBank3>>8 ;| Point $00 to the credits music bank at $03E400.
%BorW(STA, _1) ;|
LDA.B #MusicBank3>>16 ;|
%BorW(STA, _2) ;/
BRA StartMusicUpload ; Upload the data.
I_NMI: ; NMI routine.
SEI ; Disable interrupts to prevent interrupting an interrupt.
PHP ;\
REP #$30 ;| AXY->16
PHA ;| Preserve values to be restored at the end.
PHX ;| Note: direct page and $00-$04 are not preserved!
PHY ;|
PHB ;/
PHK ;
PLB ;
SEP #$30 ; AXY->8
LDA.W HW_RDNMI ; Read to clear the n flag.
LDA.W SPCIO2 ;\ If playing music in $1DFB, branch to load it.
BNE + ;/
LDY.W HW_APUIO2 ;\
CPY.W LastUsedMusic ;| If $1DFF doesn't match the currently playing music, update the music.
BNE ++ ;/
+ STA.W HW_APUIO2 ;\
STA.W LastUsedMusic ;| Keep the current sound playing, then mirror and clear $1DFB.
STZ.W SPCIO2 ;/
++ LDA.W SPCIO0 ;\
STA.W HW_APUIO0 ;|
LDA.W SPCIO1 ;|
STA.W HW_APUIO1 ;|
LDA.W SPCIO3 ;| Update the remaining sound ports and clear mirrors.
STA.W HW_APUIO3 ;|
STZ.W SPCIO0 ;|
STZ.W SPCIO1 ;|
STZ.W SPCIO3 ;/
LDA.B #!HW_DISP_FBlank ;\ Force blank.
STA.W HW_INIDISP ;/
STZ.W HW_HDMAEN ; Disable HDMA.
LDA.B Layer12Window ;\ Update layer 1 and 2 window mask settings.
STA.W HW_W12SEL ;/
LDA.B Layer34Window ;\ Update layer 3 and 4 window mask settings.
STA.W HW_W34SEL ;/
LDA.B OBJCWWindow ;\ Update sprite and color window settings.
STA.W HW_WOBJSEL ;/
LDA.B ColorAddition ;\ Initial color addition settings.
STA.W HW_CGSWSEL ;/
LDA.W IRQNMICommand ;\ Check if a regular level.
BPL RegularLevelNMI ;|
JMP Mode7NMI ;/ Otherwise, go to mode 7 routines.
RegularLevelNMI: ;\ Set color math on all layers in $40 but 3.
LDA.B ColorSettings ;|
AND.B #~!HW_CMath_BG3 ;/
STA.W HW_CGADSUB ;\ Mode 1 with layer 3 priority.
LDA.B #!HW_BG_BG3Pri|!HW_BG_Mode1 ;/
STA.W HW_BGMODE ;\
LDA.B LagFlag ;|
BEQ + ;| If the game is lagging, skip updating stuff like sprite OAM and controller data.
LDA.W IRQNMICommand ;| If in a special level, skip updating layer positions too.
LSR A ;|
BEQ NotSpecialLevelNMI ;/
JMP SpecialLevelNMI ;
+ INC.B LagFlag ; Allow the game loop to run after NMI.
JSR CODE_00A488 ; Upload palette to CGRAM.
LDA.W IRQNMICommand ;\\
LSR A ;|| Skip down if not either in a regular level, loading message (MARIO START), title screen, or castle cutscene.
BNE CODE_008222 ;|/
BCS + ;|\ Draw status bar if in a regular level.
JSR DrawStatusBar ;|/
+ LDA.W CutsceneID ;|\
CMP.B #!Cutscene_Credits ;||
BNE CODE_008209 ;||
LDA.W CreditsUpdateBG ;|| Handle DMA for the background during the credits staff roll, if applicable.
BEQ CODE_00821A ;||
JSL CODE_0C9567 ;||
BRA CODE_00821A ;|/
CODE_008209: ;|
JSL UploadOneMap16Strip ;| Update Layer 1/2 tilemaps.
LDA.W UploadMarioStart ;|\
BEQ CODE_008217 ;|| If set to do so, upload graphics for black screen messages (MARIO START/GAME OVER/TIME UP/etc).
JSR CODE_00A7C2 ;|| Then skip way down to the $12 tilemap handling.
BRA CODE_00823D ;|/
CODE_008217: ;|
JSR CODE_00A390 ;|
CODE_00821A: ;|
JSR CODE_00A436 ;| Restore the tiles overwritten by the MARIO START! message, if applicable.
JSR MarioGFXDMA ;| Handle DMA for the player/Yoshi/Podoboo tiles.
BRA CODE_00823D ;/
CODE_008222: ; On overworld.
LDA.W OverworldProcess ;\\
CMP.B #10 ;||
BNE CODE_008237 ;||
LDY.W OWSubmapSwapProcess ;|| If switching between two submaps on the overworld,
DEY #2 ;|| and currently updating Layer 1, do exactly that.
CPY.B #$4 ;|| Then skip down to controller updating.
BCS CODE_008237 ;||
JSR CODE_00A529 ;||
BRA + ;|/
CODE_008237: ;|
JSR CODE_00A4E3 ;| Upload overworld animated tile graphics and animated palettes.
JSR MarioGFXDMA ;/ Handle DMA for the player/Yoshi/Podoboo tiles.
CODE_00823D: ;
JSR LoadScrnImage ; Upload tilemap data from $12.
JSR DoSomeSpriteDMA ; Upload OAM.
+ JSR ControllerUpdate ; Get controller data.
NotSpecialLevelNMI: ; All paths rejoin.
LDA.B Layer1XPos ;\
STA.W HW_BG1HOFS ;|
LDA.B Layer1XPos+1 ;|
STA.W HW_BG1HOFS ;|
LDA.B Layer1YPos ;|
CLC ;| Upload Layer 1's position.
ADC.W ScreenShakeYOffset ;|
STA.W HW_BG1VOFS ;|
LDA.B Layer1YPos+1 ;|
ADC.W ScreenShakeYOffset+1 ;|
STA.W HW_BG1VOFS ;/
LDA.B Layer2XPos ;\
STA.W HW_BG2HOFS ;|
LDA.B Layer2XPos+1 ;|
STA.W HW_BG2HOFS ;| Upload Layer 2's position.
LDA.B Layer2YPos ;|
STA.W HW_BG2VOFS ;|
LDA.B Layer2YPos+1 ;|
STA.W HW_BG2VOFS ;/
LDA.W IRQNMICommand
BEQ CODE_008292
SpecialLevelNMI:
LDA.B #!HW_TIMEN_NMI|!HW_TIMEN_JoyRead
LDY.W CutsceneID
CPY.B #8
BNE NotCredits
LDY.W Brightness
STY.W HW_INIDISP
LDY.W HDMAEnable
STY.W HW_HDMAEN
JMP IRQNMIEnding
CODE_008292:
LDY.B #!StatusBarHeight ;\ How many scanlines the status bar uses in general.
CODE_008294: ;|
LDA.W HW_TIMEUP ;|
STY.W HW_VTIME ;| Enable IRQ #1 on this scanline, for the status bar.
STZ.W HW_VTIME+1 ;|
STZ.B IRQType ;/
LDA.B #!HW_TIMEN_NMI|!HW_TIMEN_JoyRead|!HW_TIMEN_IRQV
NotCredits:
STA.W HW_NMITIMEN
STZ.W HW_BG3HOFS
STZ.W HW_BG3HOFS
STZ.W HW_BG3VOFS
STZ.W HW_BG3VOFS
LDA.W Brightness
STA.W HW_INIDISP
LDA.W HDMAEnable
STA.W HW_HDMAEN
REP #$30
PLB
PLY
PLX
PLA
PLP
I_EMPTY:
RTI
Mode7NMI: ; NMI for Mode 7 rooms.
LDA.B LagFlag ;\ Branch if in a lag frame.
BNE Mode7Lagging ;/
INC.B LagFlag ;
LDA.W UploadMarioStart ;\
BEQ CODE_0082D4 ;| If set to do so, upload tiles for the MARIO START/TIME UP/GAME OVER messages.
JSR CODE_00A7C2 ;| Then skip down to drawing the status bar.
BRA CODE_0082E8 ;/
CODE_0082D4:
JSR CODE_00A436 ; Restore the tiles overwritten by the MARIO START! message, if applicable.
JSR MarioGFXDMA ; Handle DMA for the player/Yoshi/Podoboo tiles.
BIT.W IRQNMICommand ;\
BVC CODE_0082E8 ;|
JSR CODE_0098A9 ;|
LDA.W IRQNMICommand ;| If in Reznor/Morton/Roy/Ludwig/Bowser's battles, upload their Mode 7 tilemaps and animate their lava.
LSR A ;| If in Iggy/Larry/Reznor/Morton/Roy/Ludwig's battles, draw the status bar.
BCS + ;|
CODE_0082E8: ;|
JSR DrawStatusBar ;/
+ JSR CODE_00A488 ; Upload palette to CGRAM.
JSR LoadScrnImage ; Upload tilemap data from $12.
JSR DoSomeSpriteDMA ; Upload OAM.
JSR ControllerUpdate ; Get controller data.
Mode7Lagging: ; Transfer various RAM mirrors to the registers
LDA.B #!HW_BG_BG3Pri|!HW_BG_Mode1
STA.W HW_BGMODE
LDA.B Mode7CenterX
CLC
ADC.B #$80
STA.W HW_M7X
LDA.B Mode7CenterX+1
ADC.B #0
STA.W HW_M7X
LDA.B Mode7CenterY
CLC
ADC.B #$80
STA.W HW_M7Y
LDA.B Mode7CenterY+1
ADC.B #0
STA.W HW_M7Y
LDA.B Mode7ParamA
STA.W HW_M7A
LDA.B Mode7ParamA+1
STA.W HW_M7A
LDA.B Mode7ParamB
STA.W HW_M7B
LDA.B Mode7ParamB+1
STA.W HW_M7B
LDA.B Mode7ParamC
STA.W HW_M7C
LDA.B Mode7ParamC+1
STA.W HW_M7C
LDA.B Mode7ParamD
STA.W HW_M7D
LDA.B Mode7ParamD+1
STA.W HW_M7D
JSR SETL1SCROLL
LDA.W IRQNMICommand ;\
LSR A ;| Branch if not in Bowser's room.
BCC + ;/
LDA.W Brightness
STA.W HW_INIDISP
LDA.W HDMAEnable
STA.W HW_HDMAEN
LDA.B #!HW_TIMEN_NMI|!HW_TIMEN_JoyRead ;\ Skip the status bar IRQ and immediately prepare the registers after.
JMP CODE_0083F3 ;/
; Not in Bowser's room.
+ LDY.B #!StatusBarHeight ;\ Scanline the status bar ends at in Iggy/Larry/Ludwig/Reznor's rooms.
BIT.W IRQNMICommand ;|
BVC + ;|
LDA.W ActiveBoss ;|
ASL A ;|
TAX ;|
LDA.W BossCeilingHeights,X ;|
CMP.B #!RoyMortonCeilingHeight ;|
BNE + ;|
LDY.B #!StatusBarHeight+9 ;/ Scanline the status bar ends at in Morton/Roy's rooms.
+ JMP CODE_008294 ; Prepare IRQ, and set up a couple more registers.
I_IRQ: ; IRQ routine.
SEI ; Set Interrupt flag so routine can start
PHP ;\ Save A/X/Y/P/B
REP #$30 ;| AXY->16
PHA ;|
PHX ;|
PHY ;|
PHB ;|
PHK ;|
PLB ;/ Set B to $00
SEP #$30 ; AXY->8
LDA.W HW_TIMEUP ; Read the IRQ register, 'unapply' the interrupt
BPL ExitIRQ ; If "Timer IRQ" is clear, skip the next code block
LDA.B #!HW_TIMEN_NMI|!HW_TIMEN_JoyRead
LDY.W IRQNMICommand
BMI CODE_0083BA ; If Bit 7 (negative flag) is set, branch to a different IRQ mode
IRQNMIEnding:
STA.W HW_NMITIMEN ; Enable NMI Interrupt and Automatic Joypad reading
LDY.B #31
JSR WaitForHBlank
LDA.B Layer3XPos ;\ Adjust scroll settings for layer 3
STA.W HW_BG3HOFS ;|
LDA.B Layer3XPos+1 ;|
STA.W HW_BG3HOFS ;|
LDA.B Layer3YPos ;|
STA.W HW_BG3VOFS ;|
LDA.B Layer3YPos+1 ;|
STA.W HW_BG3VOFS ;/
CODE_0083A8:
LDA.B MainBGMode ;\ Set the layer BG sizes, L3 priority, and BG mode
STA.W HW_BGMODE ;/ (Effectively, this is the screen mode)
LDA.B ColorSettings ;\ Write CGADSUB
STA.W HW_CGADSUB ;/
ExitIRQ:
REP #$30 ; AXY->16
PLB ;\ Pull everything back
PLY ;|
PLX ;|
PLA ;|
PLP ;/
RTI ; And Return
CODE_0083BA:
BIT.W IRQNMICommand ; Get bit 6 of $0D9B
BVC CODE_0083E3 ; If clear, skip the next code section
LDY.B IRQType ;\ Skip if $11 = 0
BEQ CODE_0083D0 ;/
STA.W HW_NMITIMEN ; #$81 -> NMI / Controller Enable reg
LDY.B #20
JSR WaitForHBlank
JSR SETL1SCROLL
BRA CODE_0083A8
CODE_0083D0:
INC.B IRQType ; $11++
LDA.W HW_TIMEUP ;\ Set up the IRQ routine for layer 3
LDA.B #!BossFloorHeight ;|\ <- Scanline where floor starts in Morton/Roy/Ludwig battles
SEC ;|| Vertical Counter trigger at 174 - $1888
SBC.W ScreenShakeYOffset ;|/ Oddly enough, $1888 seems to be 16-bit, but the
STA.W HW_VTIME ;| Store to Vertical Counter Timer
STZ.W HW_VTIME+1 ;/ Make the high byte of said timer 0
LDA.B #!HW_TIMEN_NMI|!HW_TIMEN_JoyRead|!HW_TIMEN_IRQV
CODE_0083E3:
LDY.W EndLevelTimer ; if $1493 = 0 skip down
BEQ CODE_0083F3 ;
LDY.W ColorFadeTimer ;\ If $1495 is <#$40
CPY.B #2*!PaletteFadeCount ;|
BCC CODE_0083F3 ;/ Skip down
LDA.B #!HW_TIMEN_NMI|!HW_TIMEN_JoyRead ;
BRA IRQNMIEnding ; Jump up to IRQNMIEnding
CODE_0083F3: ; IRQ done; wait for H-blank, then update registers.
STA.W HW_NMITIMEN ;
JSR WaitLongForHBlank ; Wait until we enter an H-blank, then update the registers.
NOP
NOP
LDA.B #!HW_BG_Mode7
STA.W HW_BGMODE
LDA.B Mode7XPos
STA.W HW_BG1HOFS
LDA.B Mode7XPos+1
STA.W HW_BG1HOFS
LDA.B Mode7YPos
STA.W HW_BG1VOFS
LDA.B Mode7YPos+1
STA.W HW_BG1VOFS
BRA ExitIRQ
SETL1SCROLL:
LDA.B #(VRam_L1Mode7Tilemap>>8)|!HW_BGSC_Size_64x32
STA.W HW_BG1SC
LDA.B #VRam_L1Mode7Tiles>>12
STA.W HW_BG12NBA
LDA.B Layer1XPos
STA.W HW_BG1HOFS
LDA.B Layer1XPos+1
STA.W HW_BG1HOFS
LDA.B Layer1YPos
CLC
ADC.W ScreenShakeYOffset
STA.W HW_BG1VOFS
LDA.B Layer1YPos+1
STA.W HW_BG1VOFS
RTS
WaitLongForHBlank: ; Subroutine to wait for a horizontal interrupt.
- LDY.B #32 ;\
WaitForHBlank: ;|
BIT.W HW_HVBJOY ;| If in one already, wait for it to end.
BVS - ;/
- BIT.W HW_HVBJOY ;\ Wait until the next H-blank fires.
BVC - ;/
- DEY ;\ Wait until we are far enough into the blank.
BNE - ;/
RTS ;
DoSomeSpriteDMA: ; Routine to upload sprite OAM to the registers.
STZ.W HW_DMAPARAM ; Use DMA channel 0; increment, one register write once.
REP #$20 ; A->16
STZ.W HW_OAMADD ; Clear the sprite OAM index.
LDA.W #(OAMMirror<<8)|(HW_OAMDATA&$FF) ;\
STA.W HW_DMAREG ;| Set channel 0's destination to $2104 (data for OAM write)
LDA.W #OAMMirror>>8 ;| and the source to $000200 (OAM table).
STA.W HW_DMAADDR+1 ;/
LDA.W #4*!OBJCount+!OBJCount/4 ;\ Set the size to be 544 bytes.
STA.W HW_DMACNT ;/
LDY.B #!Ch0 ;\ Begin DMA transfer on channel 0.
STY.W HW_MDMAEN ;/
SEP #$20 ; A->8
LDA.B #!HW_OAM_SetPriority ;\ Set OAM object priority bit.
STA.W HW_OAMADD+1 ;/
LDA.B OAMAddress ;\ Set OAM index to $3F.
STA.W HW_OAMADD ;/
RTS
OAMTileSizeOffsets: ; Indices to $0420 for upload to the OAM table.
dw 0, 8, 16, 24, 32, 40, 48, 56 ; only even bytes are actually used.
dw 64, 72, 80, 88, 96, 104, 112
db 120
ConsolidateOAM: ; Routine to upload OAM tile sizes ($0420) to the OAM table (at $0400).
LDY.B #!OBJCount/4-2 ;
- LDX.W OAMTileSizeOffsets,Y ;\
LDA.W OAMTileSize+3,X ;|
ASL #2 ;|
ORA.W OAMTileSize+2,X ;|
ASL #2 ;| Turn four tile size bytes into one and store to the OAM table.
ORA.W OAMTileSize+1,X ;|
ASL #2 ;|
ORA.W OAMTileSize,X ;|
STA.W OAMTileBitSize,Y ;/
LDA.W OAMTileSize+7,X ;\
ASL #2 ;|
ORA.W OAMTileSize+6,X ;|
ASL #2 ;| And four more. Minimal loops yo.
ORA.W OAMTileSize+5,X ;|
ASL #2 ;|
ORA.W OAMTileSize+4,X ;|
STA.W OAMTileBitSize+1,Y ;/
DEY #2 ;\ If not at the end of the table, loop.
BPL - ;/
RTS ;
if ver_is_english(!_VER) ;\=============== U, SS, E0, & E1 ===============
CODE_0084C8: ;! Wrapper to draw stripe image
PHB ;! This is not used in the J version:
PHK ;! - Used to change enemy names in the credits after
PLB ;! special world is beaten in English verisons.
JSR LoadScrnImage ;! - Used to clear layer 1/2 tilemaps before every
PLB ;! level load in the E1 version.
RTL ;!
endif ;/===============================================
StripeImages: ; Stripe image data pointer. Indexed by $12.
dl DynamicStripeImage ; 00 - Pointer to dynamic stripe image loader
dl TitleScreenStripe ; 03 - Title screen
dl OWBorderStripe ; 06 - Overworld border
dl ClearMessageStripe ; 09 - Blank space to clear a message box
dl ContinueEndStripe ; 0C - CONTINUE/END
dl LudwigCutBGStripe ; 0F - Ludwig Castle Cutscene BG
dl PlayerSelectStripe ; 12 - 1 PLAYER GAME/2 PLAYER GAME
dl OWScrollArrowStripe ; 15 - OW scroll arrows
dl OWScrollEraseStripe ; 18 - Remove OW scroll arrows
dl ClearOWBoxStripe ; 1B - Blank space to clear overworld boxes
dl ContinueSaveStripe ; 1E - CONTINUE AND SAVE
CutMessageStripes: ;
if ver_is_japanese(!_VER) ;\====================== J ======================
dl C1Message4Stripe ;! 21 - Castle 1, Line 4: tabidatsunodearimashita.
dl C1Message3Stripe ;! 24 - Castle 1, Line 3: nisareta nakamaotasukedashi doonatsuheiyae
dl C1Message2Stripe ;! 27 - Castle 1, Line 2: taoshita mariotachiwa kuppanomahoude tamago
dl C1Message1Stripe ;! 2A - Castle 1, Line 1: Yoosutaatouno oshirode saishonokokuppao
dl C2Message4Stripe ;! 2D - Castle 2, Line 4: eteiruka? piichihimenounmeiya ikani!?
dl C2Message3Stripe ;! 30 - Castle 2, Line 3: hetosusundeiku!konosaki donnawanagamachikama
dl C2Message2Stripe ;! 33 - Castle 2, Line 2: doonatsuheiyakara chikanosekaino baniradoomu
dl C2Message1Stripe ;! 36 - Castle 2, Line 1: mariotachiwa nibanmenokokuppamo yattsukete
dl C3Message4Stripe ;! 39 - Castle 3, Line 4: shitara donnatabini narunodearouka!
dl C3Message3Stripe ;! 3C - Castle 3, Line 3: moshimo midoriyaakanosuitchio totteinaito
dl C3Message2Stripe ;! 3F - Castle 3, Line 2: hotto hitoiki. shikashikoosuwa kewashikunaru
dl C3Message1Stripe ;! 42 - Castle 3, Line 1: mariotachiwa sanbanmenokokuppamo yattsukete
dl C4Message4Stripe ;! 45 - Castle 4, Line 4: ginomori!hatashitemorionukerukotogadekirunoka?
dl C4Message3Stripe ;! 48 - Castle 4, Line 3: nazootokanaito derukotogadekinaitoiu fushi
dl C4Message2Stripe ;! 4B - Castle 4, Line 2: tachiwa korekara mayoinomorinihaitteiku!?
dl C4Message1Stripe ;! 4E - Castle 4, Line 1: yonbanmenokokuppamo nantokakuriaa mario
dl C5Message4Stripe ;! 51 - Castle 5, Line 4: pai. tsuginarutatakaino hojimarihajimarii!
dl C5Message3Stripe ;! 54 - Castle 5, Line 3: chokoreetouwa nazonokoosuto doragondeip
dl C5Message2Stripe ;! 57 - Castle 5, Line 2: to morionukerukotogadekita. daga konosakino
dl C5Message1Stripe ;! 5A - Castle 5, Line 1: mariotachiwa gobanmenokokuppaoyattsuke yat
dl C6Message4Stripe ;! 5D - Castle 6, Line 4: izoge mario! ganbare ruiji!
dl C6Message3Stripe ;! 60 - Castle 6, Line 3: iriguchiohirakutameno kagigaarurashii.
dl C6Message2Stripe ;! 63 - Castle 6, Line 2: konosakino chinbotsusenniwa kuppanotanino
dl C6Message1Stripe ;! 66 - Castle 6, Line 1: rokubanmenokokuppaotaoshitamariotachi!
dl C7Message4Stripe ;! 69 - Castle 7, Line 4: randoniheiwaotorimodosukotogadekirunoka?
dl C7Message3Stripe ;! 6C - Castle 7, Line 3: bujinipiichihimeotasukedashi konokyouryuu
dl C7Message2Stripe ;! 6F - Castle 7, Line 2: piichihimega torawareteiru kuppajounomi
dl C7Message1Stripe ;! 72 - Castle 7, Line 1: tsuini saigonokokuppaotaoshita! nokosuwa
else ;<================ U, SS, E0, & E1 ==============
dl BlankStripe ;! 21 - Castle 1, Line 8: *empty*
dl C1Message7Stripe ;! 24 - Castle 1, Line 7: travel to Donut Land.
dl C1Message6Stripe ;! 27 - Castle 1, Line 6: Together, they now
dl C1Message5Stripe ;! 2A - Castle 1, Line 5: still trapped in an egg.
dl C1Message4Stripe ;! 2D - Castle 1, Line 4: Yoshi's friend who is
dl C1Message3Stripe ;! 30 - Castle 1, Line 3: castle #1 and rescued
dl C1Message2Stripe ;! 33 - Castle 1, Line 2: demented Iggy Koopa in
dl C1Message1Stripe ;! 36 - Castle 1, Line 1: Mario has defeated the
dl C2Message8Stripe ;! 39 - Castle 2, Line 8: Princess Toadstool?
dl C2Message7Stripe ;! 3C - Castle 2, Line 7: What will become of
dl C2Message6Stripe ;! 3F - Castle 2, Line 6: Mario in this new world?
dl C2Message5Stripe ;! 42 - Castle 2, Line 5: Dome. What traps await
dl C2Message4Stripe ;! 45 - Castle 2, Line 4: the underground Vanilla
dl C2Message3Stripe ;! 48 - Castle 2, Line 3: memory. The next area is
dl C2Message2Stripe ;! 4B - Castle 2, Line 2: castle #2 is now just a
dl C2Message1Stripe ;! 4E - Castle 2, Line 1: Morton Koopa Jr. of
dl BlankStripe ;! 51 - Castle 3, Line 8: *empty*
dl C3Message7Stripe ;! 54 - Castle 3, Line 7: Green Switches yet?
dl C3Message6Stripe ;! 57 - Castle 3, Line 6: you found the Red and
dl C3Message5Stripe ;! 5A - Castle 3, Line 5: more difficult. Have
dl C3Message4Stripe ;! 5D - Castle 3, Line 4: starting to get much
dl C3Message3Stripe ;! 60 - Castle 3, Line 3: #3. Mario's quest is
dl C3Message2Stripe ;! 63 - Castle 3, Line 2: Lemmy Koopa of castle
dl C3Message1Stripe ;! 66 - Castle 3, Line 1: Mario has triumphed over
dl C4Message8Stripe ;! 69 - Castle 4, Line 8: this perplexing forest.
dl C4Message7Stripe ;! 6C - Castle 4, Line 7: to solve the puzzle of
dl C4Message6Stripe ;! 6F - Castle 4, Line 6: Mario must use his brain
dl C4Message5Stripe ;! 72 - Castle 4, Line 5: Illusion lies ahead.
dl C4Message4Stripe ;! 75 - Castle 4, Line 4: are over. The Forest of
dl C4Message3Stripe ;! 78 - Castle 4, Line 3: symphonies in castle #4
dl C4Message2Stripe ;! 7B - Castle 4, Line 2: of composing Koopa
dl C4Message1Stripe ;! 7E - Castle 4, Line 1: Ludwig von Koopa's days
dl BlankStripe ;! 81 - Castle 5, Line 8: *empty*
dl C5Message7Stripe ;! 84 - Castle 5, Line 7: tasty) Chocolate Island!
dl C5Message6Stripe ;! 87 - Castle 5, Line 6: the dangerous (but
dl C5Message5Stripe ;! 8A - Castle 5, Line 5: castle #5. Onward to
dl C5Message4Stripe ;! 8D - Castle 5, Line 4: end to Roy Koopa of
dl C5Message3Stripe ;! 90 - Castle 5, Line 3: Illusion and has put an
dl C5Message2Stripe ;! 93 - Castle 5, Line 2: through the Forest of
dl C5Message1Stripe ;! 96 - Castle 5, Line 1: Mario found his way
dl C6Message8Stripe ;! 99 - Castle 6, Line 8: to the Valley of Bowser.
dl C6Message7Stripe ;! 9C - Castle 6, Line 7: appears to be a gateway
dl C6Message6Stripe ;! 9F - Castle 6, Line 6: is a sunken ship that
dl C6Message5Stripe ;! A2 - Castle 6, Line 5: now before him. There
dl C6Message4Stripe ;! A5 - Castle 6, Line 4: the challenge that is
dl C6Message3Stripe ;! A8 - Castle 6, Line 3: song. Mario must meet
dl C6Message2Stripe ;! AB - Castle 6, Line 2: #6 has sung her last
dl C6Message1Stripe ;! AE - Castle 6, Line 1: Wendy O. Koopa in castle
dl C7Message8Stripe ;! B1 - Castle 7, Line 8: Dinosaur Land?
dl C7Message7Stripe ;! B4 - Castle 7, Line 7: restore peace to
dl C7Message6Stripe ;! B7 - Castle 7, Line 6: Can Mario rescue her and
dl C7Message5Stripe ;! BA - Castle 7, Line 5: Toadstool is being held.
dl C7Message4Stripe ;! BD - Castle 7, Line 4: Castle where Princess
dl C7Message3Stripe ;! C0 - Castle 7, Line 3: that is left is Bowser's
dl C7Message2Stripe ;! C3 - Castle 7, Line 2: Koopa in castle #7. All
dl C7Message1Stripe ;! C6 - Castle 7, Line 1: Mario has defeated Larry
endif ;/===============================================
OtherStripes:
dl LemmyCutBGStripe ; J75/UC9 - Lemmy, Larry Castle Cutscene BG
dl WendyCutBGStripe ; J78/UCC - Wendy Castle Cutscene BG
dl CutsceneCastleStripe ; J7B/UCF - Castle Cutscene Castle
dl EraseAllStripe ; J7E/UD2 - Blank space to clear all of layers 1 and 2
dl TheEndStripe ; J81/UD5 - Ending: THE END
dl EnemyNameStripe00 ; J84/UD8 - Ending: Enemies: Lakitu
dl EnemyNameStripe01 ; J87/UDB - Ending: Enemies: Hammer Bro.
dl EnemyNameStripe02 ; J8A/UDE - Ending: Enemies: Pokey
dl EnemyNameStripe03 ; J8D/UE1 - Ending: Enemies: Rex
dl EnemyNameStripe04 ; J90/UE4 - Ending: Enemies: Dino-Rhino
dl EnemyNameStripe05 ; J93/UE7 - Ending: Enemies: Blargg
dl EnemyNameStripe06 ; J96/UEA - Ending: Enemies: Urchin
dl EnemyNameStripe07 ; J99/UED - Ending: Enemies: Boo
dl EnemyNameStripe08 ; J9C/UF0 - Ending: Enemies: Dry Bones
dl EnemyNameStripe09 ; J9F/UF3 - Ending: Enemies: Grinder
dl EnemyNameStripe0A ; JA2/UF6 - Ending: Enemies: Reznor
dl EnemyNameStripe0B ; JA5/UF9 - Ending: Enemies: Mechakoopa
dl EnemyNameStripe0C ; JA8/UFC - Ending: Enemies: Bowser
dl IggyCutBGStripe ; JAB/UFF - Iggy, Morton, Roy Castle Cutscene BG
LoadScrnImage: ; Routine to upload a stripe image to VRAM (usually layer 3).
LDY.B StripeImage
LDA.W StripeImages,Y
STA.B _0
LDA.W StripeImages+1,Y
STA.B _1
LDA.W StripeImages+2,Y
STA.B _2
JSR LoadStripeImage
LDA.B StripeImage
BNE +
STA.L DynStripeImgSize
STA.L DynStripeImgSize+1
DEC A
STA.L DynamicStripeImage
+ STZ.B StripeImage ; Do not reload the same thing next frame
RTS
ClearOutLayer3: ; DMA upload routine to clean out the layer 3 tilemap.
JSR TurnOffIO ;
LDA.B #!EmptyTile ;\ Tile to use as the blank tile.
STA.B _0 ;/
STZ.W HW_VMAINC ;] Single byte VRAM upload.
STZ.W HW_VMADD ;\
LDA.B #VRam_L3Tilemap>>8 ;| Upload tilemap to Layer 3.
STA.W HW_VMADD+1 ;/
LDX.B #6 ;\ Set up and enable DMA on channel 1.
- LDA.W ClearTilemapDMAData,X ;| $4310: Fixed transfer, one register write once.
STA.W HW_DMAPARAM+$10,X ;| $4311: Destination is $2118 (VRAM low byte).
DEX ;| $4312: Source is $000000.
BPL - ;| $4315: Write x1000 bytes.
LDY.B #!Ch1 ;|
STY.W HW_MDMAEN ;/
LDA.B #!EmptyTile>>8 ;\ YXPCCCTT to use for the blank tile.
STA.B _0 ;/
LDA.B #!HW_VINC_IncOnHi ;\ Two byte VRAM upload.
STA.W HW_VMAINC ;/
STZ.W HW_VMADD ;\
LDA.B #VRam_L3Tilemap>>8 ;| Upload tilemap to Layer 3.
STA.W HW_VMADD+1 ;/
LDX.B #6 ;\
- LDA.W ClearTilemapDMAData,X ;| Set up and enable DMA on channel 1.
STA.W HW_DMAPARAM+$10,X ;| Settings are the same as the previous one.
DEX ;|
BPL - ;|
LDA.B #HW_VMDATA+1 ;|\ Change destination to $2119 (VRAM high byte).
STA.W HW_DMAREG+$10 ;|/
STY.W HW_MDMAEN ;/
STZ.B OAMAddress ; Clear the current OAM address.
JSL OAMResetRoutine ;\ Clear OAM data.
JMP DoSomeSpriteDMA ;/
ClearTilemapDMAData: ; DMA setting data for channel 1; $4310-$4316, in reverse order.
%DMASettings(!HW_DMA_ABusFix,HW_VMDATA,0,$1000)
ControllerUpdate: ; Routine to read controller data and upload to $15-$18. Part of NMI.
LDA.W HW_CNTRL1 ;\\
AND.B #!ButA|!ButX|!ButL|!ButR ;|| Get controller 1 data 2.
STA.W axlr0000P1Hold ;|/
TAY ;|\
EOR.W axlr0000P1Mask ;|| Get controller 1 data 2, one frame.
AND.W axlr0000P1Hold ;||
STA.W axlr0000P1Frame ;||
STY.W axlr0000P1Mask ;//
LDA.W HW_CNTRL1+1 ;\\ Get controller 1 data 1.
STA.W byetudlrP1Hold ;|/
TAY ;|\
EOR.W byetudlrP1Mask ;|| Get controller 1 data 1, one frame.
AND.W byetudlrP1Hold ;||
STA.W byetudlrP1Frame ;||
STY.W byetudlrP1Mask ;//
LDA.W HW_CNTRL2 ;\\
AND.B #!ButA|!ButX|!ButL|!ButR ;|| Get controller 2 data 2.
STA.W axlr0000P2Hold ;|/
TAY ;|\
EOR.W axlr0000P2Mask ;|| Get controller 2 data 2, one frame.
AND.W axlr0000P2Hold ;||
STA.W axlr0000P2Frame ;||
STY.W axlr0000P2Mask ;//
LDA.W HW_CNTRL2+1 ;\\ Get controller 2 data 1.
STA.W byetudlrP2Hold ;|/
TAY ;|\
EOR.W byetudlrP2Mask ;|| Get controller 2 data 1, one frame.
AND.W byetudlrP2Hold ;||
STA.W byetudlrP2Frame ;||
STY.W byetudlrP2Mask ;//
LDX.W ControllersPresent ;\
BPL + ;| If $0DA0 is set to use separate controllers, use the current player number as the controller port to accept input from.
LDX.W PlayerTurnLvl ;/
+ LDA.W axlr0000P1Hold,X ;\
AND.B #!ButA|!ButX ;| Set up $15, sharing the top two bits of controller data 2 (for A/X).
ORA.W byetudlrP1Hold,X ;|
STA.B byetudlrHold ;/
LDA.W axlr0000P1Hold,X ;\ Set up $17.
STA.B axlr0000Hold ;/
LDA.W axlr0000P1Frame,X ;\
AND.B #!ButX ;| Set up $16, sharing the top two bits of controller data 2 (for A/X).
ORA.W byetudlrP1Frame,X ;|
STA.B byetudlrFrame ;/
LDA.W axlr0000P1Frame,X ;\ Set up $18.
STA.B axlr0000Frame ;/
RTS ;
InitM7BossOAM: ; Subroutine to initialize OAM in Roy/Morton/Ludwig's rooms.
REP #$30 ; AXY->16
LDX.W #!BossBGOBJCount-2 ;\
LDA.W #!OBJBigSize|(!OBJBigSize<<8) ;|
- STA.W OAMTileSize,X ;| Initialize first 100 OBJs as 16x16.
DEX #2 ;|
BPL - ;/
SEP #$30 ; AXY->8
LDA.B #!OBJOffscreen ;\ Clear out OAM.
JSL OAMResetRoutine+302 ;/
RTS ;
ExecutePtr: ; Routine to jump to a 16-bit address in a table. Basically JSR (addr,a). A contains the index to jump to.
STY.B _3 ; "Push" Y
PLY
STY.B _0
REP #$30 ; AXY->16
AND.W #%0000000011111111
ASL A
TAY
PLA
STA.B _1
INY
LDA.B [_0],Y
STA.B _0
SEP #$30 ; AXY->8
LDY.B _3 ; "Pull" Y
JML.W [_0]
ExecutePtrLong: ; Routine to jump to a 24-bit address in a table. Basically JSL (long,a).
STY.B _5
PLY
STY.B _2
REP #$30 ; AXY->16
AND.W #%0000000011111111
STA.B _3
ASL A
ADC.B _3
TAY
PLA
STA.B _3
INY
LDA.B [_2],Y
STA.B _0
INY
LDA.B [_2],Y
STA.B _1
SEP #$30 ; AXY->8
LDY.B _5
JML.W [_0]
LoadStripeImage: ; Subroutine to upload a specific Layer 3 tilemap (pointer in $00) to VRAM.
REP #$10 ; XY->16
STA.W HW_DMAADDR+2+$10 ;
LDY.W #0 ;
- LDA.B [_0],Y ;\ Branch if bit 7 isn't set (i.e. end of data).
BPL + ;/
SEP #$30 ; AXY->8
RTS ;
;
+ STA.B _4 ;\
INY ;|
LDA.B [_0],Y ;|
STA.B _3 ;| $03/$04 = VRAM destination
INY ;| $07 = direction (0 = horz, 1 = vert)
LDA.B [_0],Y ;|
STZ.B _7 ;|
ASL A ;|
ROL.B _7 ;/
LDA.B #HW_VMDATA ;\ Set register to $2118.
STA.W HW_DMAREG+$10 ;/
LDA.B [_0],Y ;\
AND.B #%01000000 ;|
LSR #3 ;| Enable RLE if applicable.
STA.B _5 ;|
STZ.B _6 ;|
ORA.B #!HW_DMA_2Byte2Addr ;|
STA.W HW_DMAPARAM+$10 ;/
REP #$20 ; A->16
LDA.B _3 ;\ Set destination.
STA.W HW_VMADD ;/
LDA.B [_0],Y ;\
XBA ;|
AND.W #%0011111111111111 ;|
TAX ;|
INX ;|
INY #2 ;| Set data source and length.
TYA ;|
CLC ;|
ADC.B _0 ;|
STA.W HW_DMAADDR+$10 ;|
STX.W HW_DMACNT+$10 ;/
LDA.B _5 ;\
BEQ + ;|
SEP #$20 ;| A->8
LDA.B _7 ;|
STA.W HW_VMAINC ;|
LDA.B #!Ch1 ;|
STA.W HW_MDMAEN ;|
LDA.B #HW_VMDATA+1 ;|
STA.W HW_DMAREG+$10 ;| Set up RLE if applicable.
REP #$21 ;| A->16, CLC
LDA.B _3 ;|
STA.W HW_VMADD ;|
TYA ;|
ADC.B _0 ;|
INC A ;|
STA.W HW_DMAADDR+$10 ;|
STX.W HW_DMACNT+$10 ;/
LDX.W #2 ;
+ STX.B _3 ;
TYA ;
CLC ;
ADC.B _3 ;
TAY ;
SEP #$20 ; A->8
LDA.B _7 ;\
ORA.B #!HW_VINC_IncOnHi ;| Set direction.
STA.W HW_VMAINC ;/
LDA.B #!Ch1 ;\ Enable DMA on channel 1.
STA.W HW_MDMAEN ;/
JMP - ;
UploadOneMap16Strip: ; DMA routine to upload one row/column of Map16 data to VRAM for Layer 1/2.
SEP #$30 ; AXY->8
LDA.W Layer1VramAddr ;\
BNE + ;| If $1BE4 is non-zero, update Layer 1. Else, skip to Layer 2.
JMP UploadL2Map16Strip ;/
+ LDA.B ScreenMode ;\ Need to update Layer 1.
AND.B #!ScrMode_Layer1Vert ;| Jump down if in a vertical level.
BEQ UploadOneL1Column ;|
JMP UploadOneL1Row ;/
UploadOneL1Column:
LDY.B #!HW_VINC_IncOnHi|!HW_VINC_IncBy32 ;\ Updating horizontal Layer 1.
STY.W HW_VMAINC ;| Upload the top-left column of tiles.
LDA.W Layer1VramAddr+1 ;|\
STA.W HW_VMADD ;|| Set VRAM address to write to.
LDA.W Layer1VramAddr ;||
STA.W HW_VMADD+1 ;|/
LDX.B #6 ;|
- LDA.W Layer1Map16DMAData,X ;|
STA.W HW_DMAPARAM+$10,X ;|
DEX ;|
BPL - ;|
LDA.B #!Ch1 ;|
STA.W HW_MDMAEN ;|
STY.W HW_VMAINC ;/
LDA.W Layer1VramAddr+1 ;\ Upload the bottom-left column of tiles.
STA.W HW_VMADD ;|\
LDA.W Layer1VramAddr ;||
CLC ;|| Set VRAM address to write to (1 screen below origin).
ADC.B #(2*!TilesPerBGPage)>>8 ;|| One screen below = 2 screens forward
STA.W HW_VMADD+1 ;||
LDX.B #6 ;|/
- LDA.W Layer1Map16DMAData+7,X ;|
STA.W HW_DMAPARAM+$10,X ;|
DEX ;|
BPL - ;|
LDA.B #!Ch1 ;|
STA.W HW_MDMAEN ;|
STY.W HW_VMAINC ;/
LDA.W Layer1VramAddr+1 ;\ Upload the rop-right column of tiles.
INC A ;|\
STA.W HW_VMADD ;||