junglejourney

view mapcode.oph @ 189:a3e62b843f69

Fixed the logic for the fire button check. Merged keyboard and joystick messages, checking for both Space and Fire on the title screen.
author David Boddie <david@boddie.org.uk>
date Tue Sep 27 19:09:44 2011 +0200
parents 30d7ba9d8236
children e1a1513fde16
line source
1 ; Copyright (C) 2011 David Boddie <david@boddie.org.uk>
2 ;
3 ; This program is free software: you can redistribute it and/or modify
4 ; it under the terms of the GNU General Public License as published by
5 ; the Free Software Foundation, either version 3 of the License, or
6 ; (at your option) any later version.
7 ;
8 ; This program is distributed in the hope that it will be useful,
9 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
10 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 ; GNU General Public License for more details.
12 ;
13 ; You should have received a copy of the GNU General Public License
14 ; along with this program. If not, see <http://www.gnu.org/licenses/>.
16 .org $1e00
17 jmp main
19 seeds: .byte 100, 239, 183, 144 ; $ef, $b7, $90, $d6, $89
20 start_rooms_x: .byte 5, 3, 5, 10
21 start_rooms_y: .byte 5, 8, 1, 8
22 exit_rooms_x: .byte 7, 9, 3, 0
23 exit_rooms_y: .byte 0, 0, 9, 10
25 ; These values need to be kept in sync - the room numbers must match their
26 ; positions in the room array.
27 key_rooms_x: .byte 1, 5, 10, 1
28 key_rooms_y: .byte 0, 2, 6, 4
29 key_rooms: .byte 1, 27, 76, 45 ; ky*11 + kx
31 treasure_table: .byte 6, 5, 7, 1, 1, 5, 2, 7, 6, 2, 1, 7, 1, 7, 8, 7
32 treasure_table_: .byte 0, 7, 6, 7, 7, 7, 5, 0, 6, 3, 7, 7, 5, 7, 5, 0
34 unlimited_values: ; $7c,$7d=first,second
35 ; Add $7c and $7d, store the result in $7d and the original
36 ; $7d value in $7c, returning the sum in the accumulator.
37 lda $7c
38 sta $7b
39 lda $7d
40 sta $7c
41 adc $7b
42 sta $7d
43 clc
44 rts
46 mod9: ; A = value
47 divide_loop:
48 cmp #9
49 bcc after_divide_loop ; bmi should work here, I think, but it doesn't
50 sec
51 sbc #9
52 jmp divide_loop
54 after_divide_loop:
55 clc
56 rts ; A % 9
58 tile_values_map: .byte 0,1,0,0,0,0,2,3
60 next_value: ; no argument
61 jsr unlimited_values
62 lda $7d
63 jsr mod9
64 and #7 ; (next value % 9) & 7
65 tax
66 lda tile_values_map,x
67 sta $7b
68 rts
70 ; Room filling routines, writing to 0x579c to 0x57ff.
72 draw_top_line: ; $76=tile number for exit/wall
73 ldx #9
74 lda #2
76 draw_top_line_loop0:
77 sta $579c,x
78 dex
79 bpl draw_top_line_loop0
81 ldx #3 ; draw the exit or wall
82 lda $76
83 draw_top_line_loop1:
84 sta $579f,x
85 dex
86 bpl draw_top_line_loop1
87 clc
88 rts
90 draw_left_line: ; $77=tile number for exit/wall
91 ldx #90
92 draw_left_line_loop0:
93 lda #2
94 sta $579c,x
95 txa
96 sec
97 sbc #10
98 tax
99 bpl draw_left_line_loop0
101 ldx #30
102 draw_left_line_loop1:
103 lda $77
104 sta $57ba,x
105 txa
106 sec
107 sbc #10
108 tax
109 bpl draw_left_line_loop1
110 clc
111 rts
113 draw_bottom_line: ; $76=tile number for exit/wall
114 ldx #9
115 lda #2
116 draw_bottom_line_loop0:
117 sta $57f6,x
118 dex
119 bpl draw_bottom_line_loop0
121 ldx #3
122 lda $76
123 draw_bottom_line_loop1:
124 sta $57f9,x
125 dex
126 bpl draw_bottom_line_loop1
127 clc
128 rts
130 draw_right_line: ; $77=tile number for exit/wall
131 ldx #99
132 draw_right_line_loop0:
133 lda #2
134 sta $579c,x
135 txa
136 sec
137 sbc #10
138 tax
139 bpl draw_right_line_loop0
141 ldx #30
142 draw_right_line_loop1:
143 lda $77
144 sta $57c3,x
145 txa
146 sec
147 sbc #10
148 tax
149 bpl draw_right_line_loop1
150 clc
151 rts
153 make_empty_room:
155 ldx #99
156 make_empty_room_loop:
157 lda #0
158 sta $579c,x
159 dex
160 bpl make_empty_room_loop
162 rts
164 make_room: ; $78,$79=i,j
166 ; Fills the room array at 579c with values.
167 ; Tiles 0,1,2,3 are map tiles that will be shown by the plot_tile routine.
168 ; Other tiles are plotted separately:
169 ; 4 = exit
170 ; 5 = final exit
171 ; 6 = weapon (bits 3,4 are type)
172 ; 7 = treasure (bits 3,4 are type)
174 ; Fill the room with empty space.
176 jsr make_empty_room
178 ; Determine if there is a top exit.
180 lda #0
181 sta $76
183 lda $78 ; i == 0
184 cmp #0
185 bne not_top_screen
186 lda #2
187 sta $76
188 jmp do_top_exit
190 not_top_screen:
191 clc
193 lda $78
194 and #7 ; i & 7
195 sta $70 ; temporary result
196 lda $79
197 and #7 ; j & 7
198 cmp $70
199 beq do_top_exit
200 clc
202 lda $78
203 eor $79 ; i ^ j
204 adc $78 ; + i
205 clc
206 cmp $79 ; (i ^ j) + i == j
207 bne do_top_exit
208 lda #2
209 sta $76 ; top exit
211 do_top_exit:
212 jsr draw_top_line
214 ; Determine if there is a left exit.
215 lda #0
216 sta $77
218 lda $79
219 cmp #0
220 bne not_left_screen
221 lda #2
222 sta $77
223 jmp do_left_exit
225 not_left_screen:
226 clc
228 lda $78
229 and #3 ; i & 3
230 sta $70 ; temporary result
231 lda $79
232 and #3 ; j & 3
233 cmp $70
234 beq do_left_exit
235 clc
237 lda $78
238 ora $79 ; i | j
239 eor $79 ; ^ j
240 cmp $78 ; (i | j) ^ j == i
241 bne do_left_exit
242 lda #2
243 sta $77 ; left exit
245 do_left_exit:
246 jsr draw_left_line
248 ; Determine if there is a right exit.
249 lda #0
250 sta $77
252 lda $79
253 cmp #10
254 bne not_right_screen
255 lda #2
256 sta $77
257 jmp do_right_exit
259 not_right_screen:
260 clc
262 lda $78
263 and #3 ; i & 3
264 sta $70 ; temporary result
265 lda $79
266 adc #1
267 and #3 ; j & 3
268 cmp $70
269 beq do_right_exit
270 clc
272 lda $79
273 adc #1
274 sta $70
276 lda $78
277 ora $70 ; i | j
278 eor $70 ; ^ j
279 cmp $78 ; (i | j) ^ j == i
280 bne do_right_exit
281 lda #2
282 sta $77 ; right exit
284 do_right_exit:
285 jsr draw_right_line
287 ; Determine if there is a bottom exit.
288 lda #0
289 sta $76
291 lda $78
292 cmp #10
293 bne not_bottom_screen
294 lda #2
295 sta $76
296 jmp do_bottom_exit
298 not_bottom_screen:
299 clc
301 lda $78
302 adc #1
303 and #7 ; i & 7
304 sta $70 ; temporary result
305 lda $79
306 and #7 ; j & 7
307 cmp $70
308 beq do_bottom_exit
309 clc
311 lda $78
312 adc #1
313 sta $70
315 eor $79 ; i ^ j
316 adc $70 ; + i
317 cmp $79 ; (i ^ j) + i == j
318 bne do_bottom_exit
319 lda #2
320 sta $76 ; bottom exit
322 do_bottom_exit:
323 jsr draw_bottom_line
325 ; Add the final exit.
327 lda $578a
328 cmp #3
329 bmi make_room_no_final_exit
331 lda $78
332 cmp #0
333 bne make_room_no_final_exit
335 lda $79
336 cmp #2
337 bne make_room_no_final_exit
339 lda #6
340 sta $57a0
341 lda #7
342 sta $57a1
344 make_room_no_final_exit:
346 ; Make sure that the starting, exit, key rooms are empty.
348 ldx $578a ; level number
349 lda start_rooms_y,x
350 cmp $78
351 bne make_room_not_starting_room
352 lda start_rooms_x,x
353 cmp $79
354 bne make_room_not_starting_room
356 lda #3
357 sta $70
358 jmp add_room_decoration ; optimise away the rts
360 make_room_not_starting_room:
362 lda exit_rooms_y,x
363 cmp $78
364 bne make_room_not_exit_room
365 lda exit_rooms_x,x
366 cmp $79
367 bne make_room_not_exit_room
369 ; Add an exit to the room.
370 lda $78
371 eor $79
372 and #15
373 tax
374 lda exit_room_offsets,x
375 tax
376 lda $5780
377 and #1
378 beq exit_not_open
380 lda #5
381 sta $579c,x
382 jmp exit_decoration
384 exit_not_open:
385 clc
386 lda #4
387 sta $579c,x
389 exit_decoration:
390 lda #3
391 sta $70
392 jmp add_room_decoration ; optimise away the rts
394 make_room_not_exit_room:
396 lda key_rooms_y,x
397 cmp $78
398 bne make_room_not_key_room
399 lda key_rooms_x,x
400 cmp $79
401 bne make_room_not_key_room
403 lda #1
404 sta $70
405 jmp add_room_decoration ; optimise away the rts
407 make_room_not_key_room:
408 clc
410 ; Fill in the room details.
412 lda $79
413 sta $7c
414 sec
415 ldx $578a
416 lda seeds,x
417 sbc $78
418 sec
419 sta $7d
420 clc
422 ; Discard the first ten values.
424 ldy #10
425 make_room_loop0:
426 jsr unlimited_values
427 dey
428 bne make_room_loop0
430 ; Fill the room array with values.
432 lda #$a7
433 sta $70
434 lda #$57
435 sta $71
437 ldy #0
438 make_room_loop1:
440 jsr next_value
441 sta ($70),y
442 iny
443 cpy #8
444 bne make_room_loop1 ; continue the same row
446 lda $70
447 cmp #$ed
448 beq make_room_loop1_exit ; exit after the last row
450 adc #10
451 sta $70
452 ldy #0 ; reset the row counter
453 jmp make_room_loop1
455 make_room_loop1_exit:
456 rts
458 decoration_offsets: .byte 11,18,81,88
460 add_room_decoration:
462 lda #$9c
463 sta $8e
464 lda #$57
465 sta $8f
467 ldx #3
468 add_room_decoration_loop:
470 lda decoration_offsets,x
471 tay
472 lda $70
473 sta ($8e),y
474 dex
475 bpl add_room_decoration_loop
477 clc
478 rts
480 exit_room_offsets: .byte 35,66,63,56,34,44,64,33,36,55,65,53,45,46,54,43
481 treasure_x: .byte 3, 2, 4, 8, 2, 5, 4, 1, 3, 8, 6, 5, 7, 1, 7, 6
482 treasure_y: .byte 1, 3, 7, 7, 2, 3, 6, 1, 4, 6, 8, 5, 5, 4, 8, 2
484 eleven_times_table: .byte 0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 110
486 add_treasure: ; $78,$79 = i,j
488 lda $78
489 tax
490 lda eleven_times_table,x
491 adc $79
492 tax
494 lda $5200,x
495 ora #$80
496 sta $5200,x ; set the top bit (room visited)
497 and #$7f ; mask off the top bit to obtain the item number + 1
498 cmp #0
499 beq add_treasure_exit
501 sec
502 sbc #1
503 sta $528d ; store weapon/treasure type
504 clc
506 lda $78
507 eor $79
508 adc $528d
509 and #15
510 sta $70
512 lda #15
513 sta $8c
514 ldy #0
515 add_treasure_loop:
517 clc
519 ldx $70
520 lda treasure_y,x ; y
521 sta $8d
522 tax
523 lda room_row_offsets_low,x
524 sta $80
526 ldx $70
527 lda treasure_x,x ; x
528 sta $8e
529 adc $80
530 sta $80
532 lda #$57
533 adc #0
534 sta $81
535 clc
537 lda ($80),y ; tile
538 cmp #0
539 bne add_treasure_loop_next
541 lda #4 ; type (weapon/treasure)
542 sta $528c
543 lda $8d ; y
544 sta $528e
545 lda #1 ; dy
546 sta $528f
547 lda $8e ; x
548 sta $5290
549 lda #0 ; dx
550 sta $5291
552 lda #$8c
553 sta $74
554 lda #$52
555 sta $75
556 jmp plot_character ; optimise away the rts
558 add_treasure_loop_next:
559 dec $8c
560 bmi add_treasure_exit
562 dec $70
563 bpl add_treasure_loop
565 lda #15
566 sta $70
567 jmp add_treasure_loop
569 add_treasure_exit:
570 clc
571 rts
573 create_enemy_positions:
575 lda #31 ; counter
576 sta $7e
578 lda #1 ; x
579 sta $70
581 lda #1 ; y
582 sta $71
584 lda #$a7
585 sta $72
586 lda #$57
587 sta $73
589 ldx #15 ; offset into position areas
590 ldy #0
592 create_enemy_positions_loop:
594 jsr unlimited_values
595 and #7
596 sta $80 ; store temporarily
598 lda $72
599 adc $80
600 sta $72 ; update the offset into the room data
601 clc
603 lda $70
604 adc $80 ; update x
605 cmp #10
606 bpl create_enemy_positions_next_row
608 sta $70 ; store x
609 jmp create_enemy_positions_check_tile
611 create_enemy_positions_next_row:
613 sec
614 sbc #10
615 sta $70 ; store the x position on the next row
616 clc
618 lda $71
619 adc #1 ; update the y position
620 cmp #10
621 bpl create_enemy_positions_to_top
623 sta $71 ; store the y position for the next row
624 jmp create_enemy_positions_check_tile
626 create_enemy_positions_to_top:
628 lda #1 ; reset the x, y and offset values
629 sta $70
630 sta $71
631 lda #$a7
632 sta $72
634 create_enemy_positions_check_tile:
636 lda ($72),y
637 cmp #0
638 bne create_enemy_positions_next
640 lda $70
641 sta $0ee0,x ; store the x value
643 lda $71
644 sta $0ef0,x ; store the y value
646 dex
647 bmi create_enemy_positions_exit
649 create_enemy_positions_next:
650 clc
651 dec $7e
652 bpl create_enemy_positions_loop
654 ; The position areas were not filled. Write invalid values into the
655 ; first area for the emerge routine to find.
657 lda #0
658 create_enemy_positions_fill_loop:
660 sta $0ee0,x
661 dex
662 bpl create_enemy_positions_fill_loop
664 create_enemy_positions_exit:
665 clc
666 rts
668 plot: ; $70,$71=source address
669 ; $72,$73=destination address
670 ldy #$1f
671 plotloop0:
672 lda ($70),y
673 sta ($72),y
674 dey
675 bpl plotloop0
677 lda $72
678 adc #$20
679 sta $72
680 lda $73
681 adc #$01
682 sta $73 ; next line minus 0x20
683 clc
685 ldy #$3f
686 plotloop1:
687 lda ($70),y
688 sta ($72),y
689 dey
690 cpy #$20
691 bpl plotloop1
693 lda $72
694 adc #$20
695 sta $72
696 lda $73
697 adc #$01
698 sta $73 ; next line minus 0x20
699 clc
701 ldy #$5f
702 plotloop2:
703 lda ($70),y
704 sta ($72),y
705 dey
706 cpy #$40
707 bpl plotloop2
709 sec
710 lda $72
711 sbc #$20
712 sta $72
713 lda $73
714 sbc #$02
715 sta $73 ; back two lines minus 0x20
716 clc
718 rts
722 plot_blank_xy: ; X=y, Y=x
724 lda screen_rows_low,x
725 sta $72
726 lda screen_rows_high,x
727 sta $73
729 tya
730 tax
731 lda screen_columns_low,x
732 adc $72
733 sta $72
734 lda screen_columns_high,x
735 adc $73
736 sta $73
737 clc
738 ; run on into plot_blank
740 plot_blank: ; $72,$73=destination address
742 ldy #$1f
743 lda #0
744 plot_blank_loop0:
745 sta ($72),y
746 dey
747 bpl plot_blank_loop0
749 lda $72
750 adc #$20
751 sta $72
752 lda $73
753 adc #$01
754 sta $73 ; next line minus 0x20
755 clc
757 ldy #$3f
758 lda #0
759 plot_blank_loop1:
760 sta ($72),y
761 dey
762 cpy #$20
763 bpl plot_blank_loop1
765 lda $72
766 adc #$20
767 sta $72
768 lda $73
769 adc #$01
770 sta $73 ; next line minus 0x20
771 clc
773 ldy #$5f
774 lda #0
775 plot_blank_loop2:
776 sta ($72),y
777 dey
778 cpy #$40
779 bpl plot_blank_loop2
781 sec
782 lda $72
783 sbc #$20
784 sta $72
785 lda $73
786 sbc #$02
787 sta $73 ; back two lines minus 0x20
788 clc
790 rts
792 tile_addresses_low: .byte $00, $60, $c0, $00, $60, $c0, $20
793 tile_addresses_high: .byte $54, $54, $54, $50, $50, $50, $51
795 plot_tile: ; $7b=tile number
796 ; 1 = flowers/decoration
797 ; 2 = trees/wall
798 ; 3 = trees
799 ; 4 = exit
800 ; 5 = open exit
801 ; 6 = final exit (left)
802 ; 7 = final exit (right)
803 ; $72,$73=screen position
805 lda $7b
806 cmp #0
807 bne plot_tile_sprite
808 clc
809 jmp plot_blank ; optimise away the rts
811 plot_tile_sprite:
812 clc
813 tax
814 dex
815 lda tile_addresses_low,x
816 sta $70
817 lda tile_addresses_high,x
818 sta $71
820 lda $7b
821 cmp #4
822 bpl plot_not_blank_after_add_loop ; don't adjust the tile for later levels
824 clc
825 lda $578a
826 and #3 ; change the tile set for later levels
827 tax
829 plot_not_blank_add_loop:
831 cpx #2
832 bne plot_not_blank_not_2
833 dex
834 jmp plot_not_blank_not_0
836 plot_not_blank_not_2:
837 beq plot_not_blank_add_loop
838 cpx #0
840 plot_not_blank_not_0:
841 beq plot_not_blank_after_add_loop
842 clc
843 lda $70
844 adc #$20
845 sta $70
846 lda $71
847 adc #$01
848 sta $71
849 dex
850 jmp plot_not_blank_add_loop
852 plot_not_blank_after_add_loop:
853 clc
854 jsr plot
855 rts
857 plot_room: ; $78,$79 = i,j (from $5782,$5783)
858 jsr blank_screen
860 lda $5782
861 sta $78
862 lda $5783
863 sta $79
865 jsr make_room
866 ; Run on into the next piece of code.
868 plot_room_tiles:
870 lda #$80
871 sta $72
872 lda #$5a
873 sta $73 ; $72,$73 = screen position
875 lda #0
876 sta $7a
877 row_loop:
879 lda #9
880 sta $76
882 column_loop:
883 lda $7a
884 tax
885 lda $579c,x
886 sta $7b
887 jsr plot_tile
889 inc $7a
890 lda $76
891 sec
892 sbc #1
893 sta $76
894 clc
895 cmp #0
896 bpl column_loop
898 clc
900 lda $72
901 adc #$80
902 sta $72
903 lda $73
904 adc #$02
905 sta $73
906 clc
907 cmp #$80
908 beq end_rows
910 jmp row_loop
912 end_rows:
913 rts
915 set_room_palette: ; $78=i; $79=j
917 lda #1
918 sta $70
919 lda $78
920 eor $79
921 and #3
922 tax
923 lda room_palettes,x
924 sta $71
925 jsr set_palette
927 jsr set_core_palette
928 rts
930 room_palettes: .byte 1, 6, 5, 7
932 ; Sprite data stored in memory: 00 04 08 0c 10 14 18 1c 20 24 28 2c
934 plot8x24_y0: ; $70,$71=source address
935 ; $72,$73=destination address
937 ldx #2
939 plot8x24_y0_loop:
941 ldy #15
943 plotloop8x24_y0_0:
944 lda ($70),y
945 eor ($72),y
946 sta ($72),y
947 dey
948 bpl plotloop8x24_y0_0
950 dex
951 bmi plot8x24_y0_exit
953 lda $72
954 adc #$40
955 sta $72
956 lda $73
957 adc #$01
958 sta $73
959 clc
961 lda $70
962 adc #16
963 sta $70
964 lda $71
965 adc #0
966 sta $71
967 clc
969 jmp plot8x24_y0_loop
971 plot8x24_y0_exit:
972 clc
973 jmp plot_buffer_loop_next
976 plot8x8_y1: ; $70,$71=source address
977 ; $72,$73=destination address
978 lda #2
979 sta $7e
980 lda #10
981 sta $7f
983 lda #0 ; plotting 1 8x8 piece
984 sta $8a
986 jmp plot8x24_y123 ; optimise away the rts
988 plot8x24_y1: ; $70,$71=source address
989 ; $72,$73=destination address
990 lda #2
991 sta $7e
992 lda #10
993 sta $7f
995 lda #2 ; plotting 3 8x8 pieces
996 sta $8a
998 jmp plot8x24_y123 ; optimise away the rts
1000 plot8x8_y2: ; $70,$71=source address
1001 ; $72,$73=destination address
1002 lda #4
1003 sta $7e
1004 lda #12
1005 sta $7f
1007 lda #0 ; plotting 1 8x8 piece
1008 sta $8a
1010 jmp plot8x24_y123 ; optimise away the rts
1012 plot8x24_y2: ; $70,$71=source address
1013 ; $72,$73=destination address
1014 lda #4
1015 sta $7e
1016 lda #12
1017 sta $7f
1019 lda #2 ; plotting 3 8x8 pieces
1020 sta $8a
1022 jmp plot8x24_y123 ; optimise away the rts
1024 plot8x8_y3: ; $70,$71=source address
1025 ; $72,$73=destination address
1026 lda #6
1027 sta $7e
1028 lda #14
1029 sta $7f
1031 lda #0 ; plotting 1 8x8 piece
1032 sta $8a
1034 jmp plot8x24_y123 ; optimise away the rts
1036 plot8x24_y3: ; $70,$71=source address
1037 ; $72,$73=destination address
1038 lda #6
1039 sta $7e
1040 lda #14
1041 sta $7f
1043 lda #2 ; plotting 3 8x8 pieces
1044 sta $8a
1046 ; Run on into the next routine.
1048 plot8x24_y123: ; $70,$71=source address
1049 ; $72,$73=destination address
1050 ; $7e=offset into source data for first column
1051 ; $7f=offset into source data for second column
1053 plot8x24_y123_loop:
1055 ldx #0
1056 plot8x24_y123_upper_loop_outer:
1058 ldy $7e,x
1059 lda plot_upper_offsets,x
1060 sta $89
1062 plot8x24_y123_upper_loop_inner: ; plot the first column until
1063 dey ; we reach the start
1064 cpy $89
1065 bmi plot8x24_y123_upper_loop_inner_endloop
1066 lda ($70),y
1067 eor ($72),y
1068 sta ($72),y
1069 jmp plot8x24_y123_upper_loop_inner
1071 plot8x24_y123_upper_loop_inner_endloop:
1072 clc
1074 inx
1075 cpx #2
1076 bne plot8x24_y123_upper_loop_outer
1078 clc
1079 lda $72 ; move the destination pointer to refer to the next line
1080 adc #$38
1081 sta $72
1082 lda $73
1083 adc #$01
1084 sta $73
1085 clc
1087 ldx #0
1088 plot8x24_y123_lower_loop_outer:
1090 lda plot_lower_offsets,x
1091 tay
1092 lda $7e,x
1093 sta $89
1095 plot8x24_y123_lower_loop_inner: ; plot until we reach the initial
1096 lda ($70),y ; offset for the column
1097 eor ($72),y
1098 sta ($72),y
1099 dey
1100 cpy $89
1101 bpl plot8x24_y123_lower_loop_inner
1103 inx
1104 cpx #2
1105 bne plot8x24_y123_lower_loop_outer
1107 dec $8a
1108 bmi plot8x24_y123_exit
1110 clc
1111 lda $70 ; update the source pointer to refer to the next piece
1112 adc #16 ; of sprite data
1113 sta $70
1114 lda $71
1115 adc #0
1116 sta $71
1117 clc
1119 lda $72 ; update the destination pointer to point to the next
1120 adc #8 ; space
1121 sta $72
1122 lda $73
1123 adc #0
1124 sta $73
1125 clc
1127 jmp plot8x24_y123_loop
1129 plot8x24_y123_exit:
1130 clc
1131 jmp plot_buffer_loop_next
1133 plot16x16_y0: ; $70,$71=source address
1134 ; $72,$73=destination address
1135 ldy #31
1137 plotloop16x16_y0_0:
1138 lda ($70),y
1139 eor ($72),y
1140 sta ($72),y
1141 dey
1142 bpl plotloop16x16_y0_0
1143 clc
1145 lda $72
1146 adc #$20
1147 sta $72
1148 lda $73
1149 adc #$01
1150 sta $73 ; 0x140 - 32
1151 clc
1153 ldy #63
1155 plotloop16x16_y0_1:
1156 lda ($70),y
1157 eor ($72),y
1158 sta ($72),y
1159 dey
1160 cpy #32
1161 bpl plotloop16x16_y0_1
1162 clc
1164 jmp plot_buffer_loop_next
1166 ; Sprite data stored in memory: 00 04 08 0c 10 14 18 1c 20 24 28 2c 30 34 38 3c
1168 plot16x16_y1: ; $70,$71=source address
1169 ; $72,$73=destination address
1171 lda #2
1172 sta $7e
1173 lda #10
1174 sta $7f
1175 lda #18
1176 sta $80
1177 lda #26
1178 sta $81
1179 jmp plot16x16_y123 ; optimise away the rts
1181 plot16x16_y2: ; $70,$71=source address
1182 ; $72,$73=destination address
1184 lda #4
1185 sta $7e
1186 lda #12
1187 sta $7f
1188 lda #20
1189 sta $80
1190 lda #28
1191 sta $81
1192 jmp plot16x16_y123 ; optimise away the rts
1194 plot16x16_y3: ; $70,$71=source address
1195 ; $72,$73=destination address
1197 lda #6
1198 sta $7e
1199 lda #14
1200 sta $7f
1201 lda #22
1202 sta $80
1203 lda #30
1204 sta $81
1205 ; Run on into the next routine.
1207 plot16x16_y123: ; $70,$71=source address
1208 ; $72,$73=destination address
1209 ; $7e=offset into source data for first column
1210 ; $7f=offset into source data for second column
1211 ; $80=offset into source data for third column
1212 ; $81=offset into source data for fourth column
1214 lda #1
1215 sta $8a
1217 plot16x16_y123_loop:
1219 ldx #0
1220 plot16x16_y123_upper_loop_outer:
1222 ldy $7e,x
1223 lda plot_upper_offsets,x
1224 sta $89
1226 plot16x16_y123_upper_loop_inner:
1228 dey
1229 cpy $89
1230 bmi plot16x16_y123_upper_loop_inner_endloop
1231 lda ($70),y
1232 eor ($72),y
1233 sta ($72),y
1234 jmp plot16x16_y123_upper_loop_inner
1236 plot16x16_y123_upper_loop_inner_endloop:
1237 clc
1239 inx
1240 cpx #4
1241 bne plot16x16_y123_upper_loop_outer
1243 clc
1244 lda $72 ; move the destination pointer to refer to the next line
1245 adc #$38
1246 sta $72
1247 lda $73
1248 adc #$01
1249 sta $73
1250 clc
1252 ldx #0
1253 plot16x16_y123_lower_loop_outer:
1255 lda plot_lower_offsets,x
1256 tay
1257 lda $7e,x
1258 sta $89
1260 plot16x16_y123_lower_loop_inner: ; plot until we reach the initial offset
1261 lda ($70),y ; for the column
1262 eor ($72),y
1263 sta ($72),y
1264 dey
1265 cpy $89
1266 bpl plot16x16_y123_lower_loop_inner
1268 inx
1269 cpx #4
1270 bne plot16x16_y123_lower_loop_outer
1272 dec $8a
1273 bmi plot16x16_y123_exit
1275 clc
1276 lda $70 ; update the source pointer to refer to the next piece
1277 adc #32 ; of sprite data
1278 sta $70
1279 lda $71
1280 adc #0
1281 sta $71
1282 clc
1284 lda $72 ; update the destination pointer to point to the next
1285 adc #8 ; space
1286 sta $72
1287 lda $73
1288 adc #0
1289 sta $73
1290 clc
1292 jmp plot16x16_y123_loop
1294 plot16x16_y123_exit:
1295 clc
1296 jmp plot_buffer_loop_next
1298 plot_upper_offsets: .byte 0, 8, 16, 24
1299 plot_lower_offsets: .byte 7, 15, 23, 31
1301 plot8x8_y0: ; $70,$71=source address
1302 ; $72,$73=destination address
1303 ldy #15
1305 plotloop8x8_y0_0:
1306 lda ($70),y
1307 eor ($72),y
1308 sta ($72),y
1309 dey
1310 bpl plotloop8x8_y0_0
1311 clc
1313 jmp plot_buffer_loop_next
1316 check_key: ; x=key code
1317 lda #129 ; returns y=255 or 0
1318 ldy #255
1319 jsr $fff4
1320 rts
1322 player_direction_chars_low: .byte $00,$30,$60,$90,$c0,$f0,$20,$50, $80,$b0,$e0,$10
1323 player_direction_chars_high: .byte $3f,$3f,$3f,$3f,$3f,$3f,$40,$40, $40,$40,$40,$41
1325 screen_rows_low: .byte $80,$40,$00,$c0,$80,$40,$00,$c0,$80,$40
1326 screen_rows_high: .byte $5a,$5e,$62,$65,$69,$6d,$71,$74,$78,$7c
1327 screen_subrows_low: .byte $00,$06,$44,$82
1328 screen_subrows_high: .byte $00,$00,$01,$02
1330 screen_columns_low: .byte $00,$20,$40,$60,$80,$a0,$c0,$e0,$00,$20
1331 screen_columns_high: .byte $00,$00,$00,$00,$00,$00,$00,$00,$01,$01
1332 screen_subcolumns_low: .byte $00,$08,$10,$18
1334 enemy_direction_chars_low: .byte $c0,$00,$40,$80,$c0,$00,$40,$80
1335 enemy_direction_chars_high: .byte $41,$42,$42,$42,$42,$43,$43,$43
1337 emerge_explode_chars_low: .byte $c0,$00,$40,$80,$c0,$00,$40,$80
1338 emerge_explode_chars_high: .byte $4b,$4c,$4c,$4c,$4c,$4d,$4d,$4d
1340 item_chars_low: .byte $c0,$00,$40,$80,$c0,$00,$40,$80,$c0
1341 item_chars_high: .byte $4d,$4e,$4e,$4e,$4e,$4f,$4f,$4f,$4f
1343 projectile_chars_low: .byte $40,$50,$60,$70,$80,$90,$a0,$b0
1345 unplot_character: ; $74,$75=character address
1347 lda $82 ; store the unplot buffer address in $78,$79
1348 sta $78
1349 lda $83
1350 sta $79
1351 jsr plot_character_sprite
1352 lda $78
1353 sta $82 ; update the latest space in the unplot buffer
1354 rts
1356 plot_character: ; $74,$75=character address
1358 lda $84 ; store the plot buffer address in $78,$79
1359 sta $78
1360 lda $85
1361 sta $79
1362 jsr plot_character_sprite
1363 lda $78
1364 sta $84 ; update the latest space in the plot buffer
1365 rts
1367 plot_character_sprite: ; $74,$75=character address
1368 ; $78,$79=unplot/plot buffer address
1370 ldy #0
1371 lda ($74),y
1372 cmp #0
1373 bne plot_characters_read_character
1374 jmp plot_characters_next
1376 plot_characters_read_character:
1377 clc
1379 sta $77 ; temporarily store the object type
1381 ; Use lookup tables to load the offsets into the sprite.
1383 ; Direction
1384 iny
1385 lda ($74),y
1386 sta $80 ; temporarily store the direction
1388 ; y
1389 iny
1390 lda ($74),y
1391 tax
1392 lda screen_rows_low,x
1393 sta $72
1394 lda screen_rows_high,x
1395 sta $73
1396 clc
1398 ; dy
1399 iny
1400 lda ($74),y
1401 sta $76
1402 tax
1403 lda screen_subrows_low,x
1404 adc $72
1405 sta $72
1406 lda screen_subrows_high,x
1407 adc $73
1408 sta $73
1409 clc
1411 ; x
1412 iny
1413 lda ($74),y
1414 tax
1415 lda screen_columns_low,x
1416 adc $72
1417 sta $72
1418 lda screen_columns_high,x
1419 adc $73
1420 sta $73
1421 clc
1423 ; dx
1424 iny
1425 lda ($74),y
1426 tax
1427 lda screen_subcolumns_low,x
1428 adc $72
1429 sta $72
1430 clc
1432 lda $77
1433 cmp #1
1434 bne plot_characters_loop_not_player
1436 ; Plot 8x24 sprites (player)
1438 ldx $80
1439 lda player_direction_chars_low,x
1440 sta $70
1441 lda player_direction_chars_high,x
1442 sta $71
1444 ; Use the dy value to determine which plotting routine to use.
1446 ldy #0
1447 ldx $76
1448 lda plot_routine_indices_8x24,x
1450 sta ($78),y
1451 jmp plot_characters_stored
1454 plot_characters_loop_not_player:
1455 cmp #2
1456 bne plot_characters_loop_not_projectile
1458 ; Plot 8x8 sprites (projectiles)
1460 lda $80
1461 and #7
1462 tax
1463 lda projectile_chars_low,x
1464 sta $70
1465 lda #$41
1466 sta $71
1468 ; Use the dy value to determine which plotting routine to use.
1470 ldy #0
1471 ldx $76
1472 lda plot_routine_indices_8x8,x
1474 sta ($78),y
1475 jmp plot_characters_stored
1478 plot_characters_loop_not_projectile:
1479 cmp #3
1480 bne plot_characters_loop_not_explosion
1482 ; Plot 16x16 sprites (emerging, explosions)
1484 ; Select the sprites to use.
1486 lda $80
1487 and #7 ; only keep the bits required to find the correct sprite
1488 clc
1489 tax
1490 lda emerge_explode_chars_low,x
1491 sta $70
1492 lda emerge_explode_chars_high,x
1493 sta $71
1495 jmp plot_characters_16x16
1497 plot_characters_loop_not_explosion:
1498 cmp #4
1499 bne plot_characters_loop_not_item
1501 ; Plot 16x16 sprites (items)
1503 ; Select the sprites to use.
1505 lda $80
1506 and #$0f ; only keep the bits required to find the correct sprite
1507 clc
1508 tax
1509 lda item_chars_low,x
1510 sta $70
1511 lda item_chars_high,x
1512 sta $71
1514 jmp plot_characters_16x16
1516 plot_characters_loop_not_item:
1517 cmp #8
1518 bmi plot_characters_loop_not_enemy
1520 ; Plot 16x16 sprites (enemies)
1522 ; Select the set of sprites to use.
1524 and #$70
1525 lsr
1526 lsr
1527 lsr ; bits 4,5,6 >> 3 -> bits 1,2,3
1528 clc
1529 sta $71 ; 0x00, 0x02, 0x04, 0x06, 0x08
1531 lda $80
1532 and #7 ; keep the animation bits
1533 tax
1534 lda enemy_direction_chars_low,x
1535 sta $70
1536 lda enemy_direction_chars_high,x
1537 adc $71
1538 sta $71
1540 plot_characters_16x16:
1542 ; Use the dy value to determine which plotting routine to use.
1544 ldy #0
1545 ldx $76
1546 lda plot_routine_indices_16x16,x
1548 sta ($78),y
1550 plot_characters_stored:
1552 iny
1553 lda $70
1554 sta ($78),y
1555 iny
1556 lda $71
1557 sta ($78),y
1558 iny
1559 lda $72
1560 sta ($78),y
1561 iny
1562 lda $73
1563 sta ($78),y
1565 clc
1566 lda $78
1567 adc #12
1568 sta $78
1570 plot_characters_loop_not_enemy:
1572 plot_characters_next:
1574 lda #255 ; terminate this stream of entries in the plot buffer
1575 ldy #0
1576 sta ($78),y
1577 clc
1578 rts
1580 plot_routine_indices_8x24: .byte 1, 2, 3, 4
1581 plot_routine_indices_8x8: .byte 5, 6, 7, 8
1582 plot_routine_indices_16x16: .byte 9, 10, 11, 12
1584 reset_plot_buffer:
1585 lda #$06 ; reset the index into the plot buffer
1586 sta $84
1587 lda #$53
1588 sta $85
1590 lda #255 ; terminate the plot list
1591 ldy #0
1592 sta ($84),y
1593 rts
1595 reset_unplot_buffer:
1596 lda #$00 ; reset the index into the plot buffer
1597 sta $82
1598 lda #$53
1599 sta $83
1601 lda #255 ; terminate the unplot list
1602 ldy #0
1603 sta ($82),y
1604 rts
1606 plot_buffer_types_low: .byte <plot_buffer_loop_next
1607 plot_buffer_types_low1: .byte <plot8x24_y0, <plot8x24_y1, <plot8x24_y2, <plot8x24_y3
1608 plot_buffer_types_low2: .byte <plot8x8_y0, <plot8x8_y1, <plot8x8_y2, <plot8x8_y3
1609 plot_buffer_types_low3: .byte <plot16x16_y0, <plot16x16_y1, <plot16x16_y2, <plot16x16_y3
1611 plot_buffer_types_high: .byte >plot_buffer_loop_next
1612 plot_buffer_types_high1: .byte >plot8x24_y0, >plot8x24_y1, >plot8x24_y2, >plot8x24_y3
1613 plot_buffer_types_high2: .byte >plot8x8_y0, >plot8x8_y1, >plot8x8_y2, >plot8x8_y3
1614 plot_buffer_types_high3: .byte >plot16x16_y0, >plot16x16_y1, >plot16x16_y2, >plot16x16_y3
1616 plot_buffer:
1618 lda #$00
1619 sta $84
1620 lda #$53
1621 sta $85
1623 lda #6
1624 sta $88
1626 plot_buffer_loop:
1628 ldy #0
1629 lda ($84),y
1630 cmp #255
1631 beq plot_buffer_loop_skip
1633 clc
1634 tax
1635 lda plot_buffer_types_low,x
1636 sta $86
1637 lda plot_buffer_types_high,x
1638 sta $87
1640 iny
1641 lda ($84),y
1642 sta $70
1644 iny
1645 lda ($84),y
1646 sta $71
1648 iny
1649 lda ($84),y
1650 sta $72
1652 iny
1653 lda ($84),y
1654 sta $73
1656 jmp ($86) ; returns to plot_buffer_loop_next
1658 plot_buffer_loop_skip:
1660 lda $88
1661 cmp #12
1662 beq plot_buffer_exit ; both unplot and plot lists have terminated
1664 lda #12
1665 sta $88
1666 lda $84
1667 adc #6
1668 sta $84
1669 jmp plot_buffer_loop
1671 plot_buffer_loop_next:
1672 clc
1674 lda $84
1675 adc $88
1676 sta $84
1677 jmp plot_buffer_loop
1679 plot_buffer_exit:
1680 clc
1681 rts
1683 room_row_offsets_low: .byte $9c,$a6,$b0,$ba,$c4,$ce,$d8,$e2,$ec,$f6
1685 animate_player_left:
1687 ; Set the direction and toggle the animation bit.
1689 lda $5281
1690 and #1
1691 eor #1 ; toggle animation flag
1692 sta $5281 ; left (directional bits are 0)
1694 jsr plot_character
1695 rts
1697 animate_player_right:
1699 ; Set the direction and toggle the animation bit.
1701 lda $5281
1702 and #1 ; remove direction information (result is 0)
1703 eor #1 ; toggle animation flag
1704 ora #2 ; right
1705 sta $5281
1707 jsr plot_character
1708 rts
1710 animate_player_up:
1712 ; Set the direction and toggle the animation bit.
1714 lda $5281
1715 and #1 ; remove direction information (result is 0)
1716 eor #1 ; toggle animation flag
1717 ora #4 ; up
1718 sta $5281
1720 jsr plot_character
1721 rts
1723 animate_player_down:
1725 ; Set the direction and toggle the animation bit.
1727 lda $5281
1728 and #1 ; remove direction information (result is 0)
1729 eor #1 ; toggle animation flag
1730 ora #6 ; down
1731 sta $5281
1733 jsr plot_character
1734 rts
1736 move_player:
1738 lda $578e
1739 and #1
1740 beq move_player_allowed
1742 clc
1743 rts
1745 move_player_allowed:
1747 lda #$80 ; set up the address of the player character
1748 sta $74
1749 lda #$52
1750 sta $75
1752 ; Handle joystick
1754 lda $577e
1755 cmp #0
1756 beq move_player_handle_left_key
1758 lda #128
1759 ldx #1
1760 jsr $fff4
1761 cpy #0
1762 beq move_player_handle_joystick_up_down
1763 cpy #128
1764 bpl move_player_left
1765 jmp move_player_right
1767 move_player_handle_joystick_up_down:
1769 lda #128
1770 ldx #2
1771 jsr $fff4
1772 cpy #0
1773 beq move_player_handle_left_key
1774 cpy #128
1775 bpl move_player_not_up
1776 jmp move_player_up
1778 move_player_not_up:
1779 jmp move_player_down
1781 move_player_handle_left_key:
1783 ; Handle the left key.
1785 ldx #158 ; (Z)
1786 jsr check_key
1787 cpy #255
1788 bne move_player_not_left_key
1790 move_player_left:
1792 lda $5285 ; read dx
1793 cmp #0
1794 beq move_player_left_check_x
1796 jsr unplot_character ; unplot the player character
1797 dec $5285
1798 clc
1799 jmp animate_player_left ; optimise away the rts
1801 move_player_left_check_x: ; Check the x offset.
1803 lda $5284
1804 cmp #0
1805 beq move_player_leave_room_left
1807 clc
1808 tay
1809 dey ; x - 1
1810 lda $5282 ; load the y offset
1811 tax ; as an index
1812 lda room_row_offsets_low,x ; read the address of the row
1813 sta $70
1814 lda #$57
1815 sta $71
1816 lda ($70),y ; load the tile to the left
1818 cmp #5 ; check for the open exit or final exit
1819 bmi move_player_not_left_exit1
1820 jmp try_to_exit_level ; optimise away the rts
1822 move_player_not_left_exit1:
1823 cmp #0
1824 bne move_player_not_left_key
1826 lda $5283 ; dy
1827 cmp #0
1828 beq move_player_allow_left
1830 clc
1831 lda $70 ; dy > 0 so we need to check another tile
1832 adc #10
1833 sta $70
1834 lda ($70),y ; load the tile below and to the left
1836 cmp #5 ; check for the open exit or final exit
1837 bmi move_player_not_left_exit2
1838 jmp try_to_exit_level ; optimise away the rts
1840 move_player_not_left_exit2:
1841 cmp #0
1842 bne move_player_not_left_key
1844 move_player_allow_left:
1845 tya
1846 sta $81 ; temporary
1847 jsr unplot_character ; unplot the player character
1848 lda $81
1849 sta $5284 ; store the new room x offset
1850 lda #3
1851 sta $5285 ; dx = 3
1852 clc
1853 jmp animate_player_left ; optimise away the rts
1855 move_player_leave_room_left:
1856 sec
1857 lda $5783
1858 sbc #1
1859 sta $5783
1860 clc
1862 ; Set the player's position on the right of the screen.
1864 ; No need to unplot.
1866 lda #9 ; x = 9
1867 sta $5284
1868 lda #2 ; dx = 2
1869 sta $5285
1871 jsr animate_player_left
1872 sec ; indicate to the calling routine that the player
1873 rts ; has left the room
1875 move_player_not_left_key:
1877 ; Handle the right key.
1879 ldx #189 ; (X)
1880 jsr check_key
1881 cpy #255
1882 beq move_player_right
1883 jmp move_player_not_right_key
1885 move_player_right:
1887 lda $5285 ; read dx
1888 cmp #2
1889 beq move_player_right_check_x
1890 cmp #3
1891 beq move_player_right_tile
1893 jsr unplot_character ; unplot the player character
1894 inc $5285
1895 clc
1896 jmp animate_player_right ; optimise away the rts
1898 move_player_right_check_x: ; Check the x offset.
1900 lda $5284
1901 cmp #9
1902 beq move_player_leave_room_right
1904 clc
1905 tay
1906 iny ; x + 1
1907 lda $5282 ; load the y offset
1908 tax ; as an index
1909 lda room_row_offsets_low,x ; read the address of the row
1910 sta $70
1911 lda #$57
1912 sta $71
1913 lda ($70),y ; load the tile to the right
1915 cmp #5 ; check for the open exit or final exit
1916 bmi move_player_not_right_exit1
1917 jmp try_to_exit_level ; optimise away the rts
1919 move_player_not_right_exit1:
1920 cmp #0
1921 bne move_player_not_right_key
1923 lda $5283 ; dy
1924 cmp #0
1925 beq move_player_allow_right
1927 clc ; dy > 0 so we need to check another tile
1928 lda $70
1929 adc #10
1930 sta $70
1931 lda ($70),y ; load the tile below and to the right
1933 cmp #5 ; check for the open exit or final exit
1934 bmi move_player_not_right_exit2
1935 jmp try_to_exit_level ; optimise away the rts
1937 move_player_not_right_exit2:
1938 cmp #0
1939 bne move_player_not_right_key
1941 move_player_allow_right:
1943 jsr unplot_character ; unplot the player character
1944 inc $5285 ; update dx
1945 clc
1946 jmp animate_player_right ; optimise away the rts
1948 move_player_right_tile:
1950 jsr unplot_character ; unplot the player character
1951 inc $5284 ; store the new room x offset
1952 lda #0
1953 sta $5285 ; dx = 0
1954 clc
1955 jmp animate_player_right ; optimise away the rts
1957 move_player_leave_room_right:
1958 clc
1959 inc $5783
1960 clc
1962 ; Set the player's position on the left of the screen.
1964 ; No need to unplot.
1966 lda #0 ; x = 0
1967 sta $5284
1968 lda #0 ; dx = 0
1969 sta $5285
1971 jsr animate_player_right
1972 sec ; indicate to the calling routine that the
1973 rts ; player has left the room
1975 move_player_not_right_key:
1977 ; Handle the up key.
1979 ldx #183 ; (:)
1980 jsr check_key
1981 cpy #255
1982 bne move_player_not_up_key
1984 move_player_up:
1986 lda $5283 ; read dy
1987 cmp #0
1988 beq move_player_up_check_y
1990 jsr unplot_character ; unplot the player character
1991 dec $5283
1992 clc
1993 jmp animate_player_up ; optimise away the rts
1995 move_player_up_check_y: ; Check the y offset.
1997 lda $5282
1998 cmp #0
1999 beq move_player_leave_room_up
2001 tax ; use the y offset as an index
2002 dex ; y - 1
2003 ldy $5284 ; load the x offset
2004 lda room_row_offsets_low,x ; read the address of the row
2005 sta $70
2006 lda #$57
2007 sta $71
2008 lda ($70),y ; load the tile above
2010 cmp #5 ; check for the open exit or final exit
2011 bmi move_player_not_up_exit1
2012 jmp try_to_exit_level ; optimise away the rts
2014 move_player_not_up_exit1:
2015 cmp #0
2016 bne move_player_not_up_key
2018 lda $5285 ; dx
2019 cmp #3
2020 bmi move_player_allow_up
2022 clc ; dx > 2 so we need to check another tile
2023 iny
2024 lda ($70),y ; load the tile above and to the right
2026 cmp #5 ; check for the open exit or final exit
2027 bmi move_player_not_up_exit2
2028 jmp try_to_exit_level ; optimise away the rts
2030 move_player_not_up_exit2:
2031 cmp #0
2032 bne move_player_not_up_key
2034 move_player_allow_up:
2035 txa
2036 sta $81 ; temporary
2037 jsr unplot_character ; unplot the player character
2038 lda $81
2039 sta $5282 ; store the new room y offset
2040 lda #3
2041 sta $5283 ; dy = 3
2042 clc
2043 jmp animate_player_up ; optimise away the rts
2045 move_player_leave_room_up:
2046 sec
2047 lda $5782
2048 sbc #1
2049 sta $5782
2050 clc
2052 ; Set the player's position on the bottom of the screen.
2054 ; No need to unplot.
2056 lda #9 ; y = 9
2057 sta $5282
2058 lda #0 ; dy = 0
2059 sta $5283
2061 jsr animate_player_up
2062 sec ; indicate to the calling routine that the player
2063 rts ; has left the room
2065 move_player_not_up_key:
2067 ; Handle the down key.
2069 ldx #151 ; (/)
2070 jsr check_key
2071 cpy #255
2072 beq move_player_down
2073 jmp move_player_not_down_key
2075 move_player_down:
2077 lda $5283 ; read dy
2078 cmp #0
2079 beq move_player_down_check_y
2080 cmp #3
2081 beq move_player_down_tile
2083 jsr unplot_character ; unplot the player character
2084 inc $5283 ; 0 <= dy < 3
2085 clc
2086 jmp animate_player_down ; optimise away the rts
2088 move_player_down_check_y: ; Check the y offset.
2090 lda $5282
2091 cmp #9
2092 beq move_player_leave_room_down
2094 clc
2095 tax
2096 inx ; y + 1
2097 ldy $5284 ; load the x offset
2098 lda room_row_offsets_low,x ; read the address of the row
2099 sta $70
2100 lda #$57
2101 sta $71
2102 lda ($70),y ; load the tile below
2104 cmp #5 ; check for the open exit or final exit
2105 bmi move_player_not_down_exit1
2106 jmp try_to_exit_level ; optimise away the rts
2108 move_player_not_down_exit1:
2109 cmp #0
2110 bne move_player_not_down_key
2112 lda $5285 ; dx
2113 cmp #3
2114 bmi move_player_allow_down
2116 clc ; dx > 2 so we need to check another tile
2117 iny
2118 lda ($70),y ; load the tile below and to the right
2120 cmp #5 ; check for the open exit or final exit
2121 bmi move_player_not_down_exit2
2122 jmp try_to_exit_level ; optimise away the rts
2124 move_player_not_down_exit2:
2125 cmp #0
2126 bne move_player_not_down_key
2128 move_player_allow_down:
2130 jsr unplot_character ; unplot the player character
2131 inc $5283 ; update dy
2132 clc
2133 jmp animate_player_down ; optimise away the rts
2135 move_player_down_tile:
2137 jsr unplot_character ; unplot the player character
2138 inc $5282 ; store the new room y offset
2139 lda #0
2140 sta $5283 ; dy = 0
2141 clc
2142 jmp animate_player_down ; optimise away the rts
2144 move_player_leave_room_down:
2145 inc $5782
2146 clc
2148 ; Set the player's position on the top of the screen.
2150 ; No need to unplot.
2152 lda #0 ; y = 0
2153 sta $5282
2154 lda #0 ; dy = 0
2155 sta $5283
2157 jsr animate_player_down
2158 sec ; indicate to the calling routine that the
2159 rts ; player has left the room
2161 move_player_not_down_key:
2162 clc
2163 rts
2165 try_to_exit_level:
2167 cmp #6
2168 bmi just_exit_level
2170 lda $5780 ; set the complete game flag
2171 ora #$02
2172 jmp try_to_exit_level_exit
2174 just_exit_level:
2175 lda $5780 ; set the exit level flag
2176 ora #$80
2178 try_to_exit_level_exit:
2179 sta $5780
2181 lda #$80
2182 sta $74
2183 lda #$52
2184 sta $75
2185 jsr unplot_character ; remove the player sprite
2186 jmp destroy_enemies ; optimise away the rts
2188 check_fire_key:
2190 lda $578d
2191 bne check_fire_key_exit
2193 lda $577e
2194 beq check_fire_key_no_joystick
2196 lda #128
2197 ldx #0
2198 jsr $fff4
2199 cpx #0
2200 beq check_fire_key_fire
2202 check_fire_key_no_joystick:
2204 ldx #182 ; (Return)
2205 jsr check_key
2206 cpy #255
2207 bne check_fire_key_exit
2209 check_fire_key_fire:
2211 lda $5286
2212 cmp #0
2213 bne check_fire_key_exit
2215 lda #16
2216 sta $578d
2218 jmp create_projectile ; optimise away the rts
2220 check_fire_key_exit:
2221 clc
2222 rts
2224 create_projectile:
2226 lda #2
2227 sta $5286
2229 lda $5281
2230 and #$06 ; copy the direction information
2231 asl
2232 asl
2233 asl
2234 ora $5789 ; apply the projectile type
2235 sta $5287
2237 lda $5283 ; player dy
2238 adc $577f ; add the weapon counter
2239 adc #1
2240 cmp #4 ; if dy > 3, create the projectile on the tile below
2241 bpl create_projectile_below
2243 clc
2244 sta $5289 ; dy + weapon counter + 1
2245 lda $5282 ; y
2246 sta $5288
2247 jmp create_projectile_continue
2249 create_projectile_below:
2250 sec
2251 sbc #4
2252 sta $5289 ; dy + weapon counter + 1 - 4
2253 clc
2254 lda $5282 ; y
2255 adc #1
2256 sta $5288
2258 create_projectile_continue:
2259 lda $5284 ; x
2260 sta $528a
2262 lda $5285 ; dx
2263 sta $528b
2265 lda $577f ; toggle the weapon counter
2266 eor #1
2267 sta $577f
2269 ; Move the projectile away from the player.
2271 jsr move_projectile_after_unplot
2272 jsr move_projectile
2274 clc
2275 rts
2277 emerge_type: ; returns A=type
2278 jsr unlimited_values
2279 lda $7d
2280 and #7
2281 cmp #4
2282 bmi emerge_type_ok
2284 sec
2285 sbc #4
2286 clc
2288 emerge_type_ok:
2289 cmp $5781 ; only allow the appropriate enemies for this level
2290 bmi emerge_type_exit
2292 sec
2293 sbc $5781
2294 clc
2296 emerge_type_exit:
2297 asl
2298 asl
2299 asl
2300 asl
2301 clc
2302 rts
2304 emerge_character: ; $74,$75=character address
2306 lda #63
2307 sta $578f
2309 jsr unlimited_values
2310 and #$0f
2311 tax
2312 lda $0ee0,x
2313 cmp #0 ; check for an invalid value and exit if found
2314 beq emerge_character_exit
2316 sta $80 ; temporary
2317 lda $0ef0,x
2318 tax
2320 ; Add an emerging enemy.
2322 ldy #0
2323 lda #3 ; emerge/explosion
2324 sta ($74),y
2326 jsr emerge_type ; obtain an enemy type
2327 iny
2328 sta ($74),y
2330 txa
2331 iny
2332 sta ($74),y ; store the y position
2333 lda #1
2334 iny
2335 sta ($74),y ; store the dy offset
2337 lda $80
2338 iny
2339 sta ($74),y ; store the x position
2340 lda #0
2341 iny
2342 sta ($74),y ; store the dx offset
2344 jsr plot_character
2346 ldx #5
2347 jsr play_sound
2349 emerge_character_exit:
2350 clc
2351 rts
2353 emerge_explode: ; $74,$75=character address
2355 jsr unplot_character
2357 ldy #1
2358 lda ($74),y ; direction/animation
2359 tax
2360 adc #1 ; update the counter
2361 and #3 ; mask off everything else
2362 sta $80 ; store the masked counter value
2363 bne move_characters_explosion_not_finished
2365 txa
2366 and #4
2367 bne move_characters_remove_character
2369 ; For emerges, convert into an enemy.
2370 txa
2371 and #$70 ; only keep bits 4,5,6
2372 ora #8 ; make this an enemy
2374 ldy #0
2375 sta ($74),y ; update the type (>= 8)
2376 iny
2377 lda $7d ; prepare the direction and animation offset
2378 and #$0c
2379 sta ($74),y
2381 jsr plot_character
2382 jmp emerge_explode_exit
2384 move_characters_remove_character:
2386 ; For finished explosions, just write 0 into the character array.
2387 lda #0
2388 ldy #0
2389 sta ($74),y
2390 jmp emerge_explode_exit
2392 move_characters_explosion_not_finished:
2393 txa
2394 and #$fc
2395 ora $80
2397 ldy #1
2398 sta ($74),y
2400 jsr plot_character
2402 emerge_explode_exit:
2403 clc
2404 rts
2406 animate_enemy_left: ; $74,$75=character address
2408 ; Set the direction and toggle the animation bit.
2410 ldy #1
2411 lda ($74),y
2412 and #$fb ; keep vertical direction bit and animation bits
2413 sta ($74),y ; left (horizontal directional bit is 0)
2415 rts
2417 move_enemy_left: ; $74,$75=character address
2419 ldy #5
2420 lda ($74),y ; read dx
2421 cmp #0
2422 beq move_enemy_left_check_x
2424 sec
2425 sbc #1
2426 ldy #5
2427 sta ($74),y ; dx
2428 clc
2429 jmp animate_enemy_left ; optimise away the rts
2431 move_enemy_left_check_x:
2433 ; Check the x offset.
2435 ldy #4
2436 lda ($74),y ; x
2437 cmp #0
2438 beq move_enemy_left_exit
2440 sec
2441 sbc #1 ; x - 1
2442 sta $81 ; temporary
2443 ldy #2
2444 lda ($74),y ; load the y offset
2445 tax ; as an index
2446 lda room_row_offsets_low,x ; read the address of the row
2447 sta $70
2448 lda #$57
2449 sta $71
2450 ldy $81 ; temporary (x - 1)
2451 lda ($70),y ; load the tile to the left
2453 cmp #0
2454 bne move_enemy_left_exit
2456 ldy #3
2457 lda ($74),y ; dy
2458 cmp #2
2459 bmi move_enemy_allow_left
2461 clc
2462 lda $70 ; dy > 1 so we need to check another tile
2463 adc #10
2464 sta $70
2465 ldy $81 ; temporary (x - 1)
2466 lda ($70),y ; load the tile below and to the left
2468 cmp #0
2469 bne move_enemy_left_exit
2471 move_enemy_allow_left:
2472 lda $81
2473 ldy #4
2474 sta ($74),y ; store the new room x offset
2475 lda #3
2476 ldy #5
2477 sta ($74),y ; dx = 3
2478 clc
2479 jmp animate_enemy_left ; optimise away the rts
2481 move_enemy_left_exit:
2482 sec
2483 rts
2485 animate_enemy_right: ; $74,$75=character address
2487 ; Set the direction and toggle the animation bit.
2489 ldy #1
2490 lda ($74),y
2491 ora #$04 ; right (keep vertical direction bit and animation bits)
2492 sta ($74),y
2494 rts
2496 move_enemy_right: ; $74,$75=character_address
2498 ldy #5
2499 lda ($74),y ; read dx
2500 cmp #0
2501 beq move_enemy_right_check_x
2502 cmp #3
2503 beq move_enemy_right_tile
2505 clc
2506 adc #1
2507 ldy #5
2508 sta ($74),y
2509 jmp animate_enemy_right ; optimise away the rts
2511 move_enemy_right_check_x: ; Check the x offset.
2513 ldy #4
2514 lda ($74),y ; x
2515 cmp #9
2516 beq move_enemy_right_exit
2518 clc
2519 adc #1 ; x + 1
2520 sta $81 ; temporary (x + 1)
2521 ldy #2
2522 lda ($74),y ; load the y offset
2523 tax ; as an index
2524 lda room_row_offsets_low,x ; read the address of the row
2525 sta $70
2526 lda #$57
2527 sta $71
2528 ldy $81 ; temporary (x + 1)
2529 lda ($70),y ; load the tile to the right
2531 cmp #0
2532 bne move_enemy_right_exit
2534 ldy #3
2535 lda ($74),y ; dy
2536 cmp #2
2537 bmi move_enemy_allow_right
2539 clc ; dy > 1 so we need to check another tile
2540 lda $70
2541 adc #10
2542 sta $70
2543 ldy $81 ; temporary (x + 1)
2544 lda ($70),y ; load the tile below and to the right
2546 cmp #0
2547 bne move_enemy_right_exit
2549 move_enemy_allow_right:
2550 clc
2552 ldy #5
2553 lda ($74),y ; dx
2554 adc #1
2555 sta ($74),y ; update dx
2556 clc
2557 jmp animate_enemy_right ; optimise away the rts
2559 move_enemy_right_tile:
2560 clc
2562 ldy #4
2563 lda ($74),y ; x
2564 adc #1
2565 sta ($74),y ; store the new room x offset
2566 lda #0
2567 iny
2568 sta ($74),y ; dx = 0
2569 clc
2570 jmp animate_enemy_right ; optimise away the rts
2572 move_enemy_right_exit:
2573 sec
2574 rts
2576 animate_enemy_up: ; $74,$75=character address
2578 ; Set the direction and toggle the animation bit.
2580 ldy #1
2581 lda ($74),y
2582 and #$f7 ; keep horizontal direction bit and animation bits
2583 sta ($74),y
2585 rts
2587 move_enemy_up: ; $74,$75=character address
2589 ldy #3
2590 lda ($74),y ; read dy
2591 cmp #0
2592 beq move_enemy_up_check_y
2594 sec
2595 sbc #1
2596 ldy #3
2597 sta ($74),y ; dy
2598 clc
2599 jmp animate_enemy_up ; optimise away the rts
2601 move_enemy_up_check_y:
2603 ; Check the y offset.
2605 ldy #2
2606 lda ($74),y ; y
2607 cmp #0
2608 beq move_enemy_up_exit
2610 tax ; use the y offset as an index
2611 dex ; y - 1
2612 ldy #4
2613 lda ($74),y ; load the x offset
2614 sta $81 ; temporary (x)
2615 tay
2616 lda room_row_offsets_low,x ; read the address of the row
2617 sta $70
2618 lda #$57
2619 sta $71
2620 lda ($70),y ; load the tile above
2622 cmp #0
2623 bne move_enemy_up_exit
2625 ldy #5
2626 lda ($74),y ; dx
2627 cmp #0
2628 beq move_enemy_allow_up
2630 clc ; dx != 0 so we need to check another tile
2631 ldy $81
2632 iny
2633 lda ($70),y ; load the tile above and to the right
2635 cmp #0
2636 bne move_enemy_up_exit
2638 move_enemy_allow_up:
2639 txa
2640 ldy #2
2641 sta ($74),y ; store the new room y offset
2642 lda #3
2643 iny
2644 sta ($74),y ; dy = 3
2645 clc
2646 jmp animate_enemy_up ; optimise away the rts
2648 move_enemy_up_exit:
2649 sec
2650 rts
2652 animate_enemy_down: ; $74,$75=character address
2654 ; Set the direction and toggle the animation bit.
2656 ldy #1
2657 lda ($74),y
2658 ora #$08 ; down
2659 sta ($74),y
2661 rts
2663 move_enemy_down: ; $74,$75=character address
2665 ldy #3
2666 lda ($74),y ; dy
2667 cmp #1
2668 beq move_enemy_down_check_y
2669 cmp #3
2670 beq move_enemy_down_tile
2672 adc #1
2673 ldy #3
2674 sta ($74),y ; dy
2675 clc
2676 jmp animate_enemy_down ; optimise away the rts
2678 move_enemy_down_check_y:
2680 ; Check the y offset.
2682 ldy #2
2683 lda ($74),y
2684 cmp #9
2685 beq move_enemy_down_exit
2687 clc
2688 adc #1 ; y + 1
2689 tax
2690 ldy #4
2691 lda ($74),y ; load the x offset
2692 sta $81 ; temporary
2693 tay
2694 lda room_row_offsets_low,x ; read the address of the row
2695 sta $70
2696 lda #$57
2697 sta $71
2698 lda ($70),y ; load the tile below
2700 cmp #0
2701 bne move_enemy_down_exit
2703 ldy #5
2704 lda ($74),y ; dx
2705 cmp #0
2706 beq move_enemy_allow_down
2708 clc ; dx != 0 so we need to check another tile
2709 ldy $81 ; x
2710 iny
2711 lda ($70),y ; load the tile below and to the right
2713 cmp #0
2714 bne move_enemy_down_exit
2716 move_enemy_allow_down:
2717 clc
2719 ldy #3
2720 lda ($74),y ; dy
2721 adc #1
2722 sta ($74),y ; update dy
2723 clc
2724 jmp animate_enemy_down ; optimise away the rts
2726 move_enemy_down_tile:
2727 clc
2729 ldy #2
2730 lda ($74),y ; y
2731 adc #1
2732 sta ($74),y ; store the new room y offset
2733 lda #0
2734 iny
2735 sta ($74),y ; dy = 0
2736 clc
2737 jmp animate_enemy_down ; optimise away the rts
2739 move_enemy_down_exit:
2740 sec
2741 rts
2743 move_enemy_animate: ; $74,$75=character address
2745 ldy #1
2746 lda ($74),y ; direction/animation
2747 sta $81
2748 and #$03
2749 adc #1
2750 and #$03 ; keep animation bits
2751 sta $8f
2752 lda $81
2753 and #$fc ; mask off the animation bits
2754 ora $8f
2755 sta ($74),y
2756 rts
2758 move_enemy_next_direction: .byte $04, $0c, $00, $08
2760 move_enemy: ; $74,$75=character address
2762 lda #0
2763 sta $8d ; vertical motion value (0=no motion; 1=up; 2=down)
2764 lda #0
2765 sta $8e ; horizontal motion value (0=no motion; 1=left; 2=right)
2767 lda ($74),y ; read the enemy number (Y should be zero)
2768 and #$10
2769 beq move_enemy_homing
2770 clc
2772 ; This enemy is a non-homing enemy.
2774 jsr unplot_character ; unplot now before we change the sprite used
2776 ldy #1
2777 lda ($74),y
2778 and #$f0
2779 cmp #$f0
2780 bne move_enemy_set_direction
2781 clc
2783 ldy #1
2784 lda ($74),y
2785 and #$0c
2786 ror
2787 ror
2788 tax
2789 lda move_enemy_next_direction,x
2790 sta ($74),y
2792 move_enemy_set_direction:
2793 clc
2795 ldy #1
2796 lda ($74),y
2797 sta $7b
2799 adc #$10
2800 sta ($74),y
2801 clc
2803 lda $7b
2804 and #$04
2805 ror
2806 ror
2807 adc #1
2808 sta $8e
2810 lda $7b
2811 and #$08
2812 ror
2813 ror
2814 ror
2815 adc #1
2816 sta $8d
2818 jmp move_enemy_with_direction
2820 move_enemy_homing:
2822 ldy #2
2823 lda ($74),y ; y
2824 cmp $5282 ; player y
2825 bmi move_enemy_downwards
2826 bne move_enemy_upwards
2828 ldy #3
2829 lda ($74),y ; dy
2830 cmp $5283 ; player y
2831 beq move_enemy_horizontally
2832 bpl move_enemy_upwards
2834 move_enemy_downwards:
2835 lda #2
2836 sta $8d
2837 jmp move_enemy_horizontally
2839 move_enemy_upwards:
2840 lda #1
2841 sta $8d
2842 ;jmp move_enemy_horizontally
2844 move_enemy_horizontally:
2845 ldy #4
2846 lda ($74),y ; x
2847 cmp $5284 ; player x
2848 bmi move_enemy_rightwards
2849 bne move_enemy_leftwards
2851 ldy #5
2852 lda ($74),y ; dx
2853 cmp #0
2854 beq move_enemy_with_direction_unplot
2855 bpl move_enemy_leftwards
2857 move_enemy_rightwards:
2858 lda #2
2859 sta $8e
2860 jmp move_enemy_with_direction_unplot
2862 move_enemy_leftwards:
2863 lda #1
2864 sta $8e
2866 move_enemy_with_direction_unplot:
2867 clc
2869 jsr unplot_character
2871 move_enemy_with_direction:
2872 clc
2874 lda $8e
2875 cmp #1
2876 bne move_enemy_not_left
2877 jsr move_enemy_left
2878 clc
2879 jmp move_enemy_not_right
2881 move_enemy_not_left:
2882 lda $8e
2883 cmp #2
2884 bne move_enemy_not_right
2885 jsr move_enemy_right
2886 clc
2888 move_enemy_not_right:
2889 lda $8d
2890 cmp #1
2891 bne move_enemy_not_up
2892 jsr move_enemy_up
2893 clc
2894 jmp move_enemy_toggle
2896 move_enemy_not_up:
2897 lda $8d
2898 cmp #2
2899 bne move_enemy_toggle
2900 jsr move_enemy_down
2902 move_enemy_toggle:
2903 clc
2904 jsr move_enemy_animate
2905 jmp plot_character ; optimise away the rts
2907 move_enemy_exit:
2908 clc
2909 rts
2911 create_explosion: ; X=y, Y=x
2913 lda #3
2914 sta $52a4
2915 lda #4
2916 sta $52a5
2917 txa
2918 sta $52a6
2919 lda #1
2920 sta $52a7
2921 tya
2922 sta $52a8
2923 lda #0
2924 sta $52a9
2925 rts
2927 move_projectile_left:
2929 lda $528b
2930 cmp #0
2931 beq move_projectile_left_check_x
2933 dec $528b
2934 clc
2935 rts
2937 move_projectile_left_check_x:
2939 lda $528a
2940 cmp #0
2941 bne move_projectile_left_in_room
2942 jmp move_projectile_left_exit
2944 move_projectile_left_in_room:
2945 tay
2946 dey ; x - 1
2947 ldx $5288 ; y
2948 lda room_row_offsets_low,x ; read the address of the row
2949 sta $70
2950 lda #$57
2951 sta $71
2952 lda ($70),y ; load the tile to the left
2954 cmp #0
2955 bne move_projectile_left_wall
2957 lda $5289 ; dy
2958 cmp #3
2959 bmi move_projectile_allow_left
2961 clc ; dy > 2 so we need to check another tile
2962 lda $70
2963 adc #10
2964 sta $70
2965 lda ($70),y ; load the tile below and to the left
2966 inx ; y += 1
2968 cmp #0
2969 bne move_projectile_left_wall
2971 move_projectile_allow_left:
2973 sty $528a ; x
2974 lda #3
2975 sta $528b ; dx = 3
2977 clc
2978 rts
2980 move_projectile_left_wall: ; the projectile hit a wall
2981 clc
2983 lda $5287 ; type 2 can pass through walls
2984 and #$06
2985 cmp #4
2986 beq move_projectile_allow_left
2988 cmp #2
2989 bne move_projectile_left_not_boomerang
2991 lda $5287
2992 and #$0f
2993 cmp #8
2994 bpl move_projectile_left_exit
2996 ldx $577f ; weapon counter
2997 ora boomerang_horizontal,x
2998 sta $5287
2999 clc
3000 rts ; exit without moving or registering a collision
3002 move_projectile_left_not_boomerang:
3004 cmp #6 ; type 3 can destroy certain walls
3005 bne move_projectile_left_exit
3007 lda ($70),y ; load the tile to the left
3008 cmp #1 ; decoration can be destroyed
3009 bne move_projectile_left_exit
3010 clc
3012 lda #0
3013 sta ($70),y
3015 ; X=y, Y=x
3016 jsr create_explosion
3017 jsr plot_blank_xy ; corrupted X
3019 lda #$a4
3020 sta $74
3021 lda #$52
3022 sta $75
3023 jsr plot_character
3025 ldx #0
3026 jsr play_sound
3028 lda #16 ; prevent the player from firing a new
3029 sta $578d ; projectile until the explosion has finished
3031 move_projectile_left_exit:
3032 sec
3033 rts
3035 boomerang_horizontal: .byte $28, $38
3037 move_projectile_right:
3039 ; Fire right.
3041 lda $528b
3042 cmp #2
3043 beq move_projectile_right_check_x
3044 cmp #3
3045 beq move_projectile_right_tile
3047 inc $528b
3048 clc
3049 rts
3051 move_projectile_right_check_x:
3053 lda $528a ; x
3054 cmp #9
3055 bne move_projectile_right_not_edge
3056 jmp move_projectile_right_exit
3058 move_projectile_right_not_edge:
3059 clc
3060 tay
3061 iny ; x + 1
3062 ldx $5288 ; y
3063 lda room_row_offsets_low,x ; read the address of the row
3064 sta $70
3065 lda #$57
3066 sta $71
3067 lda ($70),y ; load the tile to the right
3069 cmp #0
3070 bne move_projectile_right_wall
3072 lda $5289 ; dy
3073 cmp #3
3074 bmi move_projectile_allow_right
3076 clc ; dy > 2 so we need to check another tile
3077 lda $70
3078 adc #10
3079 sta $70
3080 lda ($70),y ; load the tile below and to the right
3081 inx ; y += 1
3083 cmp #0
3084 bne move_projectile_right_wall
3086 move_projectile_allow_right:
3088 inc $528b ; dx
3089 clc
3090 rts
3092 move_projectile_right_tile:
3094 inc $528a ; x
3095 lda #0
3096 sta $528b ; dx
3097 clc
3098 rts
3100 move_projectile_right_wall: ; the projectile hit a wall
3101 clc
3103 lda $5287 ; type 2 can pass through walls
3104 and #$06
3105 cmp #4
3106 beq move_projectile_allow_right
3108 cmp #2
3109 bne move_projectile_right_not_boomerang
3111 lda $5287
3112 and #$0f
3113 cmp #8
3114 bpl move_projectile_right_exit
3116 ldx $577f ; weapon counter
3117 ora boomerang_horizontal,x
3118 sta $5287
3119 clc
3120 rts ; exit without moving or registering a collision
3122 move_projectile_right_not_boomerang:
3124 cmp #6 ; type 3 can destroy certain walls
3125 bne move_projectile_right_exit
3127 lda ($70),y ; load the tile to the right
3128 cmp #1 ; decoration can be destroyed
3129 bne move_projectile_right_exit
3130 clc
3132 lda #0
3133 sta ($70),y
3135 ; X=y, Y=x
3136 jsr create_explosion
3137 jsr plot_blank_xy ; corrupted X
3139 lda #$a4
3140 sta $74
3141 lda #$52
3142 sta $75
3143 jsr plot_character
3145 ldx #0
3146 jsr play_sound
3148 lda #16 ; prevent the player from firing a new
3149 sta $578d ; projectile until the explosion has finished
3151 move_projectile_right_exit:
3152 sec
3153 rts
3155 move_projectile_up:
3157 lda $5289 ; read dy
3158 cmp #0
3159 beq move_projectile_up_check_y
3161 dec $5289
3162 clc
3163 rts
3165 move_projectile_up_check_y: ; Check the y offset.
3167 lda $5288
3168 cmp #0
3169 bne move_projectile_up_not_edge
3170 jmp move_projectile_up_exit
3172 move_projectile_up_not_edge:
3173 tax ; use the y offset as an index
3174 dex ; y - 1
3175 ldy $528a ; load the x offset
3176 lda room_row_offsets_low,x ; read the address of the row
3177 sta $70
3178 lda #$57
3179 sta $71
3180 lda ($70),y ; load the tile above
3182 cmp #0
3183 bne move_projectile_up_wall
3185 lda $528b ; dx
3186 cmp #3
3187 bmi move_projectile_allow_up
3189 clc ; dx > 2 so we need to check another tile
3190 iny
3191 lda ($70),y ; load the tile above and to the right
3193 cmp #0
3194 bne move_projectile_up_wall
3196 move_projectile_allow_up:
3197 txa
3198 sta $5288 ; store the new room y offset
3199 lda #3
3200 sta $5289 ; dy = 3
3202 clc
3203 rts
3205 move_projectile_up_wall: ; the projectile hit a wall
3206 clc
3208 lda $5287 ; type 2 can pass through walls
3209 and #$06
3210 cmp #4
3211 beq move_projectile_allow_up
3213 cmp #2
3214 bne move_projectile_up_not_boomerang
3216 lda $5287
3217 and #$0f
3218 cmp #8
3219 bpl move_projectile_up_exit
3221 ldx $577f ; weapon counter
3222 ora boomerang_vertical,x
3223 sta $5287
3224 clc
3225 rts ; exit without moving or registering a collision
3227 move_projectile_up_not_boomerang:
3229 cmp #6 ; type 3 can destroy certain walls
3230 bne move_projectile_up_exit
3232 lda ($70),y ; load the tile above
3233 cmp #1 ; decoration can be destroyed
3234 bne move_projectile_up_exit
3235 clc
3237 lda #0
3238 sta ($70),y
3240 ; X=y, Y=x
3241 jsr create_explosion
3242 jsr plot_blank_xy ; corrupted X
3244 lda #$a4
3245 sta $74
3246 lda #$52
3247 sta $75
3248 jsr plot_character
3250 ldx #0
3251 jsr play_sound
3253 lda #16 ; prevent the player from firing a new
3254 sta $578d ; projectile until the explosion has finished
3256 move_projectile_up_exit:
3257 sec
3258 rts
3260 boomerang_vertical: .byte $08, $18
3262 move_projectile_down:
3264 lda $5289 ; read dy
3265 cmp #2
3266 beq move_projectile_down_check_y
3267 cmp #3
3268 beq move_projectile_down_tile
3270 inc $5289 ; 0 <= dy < 3
3271 clc
3272 rts
3274 move_projectile_down_check_y: ; Check the y offset.
3276 lda $5288
3277 cmp #9
3278 bne move_projectile_down_in_room
3279 jmp move_projectile_down_exit
3281 move_projectile_down_in_room:
3282 clc
3283 tax
3284 inx ; y + 1
3285 ldy $528a ; load the x offset
3286 lda room_row_offsets_low,x ; read the address of the row
3287 sta $70
3288 lda #$57
3289 sta $71
3290 lda ($70),y ; load the tile below
3292 cmp #0
3293 bne move_projectile_down_wall
3295 lda $528b ; dx
3296 cmp #3
3297 bmi move_projectile_allow_down
3299 clc ; dx > 2 so we need to check another tile
3300 iny
3301 lda ($70),y ; load the tile below and to the right
3303 cmp #0
3304 bne move_projectile_down_wall
3306 move_projectile_allow_down:
3308 inc $5289 ; update dy
3309 clc
3310 rts
3312 move_projectile_down_tile:
3314 inc $5288 ; store the new room y offset
3315 lda #0
3316 sta $5289 ; dy = 0
3317 clc
3318 rts
3320 move_projectile_down_wall: ; the projectile hit a wall
3321 clc
3323 lda $5287 ; type 2 can pass through walls
3324 and #$06
3325 cmp #4
3326 beq move_projectile_allow_down
3328 cmp #2
3329 bne move_projectile_down_not_boomerang
3331 lda $5287
3332 and #$0f
3333 cmp #8
3334 bpl move_projectile_down_exit
3336 ldx $577f ; weapon counter
3337 ora boomerang_vertical,x
3338 sta $5287
3339 clc
3340 rts ; exit without moving or registering a collision
3342 move_projectile_down_not_boomerang:
3344 cmp #6 ; type 3 can destroy certain walls
3345 bne move_projectile_down_exit
3347 lda ($70),y ; load the tile below
3348 cmp #1 ; decoration can be destroyed
3349 bne move_projectile_down_exit
3350 clc
3352 lda #0
3353 sta ($70),y
3355 ; X=y, Y=x
3356 jsr create_explosion
3357 jsr plot_blank_xy ; corrupted X
3359 lda #$a4
3360 sta $74
3361 lda #$52
3362 sta $75
3363 jsr plot_character
3365 ldx #0
3366 jsr play_sound
3368 lda #16 ; prevent the player from firing a new
3369 sta $578d ; projectile until the explosion has finished
3371 move_projectile_down_exit:
3372 sec
3373 rts
3375 move_projectile_animate:
3377 lda $5287
3378 eor #1
3379 sta $5287
3380 rts
3382 move_projectile:
3384 lda $5286
3385 cmp #0
3386 bne move_projectile_move
3387 jmp move_projectile_exit
3389 move_projectile_move:
3390 clc
3392 lda #$86
3393 sta $74
3394 lda #$52
3395 sta $75
3396 jsr unplot_character
3398 move_projectile_after_unplot:
3400 lda $5287
3401 and #$30 ; direction
3403 cmp #0
3404 bne move_projectile_not_left
3406 jsr move_projectile_left
3407 bcc move_projectile_toggle
3408 bcs move_projectile_destroy
3410 move_projectile_not_left:
3411 cmp #$10
3412 bne move_projectile_not_right
3414 jsr move_projectile_right
3415 bcc move_projectile_toggle
3416 bcs move_projectile_destroy
3418 move_projectile_not_right:
3419 cmp #$20
3420 bne move_projectile_not_up
3422 jsr move_projectile_up
3423 bcc move_projectile_toggle
3424 bcs move_projectile_destroy
3426 move_projectile_not_up:
3427 cmp #$30
3428 bne move_projectile_toggle
3430 jsr move_projectile_down
3431 bcs move_projectile_destroy
3433 move_projectile_toggle:
3435 jsr projectile_collide
3436 bcs move_projectile_destroy
3438 jsr move_projectile_animate
3440 lda #$86
3441 sta $74
3442 lda #$52
3443 sta $75
3444 jmp plot_character ; optimise away the rts
3446 move_projectile_destroy:
3447 clc
3449 ldy #0
3450 lda ($74),y ; type
3451 cmp #8
3452 bmi move_projectile_no_enemy_collision
3454 and #$70 ; increase the player's score
3455 lsr
3456 lsr
3457 lsr
3458 adc #2
3459 sta $70
3460 jsr add_score
3461 jmp move_projectile_create_explosion
3463 move_projectile_no_enemy_collision:
3465 cmp #4 ; items can be destroyed as well
3466 bne move_projectile_no_item_collision
3468 ldy #1 ; but not keys
3469 lda ($74),y
3470 cmp #4 ; even the mace is stopped by a key
3471 beq move_projectile_remove_projectile
3472 clc
3474 jsr remove_room_item
3476 move_projectile_create_explosion:
3478 ; Unplot the item/enemy and replace it with an explosion.
3480 jsr unplot_character
3482 lda #3 ; explosion
3483 ldy #0
3484 sta ($74),y
3486 lda #4
3487 ldy #1
3488 sta ($74),y
3490 jsr plot_character
3492 ; Play a sound.
3493 ldx #0
3494 jsr play_sound
3496 move_projectile_no_item_collision:
3498 lda $5287 ; type 2 projectiles pass through everything
3499 and #$06
3500 cmp #4
3501 bne move_projectile_remove_projectile
3503 ; Ideally, we would have recorded if the projectile left the screen so
3504 ; that we don't perform these checks again here, but it would just add
3505 ; overhead to the normal movement routines for the other weapons.
3507 lda $5288 ; y
3508 cmp #0
3509 beq move_projectile_remove_projectile
3510 cmp #9
3511 beq move_projectile_remove_projectile
3513 lda $528a ; x
3514 cmp #0
3515 beq move_projectile_remove_projectile
3516 cmp #9
3517 beq move_projectile_remove_projectile
3519 clc
3520 lda #$86
3521 sta $74
3522 lda #$52
3523 sta $75
3525 jsr plot_character
3526 jmp move_projectile_exit
3528 move_projectile_remove_projectile:
3530 lda #0 ; remove the projectile from the character list
3531 sta $5286
3533 move_projectile_exit:
3534 clc
3535 rts
3537 emerge_characters:
3539 lda #$8c ; set the character address
3540 sta $74
3541 lda #$52
3542 sta $75
3544 emerge_characters_loop:
3546 ldy #0
3547 lda ($74),y
3548 cmp #0
3549 bne emerge_characters_next
3551 jmp emerge_character ; optimise away the rts
3553 emerge_characters_next:
3554 clc
3556 ; Examine the next character.
3557 lda $74
3558 adc #6
3560 cmp #$a4
3561 bpl emerge_characters_exit
3562 sta $74
3563 jmp emerge_characters_loop
3565 emerge_characters_exit:
3566 clc
3567 rts
3569 enemy_slots: .byte 0, 6, 12, 18
3571 move_characters:
3573 lda #$8c ; set the character address
3574 sta $74
3575 lda #$52
3576 sta $75
3578 lda $578e ; read a value from 0 to 3 from the motion counter
3579 and #3
3580 tax
3581 lda enemy_slots,x ; look up the corresponding slot in the character list
3582 adc $74
3583 sta $74 ; update the character address
3585 move_characters_loop:
3587 ldy #0
3588 lda ($74),y
3589 cmp #3
3590 bne move_characters_not_emerge_explode
3592 jsr emerge_explode
3593 jmp move_characters_next
3595 move_characters_not_emerge_explode:
3596 cmp #8
3597 bmi move_characters_next
3599 jsr move_enemy
3601 move_characters_next:
3602 clc
3604 lda $74 ; for the last enemy, check the next slot
3605 cmp #$9e ; for the presence of an explosion
3606 bne move_characters_endloop ; otherwise leave the loop (only performing
3607 clc ; one iteration)
3609 adc #6
3610 sta $74
3611 jmp move_characters_loop
3613 move_characters_endloop:
3614 clc
3616 ; Check collisions with the player.
3618 jsr player_collide
3619 bcs move_characters_collisions
3620 jmp move_characters_exit
3622 move_characters_collisions:
3623 clc
3625 ldy #0
3626 lda ($74),y ; type
3627 cmp #8
3628 bpl move_character_destroy_enemy
3630 ; Unplot the item.
3631 jsr unplot_character
3633 ; Remove it from the item table.
3634 jsr remove_room_item
3636 lda #0 ; remove the item from the character list
3637 ldy #0
3638 sta ($74),y
3640 iny
3641 lda ($74),y ; get the item type
3643 sta $8d ; temporarily store A and increase the score
3644 tax
3645 lda item_scores,x
3646 sta $70
3647 jsr add_score
3648 lda $8d
3650 ; Check the item type.
3651 cmp #8
3652 bmi move_characters_not_health
3654 lda #20
3655 sta $70
3656 jsr add_strength
3657 clc
3659 ldx #2
3660 jsr play_sound
3662 rts
3664 move_characters_not_health:
3665 cmp #5
3666 bmi move_characters_not_treasure
3668 ldx #2
3669 jsr play_sound
3671 clc
3672 rts
3674 move_characters_not_treasure:
3675 cmp #4
3676 bmi move_characters_not_key
3678 ; Key - update the item/player flags byte.
3679 lda $5780
3680 ora #$01
3681 sta $5780
3682 clc
3684 ldx #3
3685 jsr play_sound
3687 rts
3689 move_characters_not_key:
3691 ; Update the player's weapon.
3692 asl
3693 sta $5789
3694 clc
3696 ldx #2
3697 jsr play_sound
3699 rts
3701 move_character_destroy_enemy:
3703 ; Unplot the enemy and replace it with an explosion.
3705 jsr unplot_character
3707 lda #3 ; explosion
3708 ldy #0
3709 sta ($74),y
3711 lda #4
3712 ldy #1
3713 sta ($74),y
3715 jsr plot_character
3717 ; Reduce the player's strength.
3719 ldx #1
3720 jsr play_sound
3722 lda #1
3723 sta $70
3724 jmp reduce_strength ; optimise away the rts
3726 move_characters_exit:
3727 clc
3728 rts
3730 remove_room_item:
3732 ldx $5782 ; current room row number
3733 lda eleven_times_table,x
3734 adc $5783 ; current room column number
3735 tax
3736 lda #$80 ; store a value with the top bit set instead of zero because we
3737 sta $5200,x ; have visited this room if we can collect the object within it
3738 clc
3739 rts
3741 item_scores: .byte $1,$4,$9,$16, $50,$20,$5,$10,$40
3742 score_vdu_bytes: .byte 1,1,31 ; reversed
3743 score_digits: .byte "0123456789"
3745 add_score: ; $70=score to add
3747 sed
3748 lda $5786
3749 adc $70
3750 sta $5786
3751 lda $5787
3752 adc #0
3753 sta $5787
3754 lda $5788
3755 adc #0
3756 sta $5788
3757 cld
3759 write_score:
3761 lda #$86
3762 sta $70
3763 lda #$57
3764 sta $71
3766 ldx #2
3767 write_score_vdu_bytes:
3768 lda score_vdu_bytes,x
3769 jsr $ffee
3770 dex
3771 bpl write_score_vdu_bytes
3773 write_score_digits: ; $70,$71=address of score bytes
3775 ldy #2
3776 write_score_loop:
3778 lda ($70),y
3779 lsr
3780 lsr
3781 lsr
3782 lsr
3783 tax
3784 lda score_digits,x
3785 jsr $ffee
3787 lda ($70),y
3788 and #$0f
3789 tax
3790 lda score_digits,x
3791 jsr $ffee
3793 dey
3794 bpl write_score_loop
3796 clc
3797 rts
3799 strength_units: .byte $00,$88,$cc,$ee
3801 add_strength: ; $70=strength to add
3803 ; Divide the initial strength by 4 to determine which half character to
3804 ; start plotting at, and multiply by 8 to get the address. The net result
3805 ; is to mask off the bottom two bits and shift left once.
3806 lda $5784
3807 and #$fc
3808 sta $71 ; strength rounded down to a multiple of four units
3809 asl
3810 clc
3811 tay
3813 lda $5784
3814 adc $70
3815 cmp #65
3816 bmi add_strength_update
3818 lda #64
3820 add_strength_update:
3821 clc
3822 sta $5784 ; the final strength
3824 sec
3825 sbc $71
3826 clc
3827 tax ; the number of units to add between the rounded original
3828 ; strength and the final strength
3830 lda #$f3 ; the start of the strength bar
3831 sta $72
3832 lda #$59
3833 sta $73
3835 cpx #4
3836 bmi add_strength_loop_extra
3838 add_strength_loop:
3840 clc
3841 lda #$ff
3842 sta ($72),y
3844 tya
3845 adc #8
3846 tay
3848 txa
3849 sec
3850 sbc #4
3851 clc
3852 tax
3854 cmp #4
3855 bpl add_strength_loop
3857 add_strength_loop_extra:
3858 cpx #0
3859 beq add_strength_exit
3861 ; For any remaining units in excess of the multiples of four units, plot
3862 ; the appropriate byte.
3863 lda $5784
3864 and #3
3865 tax
3867 lda strength_units,x
3868 sta ($72),y
3870 add_strength_exit:
3871 clc
3872 rts
3874 reduce_strength: ; $70=strength to remove
3876 lda $5784
3877 tax
3878 sec
3879 sbc $70
3880 bpl reduce_strength_update
3882 lda #0
3884 reduce_strength_update:
3885 clc
3886 sta $5784
3888 ; Divide the final strength by 4 to determine which half character to
3889 ; plot, and multiply by 8 to get the address. The net result is to mask off
3890 ; the bottom two bits and shift left once.
3891 and #$fc
3892 asl
3893 tay
3895 lda #$f3 ; the start of the strength bar
3896 sta $70
3897 lda #$59
3898 sta $71
3900 lda $5784
3901 and #3
3902 tax
3903 lda strength_units,x
3904 sta ($70),y
3906 lda $5784
3907 cmp #0
3908 bne reduce_strength_exit
3910 lda $5780 ; the player ran out of strength
3911 ora #$40
3912 sta $5780
3914 lda #64 ; reset the delay counter
3915 sta $5785
3917 lda #$80 ; unplot the player
3918 sta $74
3919 lda #$52
3920 sta $75
3922 jsr unplot_character
3924 lda #8 ; change the player's direction to the demise animation
3925 sta $5281
3927 jsr plot_character
3928 jmp destroy_enemies ; optimise away the rts
3930 reduce_strength_exit:
3931 clc
3932 rts
3934 destroy_enemies:
3936 lda #$8c
3937 sta $74
3938 lda #$52
3939 sta $75
3941 destroy_enemies_loop:
3943 ldy #0
3944 lda ($74),y
3945 cmp #8
3946 bmi destroy_enemies_not_enemy
3948 jsr unplot_character
3950 lda #3 ; emerge/explosion
3951 ldy #0
3952 sta ($74),y
3954 iny
3955 lda #4 ; explosion
3956 sta ($74),y
3958 jsr plot_character
3959 jmp destroy_enemies_not_emerging_enemy
3961 destroy_enemies_not_enemy:
3962 cmp #3
3963 bne destroy_enemies_not_emerging_enemy
3965 jsr unplot_character
3967 iny ; whether emerging or exploding, ensure that the enemy
3968 lda ($74),y ; is now exploding
3969 ora #4
3970 sta ($74),y
3972 jsr plot_character
3974 destroy_enemies_not_emerging_enemy:
3975 clc
3976 lda $74
3977 adc #6
3978 sta $74
3979 cmp #$a4
3980 bmi destroy_enemies_loop
3982 clc
3983 rts
3985 remove_characters:
3987 ; Clear the character table.
3989 ldx #6
3990 remove_characters_loop:
3991 lda #0
3992 sta $5280,x
3993 txa
3994 adc #6
3995 tax
3996 cpx #$2a
3997 bmi remove_characters_loop
3999 rts
4001 ; The player collision masks use bits to represent where the player is in a
4002 ; tile. See the collisions.txt file for more information.
4004 ; Player is above, enemy is below, checking the overlap in the lower tile.
4005 player_collision_mask_above: .byte $00, $c0, $f0, $fc
4007 projectile_collision_mask_above: .byte $00, $00, $00, $80
4009 ; Player and enemy share the same tile or player is on the tile below.
4010 player_collision_mask_below: .byte $ff, $3f, $0f, $03
4012 projectile_collision_mask_below: .byte $e0, $38, $e0, $03
4014 ; Player is above or on the same tile, enemy is below, checking the overlap in
4015 ; the lower tile.
4016 enemy_collision_mask_above: .byte $f8, $3f, $0f, $03
4018 ; Enemy is above, player is below, checking the overlap in the lower tile.
4019 enemy_collision_mask_below: .byte $00, $00, $c0, $f0
4021 ; Player is to the left, enemy is to the right, checking the overlap in the
4022 ; right hand tile.
4023 player_collision_mask_left:
4024 projectile_collision_mask_left: .byte $00, $00, $00, $08
4026 ; Player and enemy share the same tile or player is on the tile to the right.
4027 player_collision_mask_right:
4028 projectile_collision_mask_right: .byte $0c, $06, $03, $01
4030 ; Player is to the left, enemy is to the right or on the same tile, checking
4031 ; the overlap in the right hand tile.
4032 enemy_collision_mask_left: .byte $0f, $07, $03, $01
4034 ; Enemy is to the left, player is to the right, checking the overlap in the
4035 ; right hand tile.
4036 enemy_collision_mask_right: .byte $00, $08, $0c, $0e
4038 player_collide:
4040 lda $5282 ; player y
4041 sta $8a
4042 lda $5284 ; player x
4043 sta $8b
4045 ldx $5283 ; player dy
4046 lda player_collision_mask_above,x
4047 sta $86
4048 lda player_collision_mask_below,x
4049 sta $88
4050 ldx $5285 ; player dx
4051 lda player_collision_mask_left,x
4052 sta $87
4053 lda player_collision_mask_right,x
4054 sta $89
4056 jmp collide ; optimise away the rts
4058 projectile_collide:
4060 lda $5288 ; projectile y
4061 sta $8a
4062 lda $528a ; projectile x
4063 sta $8b
4065 ldx $5289 ; projectile dy
4066 lda projectile_collision_mask_above,x
4067 sta $86
4068 lda projectile_collision_mask_below,x
4069 sta $88
4070 ldx $528b ; projectile dx
4071 lda projectile_collision_mask_left,x
4072 sta $87
4073 lda projectile_collision_mask_right,x
4074 sta $89
4076 ; Run on into the next routine.
4078 collide:
4080 lda #$8c ; set the character address
4081 sta $74
4082 lda #$52
4083 sta $75
4085 collide_loop:
4087 ldy #0
4088 lda ($74),y ; type
4089 cmp #4
4090 bpl collide_check
4092 jmp collide_next
4094 collide_check:
4096 ldy #2
4097 lda ($74),y ; y
4098 sec
4099 sbc $8a ; y - player/projectile y
4100 beq check_collide_y_equal
4101 cmp #1
4102 beq check_collide_y_greater
4103 cmp #255
4104 beq check_collide_y_less
4106 jmp collide_next
4108 check_collide_y_equal:
4109 ; The enemy is on the same tile as the player/projectile so look at the
4110 ; collision on their common tile.
4111 ldy #3
4112 lda ($74),y ; dy
4113 tax
4114 lda enemy_collision_mask_above,x
4115 and $88 ; player/projectile mask below
4116 bne check_collide_x
4118 jmp collide_next
4120 check_collide_y_greater:
4121 ; The enemy is on the tile below the player/projectile so look at the
4122 ; collision on the enemy's tile.
4123 ldy #3
4124 lda ($74),y ; dy
4125 tax
4126 lda enemy_collision_mask_above,x
4127 and $86 ; player mask above
4128 bne check_collide_x
4130 jmp collide_next
4132 check_collide_y_less:
4133 ; The enemy is on the tile above the player/projectile so look at the
4134 ; collision on the player's tile.
4135 ldy #3
4136 lda ($74),y ; dy
4137 tax
4138 lda enemy_collision_mask_below,x
4139 and $88 ; player mask below
4140 bne check_collide_x
4142 jmp collide_next
4144 check_collide_x:
4145 ldy #4
4146 lda ($74),y ; x
4147 sec
4148 sbc $8b ; x - player/projectile x
4149 beq check_collide_x_equal
4150 cmp #1
4151 beq check_collide_x_greater
4152 cmp #255
4153 beq check_collide_x_less
4155 jmp collide_next
4157 check_collide_x_equal:
4158 ; The enemy is on the same tile as the player/projectile so look at the
4159 ; collision on their common tile.
4160 ldy #5
4161 lda ($74),y ; dx
4162 tax
4163 lda enemy_collision_mask_left,x
4164 and $89 ; player mask right
4165 bne check_collide_destroy
4167 jmp collide_next
4169 check_collide_x_greater:
4170 ; The enemy is the tile to the right of the player/projectile so look
4171 ; at the collision on the enemy's tile.
4172 ldy #5
4173 lda ($74),y ; dx
4174 tax
4175 lda enemy_collision_mask_left,x
4176 and $87 ; player mask left
4177 bne check_collide_destroy
4179 jmp collide_next
4181 check_collide_x_less:
4182 ; The enemy is the tile to the left of the player/projectile so look at
4183 ; the collision on the player's tile.
4184 ldy #5
4185 lda ($74),y ; dx
4186 tax
4187 lda enemy_collision_mask_right,x
4188 and $89 ; player mask right
4189 bne check_collide_destroy
4191 collide_next:
4192 clc
4194 ; Examine the next character.
4195 lda $74
4196 adc #6
4198 cmp #$a4
4199 bpl collide_exit
4200 sta $74
4201 jmp collide_loop
4203 check_collide_destroy:
4205 sec ; set the carry flag to inform the caller that the
4206 rts ; player/projectile should be destroyed
4208 collide_exit:
4209 clc
4210 rts
4212 blank_screen:
4213 lda #1
4214 sta $70
4215 lda #0
4216 sta $71
4217 jsr set_palette
4218 lda #2
4219 sta $70
4220 lda #0
4221 sta $71
4222 jsr set_palette
4223 lda #3
4224 sta $70
4225 lda #0
4226 sta $71
4227 ; Run on into set_palette.
4229 set_palette:
4230 ; $70=logical colour
4231 ; $71=physical colour
4232 lda $70
4233 sta $578b
4234 lda $71
4235 sta $578c
4236 lda #0
4237 sta $578d
4238 sta $578e
4239 sta $578f
4241 lda #$c
4242 ldx #$8b
4243 ldy #$57
4244 jsr $fff1
4245 rts
4247 sounds_low: .byte <explosion_sound, <damage_sound, <item_sound, <key_sound, <note_sound, <emerge_sound
4248 sounds_high: .byte >explosion_sound, >damage_sound, >item_sound, >key_sound, >note_sound, >emerge_sound
4250 explosion_sound: .byte 1,0, 1,0, 60,0, 2,0
4251 damage_sound: .byte 1,0, 2,0, 40,0, 4,0
4252 item_sound: .byte $13,0, 3,0, 32,0, 3,0
4253 key_sound: .byte $13,0, 4,0, 50,0, 5,0
4254 note_sound: .byte $13,0, 241,255
4255 note_pitch: .byte 0,0
4256 note_duration: .byte 4,0
4257 emerge_sound: .byte 2,0, 3,0, 0,0, 2,0
4259 play_note: ; A=pitch, Y=duration
4261 sta note_pitch
4262 sty note_duration
4263 ldx #4
4264 ; Run on into the next routine.
4266 play_sound: ; X=sound number
4268 lda sounds_high,x
4269 tay
4270 lda sounds_low,x
4271 tax
4272 lda #7
4273 jsr $fff1
4275 rts
4277 copy_title_up:
4279 lda #$00
4280 sta $70
4281 lda #$18
4282 sta $71
4284 lda #$a0
4285 sta $72
4286 lda #$5a
4287 sta $73
4289 ldx #5
4290 ; Run on into the next routine.
4292 copy_title:
4294 copy_title_loop1:
4296 ldy #0
4297 copy_title_loop2:
4299 lda ($70),y
4300 sta ($72),y
4301 iny
4302 cpy #0
4303 bne copy_title_loop2
4305 clc
4306 lda $72
4307 adc #$40
4308 sta $72
4309 lda $73
4310 adc #$01
4311 sta $73
4312 clc
4314 lda $71
4315 adc #$01
4316 sta $71
4317 clc
4319 dex
4320 bpl copy_title_loop1
4322 rts
4324 copy_completed_screen_up:
4326 lda #$00
4327 sta $70
4328 lda #$0f
4329 sta $71
4331 lda #$60
4332 sta $72
4333 lda #$5e
4334 sta $73
4336 ldx #8
4337 jmp copy_title ; optimise away the rts
4339 init:
4340 jsr cls ; clear the text window
4342 lda #26 ; unset the text window
4343 jsr $ffee
4345 ; Define the default high scores.
4346 ldy #0
4347 lda #$80
4348 sta $70
4349 lda #$51
4350 sta $71
4351 lda #$16
4352 sta $72
4354 ldx #0
4355 init_define_high_scores_loop:
4357 lda #0
4358 sta ($70),y
4359 iny
4360 lda $72
4361 sta ($70),y
4362 iny
4363 lda #0
4364 sta ($70),y
4366 iny
4367 init_define_high_score_name_loop:
4369 lda high_score_default_name1,x
4370 sta ($70),y
4371 iny
4372 inx
4373 cpx #9
4374 beq init_define_high_scores_next
4375 cpx #18
4376 bne init_define_high_score_name_loop
4378 ldx #0
4379 init_define_high_scores_next:
4381 sed
4382 lda $72
4383 sec
4384 sbc #2
4385 sta $72
4386 cld
4387 clc
4389 cpy #96
4390 bne init_define_high_scores_loop
4392 ; Disable joystick support.
4393 lda #0
4394 sta $577e
4396 rts
4398 high_score_default_name1: .byte "RETRO "
4399 high_score_default_name2: .byte " SOFTWARE"
4401 title_vdu_bytes: .byte 17,2, 31,7,28, "to play"
4402 input_message: .byte 17,2, 31,1,27, "Press SPACE / FIRE"
4403 title_vdu_bytes1: .byte 17,3, 31,1,30, "Copyright (c) 2011"
4404 title_vdu_bytes2: .byte 17,3, 31,1,30, " David Boddie "
4405 title_vdu_bytes3: .byte 17,1, 31,1,30, "for Retro Software"
4406 title_vdu_bytes4: .byte 17,3, 31,1,30, "GNU GPL 3 or later"
4408 set_standard_palette:
4410 lda #1
4411 sta $70
4412 lda #1
4413 sta $71
4414 jsr set_palette
4416 jmp set_core_palette ; optimise away the rts
4418 complete_palette_bytes: .byte 2,4, 3,5, 1,4, 3,3, 2,2
4420 set_complete_palette:
4422 lda #0
4423 sta $80
4424 lda #25
4425 sta $81
4427 set_complete_palette_loop:
4429 jsr wait_for_vsync
4431 dec $81
4432 lda $81
4433 cmp #0
4434 bne set_complete_palette_loop
4436 lda #25
4437 sta $81
4439 ldx $80
4440 lda complete_palette_bytes,x
4441 sta $70
4442 inx
4443 lda complete_palette_bytes,x
4444 sta $71
4445 inx
4446 stx $80
4447 jsr set_palette
4449 lda $80
4450 cmp #10
4451 bne set_complete_palette_loop
4453 rts
4455 set_hidden_palette:
4457 lda #1
4458 sta $70
4459 lda #0
4460 sta $71
4461 jsr set_palette
4463 ; Run on into the next routine.
4465 set_core_palette:
4467 lda #2
4468 sta $70
4469 lda #2
4470 sta $71
4471 jsr set_palette
4473 lda #3
4474 sta $70
4475 lda #3
4476 sta $71
4477 jsr set_palette
4479 rts
4481 show_title:
4483 jsr set_standard_palette
4485 ldx #0
4486 write_title_text_loop:
4487 lda title_vdu_bytes,x
4488 jsr $ffee
4489 inx
4490 cpx #12
4491 bmi write_title_text_loop
4493 jsr show_input_message
4495 ; Show the title.
4496 jsr copy_title_up
4498 ; Show the high scores.
4500 jsr colour1
4502 lda #$80
4503 sta $70
4504 lda #$51
4505 sta $71
4507 lda #8
4508 sta $80
4510 show_title_high_scores_loop:
4512 lda #31
4513 jsr $ffee
4514 lda #2
4515 jsr $ffee
4516 lda $80
4517 adc #2
4518 sta $80
4519 clc
4520 jsr $ffee
4522 jsr write_score_digits
4524 lda #32
4525 jsr $ffee
4527 ldx #8
4528 ldy #3
4529 show_title_high_scores_vdu_loop2:
4531 lda ($70),y
4532 cmp #32
4533 bmi ignore_char
4534 cmp #123
4535 bpl ignore_char
4536 jsr $ffee
4538 ignore_char:
4539 iny
4540 dex
4541 bpl show_title_high_scores_vdu_loop2
4543 lda $70
4544 adc #12
4545 sta $70
4546 cmp #$e0
4547 bne show_title_high_scores_loop
4549 lda #0 ; message counter
4550 sta $72
4552 show_title_wait_loop:
4554 lda #150
4555 sta $5785
4557 ldx $72
4558 ldy #22
4559 show_title_wait_message_loop:
4561 lda title_vdu_bytes1,x
4562 jsr $ffee
4563 inx
4564 dey
4565 bpl show_title_wait_message_loop
4567 cpx #92
4568 beq show_title_wait_reset_offset
4570 txa
4571 sta $72
4572 jmp show_title_wait_inner_loop
4574 show_title_wait_reset_offset:
4575 lda #0
4576 sta $72
4578 show_title_wait_inner_loop:
4579 jsr wait_for_vsync
4581 dec $5785
4582 beq show_title_wait_loop
4584 show_title_wait_loop_no_update:
4585 lda #128
4586 ldx #0
4587 jsr $fff4
4588 cpx #0 ; fire button pressed?
4589 beq show_title_no_joystick
4591 lda #1 ; enable joystick support
4592 sta $577e
4593 jmp show_title_exit
4595 show_title_no_joystick:
4596 ldx #157 ; SPACE
4597 jsr check_key
4598 cpy #255
4599 bne show_title_wait_inner_loop
4601 lda #0 ; disable joystick support
4602 sta $577e
4604 show_title_exit:
4605 clc
4606 rts
4608 show_input_message:
4610 ldx #0
4611 show_input_message_loop:
4613 lda input_message,x
4614 jsr $ffee
4615 inx
4616 cpx #23
4617 bne show_input_message_loop
4619 rts
4621 wait_for_vsync:
4623 lda #19
4624 jmp $fff4 ; optimise away the rts
4626 game_over_vdu_bytes: .byte 28,4,17,15,15, 12, 26, 31,4,15, 17,2, "The journey", 31,9,17, "is over"
4628 delay:
4630 delay_loop:
4632 jsr wait_for_vsync
4633 dec $5785
4634 bne delay_loop
4636 rts
4638 show_game_over:
4640 lda #128
4641 sta $5785
4642 jsr delay
4644 ldx #0
4645 write_game_over_text_loop:
4646 lda game_over_vdu_bytes,x
4647 jsr $ffee
4648 inx
4649 cpx #33
4650 bmi write_game_over_text_loop
4652 lda #192
4653 sta $5785
4654 jsr delay
4656 rts
4658 end_of_level_bytes1: .byte 31,1,3, 17,3, "Exploration bonus", 31,11,5, "x 9"
4659 end_of_level_bytes2: .byte 31,0,28, 17,2, "My journey continues"
4661 show_end_of_level_screen:
4663 ; Draw a decorative room.
4665 jsr make_empty_room
4667 ldx #5
4668 end_of_level_h_walls_loop:
4670 lda #3
4671 sta $57b2,x
4672 sta $57e4,x
4673 dex
4674 bpl end_of_level_h_walls_loop
4676 ldx #30
4677 end_of_level_v_walls_loop:
4679 lda #3
4680 sta $57bc,x
4681 sta $57c1,x
4682 txa
4683 sec
4684 sbc #10
4685 tax
4686 bpl end_of_level_v_walls_loop
4688 jsr plot_room_tiles
4689 jsr set_standard_palette
4691 ldx #0
4692 end_of_level_text_loop1:
4694 lda end_of_level_bytes1,x
4695 jsr $ffee
4696 inx
4697 cpx #28
4698 bne end_of_level_text_loop1
4700 ; Count the number of rooms explored.
4701 ldx #0
4702 lda #0
4703 sta $8d
4704 sta $8e
4705 end_of_level_room_count_loop:
4707 lda $5200,x
4708 and #$80
4709 beq end_of_level_room_count_loop_next
4711 sed
4712 lda $8d
4713 adc #1
4714 sta $8d
4715 lda $8e
4716 adc #0
4717 sta $8e
4718 cld
4719 clc
4721 end_of_level_room_count_loop_next:
4722 inx
4723 cpx #121
4724 bne end_of_level_room_count_loop
4726 ; Position the player so that we can perform an animation.
4727 jsr position_player_set_up_plotting
4729 lda $8d
4730 sta $70
4731 lda $8e
4732 sta $71
4733 jsr write_bonus
4735 lda #0 ; reset motion counter
4736 sta $578e
4738 show_end_of_level_bonus_loop:
4740 jsr wait_for_vsync
4742 clc
4743 lda $578e
4744 and #15
4745 bne end_of_level_no_animation
4747 ; Animate the player.
4749 jsr reset_unplot_buffer
4750 jsr reset_plot_buffer
4752 ; $74,$75 should be unchanged
4753 jsr unplot_character
4755 lda $5281
4756 eor #1
4757 sta $5281
4758 jsr plot_character
4760 jsr plot_buffer
4762 end_of_level_no_animation:
4763 clc
4764 lda $578e
4765 and #3
4766 bne end_of_level_no_countdown
4768 ; Transfer the bonus to the score.
4770 sed
4771 sec
4772 lda $8d
4773 sbc #1
4774 sta $8d
4775 sta $70
4776 lda $8e
4777 sbc #0
4778 sta $8e
4779 sta $71
4780 cld
4781 clc
4783 jsr write_bonus
4785 lda #9
4786 sta $70
4787 jsr add_score
4789 lda $8d
4790 and #$3f
4791 asl
4792 ldy #1
4793 jsr play_note
4795 end_of_level_no_countdown:
4796 inc $578e ; update motion counter
4797 clc
4799 lda $8d
4800 cmp #0
4801 bne show_end_of_level_bonus_loop
4803 lda $8e
4804 cmp #0
4805 bne show_end_of_level_bonus_loop
4807 lda #64 ; initialise delay counter
4808 sta $5785
4809 jsr delay
4811 ldx #0
4812 end_of_level_text_loop2:
4814 lda end_of_level_bytes2,x
4815 jsr $ffee
4816 inx
4817 cpx #25
4818 bne end_of_level_text_loop2
4820 lda $578a
4821 cmp #3
4822 bpl show_end_of_level_screen_exit
4824 lda #192 ; initialise delay counter
4825 sta $5785
4826 jsr delay
4828 show_end_of_level_screen_exit:
4829 rts
4831 level_bonus_vdu_bytes: .byte 5,6,31, 1,17 ; reversed
4833 write_bonus: ; $70,$71=value
4834 ; $72,$73=address of VDU codes
4836 ldx #4
4837 write_bonus_vdu_bytes:
4839 lda level_bonus_vdu_bytes,x
4840 jsr $ffee
4841 dex
4842 bpl write_bonus_vdu_bytes
4844 ldy #1
4845 write_bonus_loop:
4847 tya
4848 tax ; temporary
4850 lda $70,x
4851 sta $80
4852 lsr
4853 lsr
4854 lsr
4855 lsr
4856 tax
4857 lda score_digits,x
4858 jsr $ffee
4860 lda $80
4861 and #$0f
4862 tax
4863 lda score_digits,x
4864 jsr $ffee
4866 dey
4867 bpl write_bonus_loop
4869 clc
4870 rts
4872 position_player_set_up_plotting:
4874 jsr reset_player_position
4875 jsr remove_characters
4877 jsr reset_unplot_buffer
4878 jsr reset_plot_buffer
4880 ; Run on into the next routine.
4882 plot_the_player:
4884 lda #$80 ; plot the player
4885 sta $74
4886 lda #$52
4887 sta $75
4888 jsr plot_character
4890 jsr plot_buffer
4891 rts
4893 complete_game_vdu_bytes1: .byte 12
4894 complete_game_vdu_bytes2: .byte 17,3, 31,2,20, "Congratulations!"
4895 complete_game_vdu_bytes3: .byte 17,2, 31,1,22, "Now journey onward"
4896 complete_game_vdu_bytes4: .byte 17,2, 31,1,24, "to a new adventure"
4898 show_complete_game:
4900 jsr blank_screen
4902 ldx #0
4903 show_complete_game_vdu_loop:
4905 lda complete_game_vdu_bytes1,x
4906 jsr $ffee
4907 inx
4908 cpx #68
4909 bne show_complete_game_vdu_loop
4911 jsr copy_completed_screen_up
4913 jsr set_complete_palette
4915 lda #255
4916 sta $5785
4918 show_complete_game_delay_loop:
4920 jsr wait_for_vsync
4922 dec $5785
4923 bne show_complete_game_no_message
4925 jsr colour1
4926 jsr show_input_message
4928 show_complete_game_no_message:
4930 lda #128
4931 ldx #0
4932 jsr $fff4
4933 cpx #0 ; fire button pressed?
4934 beq show_complete_game_no_joystick
4935 jmp show_complete_game_exit
4937 show_complete_game_no_joystick:
4939 ldx #157
4940 jsr check_key
4941 cpy #255
4942 bne show_complete_game_delay_loop
4944 show_complete_game_exit:
4945 clc
4946 rts
4948 check_high_scores:
4950 ; Start at the bottom of the table, moving scores down as necessary, and
4951 ; write in the current score at the appropriate place.
4953 lda #$86 ; current score
4954 sta $70
4955 lda #$57
4956 sta $71
4958 lda #$80
4959 sta $72
4960 lda #$51
4961 sta $73
4963 check_high_scores_loop:
4965 ldy #2
4966 check_high_scores_digits_loop:
4968 lda ($72),y
4969 cmp ($70),y ; existing score less than current score?
4970 bmi check_high_scores_move_down
4971 beq check_high_scores_digits_next ; keep checking digits if equal
4972 jmp check_high_scores_next
4974 check_high_scores_digits_next:
4975 dey
4976 bpl check_high_scores_digits_loop
4978 check_high_scores_next:
4979 clc
4980 lda $72
4981 adc #12
4982 sta $72
4983 cmp #$e0
4984 bne check_high_scores_loop
4986 ; The player's score didn't make it into the high score table.
4987 rts
4989 check_high_scores_move_down: ; $70,$71=pointer to current score
4990 ; $72,$73=pointer to old score
4992 ; The current score exceeded the existing entry. Make a note of the
4993 ; position in the high score table, insert the player's score, and take
4994 ; the old score
4996 lda $72 ; Record the position in the high score table of the
4997 sta $8d ; player's score.
4998 lda $73
4999 sta $8e
5001 lda #$e0
5002 sta $74
5003 lda #$51
5004 sta $75
5006 ldy #0
5007 insert_blank_player_name_loop:
5009 cpy #3
5010 bpl insert_blank_player_name_score_only
5012 lda ($70),y
5013 jmp insert_blank_player_name_store
5015 insert_blank_player_name_score_only:
5016 lda #32
5018 insert_blank_player_name_store:
5019 sta ($74),y
5020 iny
5021 cpy #12
5022 bne insert_blank_player_name_loop
5024 check_high_scores_move_down_loop:
5026 ldy #0
5027 check_high_scores_copy_score_and_name:
5029 lda ($72),y ; swap the current score with the score in the table
5030 tax
5031 lda ($74),y
5032 sta ($72),y
5033 txa
5034 sta ($74),y
5035 iny
5036 cpy #12
5037 bne check_high_scores_copy_score_and_name
5039 clc
5040 lda $72
5041 adc #12
5042 sta $72
5043 cmp #$e0
5044 bne check_high_scores_move_down_loop
5046 ; Draw a decorative room.
5048 jsr set_hidden_palette
5050 jsr make_empty_room
5052 lda #3
5053 sta $76
5054 sta $77
5055 jsr draw_top_line
5056 jsr draw_bottom_line
5057 jsr draw_left_line
5059 lda #0
5060 sta $77
5061 jsr draw_right_line
5063 jsr plot_room_tiles
5065 ; Add text characters to the room.
5066 jsr colour3
5068 lda #3 ; x
5069 sta $70
5070 lda #6 ; y
5071 sta $71
5073 lda #65
5074 sta $72
5076 ldx #3
5077 plot_text_characters_loop:
5079 jsr print_xy
5081 lda $70
5082 adc #4
5083 sta $70
5085 dex
5086 bpl plot_text_characters_next
5088 lda #3
5089 sta $70
5090 lda $71
5091 adc #3
5092 sta $71
5094 ldx #3
5096 plot_text_characters_next:
5098 inc $72
5099 lda $72
5100 cmp #91
5101 bne plot_text_characters_loop
5103 lda #11
5104 sta $70
5105 lda #95 ; _ representing a space
5106 sta $72
5107 jsr print_xy
5109 lda #15
5110 sta $70
5111 lda #60 ; < representing delete
5112 sta $72
5113 jsr print_xy
5115 ; Put the player in the centre of the room.
5116 jsr position_player_set_up_plotting
5118 lda #0 ; reset motion counter
5119 sta $578e
5121 lda #0 ; not on a character
5122 sta $578d
5124 lda #0 ; reset the level number so that the correct tiles are used
5125 sta $578a
5127 lda #3 ; cursor position in the high score entry held in $8d,$8e
5128 sta $8f
5130 jsr set_standard_palette
5132 ldx #0
5133 high_score_vdu_loop:
5135 lda high_score_vdu_bytes,x
5136 jsr $ffee
5137 inx
5138 cpx #39
5139 bne high_score_vdu_loop
5141 high_score_entry_loop:
5143 jsr reset_unplot_buffer
5144 jsr reset_plot_buffer
5146 jsr move_player
5147 ; Check if the player leaves the room.
5148 bcc high_score_entry_check_position
5149 jmp high_score_entry_after_loop
5151 high_score_entry_check_position:
5153 lda $5285 ; dx
5154 cmp #2
5155 beq high_score_entry_maybe_aligned
5156 jmp high_score_entry_not_aligned
5158 high_score_entry_maybe_aligned:
5160 lda $5282 ; y
5161 tay
5162 cmp #8
5163 bpl high_score_entry_not_aligned
5165 lda $5284 ; x
5166 tax
5167 cmp #9
5168 beq high_score_entry_not_aligned
5169 and #1
5170 beq high_score_entry_not_aligned
5172 lda $5283 ; dy
5173 cmp #2
5174 bmi high_score_entry_aligned
5175 jmp high_score_entry_not_aligned
5177 lda $5282 ; y again (don't apply the touching rule to the bottom
5178 cmp #7 ; row of characters)
5179 beq high_score_entry_not_aligned
5181 iny ; we are really touching the character below
5183 high_score_entry_aligned:
5185 lda $578d
5186 cmp #1
5187 beq high_score_entry_next
5189 ; The player is aligned with a letter.
5190 txa
5191 sec
5192 sbc #1
5193 lsr
5194 sta $7e ; record (x - 1) / 2
5196 tya ; recall y
5197 sec
5198 sbc #1
5199 asl
5200 asl ; (y - 1) * 4
5201 clc
5203 adc $7e ; (y - 1) * 4 + (x - 1) / 2
5204 adc #65
5205 sta $7e ; record the ASCII code
5207 cmp #91
5208 bmi insert_character
5210 cmp #92
5211 beq delete_character
5213 ; Insert a space.
5214 lda #32
5215 sta $7e
5217 insert_character:
5218 lda $8f
5219 cmp #12
5220 bpl high_score_entry_pressed
5222 tay ; insert the character
5223 lda $7e
5224 sta ($8d),y
5225 jsr print_high_score_character
5227 inc $8f
5228 jmp high_score_entry_pressed
5230 delete_character:
5231 lda $8f
5232 cmp #4
5233 bmi high_score_entry_pressed
5235 cmp #12
5236 beq high_score_delete_previous_character
5238 tay
5239 lda #32 ; insert a space
5240 sta ($8d),y
5241 jsr print_high_score_character
5243 high_score_delete_previous_character:
5244 dec $8f
5245 lda $8f
5246 tay ; insert a space
5247 lda #32
5248 sta ($8d),y
5249 jsr print_high_score_character
5251 high_score_entry_pressed:
5252 lda #1
5253 sta $578d
5254 jmp high_score_entry_next
5256 high_score_entry_not_aligned:
5257 lda #0
5258 sta $578d
5260 high_score_entry_next:
5262 jsr wait_for_vsync
5263 jsr plot_buffer
5265 jmp high_score_entry_loop
5267 inc $578e
5268 clc
5270 high_score_entry_after_loop:
5271 clc
5273 jsr cls
5274 jsr set_hidden_palette
5276 rts
5278 high_score_vdu_bytes: .byte 17,1, 31,2,3, "Enter your name!", 17,3, 31,5,30, "> <", 17,1
5280 cls:
5281 lda #12
5282 jsr $ffee
5283 rts
5285 colour1:
5286 lda #17
5287 jsr $ffee
5288 lda #1
5289 jsr $ffee
5290 rts
5292 colour3:
5293 lda #17
5294 jsr $ffee
5295 lda #3
5296 jsr $ffee
5297 rts
5299 print_high_score_character: ; A=ASCII code
5301 clc
5302 sta $72 ; store the character
5303 lda $8f
5304 adc #3
5305 sta $70 ; store the x position of the character
5306 lda #30
5307 sta $71
5308 ; Run on into the next routine.
5310 print_xy:
5312 lda #31
5313 jsr $ffee
5314 lda $70
5315 jsr $ffee
5316 lda $71
5317 jsr $ffee
5318 lda $72
5319 jsr $ffee
5320 rts
5322 disable_sound: ; X=1 (disable); X=0 (enable)
5324 lda #210
5325 ldy #0
5326 jmp $fff4 ; optimise away the rts
5328 status_vdu_bytes: .byte 31,2,0, 17,3, "Score", 31,11,0, 17,2, "Strength", 17,1
5329 ; TAB(1,0), COLOUR 3, "Score", TAB(12,0), COLOUR 2, "Strength", COLOUR 1
5331 start_new_game:
5333 ; Clear the screen.
5334 jsr cls
5336 ; Set the level.
5337 lda #0
5338 sta $578a
5340 ; Set the score.
5341 lda #0
5342 sta $5786
5343 lda #0
5344 sta $5787
5345 lda #0
5346 sta $5788
5348 ; Blank the screen now because it will be blanked before the room is shown
5349 ; and otherwise the strength bar will show briefly.
5350 jsr blank_screen
5352 ; Set the player's strength.
5353 lda #0
5354 sta $5784
5355 lda #64
5356 sta $70
5357 jsr add_strength
5359 ; Set the projectile type.
5360 lda #0
5361 sta $5789
5363 rts
5365 reset_player_position:
5367 lda #1 ; player
5368 sta $5280
5369 lda #6 ; down (first frame)
5370 sta $5281
5371 lda #4 ; y=4
5372 sta $5282
5373 lda #2 ; dy=2
5374 sta $5283
5375 lda #4 ; x=4
5376 sta $5284
5377 lda #3 ; dx=3
5378 sta $5285
5380 rts
5382 start_level:
5384 ; Clear the item/player flags.
5385 lda #0
5386 sta $5780
5388 ; Set current room.
5390 ldx $578a
5391 lda start_rooms_y,x
5392 sta $5782
5393 lda start_rooms_x,x
5394 sta $5783
5396 ; Set the player's position.
5398 jsr reset_player_position
5400 ; Reset the weapon counter.
5401 lda #0
5402 sta $577f
5404 ; Fill the treasure table with objects.
5405 ldx $578a ; level
5406 lda key_rooms,x
5407 sta $80
5409 ldx $578a ; level
5410 lda seeds,x
5411 adc #1
5412 and #31
5413 sta $7c
5414 clc
5415 lda seeds,x
5416 adc #2
5417 and #31
5418 sta $7d
5419 clc
5421 lda $578a ; create an upper limit on the weapon type found in this level
5422 adc #2
5423 sta $5781
5424 clc
5426 lda #$00
5427 sta $8e
5428 lda #$52
5429 sta $8f
5431 ldy #0
5432 start_level_add_treasure_loop:
5434 cpy $80 ; check for the key room
5435 bne start_level_add_treasure_item
5437 lda #5 ; the value to store is type + 1
5438 jmp start_level_add_treasure_store
5440 start_level_add_treasure_item:
5441 clc
5442 jsr unlimited_values
5443 and #$0f
5444 cmp #0
5445 beq start_level_add_treasure_none
5447 clc
5448 sta $8c
5449 tya
5450 adc $8c
5451 and #31
5452 clc
5453 tax
5454 lda treasure_table,x
5456 cmp #4
5457 bmi start_level_add_treasure_weapon
5459 clc
5460 adc #1
5461 jmp start_level_add_treasure_store
5463 start_level_add_treasure_weapon:
5465 ; Only add weapons with types that equal the level number or exceed it
5466 ; by one.
5467 cmp $5781
5468 bcs start_level_add_treasure_none
5470 clc
5471 adc #1 ; store values 0-8 as values 1-9
5472 jmp start_level_add_treasure_store
5474 start_level_add_treasure_none:
5475 clc
5476 lda #0 ; do not put treasure in this room
5478 start_level_add_treasure_store:
5479 clc
5480 sta ($8e),y ; add the item to the table
5482 iny
5483 cpy #121
5484 bmi start_level_add_treasure_loop
5486 ; Write the status text.
5487 ldx #0
5488 write_status_text_loop:
5489 lda status_vdu_bytes,x
5490 jsr $ffee
5491 inx
5492 cpx #25
5493 bmi write_status_text_loop
5495 jsr write_score
5497 clc
5498 rts
5500 main:
5501 jsr init
5503 main_loop:
5505 jsr show_title
5507 jsr start_new_game
5509 level_loop:
5511 jsr start_level
5513 game_loop:
5515 jsr remove_characters
5517 jsr reset_unplot_buffer
5518 jsr reset_plot_buffer
5520 lda $5782 ; current room (y)
5521 sta $78
5522 lda $5783 ; current room (x)
5523 sta $79
5524 jsr plot_room
5525 jsr set_room_palette
5526 jsr create_enemy_positions
5527 jsr add_treasure
5529 jsr plot_the_player
5531 lda #0 ; reset projectile counter
5532 sta $578d
5534 lda #0 ; reset motion counter
5535 sta $578e
5537 lda #63 ; reset generation counter
5538 sta $578f
5540 room_loop:
5541 jsr reset_unplot_buffer
5542 jsr reset_plot_buffer
5544 jsr move_characters
5545 jsr move_projectile
5547 lda $5780 ; is player out of strength ($40), leaving the
5548 and #$c2 ; level (0x80) or completing the game (0x02)?
5549 beq room_loop_player_move
5550 clc
5552 dec $5785 ; leave the loop when the delay
5553 bne room_loop_delay_next
5554 jmp after_room_loop ; counter is about to reset
5556 room_loop_delay_next:
5558 lda $5281 ; leave the loop when the player demise
5559 cmp #11 ; animation has finished
5560 beq room_loop_after_player_move
5561 clc
5563 lda $578e
5564 and #7
5565 bne room_loop_after_player_move
5567 lda $5780 ; skip the animation if leaving the level or
5568 and #$82 ; completing the game
5569 bne room_loop_after_player_move
5571 ; Show the demise animation when appropriate.
5573 lda #$80
5574 sta $74
5575 lda #$52
5576 sta $75
5578 jsr unplot_character
5580 inc $5281
5581 jsr plot_character
5582 jmp room_loop_after_player_move
5584 room_loop_player_move:
5586 ; See if it is time to generate a new enemy.
5587 lda $578f
5588 cmp #0
5589 bne no_emerge_characters
5590 jsr emerge_characters
5592 no_emerge_characters:
5593 clc
5595 jsr check_fire_key
5596 jsr move_player
5597 bcs after_room_loop ; check if we are leaving the level
5599 room_loop_after_player_move:
5600 clc
5602 lda #19
5603 jsr $fff4
5604 jsr plot_buffer
5606 ldx #143 ; Escape key check
5607 jsr check_key
5608 cpy #255
5609 beq main_loop_play_again
5611 ldx #174 ; S key check
5612 jsr check_key
5613 cpy #255
5614 bne no_set_sound
5616 ldx #0
5617 jsr disable_sound
5618 jmp after_sound_checks
5620 no_set_sound:
5622 ldx #239 ; Q key check
5623 jsr check_key
5624 cpy #255
5625 bne after_sound_checks
5627 ldx #1
5628 jsr disable_sound
5630 after_sound_checks:
5632 ldx #200 ; P key check
5633 jsr check_key
5634 cpy #255
5635 bne no_pause
5637 pause_loop:
5639 ldx #201 ; O key check
5640 jsr check_key
5641 cpy #255
5642 bne pause_loop
5644 no_pause:
5645 clc
5647 lda $578d
5648 cmp #0
5649 beq room_loop_no_update_projectile_counter
5651 dec $578d
5653 room_loop_no_update_projectile_counter:
5655 dec $578f ; update generation counter
5657 inc $578e ; update motion counter
5658 clc
5659 jmp room_loop
5661 after_room_loop:
5662 clc
5664 lda $5780
5665 and #$80
5666 bne exit_level
5668 lda $5780
5669 and #$40
5670 bne game_over
5672 lda $5780
5673 and #$02
5674 bne complete_game
5676 jmp game_loop
5678 exit_level:
5680 jsr show_end_of_level_screen
5682 inc $578a
5683 clc
5684 jmp level_loop
5686 game_over:
5687 jsr show_game_over
5688 jmp main_loop_play_again
5690 complete_game:
5691 jsr show_end_of_level_screen
5692 jsr show_complete_game
5693 jmp main_loop_play_again
5695 main_loop_play_again:
5696 jsr cls
5698 ; Check the score against the high scores.
5699 jsr check_high_scores
5701 jmp main_loop
5703 exit:
5704 clc
5705 rts