-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathBank $81.asm
6549 lines (5859 loc) · 342 KB
/
Bank $81.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
;;; $8000: Save to SRAM ;;;
{
;; Parameter:
;; A: SRAM slot (0, 1 or 2)
; Almost returns carry clear
$81:8000 08 PHP
$81:8001 C2 30 REP #$30
$81:8003 8B PHB
$81:8004 DA PHX
$81:8005 5A PHY
$81:8006 F4 00 7E PEA $7E00 ;\
$81:8009 AB PLB ;} DB = $7E
$81:800A AB PLB ;/
$81:800B 64 14 STZ $14 [$7E:0014] ; $14 = 0 (checksum)
$81:800D 29 03 00 AND #$0003 ;\
$81:8010 0A ASL A ;} $12 = ([A] & 3) * 2
$81:8011 85 12 STA $12 [$7E:0012] ;/
$81:8013 A0 5E 00 LDY #$005E ;\
;|
$81:8016 B9 A2 09 LDA $09A2,y[$7E:0A00] ;|
$81:8019 99 C0 D7 STA $D7C0,y[$7E:D81E] ;} $D7C0..D81F = [$09A2..0A01]
$81:801C 88 DEY ;|
$81:801D 88 DEY ;|
$81:801E 10 F6 BPL $F6 [$8016] ;/
$81:8020 A2 00 00 LDX #$0000 ; >_<
$81:8023 AD 9F 07 LDA $079F [$7E:079F] ;\
$81:8026 EB XBA ;|
$81:8027 AA TAX ;|
$81:8028 A0 00 00 LDY #$0000 ;|
;|
$81:802B B9 F7 07 LDA $07F7,y[$7E:07F7] ;|
$81:802E 9D 52 CD STA $CD52,x[$7E:D352] ;} Copy 100h bytes from $07F7 to $CD52 + [area index] * 100h
$81:8031 C8 INY ;|
$81:8032 C8 INY ;|
$81:8033 E8 INX ;|
$81:8034 E8 INX ;|
$81:8035 C0 00 01 CPY #$0100 ;|
$81:8038 30 F1 BMI $F1 [$802B] ;/
$81:803A 20 4B 83 JSR $834B [$81:834B] ; Save map
$81:803D AD 8B 07 LDA $078B [$7E:078B] ;\
$81:8040 8D 16 D9 STA $D916 [$7E:D916] ;} SRAM save station index = [save station index]
$81:8043 AD 9F 07 LDA $079F [$7E:079F] ;\
$81:8046 8D 18 D9 STA $D918 [$7E:D918] ;} SRAM area index = [area index]
$81:8049 A6 12 LDX $12 [$7E:0012] ;\
$81:804B BF 2B 81 81 LDA $81812B,x[$81:812B];} X = [$81:812B + [$12]] (SRAM offset for save slot)
$81:804F AA TAX ;/
$81:8050 A0 C0 D7 LDY #$D7C0 ; Y = $D7C0
; LOOP
$81:8053 B9 00 00 LDA $0000,y[$7E:D7C0] ;\
$81:8056 9F 00 00 70 STA $700000,x[$70:0010];} $70:0000 + [X] = [[Y]]
$81:805A 18 CLC ;\
$81:805B 65 14 ADC $14 [$7E:0014] ;} $14 += [[Y]]
$81:805D 85 14 STA $14 [$7E:0014] ;/
$81:805F E8 INX ;\
$81:8060 E8 INX ;} X += 2
$81:8061 C8 INY ;\
$81:8062 C8 INY ;} Y += 2
$81:8063 C0 1C DE CPY #$DE1C ;\
$81:8066 D0 EB BNE $EB [$8053] ;} If [Y] != $DE1C: go to LOOP
$81:8068 A6 12 LDX $12 [$7E:0012] ;\
$81:806A A5 14 LDA $14 [$7E:0014] ;|
$81:806C 9F 00 00 70 STA $700000,x[$70:0000];} $70:0000 + [$12] = $70:1FF0 + [$12] = [$14] (checksums)
$81:8070 9F F0 1F 70 STA $701FF0,x[$70:1FF0];/
$81:8074 49 FF FF EOR #$FFFF ;\
$81:8077 9F 08 00 70 STA $700008,x[$70:0008];} $70:0008 + [$12] = $70:1FF8 + [$12] = ~[$14] (checksum complements)
$81:807B 9F F8 1F 70 STA $701FF8,x[$70:1FF8];/
$81:807F 7A PLY
$81:8080 FA PLX
$81:8081 18 CLC ; >_<
$81:8082 AB PLB
$81:8083 28 PLP
$81:8084 6B RTL
}
;;; $8085: Load from SRAM / clear SRAM ;;;
{
;; Parameter:
;; A: SRAM slot (0, 1 or 2)
;; Returns:
;; Carry: Set if SRAM was corrupt
; Copies all the data from the SRAM slot out to $7E:D7C0..DE1B
; If SRAM is not corrupt (according to the checksums):
; Copies data to $09A2..0A01 (Samus data and game options)
; Loads map data to $7E:CD52..D351, clears Ceres map data $7E:D352..D451 (the working copy $07F7..08F6 isn't updated)
; Copies load station index to $078B and area index to $079F
; Otherwise:
; Clears the SRAM slot
; Sets load station index to 0 and area index to Crateria
; $09A2..0A01 and map data are NOT modified
$81:8085 C2 30 REP #$30
$81:8087 8B PHB
$81:8088 DA PHX
$81:8089 5A PHY
$81:808A F4 00 7E PEA $7E00 ;\
$81:808D AB PLB ;} DB = $7E
$81:808E AB PLB ;/
$81:808F 64 14 STZ $14 [$7E:0014] ; $14 = 0 (checksum)
$81:8091 29 03 00 AND #$0003 ;\
$81:8094 0A ASL A ;} $12 = ([A] & 3) * 2
$81:8095 85 12 STA $12 [$7E:0012] ;/
$81:8097 AA TAX ;\
$81:8098 BF 2B 81 81 LDA $81812B,x[$81:812B];} X = [$81:812B + [$12]] (SRAM offset)
$81:809C AA TAX ;/
$81:809D A0 C0 D7 LDY #$D7C0 ; Y = $D7C0 (save data)
; LOOP
$81:80A0 BF 00 00 70 LDA $700000,x[$70:0010];\
$81:80A4 99 00 00 STA $0000,y[$7E:D7C0] ;} [Y] = [$70:0000 + [X]]
$81:80A7 18 CLC ;\
$81:80A8 65 14 ADC $14 [$7E:0014] ;} $14 += [Y]
$81:80AA 85 14 STA $14 [$7E:0014] ;/
$81:80AC E8 INX ;\
$81:80AD E8 INX ;} X += 2
$81:80AE C8 INY ;\
$81:80AF C8 INY ;} Y += 2
$81:80B0 C0 1C DE CPY #$DE1C ;\
$81:80B3 D0 EB BNE $EB [$80A0] ;} If [Y] != $DE1C: go to LOOP
$81:80B5 A6 12 LDX $12 [$7E:0012] ;\
$81:80B7 A5 14 LDA $14 [$7E:0014] ;|
$81:80B9 DF 00 00 70 CMP $700000,x[$70:0000];} If [$14] != [$70:0000 + [$12]]: go to BRANCH_DOUBLE_CHECK
$81:80BD D0 0B BNE $0B [$80CA] ;/
$81:80BF 49 FF FF EOR #$FFFF ;\
$81:80C2 DF 08 00 70 CMP $700008,x[$70:0008];} If ~[$14] != [$70:0008 + [$12]]: go to BRANCH_DOUBLE_CHECK
$81:80C6 D0 02 BNE $02 [$80CA] ;/
$81:80C8 80 11 BRA $11 [$80DB] ; Go to BRANCH_SUCCESS
; BRANCH_DOUBLE_CHECK
$81:80CA A5 14 LDA $14 [$7E:0014] ;\
$81:80CC DF F0 1F 70 CMP $701FF0,x[$70:1FF2];} If [$14] != [$70:1FF0 + [$12]]: go to BRANCH_CORRUPT
$81:80D0 D0 2A BNE $2A [$80FC] ;/
$81:80D2 49 FF FF EOR #$FFFF ;\
$81:80D5 DF F8 1F 70 CMP $701FF8,x[$70:1FF8];} If ~[$14] != [$70:1FF8 + [$12]]: go to BRANCH_CORRUPT
$81:80D9 D0 21 BNE $21 [$80FC] ;/
; BRANCH_SUCCESS
$81:80DB A0 5E 00 LDY #$005E ;\
;|
$81:80DE B9 C0 D7 LDA $D7C0,y[$7E:D81E] ;|
$81:80E1 99 A2 09 STA $09A2,y[$7E:0A00] ;} $09A2..0A01 = [$D7C0..D81F] (Samus data and game options)
$81:80E4 88 DEY ;|
$81:80E5 88 DEY ;|
$81:80E6 10 F6 BPL $F6 [$80DE] ;/
$81:80E8 20 E4 82 JSR $82E4 [$81:82E4] ; Load map
$81:80EB AD 16 D9 LDA $D916 [$7E:D916] ;\
$81:80EE 8D 8B 07 STA $078B [$7E:078B] ;} Load station index = [SRAM save station index]
$81:80F1 AD 18 D9 LDA $D918 [$7E:D918] ;\
$81:80F4 8D 9F 07 STA $079F [$7E:079F] ;} Area index = [SRAM area index]
$81:80F7 7A PLY
$81:80F8 FA PLX
$81:80F9 18 CLC ; Return carry clear
$81:80FA AB PLB
$81:80FB 6B RTL ; Return
; BRANCH_CORRUPT
$81:80FC 64 14 STZ $14 [$7E:0014] ; $14 = 0
$81:80FE A6 12 LDX $12 [$7E:0012] ;\
$81:8100 BF 2B 81 81 LDA $81812B,x[$81:812D];} X = [$81:812B + [$12]] (SRAM offset)
$81:8104 AA TAX ;/
$81:8105 A0 C0 D7 LDY #$D7C0 ;\
$81:8108 A9 00 00 LDA #$0000 ;|
;|
$81:810B 9F 00 00 70 STA $700000,x[$70:066C];|
$81:810F 18 CLC ;|
$81:8110 65 14 ADC $14 [$7E:0014] ;|
$81:8112 85 14 STA $14 [$7E:0014] ;} Clear 65Ch bytes at $70:0000 + [X]
$81:8114 E8 INX ;|
$81:8115 E8 INX ;|
$81:8116 C8 INY ;|
$81:8117 C8 INY ;|
$81:8118 C0 1C DE CPY #$DE1C ;|
$81:811B D0 EE BNE $EE [$810B] ;/
$81:811D A9 00 00 LDA #$0000 ;\
$81:8120 8D 8B 07 STA $078B [$7E:078B] ;} Load station index = 0
$81:8123 8D 9F 07 STA $079F [$7E:079F] ; Area index = Crateria
$81:8126 7A PLY
$81:8127 FA PLX
$81:8128 38 SEC ; Return carry set
$81:8129 AB PLB
$81:812A 6B RTL
}
;;; $812B: SRAM offsets for each save slot ;;;
{
$81:812B dw 0010, 066C, 0CC8
}
;;; $8131: Exported map data ;;;
{
; Lists of offsets into explored map data ($7E:CD52 + (area index) * 100h) whose bytes are saved to SRAM
; Map data offsets of 80h+ are specifying the right half of the map (7Fh- are specifying the left half)
; Each byte is 8 map tiles, and the first row (offsets 0..3 and 80h..83h) is meaningless padding
; Size of each exported map
$81:8131 db 4A, 48, 4C, 12, 42, 15, 08
; Offset for each exported map
$81:8138 dw 0000, 004A, 0092, 00DE, 00F0, 0132, 0147
; Crateria map offset list
{
$81:8146 db 07,
0B,
0D,0E,0F,
11, 13,
15,16,17,
19,1A,
1D,1E,1F,
21,22,
24,25,26,
28, 2A,2B,
2C, 2E,2F,
30, 32,33,
36,37,
3A,3B,
3E,3F,
42,43,
46,47,
4A,
4E,
52,
56,
84,85,
88,89,
8C,8D,
90,91,
94,95,96,97,
98,99,9A,9B,
9C, 9F,
A0, A3,
A4, A6,A7,
A8, AA,AB,
AC, AE,
B2,
B6,
BA,
00,00,00,00,00,00
}
; Brinstar map offset list
{
$81:8196 db 05,
09,0A,0B,
0D,0E,0F,
11,12,13,
14,15,16,17,
19,1A,1B,
1C,1D,1E,1F,
20,21,22,23,
25,26,27,
29,2A,2B,
2C,2D,2E,2F,
30,31,32,33,
35,36,37,
39,3A,3B,
42,43,
47,
90,
94,
98,
9C,
A0,
A4,
A8,
AC,
B0,
B4,
B8,
BC,
C0,
C4,
C8,
CC,CD,CE,CF,
D1,D2,D3,
D5,D9,
00,00,00,00,00,00,00,00
}
; Norfair map offset list
{
$81:81E6 db 05,
08,09, 0B,
0C,0D,0E,0F,
10,11,12,13,
14,15,16,17,
18,19,1A,1B,
1C,1D,1E,1F,
20,21,22,23,
24,25,26,27,
29,2A,2B,
2D,2E,2F,
31,32,33,
34,35,36,37,
38,39,3A,3B,
3C,3D,3E,3F,
40,41,42,
44,45,46,47,
48,49,4A,
8C,
98,
9C,
A0,
A4,
A8,
AC,
B0,
B4,
B8,
BC,
C0,
C4,
00,00,00,00
}
; Wrecked Ship map offset list
{
$81:8236 db 2D,2E,
31,32,
35,36,
39,3A,
3D,3E,
42,
45,46,
49,4A,
4E,
51,52,
00,00,00,00,00,00,00,00,00,00,00,00,00,00
}
; Maridia map offset list
{
$81:8256 db 07,
0B,
0E,0F,
12,13,
15,16,17,
19,1A,1B,
1D,1E,1F,
21,22,23,
25,26,27,
29,2A,2B,
2D,2E,2F,
31,32,33,
35,36,
39,3A,3B,
3D,3E,3F,
41,42,43,
45,46,47,
49,4A,
4D,
51,
84,
88,
8C,
90,
94,
98,
9C,9D,
A0,A1,
A4,A5,
A8,A9,
AC,AD,
C0,
C4,
00,00,00,00,00,00,00,00,00,00,00,00,00,00
}
; Tourian map offset list
{
$81:82A6 db 26,
2A,
2E,
32,
35,36,
39,3A,
3E,
41,42,
45,46,
4A,
4D,4E,
51,52,
55,56,
5A,
00,00,00,00,00,00,00,00,00,00,00
}
; Unused. Ceres map offset list
{
$81:82C6 db 2D,
31,
35,
39,
3D,
41,
45,46,
00,00,00,00,00,00,00,00
}
; Map offset list pointers. Indexed by area
$81:82D6 dw 8146, 8196, 81E6, 8236, 8256, 82A6, 82C6
}
;;; $82E4: Load map ;;;
{
; Doesn't load Ceres map, but does clear it
$81:82E4 8B PHB
$81:82E5 08 PHP
$81:82E6 4B PHK ;\
$81:82E7 AB PLB ;} DB = $81
$81:82E8 C2 30 REP #$30
$81:82EA A2 00 07 LDX #$0700 ;\
$81:82ED A9 00 00 LDA #$0000 ;|
;|
$81:82F0 9F 52 CD 7E STA $7ECD52,x[$7E:D452];} $7E:CD52..D453 = 0 (map tiles explored, not including debug area, although initial index 700h is off-by-2)
$81:82F4 CA DEX ;|
$81:82F5 CA DEX ;|
$81:82F6 10 F8 BPL $F8 [$82F0] ;/
$81:82F8 64 16 STZ $16 [$7E:0016] ; $16 = 0 (area index)
; LOOP_AREA
$81:82FA A5 16 LDA $16 [$7E:0016] ;\
$81:82FC EB XBA ;} $14 = (area index) * 100h (explored map base offset)
$81:82FD 85 14 STA $14 [$7E:0014] ;/
$81:82FF A6 16 LDX $16 [$7E:0016] ;\
$81:8301 BD 31 81 LDA $8131,x[$81:8131] ;|
$81:8304 29 FF 00 AND #$00FF ;} $12 = [$8131 + (area index)] (exported map size)
$81:8307 85 12 STA $12 [$7E:0012] ;/
$81:8309 A5 16 LDA $16 [$7E:0016] ;\
$81:830B 0A ASL A ;|
$81:830C AA TAX ;|
$81:830D BD D6 82 LDA $82D6,x[$81:82D6] ;} $00 = $81:0000 + [$82D6 + (area index) * 2] (explored map offset list pointer)
$81:8310 85 00 STA $00 [$7E:0000] ;|
$81:8312 A9 81 00 LDA #$0081 ;|
$81:8315 85 02 STA $02 [$7E:0002] ;/
$81:8317 BD 38 81 LDA $8138,x[$81:8138] ;\
$81:831A AA TAX ;} X = [$8138 + (area index) * 2] (exported map offset)
$81:831B A9 52 CD LDA #$CD52 ;\
$81:831E 85 03 STA $03 [$7E:0003] ;|
$81:8320 A9 7E 00 LDA #$007E ;} $03 = $7E:CD52 (explored map tiles base address)
$81:8323 85 05 STA $05 [$7E:0005] ;/
; LOOP_ROOM
$81:8325 B2 00 LDA ($00) [$81:8146] ;\
$81:8327 29 FF 00 AND #$00FF ;|
$81:832A 18 CLC ;} Y = (explored map base offset) + [(explored map offset list pointer)] (explored map offset)
$81:832B 65 14 ADC $14 [$7E:0014] ;|
$81:832D A8 TAY ;/
$81:832E E2 20 SEP #$20 ;\
$81:8330 BF 1C D9 7E LDA $7ED91C,x[$7E:D91C];|
$81:8334 97 03 STA [$03],y[$7E:CD59] ;} $7E:CD52 + (explored map offset) = [$7E:D91C + (exported map offset)]
$81:8336 C2 20 REP #$20 ;/
$81:8338 E6 00 INC $00 [$7E:0000] ; Increment (explored map offset list pointer)
$81:833A E8 INX ; Increment (exported map offset)
$81:833B C6 12 DEC $12 [$7E:0012] ; Decrement $12
$81:833D D0 E6 BNE $E6 [$8325] ; If [$12] != 0: go to LOOP_ROOM
$81:833F E6 16 INC $16 [$7E:0016] ; Increment (area index)
$81:8341 A5 16 LDA $16 [$7E:0016] ;\
$81:8343 C9 06 00 CMP #$0006 ;} If (area index) < Ceres: go to LOOP_AREA
$81:8346 30 B2 BMI $B2 [$82FA] ;/
$81:8348 28 PLP
$81:8349 AB PLB
$81:834A 60 RTS
}
;;; $834B: Save map ;;;
{
; Doesn't save Ceres
$81:834B 8B PHB
$81:834C 08 PHP
$81:834D 4B PHK ;\
$81:834E AB PLB ;} DB = $81
$81:834F C2 30 REP #$30
$81:8351 64 1A STZ $1A [$7E:001A] ; $1A = 0 (area index)
; LOOP_AREAS
$81:8353 A6 1A LDX $1A [$7E:001A] ;\
$81:8355 BD 31 81 LDA $8131,x[$81:8131] ;|
$81:8358 29 FF 00 AND #$00FF ;} $16 = [$8131 + (area index)] (exported map size)
$81:835B 85 16 STA $16 [$7E:0016] ;/
$81:835D A5 1A LDA $1A [$7E:001A] ;\
$81:835F 0A ASL A ;|
$81:8360 AA TAX ;} $00 = [$82D6 + (area index) * 2] (explored map offset list pointer)
$81:8361 BD D6 82 LDA $82D6,x[$81:82D6] ;|
$81:8364 85 00 STA $00 [$7E:0000] ;/
$81:8366 BD 38 81 LDA $8138,x[$81:8138] ;\
$81:8369 AA TAX ;} X = [$8138 + (area index) * 2] (exported map offset)
$81:836A A5 1A LDA $1A [$7E:001A] ;\
$81:836C EB XBA ;} $18 = (area index) * 100h (explored map base offset)
$81:836D 85 18 STA $18 [$7E:0018] ;/
$81:836F A9 52 CD LDA #$CD52 ;\
$81:8372 85 03 STA $03 [$7E:0003] ;|
$81:8374 A9 7E 00 LDA #$007E ;} $03 = $7E:CD52 (explored map tiles base address)
$81:8377 85 05 STA $05 [$7E:0005] ;/
; LOOP_ROOMS
$81:8379 B2 00 LDA ($00) [$81:8146] ;\
$81:837B 29 FF 00 AND #$00FF ;|
$81:837E 18 CLC ;} Y = (explored map base offset) + [(explored map offset list pointer)] (explored map offset)
$81:837F 65 18 ADC $18 [$7E:0018] ;|
$81:8381 A8 TAY ;/
$81:8382 E2 20 SEP #$20 ;\
$81:8384 B7 03 LDA [$03],y[$7E:CD59] ;|
$81:8386 9F 1C D9 7E STA $7ED91C,x[$7E:D91C];} $7E:D91C + (exported map offset) = [$7E:CD52 + (explored map offset)]
$81:838A C2 20 REP #$20 ;/
$81:838C E6 00 INC $00 [$7E:0000] ; Increment (explored map offset list pointer)
$81:838E E8 INX ; Increment (exported map offset)
$81:838F C6 16 DEC $16 [$7E:0016] ; Decrement $16
$81:8391 D0 E6 BNE $E6 [$8379] ; If [$16] != 0: go to LOOP_ROOMS
$81:8393 E6 1A INC $1A [$7E:001A] ; Increment (area index)
$81:8395 A5 1A LDA $1A [$7E:001A] ;\
$81:8397 C9 06 00 CMP #$0006 ;} If (area index) < Ceres: go to LOOP_AREAS
$81:839A 30 B7 BMI $B7 [$8353] ;/
$81:839C 28 PLP
$81:839D AB PLB
$81:839E 60 RTS
}
;;; $839F..8CF3: Spritemap processing ;;;
{
;;; $839F: Map of OAM index to high X position bit and size bit ;;;
{
; ______ High X position bit
; | _ Size bit
; | |
$81:839F dw 0001,0002, 0004,0008, 0010,0020, 0040,0080, 0100,0200, 0400,0800, 1000,2000, 4000,8000,
0001,0002, 0004,0008, 0010,0020, 0040,0080, 0100,0200, 0400,0800, 1000,2000, 4000,8000,
0001,0002, 0004,0008, 0010,0020, 0040,0080, 0100,0200, 0400,0800, 1000,2000, 4000,8000,
0001,0002, 0004,0008, 0010,0020, 0040,0080, 0100,0200, 0400,0800, 1000,2000, 4000,8000,
0001,0002, 0004,0008, 0010,0020, 0040,0080, 0100,0200, 0400,0800, 1000,2000, 4000,8000,
0001,0002, 0004,0008, 0010,0020, 0040,0080, 0100,0200, 0400,0800, 1000,2000, 4000,8000,
0001,0002, 0004,0008, 0010,0020, 0040,0080, 0100,0200, 0400,0800, 1000,2000, 4000,8000,
0001,0002, 0004,0008, 0010,0020, 0040,0080, 0100,0200, 0400,0800, 1000,2000, 4000,8000,
0001,0002, 0004,0008, 0010,0020, 0040,0080, 0100,0200, 0400,0800, 1000,2000, 4000,8000,
0001,0002, 0004,0008, 0010,0020, 0040,0080, 0100,0200, 0400,0800, 1000,2000, 4000,8000,
0001,0002, 0004,0008, 0010,0020, 0040,0080, 0100,0200, 0400,0800, 1000,2000, 4000,8000,
0001,0002, 0004,0008, 0010,0020, 0040,0080, 0100,0200, 0400,0800, 1000,2000, 4000,8000,
0001,0002, 0004,0008, 0010,0020, 0040,0080, 0100,0200, 0400,0800, 1000,2000, 4000,8000,
0001,0002, 0004,0008, 0010,0020, 0040,0080, 0100,0200, 0400,0800, 1000,2000, 4000,8000,
0001,0002, 0004,0008, 0010,0020, 0040,0080, 0100,0200, 0400,0800, 1000,2000, 4000,8000,
0001,0002, 0004,0008, 0010,0020, 0040,0080, 0100,0200, 0400,0800, 1000,2000, 4000,8000
}
;;; $859F: Map of OAM index to high OAM address and corresponding bitmask ;;;
{
$81:859F dw 0570,0003, 0570,000C, 0570,0030, 0570,00C0, 0570,0300, 0570,0C00, 0570,3000, 0570,C000,
0572,0003, 0572,000C, 0572,0030, 0572,00C0, 0572,0300, 0572,0C00, 0572,3000, 0572,C000,
0574,0003, 0574,000C, 0574,0030, 0574,00C0, 0574,0300, 0574,0C00, 0574,3000, 0574,C000,
0576,0003, 0576,000C, 0576,0030, 0576,00C0, 0576,0300, 0576,0C00, 0576,3000, 0576,C000,
0578,0003, 0578,000C, 0578,0030, 0578,00C0, 0578,0300, 0578,0C00, 0578,3000, 0578,C000,
057A,0003, 057A,000C, 057A,0030, 057A,00C0, 057A,0300, 057A,0C00, 057A,3000, 057A,C000,
057C,0003, 057C,000C, 057C,0030, 057C,00C0, 057C,0300, 057C,0C00, 057C,3000, 057C,C000,
057E,0003, 057E,000C, 057E,0030, 057E,00C0, 057E,0300, 057E,0C00, 057E,3000, 057E,C000,
0580,0003, 0580,000C, 0580,0030, 0580,00C0, 0580,0300, 0580,0C00, 0580,3000, 0580,C000,
0582,0003, 0582,000C, 0582,0030, 0582,00C0, 0582,0300, 0582,0C00, 0582,3000, 0582,C000,
0584,0003, 0584,000C, 0584,0030, 0584,00C0, 0584,0300, 0584,0C00, 0584,3000, 0584,C000,
0586,0003, 0586,000C, 0586,0030, 0586,00C0, 0586,0300, 0586,0C00, 0586,3000, 0586,C000,
0588,0003, 0588,000C, 0588,0030, 0588,00C0, 0588,0300, 0588,0C00, 0588,3000, 0588,C000,
058A,0003, 058A,000C, 058A,0030, 058A,00C0, 058A,0300, 058A,0C00, 058A,3000, 058A,C000,
058C,0003, 058C,000C, 058C,0030, 058C,00C0, 058C,0300, 058C,0C00, 058C,3000, 058C,C000,
058E,0003, 058E,000C, 058E,0030, 058E,00C0, 058E,0300, 058E,0C00, 058E,3000, 058E,C000
}
;;; $879F: Add spritemap to OAM - Y origin on-screen ;;;
{
;; Parameters:
;; DB:Y: Address of spritemap
;; $12: Spritemap Y origin
;; $14: Spritemap X origin
;; $16: Palette bits of sprite (palette * 200h)
; Spritemap format is roughly:
; nnnn ; Number of entries (2 bytes)
; xxxx yy attt ; Entry 0 (5 bytes)
; ... ; Entry 1...
; Where:
; n = number of entries
; x = sprite X offset
; y = sprite Y offset
; a = attributes
; t = tile number
; More specifically, a spritemap entry is:
; s000000xxxxxxxxx yyyyyyyy YXpp000ttttttttt
; Where:
; s = size bit
; x = sprite X offset
; y = sprite Y offset
; Y = Y flip
; X = X flip
; p = priority (relative to background)
; t = tile number
; Called by:
; $80:9FB3: Draw timer spritemap
; $82:8CA1: Draw options menu spritemaps
; $8B:936B: Add Nintendo boot logo spritemap to OAM
; $8B:9746: Draw cinematic sprite objects - intro/title sequence
; $8B:9799: Draw cinematic sprite objects - ending/credits
; $A6:A2F2: Enemy graphics drawn hook - Ceres Ridley - draw Baby Metroid and door
$81:879F DA PHX
$81:87A0 B9 00 00 LDA $0000,y[$8C:80BB] ;\
$81:87A3 D0 05 BNE $05 [$87AA] ;|
$81:87A5 FA PLX ;|
$81:87A6 6B RTL ;} If [[Y]] = 0: return
;|
$81:87A7 4C 4E 88 JMP $884E ;/
$81:87AA 85 18 STA $18 [$7E:0018] ; $18 = [[Y]] (size)
$81:87AC C8 INY ;\
$81:87AD C8 INY ;} Y += 2
$81:87AE AD 90 05 LDA $0590 [$7E:0590] ;\
$81:87B1 89 00 FE BIT #$FE00 ;} If [OAM stack pointer] >= 200h: return
$81:87B4 D0 F1 BNE $F1 [$87A7] ;/
$81:87B6 AA TAX ; X = [OAM stack pointer]
$81:87B7 18 CLC
; LOOP
$81:87B8 B9 00 00 LDA $0000,y[$8C:80BD] ;\
$81:87BB 65 14 ADC $14 [$7E:0014] ;} OAM entry X position = [$14] + [[Y]] (X position)
$81:87BD 9D 70 03 STA $0370,x[$7E:0370] ;/
$81:87C0 29 00 01 AND #$0100 ;\
$81:87C3 F0 26 BEQ $26 [$87EB] ;} If [OAM entry X position] % 200h < 100h: BRANCH_X_HIGH_CLEAR
$81:87C5 B9 00 00 LDA $0000,y[$82:CBD9] ;\
$81:87C8 10 11 BPL $11 [$87DB] ;} If [[Y]] & 8000h (size bit) != 0:
$81:87CA BF 9F 85 81 LDA $81859F,x[$81:859F];\
$81:87CE 85 1C STA $1C [$7E:001C] ;|
$81:87D0 B2 1C LDA ($1C) [$7E:0570] ;} Set OAM entry high X position bit and size bit
$81:87D2 1F A1 85 81 ORA $8185A1,x[$81:85A1];|
$81:87D6 92 1C STA ($1C) [$7E:0570] ;/
$81:87D8 4C FE 87 JMP $87FE [$81:87FE] ; Go to BRANCH_MERGE
$81:87DB BF 9F 85 81 LDA $81859F,x[$81:859F];\
$81:87DF 85 1C STA $1C [$7E:001C] ;|
$81:87E1 B2 1C LDA ($1C) [$7E:0570] ;} Set OAM entry high X position bit
$81:87E3 1F 9F 83 81 ORA $81839F,x[$81:839F];|
$81:87E7 92 1C STA ($1C) [$7E:0570] ;/
$81:87E9 80 13 BRA $13 [$87FE] ; Go to BRANCH_MERGE
; BRANCH_X_HIGH_CLEAR
$81:87EB B9 00 00 LDA $0000,y[$8C:80BD] ;\
$81:87EE 10 0E BPL $0E [$87FE] ;} If [[Y]] & 8000h (size bit) != 0:
$81:87F0 BF 9F 85 81 LDA $81859F,x[$81:859F];\
$81:87F4 85 1C STA $1C [$7E:001C] ;|
$81:87F6 B2 1C LDA ($1C) [$7E:0570] ;} Set OAM entry size bit
$81:87F8 1F A1 83 81 ORA $8183A1,x[$81:83A1];|
$81:87FC 92 1C STA ($1C) [$7E:0570] ;/
; BRANCH_MERGE
$81:87FE E2 20 SEP #$20
$81:8800 B9 02 00 LDA $0002,y[$8C:80BF] ;\
$81:8803 18 CLC ;} If [[Y] + 2] (Y offset) >= 0:
$81:8804 30 0A BMI $0A [$8810] ;/
$81:8806 65 12 ADC $12 [$7E:0012] ;\
$81:8808 B0 14 BCS $14 [$881E] ;|
$81:880A C9 E0 CMP #$E0 ;} If [$12] + [[Y] + 2] (Y position) < E0h: go to BRANCH_ON_SCREEN
$81:880C 90 15 BCC $15 [$8823] ;|
$81:880E 80 0E BRA $0E [$881E] ;/
$81:8810 65 12 ADC $12 [$7E:0012] ;\ Else ((Y offset) < 0):
$81:8812 B0 06 BCS $06 [$881A] ;|
$81:8814 C9 E0 CMP #$E0 ;|
$81:8816 B0 0B BCS $0B [$8823] ;|
$81:8818 80 04 BRA $04 [$881E] ;} If -20h <= (Y position) < E0h: go to BRANCH_ON_SCREEN
;|
$81:881A C9 E0 CMP #$E0 ;|
$81:881C 90 05 BCC $05 [$8823] ;/
$81:881E 20 07 89 JSR $8907 [$81:8907] ; OAM entry X position = 180h
$81:8821 A9 E0 LDA #$E0 ; Use E0h as Y position
; BRANCH_ON_SCREEN
$81:8823 9D 71 03 STA $0371,x[$7E:0371] ; OAM entry Y position = (Y position)
$81:8826 C2 21 REP #$21
$81:8828 B9 03 00 LDA $0003,y[$8C:80C0] ;\
$81:882B 29 FF F1 AND #$F1FF ;|
$81:882E 05 16 ORA $16 [$7E:0016] ;} OAM entry tile number and attributes = [[Y] + 3] & F1FFh | [$16] (palette)
$81:8830 9D 72 03 STA $0372,x[$7E:0372] ;/
$81:8833 8A TXA ;\
$81:8834 69 04 00 ADC #$0004 ;|
$81:8837 89 00 FE BIT #$FE00 ;} If [X] + 4 >= 200h: OAM stack pointer = [X] + 4, return
$81:883A D0 12 BNE $12 [$884E] ;/
$81:883C AA TAX ; X += 4 (next OAM entry)
$81:883D 98 TYA ;\
$81:883E 69 05 00 ADC #$0005 ;} Y += 5 (next sprite map entry)
$81:8841 A8 TAY ;/
$81:8842 C6 18 DEC $18 [$7E:0018] ; Decrement $18
$81:8844 F0 03 BEQ $03 [$8849] ; If [$18] != 0:
$81:8846 4C B8 87 JMP $87B8 [$81:87B8] ; Go to LOOP
$81:8849 8E 90 05 STX $0590 [$7E:0590] ; OAM stack pointer = [X]
$81:884C FA PLX
$81:884D 6B RTL ; Return
$81:884E 8D 90 05 STA $0590 [$7E:0590] ; OAM stack pointer = [A]
$81:8851 FA PLX
$81:8852 6B RTL
}
;;; $8853: Add spritemap to OAM - Y origin off-screen ;;;
{
;; Parameters:
;; DB:Y: Address of spritemap
;; $12: Spritemap Y origin
;; $14: Spritemap X origin
;; $16: Palette bits of sprite (palette * 200h)
; Called by:
; $8B:9746: Draw cinematic sprite objects - intro/title sequence
; $8B:9799: Draw cinematic sprite objects - ending/credits
; See $879F for spritemap format
$81:8853 DA PHX
$81:8854 B9 00 00 LDA $0000,y[$8C:975E] ;\
$81:8857 D0 05 BNE $05 [$885E] ;|
$81:8859 FA PLX ;|
$81:885A 6B RTL ;} If [[Y]] = 0: return
;|
$81:885B 4C 02 89 JMP $8902 [$81:8902] ;/
$81:885E 85 18 STA $18 [$7E:0018] ; $18 = [[Y]] (size)
$81:8860 C8 INY ;\
$81:8861 C8 INY ;} Y += 2
$81:8862 AD 90 05 LDA $0590 [$7E:0590] ;\
$81:8865 89 00 FE BIT #$FE00 ;} If [OAM stack pointer] >= 200h: return
$81:8868 D0 F1 BNE $F1 [$885B] ;/
$81:886A AA TAX ; X = [OAM stack pointer]
$81:886B 18 CLC
; LOOP
$81:886C B9 00 00 LDA $0000,y[$8C:9760] ;\
$81:886F 65 14 ADC $14 [$7E:0014] ;} OAM entry X position = [$14] + [[Y]] (X position)
$81:8871 9D 70 03 STA $0370,x[$7E:0438] ;/
$81:8874 29 00 01 AND #$0100 ;\
$81:8877 F0 26 BEQ $26 [$889F] ;} If [OAM entry X position] % 200h < 100h: BRANCH_X_HIGH_CLEAR
$81:8879 B9 00 00 LDA $0000,y[$8C:B8DF] ;\
$81:887C 10 11 BPL $11 [$888F] ;} If [[Y]] & 8000h (size bit) != 0:
$81:887E BF 9F 85 81 LDA $81859F,x[$81:85AF];\
$81:8882 85 1C STA $1C [$7E:001C] ;|
$81:8884 B2 1C LDA ($1C) [$7E:0570] ;} Set OAM entry high X position bit and size bit
$81:8886 1F A1 85 81 ORA $8185A1,x[$81:85B1];|
$81:888A 92 1C STA ($1C) [$7E:0570] ;/
$81:888C 4C B2 88 JMP $88B2 [$81:88B2] ; Go to BRANCH_MERGE
$81:888F BF 9F 85 81 LDA $81859F,x[$81:869F];\
$81:8893 85 1C STA $1C [$7E:001C] ;|
$81:8895 B2 1C LDA ($1C) [$7E:0580] ;} Set OAM entry high X position bit
$81:8897 1F 9F 83 81 ORA $81839F,x[$81:849F];|
$81:889B 92 1C STA ($1C) [$7E:0580] ;/
$81:889D 80 13 BRA $13 [$88B2] ; Go to BRANCH_MERGE
; BRANCH_X_HIGH_CLEAR
$81:889F B9 00 00 LDA $0000,y[$8C:9760] ;\
$81:88A2 10 0E BPL $0E [$88B2] ;} If [[Y]] & 8000h (size bit) != 0:
$81:88A4 BF 9F 85 81 LDA $81859F,x[$81:85DB];\
$81:88A8 85 1C STA $1C [$7E:001C] ;|
$81:88AA B2 1C LDA ($1C) [$7E:0572] ;} Set OAM entry size bit
$81:88AC 1F A1 83 81 ORA $8183A1,x[$81:83DD];|
$81:88B0 92 1C STA ($1C) [$7E:0572] ;/
; BRANCH_MERGE
$81:88B2 E2 20 SEP #$20
$81:88B4 B9 02 00 LDA $0002,y[$8C:9762] ;\
$81:88B7 18 CLC ;} If [[Y] + 2] (Y offset) >= 0:
$81:88B8 30 0A BMI $0A [$88C4] ;/
$81:88BA 65 12 ADC $12 [$7E:0012] ;\
$81:88BC B0 19 BCS $19 [$88D7] ;|
$81:88BE C9 E0 CMP #$E0 ;} If [$12] + [[Y] + 2] (Y position) >= -20h: go to BRANCH_ON_SCREEN
$81:88C0 B0 15 BCS $15 [$88D7] ;|
$81:88C2 80 0E BRA $0E [$88D2] ;/
$81:88C4 65 12 ADC $12 [$7E:0012] ;\ Else (Y offset < 0):
$81:88C6 B0 06 BCS $06 [$88CE] ;|
$81:88C8 C9 E0 CMP #$E0 ;|
$81:88CA 90 0B BCC $0B [$88D7] ;|
$81:88CC 80 04 BRA $04 [$88D2] ;} If -20 <= (Y position) < E0h: go to BRANCH_ON_SCREEN
;|
$81:88CE C9 E0 CMP #$E0 ;|
$81:88D0 B0 05 BCS $05 [$88D7] ;/
$81:88D2 20 07 89 JSR $8907 [$81:8907] ; OAM entry X position = 180h
$81:88D5 A9 E0 LDA #$E0 ; Use E0h as Y position
; BRANCH_ON_SCREEN
$81:88D7 9D 71 03 STA $0371,x[$7E:0439] ; OAM entry Y position = (Y position)
$81:88DA C2 21 REP #$21
$81:88DC B9 03 00 LDA $0003,y[$8C:9763] ;\
$81:88DF 29 FF F1 AND #$F1FF ;|
$81:88E2 05 16 ORA $16 [$7E:0016] ;} OAM entry tile number and attributes = [[Y] + 3] & F1FFh | [$16] (palette)
$81:88E4 9D 72 03 STA $0372,x[$7E:043A] ;/
$81:88E7 8A TXA ;\
$81:88E8 69 04 00 ADC #$0004 ;|
$81:88EB 89 00 FE BIT #$FE00 ;} If [X] + 4 >= 200h: OAM stack pointer = [X] + 4, return
$81:88EE D0 12 BNE $12 [$8902] ;/
$81:88F0 AA TAX ; X += 4 (next OAM entry)
$81:88F1 98 TYA ;\
$81:88F2 69 05 00 ADC #$0005 ;} Y += 5 (next sprite map entry)
$81:88F5 A8 TAY ;/
$81:88F6 C6 18 DEC $18 [$7E:0018] ; Decrement $18
$81:88F8 F0 03 BEQ $03 [$88FD] ; If [$18] != 0:
$81:88FA 4C 6C 88 JMP $886C [$81:886C] ; Go to LOOP
$81:88FD 8E 90 05 STX $0590 [$7E:0590] ; OAM stack pointer = [X]
$81:8900 FA PLX
$81:8901 6B RTL ; Return
$81:8902 8D 90 05 STA $0590 [$7E:0590] ; OAM stack pointer = [A]
$81:8905 FA PLX
$81:8906 6B RTL
}
;;; $8907: OAM entry X position = 180h ;;;
{
;; Parameters:
;; X: OAM entry index
$81:8907 A9 80 LDA #$80 ;\
$81:8909 9D 70 03 STA $0370,x[$7E:038C] ;} OAM entry X position = 80h
$81:890C C2 20 REP #$20
$81:890E BF 9F 85 81 LDA $81859F,x[$81:85BB];\
$81:8912 85 1C STA $1C [$7E:001C] ;|
$81:8914 B2 1C LDA ($1C) [$7E:0570] ;} Set OAM entry high X position bit
$81:8916 1F 9F 83 81 ORA $81839F,x[$81:83BB];|
$81:891A 92 1C STA ($1C) [$7E:0570] ;/
$81:891C E2 20 SEP #$20
$81:891E 60 RTS
}
;;; $891F: Add pause menu / menu spritemap to OAM ;;;
{
;; Parameters:
;; A: Index into pause menu / menu spritemap table ($82:C569)
{
;; 4: Map scrolling arrow - right
;; 5: Map scrolling arrow - left
;; 6: Map scrolling arrow - up
;; 7: Map scrolling arrow - down
;; 8: Save icon
;; 9: Boss icon
;; Ah: Energy station icon
;; Bh: Missile station icon
;; Ch: Debug save icon
;; 12h: File select map Samus icon
;; 14h: Equipment screen item selector - tanks
;; 15h: Equipment screen item selector - weapons
;; 16h: Equipment screen item selector - suit/misc/boots
;; 17h: Debug elevator icon
;; 1Bh: Full equipment screen reserve tank
;; 1Fh: End of equipment screen reserve health bar
;; 20h: Empty equipment screen reserve tank
;; 21h: Equipment screen 1/7 reserve tank
;; 22h: Equipment screen 2/7 reserve tank
;; 23h: Equipment screen 3/7 reserve tank
;; 24h: Equipment screen 4/7 reserve tank
;; 25h: Equipment screen 5/7 reserve tank
;; 26h: Equipment screen 6/7 reserve tank
;; 27h: Equipment screen 7/7 reserve tank
;; 28h: L button pressed highlight
;; 29h: R button pressed highlight
;; 2Ah: L/R highlight
;; 2Bh: Start button pressed highlight
;; 2Ch: File select menu Samus helmet (frame 0)
;; 2Dh: File select menu Samus helmet (frame 1)
;; 2Eh: File select menu Samus helmet (frame 2)
;; 2Fh: File select menu Samus helmet (frame 3)
;; 30h: File select menu Samus helmet (frame 4)
;; 31h: File select menu Samus helmet (frame 5)
;; 32h: File select menu Samus helmet (frame 6)
;; 33h: File select menu Samus helmet (frame 7)
;; 34h: Menu selection missile (frame 0)
;; 35h: Menu selection missile (frame 1)
;; 36h: Menu selection missile (frame 2)
;; 37h: Menu selection missile (frame 3)
;; 38h: Area select - planet Zebes
;; 39h: Area select - Crateria
;; 3Ah: Area select - Brinstar
;; 3Bh: Area select - Norfair
;; 3Ch: Area select - Wrecked Ship
;; 3Dh: Area select - Maridia
;; 3Eh: Area select - Tourian
;; 40h: File copy arrow - one slot down
;; 41h: File copy arrow - one slot up
;; 42h: File copy arrow - two slots down
;; 43h: File copy arrow - two slots up
;; 48h: Border around SAMUS DATA
;; 49h: Border around DATA COPY MODE
;; 4Ah: Border around DATA CLEAR MODE
;; 4Bh: Border around OPTION MODE
;; 4Ch: Border around CONTROLLER SETTING MODE
;; 4Dh: Border around SPECIAL SETTING MODE
;; 4Eh: Map station icon
;; 59h: Elevator destination - Crateria
;; 5Ah: Elevator destination - Brinstar
;; 5Bh: Elevator destination - Norfair
;; 5Ch: Elevator destination - Wrecked Ship
;; 5Dh: Elevator destination - Maridia
;; 5Eh: Elevator destination - Tourian
;; 5Fh: Samus position indicator (frame 0)
;; 60h: Samus position indicator (frame 1)
;; 61h: Samus position indicator (frame 2)
;; 62h: Boss cross-out icon
;; 63h: Gunship icon
;; 64h: Game over baby metroid container
;; 65h: Game over baby metroid (frame 0)
;; 66h: Game over baby metroid (frame 1)
;; 67h: Game over baby metroid (frame 2)
}
;; X: Spritemap X origin
;; Y: Spritemap Y origin
;; $03: Palette bits of sprite (palette * 200h)
; See $879F for spritemap format
$81:891F 8B PHB
$81:8920 F4 00 82 PEA $8200 ;\
$81:8923 AB PLB ;} DB = $82
$81:8924 AB PLB ;/
$81:8925 84 12 STY $12 [$7E:0012] ; $12 = [Y]
$81:8927 86 14 STX $14 [$7E:0014] ; $14 = [X]
$81:8929 0A ASL A ;\
$81:892A AA TAX ;} Y = [$C569 + [A] * 2] (address of spritemap)
$81:892B BC 69 C5 LDY $C569,x[$82:C5C1] ;/
$81:892E B9 00 00 LDA $0000,y[$82:CAE9] ;\
$81:8931 F0 79 BEQ $79 [$89AC] ;} If [[Y]] = 0: return
$81:8933 85 18 STA $18 [$7E:0018] ; $18 = [[Y]] (size)
$81:8935 C8 INY ;\
$81:8936 C8 INY ;} Y += 2
$81:8937 AE 90 05 LDX $0590 [$7E:0590] ; X = [OAM stack pointer]
$81:893A 18 CLC
; LOOP
$81:893B B9 00 00 LDA $0000,y[$82:CAEB] ;\
$81:893E 65 14 ADC $14 [$7E:0014] ;} OAM entry X position = [$14] + [[Y]] (X position)
$81:8940 9D 70 03 STA $0370,x[$7E:0370] ;/
$81:8943 29 00 01 AND #$0100 ;\
$81:8946 F0 27 BEQ $27 [$896F] ;} If [OAM entry X position] % 200h < 100h: BRANCH_X_HIGH_CLEAR
$81:8948 B9 00 00 LDA $0000,y[$82:C4F3] ;\
$81:894B 10 11 BPL $11 [$895E] ;} If [[Y]] & 8000h (size bit) != 0:
$81:894D BF 9F 85 81 LDA $81859F,x ;\
$81:8951 85 16 STA $16 [$7E:0016] ;|
$81:8953 B2 16 LDA ($16) ;} Set OAM entry high X position bit and size bit
$81:8955 1F A1 85 81 ORA $8185A1,x ;|
$81:8959 92 16 STA ($16) ;/
$81:895B 4C 82 89 JMP $8982 [$81:8982] ; Go to BRANCH_MERGE
$81:895E BF 9F 85 81 LDA $81859F,x[$81:85BF];\
$81:8962 85 16 STA $16 [$7E:0016] ;|
$81:8964 B2 16 LDA ($16) [$7E:0572] ;} Set OAM entry high X position bit
$81:8966 1F 9F 83 81 ORA $81839F,x[$81:83BF];|
$81:896A 92 16 STA ($16) [$7E:0572] ;/
$81:896C 4C 82 89 JMP $8982 [$81:8982] ; Go to BRANCH_MERGE
; BRANCH_X_HIGH_CLEAR
$81:896F B9 00 00 LDA $0000,y[$82:CAEB] ;\
$81:8972 10 0E BPL $0E [$8982] ;} If [[Y]] & 8000h (size bit) != 0:
$81:8974 BF 9F 85 81 LDA $81859F,x[$81:859F];\
$81:8978 85 16 STA $16 [$7E:0016] ;|
$81:897A B2 16 LDA ($16) [$7E:0570] ;} Set OAM entry size bit
$81:897C 1F A1 83 81 ORA $8183A1,x[$81:83A1];|
$81:8980 92 16 STA ($16) [$7E:0570] ;/
; BRANCH_MERGE
$81:8982 B9 02 00 LDA $0002,y[$82:CAED] ;\
$81:8985 18 CLC ;|
$81:8986 65 12 ADC $12 [$7E:0012] ;} OAM entry Y position = [$12] + [[Y] + 2] (Y position)
$81:8988 9D 71 03 STA $0371,x[$7E:0371] ;/
$81:898B B9 03 00 LDA $0003,y[$82:CAEE] ;\
$81:898E 29 FF F1 AND #$F1FF ;|
$81:8991 05 03 ORA $03 [$7E:0003] ;} OAM entry tile number and attributes = [[Y] + 3] & F1FFh | [$03] (palette)
$81:8993 9D 72 03 STA $0372,x[$7E:0372] ;/
$81:8996 98 TYA ;\
$81:8997 18 CLC ;|
$81:8998 69 05 00 ADC #$0005 ;} Y += 5 (next sprite map entry)
$81:899B A8 TAY ;/
$81:899C 8A TXA ;\
$81:899D 18 CLC ;|
$81:899E 69 04 00 ADC #$0004 ;} X += 4 (next OAM entry)
$81:89A1 29 FF 01 AND #$01FF ;|
$81:89A4 AA TAX ;/
$81:89A5 C6 18 DEC $18 [$7E:0018] ; Decrement $18
$81:89A7 D0 92 BNE $92 [$893B] ; If [$18] != 0: go to LOOP
$81:89A9 8E 90 05 STX $0590 [$7E:0590] ; OAM stack pointer = [X]
$81:89AC AB PLB
$81:89AD 6B RTL
}