-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinput.asm
1612 lines (1351 loc) · 26.9 KB
/
input.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
; handles all inputs
input_handler:
; reset latch
lda #$01
sta $4016
lda #$00
sta $4016 ; both controllers are latching now
lda nmi_flags
and #%00100000 ; check disable input flag
beq @not_disabled
; latch buttons anyway
lda $4016
rts
@not_disabled:
lda last_inputs
sta prev_inputs
lda #$00
sta last_inputs
; latch all inputs and place them in last input register
ldx #$08
@read_loop:
asl
sta last_inputs
lda $4016 ; read each input in order A, B, select, start, u, d, l, r
and #$01
ora last_inputs
dex
bne @read_loop
sta last_inputs
; all inputs are now read
lda last_inputs ; p1 - A
and #%10000000
beq @no_a
lda prev_inputs
and #%10000000
bne @skip_a ; don't allow held inputs
jsr a_input
@skip_a:
@no_a:
lda last_inputs ; p1 - B
and #%01000000
beq @no_b
lda prev_inputs
and #%01000000
bne @skip_b ; don't allow held input
jsr b_input
@skip_b:
@no_b:
lda last_inputs ; p1 - select
and #%00100000
beq @no_select
jsr select_input
@no_select:
lda last_inputs ; p1 - start
and #%00010000
beq @no_start
jsr start_input
@no_start:
lda last_inputs ; p1 - up
and #%00001000
beq @no_up
jsr go_up
@no_up:
lda last_inputs ; p1 - down
and #%00000100
beq @no_down
jsr go_down
@no_down:
lda last_inputs ; p1 - left
and #%00000010
beq @no_left
jsr go_left
@no_left:
lda last_inputs ; p1 - right
and #%00000001
beq @no_right
jsr go_right
@no_right:
rts
; make movement check
; uses move delay
; inputs:
; none
; returns:
; a -> 0 if move can go ahead
; a -> 1 if move cannot go ahead
can_move:
lda move_delay
rts
; makse select check,
; uses select delay
; inputs:
; none
; returns:
; a-> 0 if select possible
; a-> 1 if select cannot go ahead
can_select:
lda select_delay
rts
; a input
; places the player's current tile at the player's current
; location. only works in EDITOR_MODE
a_input:
jsr can_select
bne @done
lda #MOVE_DELAY_FRAMES
sta select_delay
lda game_mode
cmp #GAME_MODE_EDITOR
bne @not_editor
jsr update_tile
rts
@not_editor:
cmp #GAME_MODE_EDITOR_MENU
bne @not_editor_menu
jsr a_input_editor_menu
rts
@not_editor_menu:
cmp #GAME_MODE_MENU
bne @not_main_menu
jsr a_input_main_menu
rts
@not_main_menu:
cmp #GAME_MODE_GAME
bne @not_game
jsr a_input_game
rts
@not_game:
cmp #GAME_MODE_PAUSE
bne @done
jsr a_input_pause
@done:
rts
; in-game a input
a_input_game:
ldy weapon_type
; no weapon if 0
bne @init
rts
@init:
; disable blinking animation
lda sprite_data+1
and #%01111111
sta sprite_data+1
jsr init_sword_noise
lda weapon_update_lo, y
sta delay_update
lda weapon_update_hi, y
sta delay_update+1
lda weapon_done_lo, y
sta delay_done
lda weapon_done_hi, y
sta delay_done+1
lda weapon_timer_16, y
sta delay_timer+1
lda weapon_timer, y
sta delay_timer
; disable inputs
lda nmi_flags
ora #%00100000
sta nmi_flags
; move weapon x and y based on last inputs
lda player_x
sta weapon_x
lda player_y
sta weapon_y
lda weapon_sprite, y ; tile
sta sprite_data_1+1
lda last_move
cmp #UP
bne @no_up
dec weapon_y
lda #%10000000 ; flip
sta sprite_data_1+2
rts
@no_up:
cmp #DOWN
bne @no_down
inc weapon_y
lda #%00000000 ; no flip
sta sprite_data_1+2
rts
@no_down:
lda weapon_sprite, y ; tile
ora #%10000000 ; get horizontal version
sta sprite_data_1+1
lda last_move
cmp #LEFT
bne @no_left
dec weapon_x
lda #%01000000 ; flip
sta sprite_data_1+2
rts
@no_left:
cmp #RIGHT
bne @no_right
inc weapon_x
lda #%00000000 ; flip
sta sprite_data_1+2
rts
@no_right:
rts
; editor menu code for a input
a_input_editor_menu:
lda editor_flags
and #%10000000
beq @not_tile_select_mode
ldx #$01 ; get current tile from nt 1
lda player_x
sta get_tile_x
lda player_y
sta get_tile_y
jsr get_tile_nametable
sta sprite_data_1+1
rts
@not_tile_select_mode:
lda #MOVE_DELAY_FRAMES*2
sta select_delay
; set up the right pointers for data write
; save slot is based on menu select
lda menu_select
cmp #EDITOR_MENU_SAVE3
bne @not_slot3
lda #<save_3
sta level_data_ptr
lda #>save_3
sta level_data_ptr+1
lda #<attr_3
sta attr_ptr
lda #>attr_3
sta attr_ptr+1
lda #<palette_3
sta dest_ptr
lda #>palette_3
sta dest_ptr+1
jmp @slot_slected
@not_slot3:
cmp #EDITOR_MENU_SAVE2
bne @not_slot2
lda #<save_2
sta level_data_ptr
lda #>save_2
sta level_data_ptr+1
lda #<attr_2
sta attr_ptr
lda #>attr_2
sta attr_ptr+1
lda #<palette_2
sta dest_ptr
lda #>palette_2
sta dest_ptr+1
jmp @slot_slected
@not_slot2:
; new slot should not save, but instead is a debug feature that loads a map based on the selected tile id
cmp #EDITOR_MENU_NEW
bne @dont_load_debug_map
jmp @load_debug_map
@dont_load_debug_map:
cmp #EDITOR_MENU_SAVE1
beq @slot_1
jmp @no_slot:
@slot_1:
; always pick slot 1 as default option
lda #<save_1
sta level_data_ptr
lda #>save_1
sta level_data_ptr+1
lda #<attr_1
sta attr_ptr
lda #>attr_1
sta attr_ptr+1
lda #<palette_1
sta dest_ptr
lda #>palette_1
sta dest_ptr+1
@slot_slected:
lda #$00
sta $2001 ; disable rendering
lda #<level_data
sta level_ptr
lda #>level_data
sta level_ptr+1
; disable NMI, don't change other flags
; NMI needs to be disabled
; to prevent it being called again
; while compression is ongoing
set_nmi_flag
jsr compress_level
vblank_wait
ldx #$00
; stx $2005
; stx $2005 ; no scrolling
jsr write_attr
;lda $2000
;ora #%10000000
;sta $2000 ; enable NMI again
; copy palette
lda #<level_palette
sta src_ptr
lda #>level_palette
sta src_ptr+1
ldy #PALETTE_SIZE
jsr memcpy
vblank_wait
rts
@no_slot:
cmp #EDITOR_MENU_BACK
bne @not_back
; load nametable
lda #$00
sta $2001 ; no rendering
set_nmi_flag
ldx #$00
stx menu_select
jsr load_menu
vblank_wait
; lda #$00
; sta $2005
; sta $2005 ; no scrolling
jsr init_main_menu
vblank_wait
rts
@not_back:
@done:
rts
@load_debug_map:
ldx #$00
stx $2001 ; disable rendering
; select the map to load
ldx sprite_data_1+1 ; based on tile
lda map_table_lo, x
sta level_data_ptr
lda map_table_hi, x
sta level_data_ptr+1
lda attr_table_lo, x
sta attr_ptr
lda attr_table_hi, x
sta attr_ptr+1
; for memcpy, copy palette
lda palette_table_lo, x
sta src_ptr
lda palette_table_hi, x
sta src_ptr+1
lda #<level_palette
sta dest_ptr
lda #>level_palette
sta dest_ptr+1
lda #<level_data
sta level_ptr
lda #>level_data
sta level_ptr+1
; disable NMI until load is complete
set_nmi_flag
jsr decompress_level
; copy palette we set up earlier
ldy #PALETTE_SIZE ; size to copy
jsr memcpy
ldx #$00 ; nametable 0
jsr load_level
jsr load_attr
vblank_wait
; lda #$00
; sta $2005
; sta $2005 ; no scrolling
jsr load_palette
lda #GAME_MODE_EDITOR
sta game_mode
vblank_wait
; lda #$00
; sta $2005
; sta $2005 ; no scrolling again
jsr init_editor
lda #$00
sta nametable
jsr init_ai_tiles
jsr find_start
vblank_wait
rts
; main menu code for A
a_input_main_menu:
ldx #$00
stx $2001 ; disable rendering
; disable NMI until load is complete
set_nmi_flag
lda menu_select
cmp #MAIN_MENU_EDITOR
bne @not_editor
; init editor
lda #GAME_MODE_EDITOR_MENU
sta game_mode
tax
jsr load_menu
lda #$00
sta menu_select
sta sprite_data+1
vblank_wait
; lda #$00
; sta $2005
; sta $2005 ; no scrolling
jsr init_editor_menu
rts
@not_editor:
; at this point all choices will load a map
; load pause menu into nt1
ldx #GAME_MODE_PAUSE
jsr load_menu
lda menu_select ; need to restore menu_select in A after load
cmp #MAIN_MENU_LEVEL
bne @not_level_select
@level_select:
; select the map to load
ldx level_select ; based on tile
lda map_table_lo, x
sta level_data_ptr
lda map_table_hi, x
sta level_data_ptr+1
lda attr_table_lo, x
sta attr_ptr
lda attr_table_hi, x
sta attr_ptr+1
; for memcpy, copy palette
lda palette_table_lo, x
sta src_ptr
lda palette_table_hi, x
sta src_ptr+1
; load sub routine
lda map_sub_lo, x
sta map_sub_ptr
lda map_sub_hi, x
sta map_sub_ptr+1
jmp @slot_selected
@not_level_select:
cmp #MAIN_MENU_RANDOM
bne @not_random
lda #%10000000
sta load_flags
jmp @level_select
@not_random:
cmp #MAIN_MENU_RESUME
bne @no_resume
lda #%10100000
sta load_flags
jmp @level_select
@no_resume:
cmp #MAIN_MENU_SET_SEED
bne @not_set_seed
lda seed_input
sta seed
lda seed_input+1
sta seed+1
lda #%10000000
sta load_flags
jmp @level_select
@not_set_seed:
; check which slot is selected
cmp #MAIN_MENU_SLOT_1
bne @not_slot_1
; slot 1 selected, set up pointers
lda #<save_1
sta level_data_ptr
lda #>save_1
sta level_data_ptr+1
lda #<attr_1
sta attr_ptr
lda #>attr_1
sta attr_ptr+1
lda #<palette_1
sta src_ptr
lda #>palette_1
sta src_ptr+1
; load no update routine for custom levels
lda #<save_sub_1
sta map_sub_ptr
lda #>save_sub_1
sta map_sub_ptr+1
jmp @slot_selected
@not_slot_1:
cmp #MAIN_MENU_SLOT_2
bne @not_slot2
lda #<save_2
sta level_data_ptr
lda #>save_2
sta level_data_ptr+1
lda #<attr_2
sta attr_ptr
lda #>attr_2
sta attr_ptr+1
lda #<palette_2
sta src_ptr
lda #>palette_2
sta src_ptr+1
; load no update routine for custom levels
lda #<save_sub_2
sta map_sub_ptr
lda #>save_sub_2
sta map_sub_ptr+1
jmp @slot_selected
@not_slot2:
cmp #MAIN_MENU_SLOT_3
beq @slot3
jmp @no_slot
@slot3:
lda #<save_3
sta level_data_ptr
lda #>save_3
sta level_data_ptr+1
lda #<attr_3
sta attr_ptr
lda #>attr_3
sta attr_ptr+1
lda #<palette_3
sta src_ptr
lda #>palette_3
sta src_ptr+1
; load no update routine for custom levels
lda #<save_sub_3
sta map_sub_ptr
lda #>save_sub_3
sta map_sub_ptr+1
@slot_selected:
; store pointers in backup
lda level_data_ptr
sta level_data_ptr_bac
lda level_data_ptr+1
sta level_data_ptr_bac+1
lda attr_ptr
sta attr_ptr_bac
lda attr_ptr+1
sta attr_ptr_bac+1
lda src_ptr
sta palette_ptr_bac
lda src_ptr+1
sta palette_ptr_bac+1
lda seed
sta seed_bac
lda seed+1
sta seed_bac+1
; now all pointers are backed up
; load level $00 because init_game increments it
lda #$00
sta level
; enable low visiblity mode
lda load_flags
ora #%01000000
sta load_flags
jsr reload_room
;ldx #$00
;stx $2001 ; disable rendering
; load an empty map first
;lda #<empty_map
;sta level_data_ptr
;lda #>empty_map
;sta level_data_ptr+1
;lda #<level_data
;sta level_ptr
;lda #>level_data
;sta level_ptr+1
; disable NMI until load is complete
;set_nmi_flag
;jsr decompress_level
;ldx #$00 ; nt 0
;jsr load_level
; load actual map
;lda level_data_ptr_bac
;sta level_data_ptr
;lda level_data_ptr_bac+1
;sta level_data_ptr+1
;lda #<level_data
;sta level_ptr
;lda #>level_data
;sta level_ptr+1
;jsr decompress_level
;ldx #$00 ; nametable 0
; test which load needs to be done
;lda load_flags
;and #%01000000 ; flag for partial load
;bne @load_part
;jsr load_level
; partial load depends on start tile
; therefore it will happen after init_game is called
;@load_part:
;jsr load_attr
; copy palette
;lda #<level_palette
;sta dest_ptr
;lda #>level_palette
;sta dest_ptr+1
;ldy #PALETTE_SIZE
;jsr memcpy
;lda #$00
;sta nametable
;vblank_wait
; lda #$00
; sta $2005
; sta $2005 ; no scrolling
;jsr init_game
; test if partial load is needed now
; if so we have start location and can go ahead
;lda load_flags
;and #%01000000 ; flag for partial load
;beq @no_part_load
;lda player_x
;sta get_tile_x
;lda player_y
;sta get_tile_y
;ldx #$00 ; nametable 0
;jsr load_level_part
;@no_part_load:
;vblank_wait
@no_slot:
@done:
rts
; a input pause menu
a_input_pause:
lda menu_select
cmp #PAUSE_MENU_RESUME
bne @not_resume:
jsr resume_game
rts
@not_resume:
cmp #PAUSE_MENU_QUIT
bne @not_quit
jsr resume_game
jsr start_input_message ; back to main menu
rts
@not_quit:
@done:
rts
; b button input
; b loads a map in editor menu
b_input:
lda game_mode
cmp #GAME_MODE_EDITOR_MENU
beq @editor_menu
jmp @not_editor_menu ; branch was out of range qq
@editor_menu:
jsr b_input_editor_menu
rts
@not_editor_menu:
cmp #GAME_MODE_EDITOR
bne @not_editor
; editor mode
jsr update_attr
rts
@not_editor:
cmp #GAME_MODE_GAME
bne @done
; debug decrease magic
jsr b_input_game
; debug projectile spawn
; TODO remove
; lda player_x
; sta get_tile_x
; lda player_y
; sta get_tile_y
; lda last_move
; jsr spawn_projectile
@done:
rts
; in-game a input
b_input_game:
ldy spell_type
; no weapon if 0
bne @init
rts
@init:
lda pmagic
bne @magic
rts ; if not enough magic
@magic:
dec pmagic ; -1
; disable blinking animation
lda sprite_data+1
and #%01111111
sta sprite_data+1
jsr init_sword_noise
lda weapon_update_lo, y
sta delay_update
lda weapon_update_hi, y
sta delay_update+1
lda weapon_done_lo, y
sta delay_done
lda weapon_done_hi, y
sta delay_done+1
lda weapon_timer_16, y
sta delay_timer+1
lda weapon_timer, y
sta delay_timer
; store player damage and load
; spell damage
lda player_damage
sta seed_input ; unused area in ram, use it as temp storage
lda spell_damage, y ; damage
sta player_damage
; disable inputs
lda nmi_flags
ora #%00100000
sta nmi_flags
; move weapon x and y based on last inputs
lda player_x
sta weapon_x
lda player_y
sta weapon_y
lda weapon_sprite, y ; tile
sta sprite_data_1+1
rts
; b input for editor menu
b_input_editor_menu:
lda editor_flags
and #%10000000
beq @not_tile_select_mode
rts
@not_tile_select_mode:
lda #MOVE_DELAY_FRAMES*2
sta select_delay
lda menu_select
cmp #EDITOR_MENU_NEW
bne @not_new_map
lda #<empty_map
sta level_data_ptr
lda #>empty_map
sta level_data_ptr+1
lda #<test_attr
sta attr_ptr
lda #>test_attr
sta attr_ptr+1
lda #<palette_data
sta src_ptr
lda #>palette_data
sta src_ptr+1
jmp @slot_selected
@not_new_map:
cmp #EDITOR_MENU_SAVE2
bne @not_slot2
lda #<save_2
sta level_data_ptr
lda #>save_2
sta level_data_ptr+1
lda #<attr_2
sta attr_ptr
lda #>attr_2
sta attr_ptr+1
lda #<palette_2
sta src_ptr
lda #>palette_2
sta src_ptr+1
jmp @slot_selected
@not_slot2:
cmp #EDITOR_MENU_SAVE3
bne @not_slot3
lda #<save_3
sta level_data_ptr
lda #>save_3
sta level_data_ptr+1
lda #<attr_3
sta attr_ptr
lda #>attr_3
sta attr_ptr+1
lda #<palette_3
sta src_ptr
lda #>palette_3
sta src_ptr+1
jmp @slot_selected
; set up for load
@not_slot3:
; otherwise it is slot 1
cmp #EDITOR_MENU_SAVE1
beq @slot_1
rts
@slot_1:
lda #<save_1
sta level_data_ptr
lda #>save_1
sta level_data_ptr+1
lda #<attr_1
sta attr_ptr
lda #>attr_1
sta attr_ptr+1
lda #<palette_1
sta src_ptr
lda #>palette_1
sta src_ptr+1
@slot_selected:
ldx #$00
stx $2001 ; disable rendering
; disable NMI until load is complete
set_nmi_flag
lda #<level_data
sta level_ptr
lda #>level_data
sta level_ptr+1
jsr decompress_level
ldx $00 ; nametable 0
jsr load_level
jsr load_attr
; copy palette
lda #<level_palette
sta dest_ptr
lda #>level_palette
sta dest_ptr+1
ldy #PALETTE_SIZE
jsr memcpy
lda #GAME_MODE_EDITOR
sta game_mode
vblank_wait
; lda #$00
; sta $2005
; sta $2005 ; no scrolling
jsr init_editor
lda #$00
sta nametable
jsr init_ai_tiles
jsr find_start
vblank_wait
rts
; select button input