junglejourney

view mapcode.oph @ 220:f25989daa9f9

Adjusted the joystick threshold values. Ensured that only joystick or keyboard checks are performed depending on the mode of input.
author David Boddie <david@boddie.org.uk>
date Sun Nov 06 02:18:39 2011 +0100
parents 02610f059ac0
children 9011c5310b27
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 jmp main
18 seeds: .byte 100, 239, 183, 144 ; $ef, $b7, $90, $d6, $89
19 start_rooms_x: .byte 5, 3, 5, 10
20 start_rooms_y: .byte 5, 8, 1, 8
21 exit_rooms_x: .byte 7, 9, 3, 0
22 exit_rooms_y: .byte 0, 0, 9, 10
24 ; These values need to be kept in sync - the room numbers must match their
25 ; positions in the room array.
26 key_rooms_x: .byte 1, 5, 10, 1
27 key_rooms_y: .byte 0, 2, 6, 4
28 key_rooms: .byte 1, 27, 76, 45 ; ky*11 + kx
30 treasure_table: .byte 6, 5, 7, 1, 1, 5, 2, 7, 6, 2, 1, 7, 1, 7, 8, 7
31 treasure_table_: .byte 0, 7, 6, 7, 7, 7, 5, 0, 6, 3, 7, 7, 5, 7, 5, 0
33 unlimited_values: ; $7c,$7d=first,second
34 ; Add $7c and $7d, store the result in $7d and the original
35 ; $7d value in $7c, returning the sum in the accumulator.
36 lda $7c
37 sta $7b
38 lda $7d
39 sta $7c
40 adc $7b
41 sta $7d
42 clc
43 rts
45 mod9: ; A = value
46 divide_loop:
47 cmp #9
48 bcc after_divide_loop ; bmi should work here, I think, but it doesn't
49 sec
50 sbc #9
51 jmp divide_loop
53 after_divide_loop:
54 clc
55 rts ; A % 9
57 tile_values_map: .byte 0,1,0,0,0,0,2,3
59 next_value: ; no argument
60 jsr unlimited_values
61 lda $7d
62 jsr mod9
63 and #7 ; (next value % 9) & 7
64 tax
65 lda tile_values_map,x
66 sta $7b
67 rts
69 ; Room filling routines, writing to 0x579c to 0x57ff.
71 draw_top_line: ; $76=tile number for exit/wall
72 ldx #9
73 lda #2
75 draw_top_line_loop0:
76 sta $579c,x
77 dex
78 bpl draw_top_line_loop0
80 ldx #3 ; draw the exit or wall
81 lda $76
82 draw_top_line_loop1:
83 sta $579f,x
84 dex
85 bpl draw_top_line_loop1
86 clc
87 rts
89 draw_left_line: ; $77=tile number for exit/wall
90 ldx #90
91 draw_left_line_loop0:
92 lda #2
93 sta $579c,x
94 txa
95 sec
96 sbc #10
97 tax
98 bpl draw_left_line_loop0
100 ldx #30
101 draw_left_line_loop1:
102 lda $77
103 sta $57ba,x
104 txa
105 sec
106 sbc #10
107 tax
108 bpl draw_left_line_loop1
109 clc
110 rts
112 draw_bottom_line: ; $76=tile number for exit/wall
113 ldx #9
114 lda #2
115 draw_bottom_line_loop0:
116 sta $57f6,x
117 dex
118 bpl draw_bottom_line_loop0
120 ldx #3
121 lda $76
122 draw_bottom_line_loop1:
123 sta $57f9,x
124 dex
125 bpl draw_bottom_line_loop1
126 clc
127 rts
129 draw_right_line: ; $77=tile number for exit/wall
130 ldx #99
131 draw_right_line_loop0:
132 lda #2
133 sta $579c,x
134 txa
135 sec
136 sbc #10
137 tax
138 bpl draw_right_line_loop0
140 ldx #30
141 draw_right_line_loop1:
142 lda $77
143 sta $57c3,x
144 txa
145 sec
146 sbc #10
147 tax
148 bpl draw_right_line_loop1
149 clc
150 rts
152 make_empty_room:
154 ldx #99
155 make_empty_room_loop:
156 lda #0
157 sta $579c,x
158 dex
159 bpl make_empty_room_loop
161 rts
163 make_room: ; $78,$79=i,j
165 ; Fills the room array at 579c with values.
166 ; Tiles 0,1,2,3 are map tiles that will be shown by the plot_tile routine.
167 ; Other tiles are plotted separately:
168 ; 4 = exit
169 ; 5 = final exit
170 ; 6 = weapon (bits 3,4 are type)
171 ; 7 = treasure (bits 3,4 are type)
173 ; Fill the room with empty space.
175 jsr make_empty_room
177 ; Determine if there is a top exit.
179 lda #0
180 sta $76
182 lda $78 ; i == 0
183 cmp #0
184 bne not_top_screen
185 lda #2
186 sta $76
187 jmp do_top_exit
189 not_top_screen:
190 clc
192 lda $78
193 and #7 ; i & 7
194 sta $70 ; temporary result
195 lda $79
196 and #7 ; j & 7
197 cmp $70
198 beq do_top_exit
199 clc
201 lda $78
202 eor $79 ; i ^ j
203 adc $78 ; + i
204 clc
205 cmp $79 ; (i ^ j) + i == j
206 bne do_top_exit
207 lda #2
208 sta $76 ; top exit
210 do_top_exit:
211 jsr draw_top_line
213 ; Determine if there is a left exit.
214 lda #0
215 sta $77
217 lda $79
218 cmp #0
219 bne not_left_screen
220 lda #2
221 sta $77
222 jmp do_left_exit
224 not_left_screen:
225 clc
227 lda $78
228 and #3 ; i & 3
229 sta $70 ; temporary result
230 lda $79
231 and #3 ; j & 3
232 cmp $70
233 beq do_left_exit
234 clc
236 lda $78
237 ora $79 ; i | j
238 eor $79 ; ^ j
239 cmp $78 ; (i | j) ^ j == i
240 bne do_left_exit
241 lda #2
242 sta $77 ; left exit
244 do_left_exit:
245 jsr draw_left_line
247 ; Determine if there is a right exit.
248 lda #0
249 sta $77
251 lda $79
252 cmp #10
253 bne not_right_screen
254 lda #2
255 sta $77
256 jmp do_right_exit
258 not_right_screen:
259 clc
261 lda $78
262 and #3 ; i & 3
263 sta $70 ; temporary result
264 lda $79
265 adc #1
266 and #3 ; j & 3
267 cmp $70
268 beq do_right_exit
269 clc
271 lda $79
272 adc #1
273 sta $70
275 lda $78
276 ora $70 ; i | j
277 eor $70 ; ^ j
278 cmp $78 ; (i | j) ^ j == i
279 bne do_right_exit
280 lda #2
281 sta $77 ; right exit
283 do_right_exit:
284 jsr draw_right_line
286 ; Determine if there is a bottom exit.
287 lda #0
288 sta $76
290 lda $78
291 cmp #10
292 bne not_bottom_screen
293 lda #2
294 sta $76
295 jmp do_bottom_exit
297 not_bottom_screen:
298 clc
300 lda $78
301 adc #1
302 and #7 ; i & 7
303 sta $70 ; temporary result
304 lda $79
305 and #7 ; j & 7
306 cmp $70
307 beq do_bottom_exit
308 clc
310 lda $78
311 adc #1
312 sta $70
314 eor $79 ; i ^ j
315 adc $70 ; + i
316 cmp $79 ; (i ^ j) + i == j
317 bne do_bottom_exit
318 lda #2
319 sta $76 ; bottom exit
321 do_bottom_exit:
322 jsr draw_bottom_line
324 ; Add the final exit.
326 lda $578a
327 cmp #3
328 bmi make_room_no_final_exit
330 lda $78
331 cmp #0
332 bne make_room_no_final_exit
334 lda $79
335 cmp #2
336 bne make_room_no_final_exit
338 lda #6
339 sta $57a0
340 lda #7
341 sta $57a1
343 make_room_no_final_exit:
345 ; Make sure that the starting, exit, key rooms are empty.
347 ldx $578a ; level number
348 lda start_rooms_y,x
349 cmp $78
350 bne make_room_not_starting_room
351 lda start_rooms_x,x
352 cmp $79
353 bne make_room_not_starting_room
355 lda #3
356 sta $70
357 jmp add_room_decoration ; optimise away the rts
359 make_room_not_starting_room:
361 lda exit_rooms_y,x
362 cmp $78
363 bne make_room_not_exit_room
364 lda exit_rooms_x,x
365 cmp $79
366 bne make_room_not_exit_room
368 ; Add an exit to the room.
369 lda $78
370 eor $79
371 and #15
372 tax
373 lda exit_room_offsets,x
374 tax
375 lda $5780
376 and #1
377 beq exit_not_open
379 lda #5
380 sta $579c,x
381 jmp exit_decoration
383 exit_not_open:
384 clc
385 lda #4
386 sta $579c,x
388 exit_decoration:
389 lda #3
390 sta $70
391 jmp add_room_decoration ; optimise away the rts
393 make_room_not_exit_room:
395 lda key_rooms_y,x
396 cmp $78
397 bne make_room_not_key_room
398 lda key_rooms_x,x
399 cmp $79
400 bne make_room_not_key_room
402 lda #1
403 sta $70
404 jmp add_room_decoration ; optimise away the rts
406 make_room_not_key_room:
407 clc
409 ; Fill in the room details.
411 lda $79
412 sta $7c
413 sec
414 ldx $578a
415 lda seeds,x
416 sbc $78
417 sec
418 sta $7d
419 clc
421 ; Discard the first ten values.
423 ldy #10
424 make_room_loop0:
425 jsr unlimited_values
426 dey
427 bne make_room_loop0
429 ; Fill the room array with values.
431 lda #$a7
432 sta $70
433 lda #$57
434 sta $71
436 ldy #0
437 make_room_loop1:
439 jsr next_value
440 sta ($70),y
441 iny
442 cpy #8
443 bne make_room_loop1 ; continue the same row
445 lda $70
446 cmp #$ed
447 beq make_room_loop1_exit ; exit after the last row
449 adc #10
450 sta $70
451 ldy #0 ; reset the row counter
452 jmp make_room_loop1
454 make_room_loop1_exit:
455 rts
457 decoration_offsets: .byte 11,18,81,88
459 add_room_decoration:
461 lda #$9c
462 sta $8e
463 lda #$57
464 sta $8f
466 ldx #3
467 add_room_decoration_loop:
469 lda decoration_offsets,x
470 tay
471 lda $70
472 sta ($8e),y
473 dex
474 bpl add_room_decoration_loop
476 clc
477 rts
479 exit_room_offsets: .byte 35,66,63,56,34,44,64,33,36,55,65,53,45,46,54,43
480 treasure_x: .byte 3, 2, 4, 8, 2, 5, 4, 1, 3, 8, 6, 5, 7, 1, 7, 6
481 treasure_y: .byte 1, 3, 7, 7, 2, 3, 6, 1, 4, 6, 8, 5, 5, 4, 8, 2
483 eleven_times_table: .byte 0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 110
485 add_treasure: ; $78,$79 = i,j
487 lda $78
488 tax
489 lda eleven_times_table,x
490 adc $79
491 tax
493 lda $5200,x
494 ora #$80
495 sta $5200,x ; set the top bit (room visited)
496 and #$7f ; mask off the top bit to obtain the item number + 1
497 cmp #0
498 beq add_treasure_exit
500 sec
501 sbc #1
502 sta $528d ; store weapon/treasure type
503 clc
505 lda $78
506 eor $79
507 adc $528d
508 and #15
509 sta $70
511 lda #15
512 sta $8c
513 ldy #0
514 add_treasure_loop:
516 clc
518 ldx $70
519 lda treasure_y,x ; y
520 sta $8d
521 tax
522 lda room_row_offsets_low,x
523 sta $80
525 ldx $70
526 lda treasure_x,x ; x
527 sta $8e
528 adc $80
529 sta $80
531 lda #$57
532 adc #0
533 sta $81
534 clc
536 lda ($80),y ; tile
537 cmp #0
538 bne add_treasure_loop_next
540 lda #4 ; type (weapon/treasure)
541 sta $528c
542 lda $8d ; y
543 sta $528e
544 lda #1 ; dy
545 sta $528f
546 lda $8e ; x
547 sta $5290
548 lda #0 ; dx
549 sta $5291
551 lda #$8c
552 sta $74
553 lda #$52
554 sta $75
555 jmp plot_character ; optimise away the rts
557 add_treasure_loop_next:
558 dec $8c
559 bmi add_treasure_exit
561 dec $70
562 bpl add_treasure_loop
564 lda #15
565 sta $70
566 jmp add_treasure_loop
568 add_treasure_exit:
569 clc
570 rts
572 create_enemy_positions:
574 lda #31 ; counter
575 sta $7e
577 lda #1 ; x
578 sta $70
580 lda #1 ; y
581 sta $71
583 lda #$a7
584 sta $72
585 lda #$57
586 sta $73
588 ldx #15 ; offset into position areas
589 ldy #0
591 create_enemy_positions_loop:
593 jsr unlimited_values
594 and #7
595 sta $80 ; store temporarily
597 lda $72
598 adc $80
599 sta $72 ; update the offset into the room data
600 clc
602 lda $70
603 adc $80 ; update x
604 cmp #10
605 bpl create_enemy_positions_next_row
607 sta $70 ; store x
608 jmp create_enemy_positions_check_tile
610 create_enemy_positions_next_row:
612 sec
613 sbc #10
614 sta $70 ; store the x position on the next row
615 clc
617 lda $71
618 adc #1 ; update the y position
619 cmp #10
620 bpl create_enemy_positions_to_top
622 sta $71 ; store the y position for the next row
623 jmp create_enemy_positions_check_tile
625 create_enemy_positions_to_top:
627 lda #1 ; reset the x, y and offset values
628 sta $70
629 sta $71
630 lda #$a7
631 sta $72
633 create_enemy_positions_check_tile:
635 lda ($72),y
636 cmp #0
637 bne create_enemy_positions_next
639 lda $70
640 sta $0ee0,x ; store the x value
642 lda $71
643 sta $0ef0,x ; store the y value
645 dex
646 bmi create_enemy_positions_exit
648 create_enemy_positions_next:
649 clc
650 dec $7e
651 bpl create_enemy_positions_loop
653 ; The position areas were not filled. Write invalid values into the
654 ; first area for the emerge routine to find.
656 lda #0
657 create_enemy_positions_fill_loop:
659 sta $0ee0,x
660 dex
661 bpl create_enemy_positions_fill_loop
663 create_enemy_positions_exit:
664 clc
665 rts
667 plot: ; $70,$71=source address
668 ; $72,$73=destination address
669 ldy #$1f
670 plotloop0:
671 lda ($70),y
672 sta ($72),y
673 dey
674 bpl plotloop0
676 lda $72
677 adc #$20
678 sta $72
679 lda $73
680 adc #$01
681 sta $73 ; next line minus 0x20
682 clc
684 ldy #$3f
685 plotloop1:
686 lda ($70),y
687 sta ($72),y
688 dey
689 cpy #$20
690 bpl plotloop1
692 lda $72
693 adc #$20
694 sta $72
695 lda $73
696 adc #$01
697 sta $73 ; next line minus 0x20
698 clc
700 ldy #$5f
701 plotloop2:
702 lda ($70),y
703 sta ($72),y
704 dey
705 cpy #$40
706 bpl plotloop2
708 sec
709 lda $72
710 sbc #$20
711 sta $72
712 lda $73
713 sbc #$02
714 sta $73 ; back two lines minus 0x20
715 clc
717 rts
721 plot_blank_xy: ; X=y, Y=x
723 lda screen_rows_low,x
724 sta $72
725 lda screen_rows_high,x
726 sta $73
728 tya
729 tax
730 lda screen_columns_low,x
731 adc $72
732 sta $72
733 lda screen_columns_high,x
734 adc $73
735 sta $73
736 clc
737 ; run on into plot_blank
739 plot_blank: ; $72,$73=destination address
741 ldy #$1f
742 lda #0
743 plot_blank_loop0:
744 sta ($72),y
745 dey
746 bpl plot_blank_loop0
748 lda $72
749 adc #$20
750 sta $72
751 lda $73
752 adc #$01
753 sta $73 ; next line minus 0x20
754 clc
756 ldy #$3f
757 lda #0
758 plot_blank_loop1:
759 sta ($72),y
760 dey
761 cpy #$20
762 bpl plot_blank_loop1
764 lda $72
765 adc #$20
766 sta $72
767 lda $73
768 adc #$01
769 sta $73 ; next line minus 0x20
770 clc
772 ldy #$5f
773 lda #0
774 plot_blank_loop2:
775 sta ($72),y
776 dey
777 cpy #$40
778 bpl plot_blank_loop2
780 sec
781 lda $72
782 sbc #$20
783 sta $72
784 lda $73
785 sbc #$02
786 sta $73 ; back two lines minus 0x20
787 clc
789 rts
791 plot_tile: ; $7b=tile number
792 ; 1 = flowers/decoration
793 ; 2 = trees/wall
794 ; 3 = trees
795 ; 4 = exit
796 ; 5 = open exit
797 ; 6 = final exit (left)
798 ; 7 = final exit (right)
799 ; $72,$73=screen position
801 lda $7b
802 cmp #0
803 bne plot_tile_sprite
804 clc
805 jmp plot_blank ; optimise away the rts
807 plot_tile_sprite:
808 clc
809 tax
810 dex
811 lda tile_addresses_low,x
812 sta $70
813 lda tile_addresses_high,x
814 sta $71
816 lda $7b
817 cmp #4
818 bpl plot_not_blank_after_add_loop ; don't adjust the tile for later levels
820 clc
821 lda $578a
822 and #3 ; change the tile set for later levels
823 tax
825 plot_not_blank_add_loop:
827 cpx #2
828 bne plot_not_blank_not_2
829 dex
830 jmp plot_not_blank_not_0
832 plot_not_blank_not_2:
833 beq plot_not_blank_add_loop
834 cpx #0
836 plot_not_blank_not_0:
837 beq plot_not_blank_after_add_loop
838 clc
839 lda $70
840 adc #$20
841 sta $70
842 lda $71
843 adc #$01
844 sta $71
845 dex
846 jmp plot_not_blank_add_loop
848 plot_not_blank_after_add_loop:
849 clc
850 jsr plot
851 rts
853 plot_room: ; $78,$79 = i,j (from $5782,$5783)
854 jsr blank_screen
856 lda $5782
857 sta $78
858 lda $5783
859 sta $79
861 jsr make_room
862 ; Run on into the next piece of code.
864 plot_room_tiles:
866 lda #$80
867 sta $72
868 lda #$5a
869 sta $73 ; $72,$73 = screen position
871 lda #0
872 sta $7a
873 row_loop:
875 lda #9
876 sta $76
878 column_loop:
879 lda $7a
880 tax
881 lda $579c,x
882 sta $7b
883 jsr plot_tile
885 inc $7a
886 lda $76
887 sec
888 sbc #1
889 sta $76
890 clc
891 cmp #0
892 bpl column_loop
894 clc
896 lda $72
897 adc #$80
898 sta $72
899 lda $73
900 adc #$02
901 sta $73
902 clc
903 cmp #$80
904 beq end_rows
906 jmp row_loop
908 end_rows:
909 rts
911 set_room_palette: ; $78=i; $79=j
913 lda #1
914 sta $70
915 lda $78
916 eor $79
917 and #3
918 tax
919 lda room_palettes,x
920 sta $71
921 jsr set_palette
923 jsr set_core_palette
924 rts
926 room_palettes: .byte 1, 6, 5, 7
928 ; Sprite data stored in memory: 00 04 08 0c 10 14 18 1c 20 24 28 2c
930 plot8x24_y0: ; $70,$71=source address
931 ; $72,$73=destination address
933 ldx #2
935 plot8x24_y0_loop:
937 ldy #15
939 plotloop8x24_y0_0:
940 lda ($70),y
941 eor ($72),y
942 sta ($72),y
943 dey
944 bpl plotloop8x24_y0_0
946 dex
947 bmi plot8x24_y0_exit
949 lda $72
950 adc #$40
951 sta $72
952 lda $73
953 adc #$01
954 sta $73
955 clc
957 lda $70
958 adc #16
959 sta $70
960 lda $71
961 adc #0
962 sta $71
963 clc
965 jmp plot8x24_y0_loop
967 plot8x24_y0_exit:
968 clc
969 jmp plot_buffer_loop_next
972 plot8x8_y1: ; $70,$71=source address
973 ; $72,$73=destination address
974 lda #2
975 sta $7e
976 lda #10
977 sta $7f
979 lda #0 ; plotting 1 8x8 piece
980 sta $8a
982 jmp plot8x24_y123 ; optimise away the rts
984 plot8x24_y1: ; $70,$71=source address
985 ; $72,$73=destination address
986 lda #2
987 sta $7e
988 lda #10
989 sta $7f
991 lda #2 ; plotting 3 8x8 pieces
992 sta $8a
994 jmp plot8x24_y123 ; optimise away the rts
996 plot8x8_y2: ; $70,$71=source address
997 ; $72,$73=destination address
998 lda #4
999 sta $7e
1000 lda #12
1001 sta $7f
1003 lda #0 ; plotting 1 8x8 piece
1004 sta $8a
1006 jmp plot8x24_y123 ; optimise away the rts
1008 plot8x24_y2: ; $70,$71=source address
1009 ; $72,$73=destination address
1010 lda #4
1011 sta $7e
1012 lda #12
1013 sta $7f
1015 lda #2 ; plotting 3 8x8 pieces
1016 sta $8a
1018 jmp plot8x24_y123 ; optimise away the rts
1020 plot8x8_y3: ; $70,$71=source address
1021 ; $72,$73=destination address
1022 lda #6
1023 sta $7e
1024 lda #14
1025 sta $7f
1027 lda #0 ; plotting 1 8x8 piece
1028 sta $8a
1030 jmp plot8x24_y123 ; optimise away the rts
1032 plot8x24_y3: ; $70,$71=source address
1033 ; $72,$73=destination address
1034 lda #6
1035 sta $7e
1036 lda #14
1037 sta $7f
1039 lda #2 ; plotting 3 8x8 pieces
1040 sta $8a
1042 ; Run on into the next routine.
1044 plot8x24_y123: ; $70,$71=source address
1045 ; $72,$73=destination address
1046 ; $7e=offset into source data for first column
1047 ; $7f=offset into source data for second column
1049 plot8x24_y123_loop:
1051 ldx #0
1052 plot8x24_y123_upper_loop_outer:
1054 ldy $7e,x
1055 lda plot_upper_offsets,x
1056 sta $89
1058 plot8x24_y123_upper_loop_inner: ; plot the first column until
1059 dey ; we reach the start
1060 cpy $89
1061 bmi plot8x24_y123_upper_loop_inner_endloop
1062 lda ($70),y
1063 eor ($72),y
1064 sta ($72),y
1065 jmp plot8x24_y123_upper_loop_inner
1067 plot8x24_y123_upper_loop_inner_endloop:
1068 clc
1070 inx
1071 cpx #2
1072 bne plot8x24_y123_upper_loop_outer
1074 clc
1075 lda $72 ; move the destination pointer to refer to the next line
1076 adc #$38
1077 sta $72
1078 lda $73
1079 adc #$01
1080 sta $73
1081 clc
1083 ldx #0
1084 plot8x24_y123_lower_loop_outer:
1086 lda plot_lower_offsets,x
1087 tay
1088 lda $7e,x
1089 sta $89
1091 plot8x24_y123_lower_loop_inner: ; plot until we reach the initial
1092 lda ($70),y ; offset for the column
1093 eor ($72),y
1094 sta ($72),y
1095 dey
1096 cpy $89
1097 bpl plot8x24_y123_lower_loop_inner
1099 inx
1100 cpx #2
1101 bne plot8x24_y123_lower_loop_outer
1103 dec $8a
1104 bmi plot8x24_y123_exit
1106 clc
1107 lda $70 ; update the source pointer to refer to the next piece
1108 adc #16 ; of sprite data
1109 sta $70
1110 lda $71
1111 adc #0
1112 sta $71
1113 clc
1115 lda $72 ; update the destination pointer to point to the next
1116 adc #8 ; space
1117 sta $72
1118 lda $73
1119 adc #0
1120 sta $73
1121 clc
1123 jmp plot8x24_y123_loop
1125 plot8x24_y123_exit:
1126 clc
1127 jmp plot_buffer_loop_next
1129 plot16x16_y0: ; $70,$71=source address
1130 ; $72,$73=destination address
1131 ldy #31
1133 plotloop16x16_y0_0:
1134 lda ($70),y
1135 eor ($72),y
1136 sta ($72),y
1137 dey
1138 bpl plotloop16x16_y0_0
1139 clc
1141 lda $72
1142 adc #$20
1143 sta $72
1144 lda $73
1145 adc #$01
1146 sta $73 ; 0x140 - 32
1147 clc
1149 ldy #63
1151 plotloop16x16_y0_1:
1152 lda ($70),y
1153 eor ($72),y
1154 sta ($72),y
1155 dey
1156 cpy #32
1157 bpl plotloop16x16_y0_1
1158 clc
1160 jmp plot_buffer_loop_next
1162 ; Sprite data stored in memory: 00 04 08 0c 10 14 18 1c 20 24 28 2c 30 34 38 3c
1164 plot16x16_y1: ; $70,$71=source address
1165 ; $72,$73=destination address
1167 lda #2
1168 sta $7e
1169 lda #10
1170 sta $7f
1171 lda #18
1172 sta $80
1173 lda #26
1174 sta $81
1175 jmp plot16x16_y123 ; optimise away the rts
1177 plot16x16_y2: ; $70,$71=source address
1178 ; $72,$73=destination address
1180 lda #4
1181 sta $7e
1182 lda #12
1183 sta $7f
1184 lda #20
1185 sta $80
1186 lda #28
1187 sta $81
1188 jmp plot16x16_y123 ; optimise away the rts
1190 plot16x16_y3: ; $70,$71=source address
1191 ; $72,$73=destination address
1193 lda #6
1194 sta $7e
1195 lda #14
1196 sta $7f
1197 lda #22
1198 sta $80
1199 lda #30
1200 sta $81
1201 ; Run on into the next routine.
1203 plot16x16_y123: ; $70,$71=source address
1204 ; $72,$73=destination address
1205 ; $7e=offset into source data for first column
1206 ; $7f=offset into source data for second column
1207 ; $80=offset into source data for third column
1208 ; $81=offset into source data for fourth column
1210 lda #1
1211 sta $8a
1213 plot16x16_y123_loop:
1215 ldx #0
1216 plot16x16_y123_upper_loop_outer:
1218 ldy $7e,x
1219 lda plot_upper_offsets,x
1220 sta $89
1222 plot16x16_y123_upper_loop_inner:
1224 dey
1225 cpy $89
1226 bmi plot16x16_y123_upper_loop_inner_endloop
1227 lda ($70),y
1228 eor ($72),y
1229 sta ($72),y
1230 jmp plot16x16_y123_upper_loop_inner
1232 plot16x16_y123_upper_loop_inner_endloop:
1233 clc
1235 inx
1236 cpx #4
1237 bne plot16x16_y123_upper_loop_outer
1239 clc
1240 lda $72 ; move the destination pointer to refer to the next line
1241 adc #$38
1242 sta $72
1243 lda $73
1244 adc #$01
1245 sta $73
1246 clc
1248 ldx #0
1249 plot16x16_y123_lower_loop_outer:
1251 lda plot_lower_offsets,x
1252 tay
1253 lda $7e,x
1254 sta $89
1256 plot16x16_y123_lower_loop_inner: ; plot until we reach the initial offset
1257 lda ($70),y ; for the column
1258 eor ($72),y
1259 sta ($72),y
1260 dey
1261 cpy $89
1262 bpl plot16x16_y123_lower_loop_inner
1264 inx
1265 cpx #4
1266 bne plot16x16_y123_lower_loop_outer
1268 dec $8a
1269 bmi plot16x16_y123_exit
1271 clc
1272 lda $70 ; update the source pointer to refer to the next piece
1273 adc #32 ; of sprite data
1274 sta $70
1275 lda $71
1276 adc #0
1277 sta $71
1278 clc
1280 lda $72 ; update the destination pointer to point to the next
1281 adc #8 ; space
1282 sta $72
1283 lda $73
1284 adc #0
1285 sta $73
1286 clc
1288 jmp plot16x16_y123_loop
1290 plot16x16_y123_exit:
1291 clc
1292 jmp plot_buffer_loop_next
1294 plot_upper_offsets: .byte 0, 8, 16, 24
1295 plot_lower_offsets: .byte 7, 15, 23, 31
1297 plot8x8_y0: ; $70,$71=source address
1298 ; $72,$73=destination address
1299 ldy #15
1301 plotloop8x8_y0_0:
1302 lda ($70),y
1303 eor ($72),y
1304 sta ($72),y
1305 dey
1306 bpl plotloop8x8_y0_0
1307 clc
1309 jmp plot_buffer_loop_next
1312 check_key: ; x=key code
1313 lda #129 ; returns y=255 or 0
1314 ldy #255
1315 jsr $fff4
1316 rts
1318 screen_rows_low: .byte $80,$40,$00,$c0,$80,$40,$00,$c0,$80,$40
1319 screen_rows_high: .byte $5a,$5e,$62,$65,$69,$6d,$71,$74,$78,$7c
1320 screen_subrows_low: .byte $00,$06,$44,$82
1321 screen_subrows_high: .byte $00,$00,$01,$02
1323 screen_columns_low: .byte $00,$20,$40,$60,$80,$a0,$c0,$e0,$00,$20
1324 screen_columns_high: .byte $00,$00,$00,$00,$00,$00,$00,$00,$01,$01
1325 screen_subcolumns_low: .byte $00,$08,$10,$18
1327 unplot_character: ; $74,$75=character address
1329 lda $82 ; store the unplot buffer address in $78,$79
1330 sta $78
1331 lda $83
1332 sta $79
1333 jsr plot_character_sprite
1334 lda $78
1335 sta $82 ; update the latest space in the unplot buffer
1336 rts
1338 plot_character: ; $74,$75=character address
1340 lda $84 ; store the plot buffer address in $78,$79
1341 sta $78
1342 lda $85
1343 sta $79
1344 jsr plot_character_sprite
1345 lda $78
1346 sta $84 ; update the latest space in the plot buffer
1347 rts
1349 plot_character_sprite: ; $74,$75=character address
1350 ; $78,$79=unplot/plot buffer address
1352 ldy #0
1353 lda ($74),y
1354 cmp #0
1355 bne plot_characters_read_character
1356 jmp plot_characters_next
1358 plot_characters_read_character:
1359 clc
1361 sta $77 ; temporarily store the object type
1363 ; Use lookup tables to load the offsets into the sprite.
1365 ; Direction
1366 iny
1367 lda ($74),y
1368 sta $80 ; temporarily store the direction
1370 ; y
1371 iny
1372 lda ($74),y
1373 tax
1374 lda screen_rows_low,x
1375 sta $72
1376 lda screen_rows_high,x
1377 sta $73
1378 clc
1380 ; dy
1381 iny
1382 lda ($74),y
1383 sta $76
1384 tax
1385 lda screen_subrows_low,x
1386 adc $72
1387 sta $72
1388 lda screen_subrows_high,x
1389 adc $73
1390 sta $73
1391 clc
1393 ; x
1394 iny
1395 lda ($74),y
1396 tax
1397 lda screen_columns_low,x
1398 adc $72
1399 sta $72
1400 lda screen_columns_high,x
1401 adc $73
1402 sta $73
1403 clc
1405 ; dx
1406 iny
1407 lda ($74),y
1408 tax
1409 lda screen_subcolumns_low,x
1410 adc $72
1411 sta $72
1412 clc
1414 lda $77
1415 cmp #1
1416 bne plot_characters_loop_not_player
1418 ; Plot 8x24 sprites (player)
1420 ldx $80
1421 lda player_direction_chars_low,x
1422 sta $70
1423 lda player_direction_chars_high,x
1424 sta $71
1426 ; Use the dy value to determine which plotting routine to use.
1428 ldy #0
1429 ldx $76
1430 lda plot_routine_indices_8x24,x
1432 sta ($78),y
1433 jmp plot_characters_stored
1436 plot_characters_loop_not_player:
1437 cmp #2
1438 bne plot_characters_loop_not_projectile
1440 ; Plot 8x8 sprites (projectiles)
1442 lda $80
1443 and #7
1444 tax
1445 lda projectile_chars_low,x
1446 sta $70
1447 lda #projectile_chars_high
1448 sta $71
1450 ; Use the dy value to determine which plotting routine to use.
1452 ldy #0
1453 ldx $76
1454 lda plot_routine_indices_8x8,x
1456 sta ($78),y
1457 jmp plot_characters_stored
1460 plot_characters_loop_not_projectile:
1461 cmp #3
1462 bne plot_characters_loop_not_explosion
1464 ; Plot 16x16 sprites (emerging, explosions)
1466 ; Select the sprites to use.
1468 lda $80
1469 and #7 ; only keep the bits required to find the correct sprite
1470 clc
1471 tax
1472 lda emerge_explode_chars_low,x
1473 sta $70
1474 lda emerge_explode_chars_high,x
1475 sta $71
1477 jmp plot_characters_16x16
1479 plot_characters_loop_not_explosion:
1480 cmp #4
1481 bne plot_characters_loop_not_item
1483 ; Plot 16x16 sprites (items)
1485 ; Select the sprites to use.
1487 lda $80
1488 and #$0f ; only keep the bits required to find the correct sprite
1489 clc
1490 tax
1491 lda item_chars_low,x
1492 sta $70
1493 lda item_chars_high,x
1494 sta $71
1496 jmp plot_characters_16x16
1498 plot_characters_loop_not_item:
1499 cmp #8
1500 bmi plot_characters_loop_not_enemy
1502 ; Plot 16x16 sprites (enemies)
1504 ; Select the set of sprites to use.
1506 and #$70
1507 lsr
1508 lsr
1509 lsr ; bits 4,5,6 >> 3 -> bits 1,2,3
1510 clc
1511 sta $71 ; 0x00, 0x02, 0x04, 0x06, 0x08
1513 lda $80
1514 and #7 ; keep the animation bits
1515 tax
1516 lda enemy_direction_chars_low,x
1517 sta $70
1518 lda enemy_direction_chars_high,x
1519 adc $71
1520 sta $71
1522 plot_characters_16x16:
1524 ; Use the dy value to determine which plotting routine to use.
1526 ldy #0
1527 ldx $76
1528 lda plot_routine_indices_16x16,x
1530 sta ($78),y
1532 plot_characters_stored:
1534 iny
1535 lda $70
1536 sta ($78),y
1537 iny
1538 lda $71
1539 sta ($78),y
1540 iny
1541 lda $72
1542 sta ($78),y
1543 iny
1544 lda $73
1545 sta ($78),y
1547 clc
1548 lda $78
1549 adc #12
1550 sta $78
1552 plot_characters_loop_not_enemy:
1554 plot_characters_next:
1556 lda #255 ; terminate this stream of entries in the plot buffer
1557 ldy #0
1558 sta ($78),y
1559 clc
1560 rts
1562 plot_routine_indices_8x24: .byte 1, 2, 3, 4
1563 plot_routine_indices_8x8: .byte 5, 6, 7, 8
1564 plot_routine_indices_16x16: .byte 9, 10, 11, 12
1566 reset_plot_buffer:
1567 lda #$06 ; reset the index into the plot buffer
1568 sta $84
1569 lda #$53
1570 sta $85
1572 lda #255 ; terminate the plot list
1573 ldy #0
1574 sta ($84),y
1575 rts
1577 reset_unplot_buffer:
1578 lda #$00 ; reset the index into the plot buffer
1579 sta $82
1580 lda #$53
1581 sta $83
1583 lda #255 ; terminate the unplot list
1584 ldy #0
1585 sta ($82),y
1586 rts
1588 plot_buffer_types_low: .byte <plot_buffer_loop_next
1589 plot_buffer_types_low1: .byte <plot8x24_y0, <plot8x24_y1, <plot8x24_y2, <plot8x24_y3
1590 plot_buffer_types_low2: .byte <plot8x8_y0, <plot8x8_y1, <plot8x8_y2, <plot8x8_y3
1591 plot_buffer_types_low3: .byte <plot16x16_y0, <plot16x16_y1, <plot16x16_y2, <plot16x16_y3
1593 plot_buffer_types_high: .byte >plot_buffer_loop_next
1594 plot_buffer_types_high1: .byte >plot8x24_y0, >plot8x24_y1, >plot8x24_y2, >plot8x24_y3
1595 plot_buffer_types_high2: .byte >plot8x8_y0, >plot8x8_y1, >plot8x8_y2, >plot8x8_y3
1596 plot_buffer_types_high3: .byte >plot16x16_y0, >plot16x16_y1, >plot16x16_y2, >plot16x16_y3
1598 plot_buffer:
1600 lda #$00
1601 sta $84
1602 lda #$53
1603 sta $85
1605 lda #6
1606 sta $88
1608 plot_buffer_loop:
1610 ldy #0
1611 lda ($84),y
1612 cmp #255
1613 beq plot_buffer_loop_skip
1615 clc
1616 tax
1617 lda plot_buffer_types_low,x
1618 sta $86
1619 lda plot_buffer_types_high,x
1620 sta $87
1622 iny
1623 lda ($84),y
1624 sta $70
1626 iny
1627 lda ($84),y
1628 sta $71
1630 iny
1631 lda ($84),y
1632 sta $72
1634 iny
1635 lda ($84),y
1636 sta $73
1638 jmp ($86) ; returns to plot_buffer_loop_next
1640 plot_buffer_loop_skip:
1642 lda $88
1643 cmp #12
1644 beq plot_buffer_exit ; both unplot and plot lists have terminated
1646 lda #12
1647 sta $88
1648 lda $84
1649 adc #6
1650 sta $84
1651 jmp plot_buffer_loop
1653 plot_buffer_loop_next:
1654 clc
1656 lda $84
1657 adc $88
1658 sta $84
1659 jmp plot_buffer_loop
1661 plot_buffer_exit:
1662 clc
1663 rts
1665 room_row_offsets_low: .byte $9c,$a6,$b0,$ba,$c4,$ce,$d8,$e2,$ec,$f6
1667 animate_player_left:
1669 ; Set the direction and toggle the animation bit.
1671 lda $5281
1672 and #1
1673 eor #1 ; toggle animation flag
1674 sta $5281 ; left (directional bits are 0)
1676 jsr plot_character
1677 rts
1679 animate_player_right:
1681 ; Set the direction and toggle the animation bit.
1683 lda $5281
1684 and #1 ; remove direction information (result is 0)
1685 eor #1 ; toggle animation flag
1686 ora #2 ; right
1687 sta $5281
1689 jsr plot_character
1690 rts
1692 animate_player_up:
1694 ; Set the direction and toggle the animation bit.
1696 lda $5281
1697 and #1 ; remove direction information (result is 0)
1698 eor #1 ; toggle animation flag
1699 ora #4 ; up
1700 sta $5281
1702 jsr plot_character
1703 rts
1705 animate_player_down:
1707 ; Set the direction and toggle the animation bit.
1709 lda $5281
1710 and #1 ; remove direction information (result is 0)
1711 eor #1 ; toggle animation flag
1712 ora #6 ; down
1713 sta $5281
1715 jsr plot_character
1716 rts
1718 move_player:
1720 lda $578e
1721 and #1
1722 beq move_player_allowed
1724 clc
1725 rts
1727 move_player_allowed:
1729 lda #$80 ; set up the address of the player character
1730 sta $74
1731 lda #$52
1732 sta $75
1734 ; Handle joystick
1736 lda $577e
1737 cmp #0
1738 beq move_player_handle_left_key
1740 lda #128
1741 ldx #1
1742 jsr $fff4
1743 cpy #96 ; <= -32
1744 bcs move_player_check_joystick_left
1745 jmp move_player_right
1747 move_player_check_joystick_left:
1748 cpy #160 ; >= 32
1749 bcs move_player_left
1750 jmp move_player_handle_joystick_up_down
1752 move_player_handle_left_key:
1754 ; Handle the left key.
1756 ldx #158 ; (Z)
1757 jsr check_key
1758 cpy #255
1759 beq move_player_left
1760 jmp move_player_check_right_key
1762 move_player_left:
1764 lda $5285 ; read dx
1765 cmp #0
1766 beq move_player_left_check_x
1768 jsr unplot_character ; unplot the player character
1769 dec $5285
1770 clc
1771 jmp animate_player_left ; optimise away the rts
1773 move_player_left_check_x: ; Check the x offset.
1775 lda $5284
1776 cmp #0
1777 beq move_player_leave_room_left
1779 clc
1780 tay
1781 dey ; x - 1
1782 lda $5282 ; load the y offset
1783 tax ; as an index
1784 lda room_row_offsets_low,x ; read the address of the row
1785 sta $70
1786 lda #$57
1787 sta $71
1788 lda ($70),y ; load the tile to the left
1790 cmp #5 ; check for the open exit or final exit
1791 bmi move_player_not_left_exit1
1792 jmp try_to_exit_level ; optimise away the rts
1794 move_player_not_left_exit1:
1795 cmp #0
1796 beq move_player_left_check_dy
1797 jmp move_player_not_horizontal
1799 move_player_left_check_dy:
1801 lda $5283 ; dy
1802 cmp #0
1803 beq move_player_allow_left
1805 clc
1806 lda $70 ; dy > 0 so we need to check another tile
1807 adc #10
1808 sta $70
1809 lda ($70),y ; load the tile below and to the left
1811 cmp #5 ; check for the open exit or final exit
1812 bmi move_player_not_left_exit2
1813 jmp try_to_exit_level ; optimise away the rts
1815 move_player_not_left_exit2:
1816 cmp #0
1817 beq move_player_allow_left
1818 jmp move_player_not_horizontal
1820 move_player_allow_left:
1821 tya
1822 sta $81 ; temporary
1823 jsr unplot_character ; unplot the player character
1824 lda $81
1825 sta $5284 ; store the new room x offset
1826 lda #3
1827 sta $5285 ; dx = 3
1828 clc
1829 jmp animate_player_left ; optimise away the rts
1831 move_player_leave_room_left:
1832 sec
1833 lda $5783
1834 sbc #1
1835 sta $5783
1836 clc
1838 ; Set the player's position on the right of the screen.
1840 ; No need to unplot.
1842 lda #9 ; x = 9
1843 sta $5284
1844 lda #2 ; dx = 2
1845 sta $5285
1847 jsr animate_player_left
1848 sec ; indicate to the calling routine that the player
1849 rts ; has left the room
1851 move_player_check_right_key:
1853 ; Handle the right key.
1855 ldx #189 ; (X)
1856 jsr check_key
1857 cpy #255
1858 beq move_player_right
1859 jmp move_player_not_horizontal
1861 move_player_right:
1863 lda $5285 ; read dx
1864 cmp #2
1865 beq move_player_right_check_x
1866 cmp #3
1867 beq move_player_right_tile
1869 jsr unplot_character ; unplot the player character
1870 inc $5285
1871 clc
1872 jmp animate_player_right ; optimise away the rts
1874 move_player_right_check_x: ; Check the x offset.
1876 lda $5284
1877 cmp #9
1878 beq move_player_leave_room_right
1880 clc
1881 tay
1882 iny ; x + 1
1883 lda $5282 ; load the y offset
1884 tax ; as an index
1885 lda room_row_offsets_low,x ; read the address of the row
1886 sta $70
1887 lda #$57
1888 sta $71
1889 lda ($70),y ; load the tile to the right
1891 cmp #5 ; check for the open exit or final exit
1892 bmi move_player_not_right_exit1
1893 jmp try_to_exit_level ; optimise away the rts
1895 move_player_not_right_exit1:
1896 cmp #0
1897 bne move_player_not_horizontal
1899 lda $5283 ; dy
1900 cmp #0
1901 beq move_player_allow_right
1903 clc ; dy > 0 so we need to check another tile
1904 lda $70
1905 adc #10
1906 sta $70
1907 lda ($70),y ; load the tile below and to the right
1909 cmp #5 ; check for the open exit or final exit
1910 bmi move_player_not_right_exit2
1911 jmp try_to_exit_level ; optimise away the rts
1913 move_player_not_right_exit2:
1914 cmp #0
1915 bne move_player_not_horizontal
1917 move_player_allow_right:
1919 jsr unplot_character ; unplot the player character
1920 inc $5285 ; update dx
1921 clc
1922 jmp animate_player_right ; optimise away the rts
1924 move_player_right_tile:
1926 jsr unplot_character ; unplot the player character
1927 inc $5284 ; store the new room x offset
1928 lda #0
1929 sta $5285 ; dx = 0
1930 clc
1931 jmp animate_player_right ; optimise away the rts
1933 move_player_leave_room_right:
1934 clc
1935 inc $5783
1936 clc
1938 ; Set the player's position on the left of the screen.
1940 ; No need to unplot.
1942 lda #0 ; x = 0
1943 sta $5284
1944 lda #0 ; dx = 0
1945 sta $5285
1947 jsr animate_player_right
1948 sec ; indicate to the calling routine that the
1949 rts ; player has left the room
1951 move_player_not_horizontal:
1953 ; Handle joystick
1955 lda $577e
1956 cmp #0
1957 beq move_player_handle_up_key
1959 move_player_handle_joystick_up_down:
1961 lda #128
1962 ldx #2
1963 jsr $fff4
1964 cpy #96 ; <= -32
1965 bcs move_player_check_joystick_up
1966 jmp move_player_down
1968 move_player_check_joystick_up:
1969 cpy #160
1970 bcc move_player_no_joystick_input
1971 jmp move_player_up ; >= 32
1973 move_player_no_joystick_input:
1974 clc
1975 rts
1977 move_player_handle_up_key:
1979 ; Handle the up key.
1981 ldx #183 ; (:)
1982 jsr check_key
1983 cpy #255
1984 beq move_player_up
1986 ; Handle the down key.
1988 ldx #151 ; (/)
1989 jsr check_key
1990 cpy #255
1991 beq move_player_down
1992 jmp move_player_not_vertical
1994 move_player_up:
1996 lda $5283 ; read dy
1997 cmp #0
1998 beq move_player_up_check_y
2000 jsr unplot_character ; unplot the player character
2001 dec $5283
2002 clc
2003 jmp animate_player_up ; optimise away the rts
2005 move_player_up_check_y: ; Check the y offset.
2007 lda $5282
2008 cmp #0
2009 beq move_player_leave_room_up
2011 tax ; use the y offset as an index
2012 dex ; y - 1
2013 ldy $5284 ; load the x offset
2014 lda room_row_offsets_low,x ; read the address of the row
2015 sta $70
2016 lda #$57
2017 sta $71
2018 lda ($70),y ; load the tile above
2020 cmp #5 ; check for the open exit or final exit
2021 bmi move_player_not_up_exit1
2022 jmp try_to_exit_level ; optimise away the rts
2024 move_player_not_up_exit1:
2025 cmp #0
2026 beq move_player_up_check_dx
2027 clc
2028 rts
2030 move_player_up_check_dx:
2032 lda $5285 ; dx
2033 cmp #3
2034 bmi move_player_allow_up
2036 clc ; dx > 2 so we need to check another tile
2037 iny
2038 lda ($70),y ; load the tile above and to the right
2040 cmp #5 ; check for the open exit or final exit
2041 bmi move_player_not_up_exit2
2042 jmp try_to_exit_level ; optimise away the rts
2044 move_player_not_up_exit2:
2045 cmp #0
2046 beq move_player_allow_up
2047 clc
2048 rts
2050 move_player_allow_up:
2051 txa
2052 sta $81 ; temporary
2053 jsr unplot_character ; unplot the player character
2054 lda $81
2055 sta $5282 ; store the new room y offset
2056 lda #3
2057 sta $5283 ; dy = 3
2058 clc
2059 jmp animate_player_up ; optimise away the rts
2061 move_player_leave_room_up:
2062 sec
2063 lda $5782
2064 sbc #1
2065 sta $5782
2066 clc
2068 ; Set the player's position on the bottom of the screen.
2070 ; No need to unplot.
2072 lda #9 ; y = 9
2073 sta $5282
2074 lda #0 ; dy = 0
2075 sta $5283
2077 jsr animate_player_up
2078 sec ; indicate to the calling routine that the player
2079 rts ; has left the room
2081 move_player_down:
2083 lda $5283 ; read dy
2084 cmp #0
2085 beq move_player_down_check_y
2086 cmp #3
2087 beq move_player_down_tile
2089 jsr unplot_character ; unplot the player character
2090 inc $5283 ; 0 <= dy < 3
2091 clc
2092 jmp animate_player_down ; optimise away the rts
2094 move_player_down_check_y: ; Check the y offset.
2096 lda $5282
2097 cmp #9
2098 beq move_player_leave_room_down
2100 clc
2101 tax
2102 inx ; y + 1
2103 ldy $5284 ; load the x offset
2104 lda room_row_offsets_low,x ; read the address of the row
2105 sta $70
2106 lda #$57
2107 sta $71
2108 lda ($70),y ; load the tile below
2110 cmp #5 ; check for the open exit or final exit
2111 bmi move_player_not_down_exit1
2112 jmp try_to_exit_level ; optimise away the rts
2114 move_player_not_down_exit1:
2115 cmp #0
2116 bne move_player_not_vertical
2118 lda $5285 ; dx
2119 cmp #3
2120 bmi move_player_allow_down
2122 clc ; dx > 2 so we need to check another tile
2123 iny
2124 lda ($70),y ; load the tile below and to the right
2126 cmp #5 ; check for the open exit or final exit
2127 bmi move_player_not_down_exit2
2128 jmp try_to_exit_level ; optimise away the rts
2130 move_player_not_down_exit2:
2131 cmp #0
2132 bne move_player_not_vertical
2134 move_player_allow_down:
2136 jsr unplot_character ; unplot the player character
2137 inc $5283 ; update dy
2138 clc
2139 jmp animate_player_down ; optimise away the rts
2141 move_player_down_tile:
2143 jsr unplot_character ; unplot the player character
2144 inc $5282 ; store the new room y offset
2145 lda #0
2146 sta $5283 ; dy = 0
2147 clc
2148 jmp animate_player_down ; optimise away the rts
2150 move_player_leave_room_down:
2151 inc $5782
2152 clc
2154 ; Set the player's position on the top of the screen.
2156 ; No need to unplot.
2158 lda #0 ; y = 0
2159 sta $5282
2160 lda #0 ; dy = 0
2161 sta $5283
2163 jsr animate_player_down
2164 sec ; indicate to the calling routine that the
2165 rts ; player has left the room
2167 move_player_not_vertical:
2168 clc
2169 rts
2171 try_to_exit_level:
2173 cmp #6
2174 bmi just_exit_level
2176 lda $5780 ; set the complete game flag
2177 ora #$02
2178 jmp try_to_exit_level_exit
2180 just_exit_level:
2181 lda $5780 ; set the exit level flag
2182 ora #$80
2184 try_to_exit_level_exit:
2185 sta $5780
2187 lda #$80
2188 sta $74
2189 lda #$52
2190 sta $75
2191 jsr unplot_character ; remove the player sprite
2192 jmp destroy_enemies ; optimise away the rts
2194 check_fire_key:
2196 lda $578d
2197 bne check_fire_key_exit
2199 lda $577e
2200 beq check_fire_key_no_joystick
2202 lda #128
2203 ldx #0
2204 jsr $fff4
2205 txa
2206 and #1
2207 bne check_fire_key_fire
2209 clc
2210 rts
2212 check_fire_key_no_joystick:
2214 ldx #182 ; (Return)
2215 jsr check_key
2216 cpy #255
2217 bne check_fire_key_exit
2219 check_fire_key_fire:
2221 lda $5286
2222 cmp #0
2223 bne check_fire_key_exit
2225 lda #16
2226 sta $578d
2228 jmp create_projectile ; optimise away the rts
2230 check_fire_key_exit:
2231 clc
2232 rts
2234 create_projectile:
2236 lda #2
2237 sta $5286
2239 lda $5281
2240 and #$06 ; copy the direction information
2241 asl
2242 asl
2243 asl
2244 ora $5789 ; apply the projectile type
2245 sta $5287
2247 lda $5283 ; player dy
2248 adc $577f ; add the weapon counter
2249 adc #1
2250 cmp #4 ; if dy > 3, create the projectile on the tile below
2251 bpl create_projectile_below
2253 clc
2254 sta $5289 ; dy + weapon counter + 1
2255 lda $5282 ; y
2256 sta $5288
2257 jmp create_projectile_continue
2259 create_projectile_below:
2260 sec
2261 sbc #4
2262 sta $5289 ; dy + weapon counter + 1 - 4
2263 clc
2264 lda $5282 ; y
2265 adc #1
2266 sta $5288
2268 create_projectile_continue:
2269 lda $5284 ; x
2270 sta $528a
2272 lda $5285 ; dx
2273 sta $528b
2275 lda $577f ; toggle the weapon counter
2276 eor #1
2277 sta $577f
2279 ; Move the projectile away from the player.
2281 lda #$86
2282 sta $74
2283 lda #$52
2284 sta $75
2285 jsr move_projectile_after_unplot
2287 jsr move_projectile
2289 clc
2290 rts
2292 emerge_type: ; returns A=type
2293 jsr unlimited_values
2294 lda $7d
2295 and #7
2296 cmp #5
2297 bmi emerge_type_ok
2299 sec
2300 sbc #5
2301 clc
2303 emerge_type_ok:
2304 cmp $5781 ; only allow the appropriate enemies for this level
2305 bmi emerge_type_exit
2306 beq emerge_type_reduce
2308 sec
2309 sbc #1
2311 emerge_type_reduce:
2312 sec
2313 sbc $5781
2314 clc
2316 emerge_type_exit:
2317 asl
2318 asl
2319 asl
2320 asl
2321 clc
2322 rts
2324 emerge_character: ; $74,$75=character address
2326 lda #63
2327 sta $578f
2329 jsr unlimited_values
2330 and #$0f
2331 tax
2332 lda $0ee0,x
2333 cmp #0 ; check for an invalid value and exit if found
2334 beq emerge_character_exit
2336 sta $80 ; temporary
2337 lda $0ef0,x
2338 tax
2340 ; Add an emerging enemy.
2342 ldy #0
2343 lda #3 ; emerge/explosion
2344 sta ($74),y
2346 jsr emerge_type ; obtain an enemy type
2347 iny
2348 sta ($74),y
2350 txa
2351 iny
2352 sta ($74),y ; store the y position
2353 lda #1
2354 iny
2355 sta ($74),y ; store the dy offset
2357 lda $80
2358 iny
2359 sta ($74),y ; store the x position
2360 lda #0
2361 iny
2362 sta ($74),y ; store the dx offset
2364 jsr plot_character
2366 ldx #5
2367 jsr play_sound
2369 emerge_character_exit:
2370 clc
2371 rts
2373 emerge_explode: ; $74,$75=character address
2375 jsr unplot_character
2377 ldy #1
2378 lda ($74),y ; direction/animation
2379 tax
2380 adc #1 ; update the counter
2381 and #3 ; mask off everything else
2382 sta $80 ; store the masked counter value
2383 bne move_characters_explosion_not_finished
2385 txa
2386 and #4
2387 bne move_characters_remove_character
2389 ; For emerges, convert into an enemy.
2390 txa
2391 and #$70 ; only keep bits 4,5,6
2392 ora #8 ; make this an enemy
2394 ldy #0
2395 sta ($74),y ; update the type (>= 8)
2396 iny
2397 lda $7d ; prepare the direction and animation offset
2398 and #$0c
2399 sta ($74),y
2401 jsr plot_character
2402 jmp emerge_explode_exit
2404 move_characters_remove_character:
2406 ; For finished explosions, just write 0 into the character array.
2407 lda #0
2408 ldy #0
2409 sta ($74),y
2410 jmp emerge_explode_exit
2412 move_characters_explosion_not_finished:
2413 txa
2414 and #$fc
2415 ora $80
2417 ldy #1
2418 sta ($74),y
2420 jsr plot_character
2422 emerge_explode_exit:
2423 clc
2424 rts
2426 animate_enemy_left: ; $74,$75=character address
2428 ; Set the direction and toggle the animation bit.
2430 ldy #1
2431 lda ($74),y
2432 and #$fb ; keep vertical direction bit and animation bits
2433 sta ($74),y ; left (horizontal directional bit is 0)
2435 rts
2437 move_enemy_left: ; $74,$75=character address
2439 ldy #5
2440 lda ($74),y ; read dx
2441 cmp #0
2442 beq move_enemy_left_check_x
2444 sec
2445 sbc #1
2446 ldy #5
2447 sta ($74),y ; dx
2448 clc
2449 jmp animate_enemy_left ; optimise away the rts
2451 move_enemy_left_check_x:
2453 ; Check the x offset.
2455 ldy #4
2456 lda ($74),y ; x
2457 cmp #0
2458 beq move_enemy_left_exit
2460 sec
2461 sbc #1 ; x - 1
2462 sta $81 ; temporary
2463 ldy #2
2464 lda ($74),y ; load the y offset
2465 tax ; as an index
2466 lda room_row_offsets_low,x ; read the address of the row
2467 sta $70
2468 lda #$57
2469 sta $71
2470 ldy $81 ; temporary (x - 1)
2471 lda ($70),y ; load the tile to the left
2473 cmp #0
2474 bne move_enemy_left_exit
2476 ldy #3
2477 lda ($74),y ; dy
2478 cmp #2
2479 bmi move_enemy_allow_left
2481 clc
2482 lda $70 ; dy > 1 so we need to check another tile
2483 adc #10
2484 sta $70
2485 ldy $81 ; temporary (x - 1)
2486 lda ($70),y ; load the tile below and to the left
2488 cmp #0
2489 bne move_enemy_left_exit
2491 move_enemy_allow_left:
2492 lda $81
2493 ldy #4
2494 sta ($74),y ; store the new room x offset
2495 lda #3
2496 ldy #5
2497 sta ($74),y ; dx = 3
2498 clc
2499 jmp animate_enemy_left ; optimise away the rts
2501 move_enemy_left_exit:
2502 sec
2503 rts
2505 animate_enemy_right: ; $74,$75=character address
2507 ; Set the direction and toggle the animation bit.
2509 ldy #1
2510 lda ($74),y
2511 ora #$04 ; right (keep vertical direction bit and animation bits)
2512 sta ($74),y
2514 rts
2516 move_enemy_right: ; $74,$75=character_address
2518 ldy #5
2519 lda ($74),y ; read dx
2520 cmp #0
2521 beq move_enemy_right_check_x
2522 cmp #3
2523 beq move_enemy_right_tile
2525 clc
2526 adc #1
2527 ldy #5
2528 sta ($74),y
2529 jmp animate_enemy_right ; optimise away the rts
2531 move_enemy_right_check_x: ; Check the x offset.
2533 ldy #4
2534 lda ($74),y ; x
2535 cmp #9
2536 beq move_enemy_right_exit
2538 clc
2539 adc #1 ; x + 1
2540 sta $81 ; temporary (x + 1)
2541 ldy #2
2542 lda ($74),y ; load the y offset
2543 tax ; as an index
2544 lda room_row_offsets_low,x ; read the address of the row
2545 sta $70
2546 lda #$57
2547 sta $71
2548 ldy $81 ; temporary (x + 1)
2549 lda ($70),y ; load the tile to the right
2551 cmp #0
2552 bne move_enemy_right_exit
2554 ldy #3
2555 lda ($74),y ; dy
2556 cmp #2
2557 bmi move_enemy_allow_right
2559 clc ; dy > 1 so we need to check another tile
2560 lda $70
2561 adc #10
2562 sta $70
2563 ldy $81 ; temporary (x + 1)
2564 lda ($70),y ; load the tile below and to the right
2566 cmp #0
2567 bne move_enemy_right_exit
2569 move_enemy_allow_right:
2570 clc
2572 ldy #5
2573 lda ($74),y ; dx
2574 adc #1
2575 sta ($74),y ; update dx
2576 clc
2577 jmp animate_enemy_right ; optimise away the rts
2579 move_enemy_right_tile:
2580 clc
2582 ldy #4
2583 lda ($74),y ; x
2584 adc #1
2585 sta ($74),y ; store the new room x offset
2586 lda #0
2587 iny
2588 sta ($74),y ; dx = 0
2589 clc
2590 jmp animate_enemy_right ; optimise away the rts
2592 move_enemy_right_exit:
2593 sec
2594 rts
2596 animate_enemy_up: ; $74,$75=character address
2598 ; Set the direction and toggle the animation bit.
2600 ldy #1
2601 lda ($74),y
2602 and #$f7 ; keep horizontal direction bit and animation bits
2603 sta ($74),y
2605 rts
2607 move_enemy_up: ; $74,$75=character address
2609 ldy #3
2610 lda ($74),y ; read dy
2611 cmp #0
2612 beq move_enemy_up_check_y
2614 sec
2615 sbc #1
2616 ldy #3
2617 sta ($74),y ; dy
2618 clc
2619 jmp animate_enemy_up ; optimise away the rts
2621 move_enemy_up_check_y:
2623 ; Check the y offset.
2625 ldy #2
2626 lda ($74),y ; y
2627 cmp #0
2628 beq move_enemy_up_exit
2630 tax ; use the y offset as an index
2631 dex ; y - 1
2632 ldy #4
2633 lda ($74),y ; load the x offset
2634 sta $81 ; temporary (x)
2635 tay
2636 lda room_row_offsets_low,x ; read the address of the row
2637 sta $70
2638 lda #$57
2639 sta $71
2640 lda ($70),y ; load the tile above
2642 cmp #0
2643 bne move_enemy_up_exit
2645 ldy #5
2646 lda ($74),y ; dx
2647 cmp #0
2648 beq move_enemy_allow_up
2650 clc ; dx != 0 so we need to check another tile
2651 ldy $81
2652 iny
2653 lda ($70),y ; load the tile above and to the right
2655 cmp #0
2656 bne move_enemy_up_exit
2658 move_enemy_allow_up:
2659 txa
2660 ldy #2
2661 sta ($74),y ; store the new room y offset
2662 lda #3
2663 iny
2664 sta ($74),y ; dy = 3
2665 clc
2666 jmp animate_enemy_up ; optimise away the rts
2668 move_enemy_up_exit:
2669 sec
2670 rts
2672 animate_enemy_down: ; $74,$75=character address
2674 ; Set the direction and toggle the animation bit.
2676 ldy #1
2677 lda ($74),y
2678 ora #$08 ; down
2679 sta ($74),y
2681 rts
2683 move_enemy_down: ; $74,$75=character address
2685 ldy #3
2686 lda ($74),y ; dy
2687 cmp #1
2688 beq move_enemy_down_check_y
2689 cmp #3
2690 beq move_enemy_down_tile
2692 adc #1
2693 ldy #3
2694 sta ($74),y ; dy
2695 clc
2696 jmp animate_enemy_down ; optimise away the rts
2698 move_enemy_down_check_y:
2700 ; Check the y offset.
2702 ldy #2
2703 lda ($74),y
2704 cmp #9
2705 beq move_enemy_down_exit
2707 clc
2708 adc #1 ; y + 1
2709 tax
2710 ldy #4
2711 lda ($74),y ; load the x offset
2712 sta $81 ; temporary
2713 tay
2714 lda room_row_offsets_low,x ; read the address of the row
2715 sta $70
2716 lda #$57
2717 sta $71
2718 lda ($70),y ; load the tile below
2720 cmp #0
2721 bne move_enemy_down_exit
2723 ldy #5
2724 lda ($74),y ; dx
2725 cmp #0
2726 beq move_enemy_allow_down
2728 clc ; dx != 0 so we need to check another tile
2729 ldy $81 ; x
2730 iny
2731 lda ($70),y ; load the tile below and to the right
2733 cmp #0
2734 bne move_enemy_down_exit
2736 move_enemy_allow_down:
2737 clc
2739 ldy #3
2740 lda ($74),y ; dy
2741 adc #1
2742 sta ($74),y ; update dy
2743 clc
2744 jmp animate_enemy_down ; optimise away the rts
2746 move_enemy_down_tile:
2747 clc
2749 ldy #2
2750 lda ($74),y ; y
2751 adc #1
2752 sta ($74),y ; store the new room y offset
2753 lda #0
2754 iny
2755 sta ($74),y ; dy = 0
2756 clc
2757 jmp animate_enemy_down ; optimise away the rts
2759 move_enemy_down_exit:
2760 sec
2761 rts
2763 move_enemy_animate: ; $74,$75=character address
2765 ldy #1
2766 lda ($74),y ; direction/animation
2767 sta $81
2768 and #$03
2769 adc #1
2770 and #$03 ; keep animation bits
2771 sta $8f
2772 lda $81
2773 and #$fc ; mask off the animation bits
2774 ora $8f
2775 sta ($74),y
2776 rts
2778 move_enemy_next_direction: .byte $04, $0c, $00, $08
2780 move_enemy: ; $74,$75=character address
2782 lda #0
2783 sta $8d ; vertical motion value (0=no motion; 1=up; 2=down)
2784 lda #0
2785 sta $8e ; horizontal motion value (0=no motion; 1=left; 2=right)
2787 lda ($74),y ; read the enemy number (Y should be zero)
2788 and #$10
2789 beq move_enemy_homing
2790 clc
2792 ; This enemy is a non-homing enemy.
2794 jsr unplot_character ; unplot now before we change the sprite used
2796 ldy #1
2797 lda ($74),y
2798 and #$f0
2799 cmp #$f0
2800 bne move_enemy_set_direction
2801 clc
2803 ldy #1
2804 lda ($74),y
2805 and #$0c
2806 ror
2807 ror
2808 tax
2809 lda move_enemy_next_direction,x
2810 sta ($74),y
2812 move_enemy_set_direction:
2813 clc
2815 ldy #1
2816 lda ($74),y
2817 sta $7b
2819 adc #$10
2820 sta ($74),y
2821 clc
2823 lda $7b
2824 and #$04
2825 ror
2826 ror
2827 adc #1
2828 sta $8e
2830 lda $7b
2831 and #$08
2832 ror
2833 ror
2834 ror
2835 adc #1
2836 sta $8d
2838 jmp move_enemy_with_direction
2840 move_enemy_homing:
2842 ldy #2
2843 lda ($74),y ; y
2844 cmp $5282 ; player y
2845 bmi move_enemy_downwards
2846 bne move_enemy_upwards
2848 ldy #3
2849 lda ($74),y ; dy
2850 cmp $5283 ; player y
2851 beq move_enemy_horizontally
2852 bpl move_enemy_upwards
2854 move_enemy_downwards:
2855 lda #2
2856 sta $8d
2857 jmp move_enemy_horizontally
2859 move_enemy_upwards:
2860 lda #1
2861 sta $8d
2862 ;jmp move_enemy_horizontally
2864 move_enemy_horizontally:
2865 ldy #4
2866 lda ($74),y ; x
2867 cmp $5284 ; player x
2868 bmi move_enemy_rightwards
2869 bne move_enemy_leftwards
2871 ldy #5
2872 lda ($74),y ; dx
2873 cmp #0
2874 beq move_enemy_with_direction_unplot
2875 bpl move_enemy_leftwards
2877 move_enemy_rightwards:
2878 lda #2
2879 sta $8e
2880 jmp move_enemy_with_direction_unplot
2882 move_enemy_leftwards:
2883 lda #1
2884 sta $8e
2886 move_enemy_with_direction_unplot:
2887 clc
2889 jsr unplot_character
2891 move_enemy_with_direction:
2892 clc
2894 lda $8e
2895 cmp #1
2896 bne move_enemy_not_left
2897 jsr move_enemy_left
2898 clc
2899 jmp move_enemy_not_right
2901 move_enemy_not_left:
2902 lda $8e
2903 cmp #2
2904 bne move_enemy_not_right
2905 jsr move_enemy_right
2906 clc
2908 move_enemy_not_right:
2909 lda $8d
2910 cmp #1
2911 bne move_enemy_not_up
2912 jsr move_enemy_up
2913 clc
2914 jmp move_enemy_toggle
2916 move_enemy_not_up:
2917 lda $8d
2918 cmp #2
2919 bne move_enemy_toggle
2920 jsr move_enemy_down
2922 move_enemy_toggle:
2923 clc
2924 jsr move_enemy_animate
2925 jmp plot_character ; optimise away the rts
2927 move_enemy_exit:
2928 clc
2929 rts
2931 create_explosion: ; X=y, Y=x
2933 lda #3
2934 sta $52a4
2935 lda #4
2936 sta $52a5
2937 txa
2938 sta $52a6
2939 lda #1
2940 sta $52a7
2941 tya
2942 sta $52a8
2943 lda #0
2944 sta $52a9
2945 rts
2947 move_projectile_left:
2949 lda $528b
2950 cmp #0
2951 beq move_projectile_left_check_x
2953 dec $528b
2954 clc
2955 rts
2957 move_projectile_left_check_x:
2959 lda $528a
2960 cmp #0
2961 bne move_projectile_left_in_room
2962 jmp move_projectile_left_exit
2964 move_projectile_left_in_room:
2965 tay
2966 dey ; x - 1
2967 ldx $5288 ; y
2968 lda room_row_offsets_low,x ; read the address of the row
2969 sta $70
2970 lda #$57
2971 sta $71
2972 lda ($70),y ; load the tile to the left
2974 cmp #0
2975 bne move_projectile_left_wall
2977 lda $5289 ; dy
2978 cmp #3
2979 bmi move_projectile_allow_left
2981 clc ; dy > 2 so we need to check another tile
2982 lda $70
2983 adc #10
2984 sta $70
2985 lda ($70),y ; load the tile below and to the left
2986 inx ; y += 1
2988 cmp #0
2989 bne move_projectile_left_wall
2991 move_projectile_allow_left:
2993 sty $528a ; x
2994 lda #3
2995 sta $528b ; dx = 3
2997 clc
2998 rts
3000 move_projectile_left_wall: ; the projectile hit a wall
3001 clc
3003 lda $5287 ; type 2 can pass through walls
3004 and #$06
3005 cmp #4
3006 beq move_projectile_allow_left
3008 cmp #2
3009 bne move_projectile_left_not_boomerang
3011 lda $5287
3012 and #$0f
3013 cmp #8
3014 bpl move_projectile_left_exit
3016 ldx $577f ; weapon counter
3017 ora boomerang_horizontal,x
3018 sta $5287
3019 clc
3020 rts ; exit without moving or registering a collision
3022 move_projectile_left_not_boomerang:
3024 cmp #6 ; type 3 can destroy certain walls
3025 bne move_projectile_left_exit
3027 lda ($70),y ; load the tile to the left
3028 cmp #1 ; decoration can be destroyed
3029 bne move_projectile_left_exit
3030 clc
3032 lda #0
3033 sta ($70),y
3035 ; X=y, Y=x
3036 jsr create_explosion
3037 jsr plot_blank_xy ; corrupted X
3039 lda #$a4
3040 sta $74
3041 lda #$52
3042 sta $75
3043 jsr plot_character
3045 ldx #0
3046 jsr play_sound
3048 lda #16 ; prevent the player from firing a new
3049 sta $578d ; projectile until the explosion has finished
3051 move_projectile_left_exit:
3052 sec
3053 rts
3055 boomerang_horizontal: .byte $28, $38
3057 move_projectile_right:
3059 ; Fire right.
3061 lda $528b
3062 cmp #2
3063 beq move_projectile_right_check_x
3064 cmp #3
3065 beq move_projectile_right_tile
3067 inc $528b
3068 clc
3069 rts
3071 move_projectile_right_check_x:
3073 lda $528a ; x
3074 cmp #9
3075 bne move_projectile_right_not_edge
3076 jmp move_projectile_right_exit
3078 move_projectile_right_not_edge:
3079 clc
3080 tay
3081 iny ; x + 1
3082 ldx $5288 ; y
3083 lda room_row_offsets_low,x ; read the address of the row
3084 sta $70
3085 lda #$57
3086 sta $71
3087 lda ($70),y ; load the tile to the right
3089 cmp #0
3090 bne move_projectile_right_wall
3092 lda $5289 ; dy
3093 cmp #3
3094 bmi move_projectile_allow_right
3096 clc ; dy > 2 so we need to check another tile
3097 lda $70
3098 adc #10
3099 sta $70
3100 lda ($70),y ; load the tile below and to the right
3101 inx ; y += 1
3103 cmp #0
3104 bne move_projectile_right_wall
3106 move_projectile_allow_right:
3108 inc $528b ; dx
3109 clc
3110 rts
3112 move_projectile_right_tile:
3114 inc $528a ; x
3115 lda #0
3116 sta $528b ; dx
3117 clc
3118 rts
3120 move_projectile_right_wall: ; the projectile hit a wall
3121 clc
3123 lda $5287 ; type 2 can pass through walls
3124 and #$06
3125 cmp #4
3126 beq move_projectile_allow_right
3128 cmp #2
3129 bne move_projectile_right_not_boomerang
3131 lda $5287
3132 and #$0f
3133 cmp #8
3134 bpl move_projectile_right_exit
3136 ldx $577f ; weapon counter
3137 ora boomerang_horizontal,x
3138 sta $5287
3139 clc
3140 rts ; exit without moving or registering a collision
3142 move_projectile_right_not_boomerang:
3144 cmp #6 ; type 3 can destroy certain walls
3145 bne move_projectile_right_exit
3147 lda ($70),y ; load the tile to the right
3148 cmp #1 ; decoration can be destroyed
3149 bne move_projectile_right_exit
3150 clc
3152 lda #0
3153 sta ($70),y
3155 ; X=y, Y=x
3156 jsr create_explosion
3157 jsr plot_blank_xy ; corrupted X
3159 lda #$a4
3160 sta $74
3161 lda #$52
3162 sta $75
3163 jsr plot_character
3165 ldx #0
3166 jsr play_sound
3168 lda #16 ; prevent the player from firing a new
3169 sta $578d ; projectile until the explosion has finished
3171 move_projectile_right_exit:
3172 sec
3173 rts
3175 move_projectile_up:
3177 lda $5289 ; read dy
3178 cmp #0
3179 beq move_projectile_up_check_y
3181 dec $5289
3182 clc
3183 rts
3185 move_projectile_up_check_y: ; Check the y offset.
3187 lda $5288
3188 cmp #0
3189 bne move_projectile_up_not_edge
3190 jmp move_projectile_up_exit
3192 move_projectile_up_not_edge:
3193 tax ; use the y offset as an index
3194 dex ; y - 1
3195 ldy $528a ; load the x offset
3196 lda room_row_offsets_low,x ; read the address of the row
3197 sta $70
3198 lda #$57
3199 sta $71
3200 lda ($70),y ; load the tile above
3202 cmp #0
3203 bne move_projectile_up_wall
3205 lda $528b ; dx
3206 cmp #3
3207 bmi move_projectile_allow_up
3209 clc ; dx > 2 so we need to check another tile
3210 iny
3211 lda ($70),y ; load the tile above and to the right
3213 cmp #0
3214 bne move_projectile_up_wall
3216 move_projectile_allow_up:
3217 txa
3218 sta $5288 ; store the new room y offset
3219 lda #3
3220 sta $5289 ; dy = 3
3222 clc
3223 rts
3225 move_projectile_up_wall: ; the projectile hit a wall
3226 clc
3228 lda $5287 ; type 2 can pass through walls
3229 and #$06
3230 cmp #4
3231 beq move_projectile_allow_up
3233 cmp #2
3234 bne move_projectile_up_not_boomerang
3236 lda $5287
3237 and #$0f
3238 cmp #8
3239 bpl move_projectile_up_exit
3241 ldx $577f ; weapon counter
3242 ora boomerang_vertical,x
3243 sta $5287
3244 clc
3245 rts ; exit without moving or registering a collision
3247 move_projectile_up_not_boomerang:
3249 cmp #6 ; type 3 can destroy certain walls
3250 bne move_projectile_up_exit
3252 lda ($70),y ; load the tile above
3253 cmp #1 ; decoration can be destroyed
3254 bne move_projectile_up_exit
3255 clc
3257 lda #0
3258 sta ($70),y
3260 ; X=y, Y=x
3261 jsr create_explosion
3262 jsr plot_blank_xy ; corrupted X
3264 lda #$a4
3265 sta $74
3266 lda #$52
3267 sta $75
3268 jsr plot_character
3270 ldx #0
3271 jsr play_sound
3273 lda #16 ; prevent the player from firing a new
3274 sta $578d ; projectile until the explosion has finished
3276 move_projectile_up_exit:
3277 sec
3278 rts
3280 boomerang_vertical: .byte $08, $18
3282 move_projectile_down:
3284 lda $5289 ; read dy
3285 cmp #2
3286 beq move_projectile_down_check_y
3287 cmp #3
3288 beq move_projectile_down_tile
3290 inc $5289 ; 0 <= dy < 3
3291 clc
3292 rts
3294 move_projectile_down_check_y: ; Check the y offset.
3296 lda $5288
3297 cmp #9
3298 bne move_projectile_down_in_room
3299 jmp move_projectile_down_exit
3301 move_projectile_down_in_room:
3302 clc
3303 tax
3304 inx ; y + 1
3305 ldy $528a ; load the x offset
3306 lda room_row_offsets_low,x ; read the address of the row
3307 sta $70
3308 lda #$57
3309 sta $71
3310 lda ($70),y ; load the tile below
3312 cmp #0
3313 bne move_projectile_down_wall
3315 lda $528b ; dx
3316 cmp #3
3317 bmi move_projectile_allow_down
3319 clc ; dx > 2 so we need to check another tile
3320 iny
3321 lda ($70),y ; load the tile below and to the right
3323 cmp #0
3324 bne move_projectile_down_wall
3326 move_projectile_allow_down:
3328 inc $5289 ; update dy
3329 clc
3330 rts
3332 move_projectile_down_tile:
3334 inc $5288 ; store the new room y offset
3335 lda #0
3336 sta $5289 ; dy = 0
3337 clc
3338 rts
3340 move_projectile_down_wall: ; the projectile hit a wall
3341 clc
3343 lda $5287 ; type 2 can pass through walls
3344 and #$06
3345 cmp #4
3346 beq move_projectile_allow_down
3348 cmp #2
3349 bne move_projectile_down_not_boomerang
3351 lda $5287
3352 and #$0f
3353 cmp #8
3354 bpl move_projectile_down_exit
3356 ldx $577f ; weapon counter
3357 ora boomerang_vertical,x
3358 sta $5287
3359 clc
3360 rts ; exit without moving or registering a collision
3362 move_projectile_down_not_boomerang:
3364 cmp #6 ; type 3 can destroy certain walls
3365 bne move_projectile_down_exit
3367 lda ($70),y ; load the tile below
3368 cmp #1 ; decoration can be destroyed
3369 bne move_projectile_down_exit
3370 clc
3372 lda #0
3373 sta ($70),y
3375 ; X=y, Y=x
3376 jsr create_explosion
3377 jsr plot_blank_xy ; corrupted X
3379 lda #$a4
3380 sta $74
3381 lda #$52
3382 sta $75
3383 jsr plot_character
3385 ldx #0
3386 jsr play_sound
3388 lda #16 ; prevent the player from firing a new
3389 sta $578d ; projectile until the explosion has finished
3391 move_projectile_down_exit:
3392 sec
3393 rts
3395 move_projectile_animate:
3397 lda $5287
3398 eor #1
3399 sta $5287
3400 rts
3402 move_projectile:
3404 lda $5286
3405 cmp #0
3406 bne move_projectile_move
3407 jmp move_projectile_exit
3409 move_projectile_move:
3410 clc
3412 lda #$86
3413 sta $74
3414 lda #$52
3415 sta $75
3416 jsr unplot_character
3418 move_projectile_after_unplot:
3420 lda $5287
3421 and #$30 ; direction
3423 cmp #0
3424 bne move_projectile_not_left
3426 jsr move_projectile_left
3427 bcc move_projectile_toggle
3428 bcs move_projectile_destroy
3430 move_projectile_not_left:
3431 cmp #$10
3432 bne move_projectile_not_right
3434 jsr move_projectile_right
3435 bcc move_projectile_toggle
3436 bcs move_projectile_destroy
3438 move_projectile_not_right:
3439 cmp #$20
3440 bne move_projectile_not_up
3442 jsr move_projectile_up
3443 bcc move_projectile_toggle
3444 bcs move_projectile_destroy
3446 move_projectile_not_up:
3447 cmp #$30
3448 bne move_projectile_toggle
3450 jsr move_projectile_down
3451 bcs move_projectile_destroy
3453 move_projectile_toggle:
3455 jsr projectile_collide
3456 bcs move_projectile_destroy
3458 jsr move_projectile_animate
3460 lda #$86
3461 sta $74
3462 lda #$52
3463 sta $75
3464 jmp plot_character ; optimise away the rts
3466 move_projectile_destroy:
3467 clc
3469 ldy #0
3470 lda ($74),y ; type
3471 cmp #8
3472 bmi move_projectile_no_enemy_collision
3474 and #$70 ; increase the player's score
3475 lsr
3476 lsr
3477 lsr
3478 adc #2
3479 sta $70
3480 jsr add_score
3481 jmp move_projectile_create_explosion
3483 move_projectile_no_enemy_collision:
3485 cmp #4 ; items can be destroyed as well
3486 bne move_projectile_no_item_collision
3488 ldy #1 ; but not keys
3489 lda ($74),y
3490 cmp #4 ; even the mace is stopped by a key
3491 beq move_projectile_remove_projectile
3492 clc
3494 jsr remove_room_item
3496 move_projectile_create_explosion:
3498 ; Unplot the item/enemy and replace it with an explosion.
3500 jsr unplot_character
3502 lda #3 ; explosion
3503 ldy #0
3504 sta ($74),y
3506 lda #4
3507 ldy #1
3508 sta ($74),y
3510 jsr plot_character
3512 ; Play a sound.
3513 ldx #0
3514 jsr play_sound
3516 move_projectile_no_item_collision:
3518 lda $5287 ; type 2 projectiles pass through everything
3519 and #$06
3520 cmp #4
3521 bne move_projectile_remove_projectile
3523 ; Ideally, we would have recorded if the projectile left the screen so
3524 ; that we don't perform these checks again here, but it would just add
3525 ; overhead to the normal movement routines for the other weapons.
3527 lda $5288 ; y
3528 cmp #0
3529 beq move_projectile_remove_projectile
3530 cmp #9
3531 beq move_projectile_remove_projectile
3533 lda $528a ; x
3534 cmp #0
3535 beq move_projectile_remove_projectile
3536 cmp #9
3537 beq move_projectile_remove_projectile
3539 clc
3540 lda #$86
3541 sta $74
3542 lda #$52
3543 sta $75
3545 jsr plot_character
3546 jmp move_projectile_exit
3548 move_projectile_remove_projectile:
3550 lda #0 ; remove the projectile from the character list
3551 sta $5286
3553 move_projectile_exit:
3554 clc
3555 rts
3557 emerge_characters:
3559 lda #$8c ; set the character address
3560 sta $74
3561 lda #$52
3562 sta $75
3564 emerge_characters_loop:
3566 ldy #0
3567 lda ($74),y
3568 cmp #0
3569 bne emerge_characters_next
3571 jmp emerge_character ; optimise away the rts
3573 emerge_characters_next:
3574 clc
3576 ; Examine the next character.
3577 lda $74
3578 adc #6
3580 cmp #$a4
3581 bpl emerge_characters_exit
3582 sta $74
3583 jmp emerge_characters_loop
3585 emerge_characters_exit:
3586 clc
3587 rts
3589 enemy_slots: .byte 0, 6, 12, 18
3591 move_characters:
3593 lda #$8c ; set the character address
3594 sta $74
3595 lda #$52
3596 sta $75
3598 lda $578e ; read a value from 0 to 3 from the motion counter
3599 and #3
3600 tax
3601 lda enemy_slots,x ; look up the corresponding slot in the character list
3602 adc $74
3603 sta $74 ; update the character address
3605 move_characters_loop:
3607 ldy #0
3608 lda ($74),y
3609 cmp #3
3610 bne move_characters_not_emerge_explode
3612 jsr emerge_explode
3613 jmp move_characters_next
3615 move_characters_not_emerge_explode:
3616 cmp #8
3617 bmi move_characters_next
3619 jsr move_enemy
3621 move_characters_next:
3622 clc
3624 lda $74 ; for the last enemy, check the next slot
3625 cmp #$9e ; for the presence of an explosion
3626 bne move_characters_endloop ; otherwise leave the loop (only performing
3627 clc ; one iteration)
3629 adc #6
3630 sta $74
3631 jmp move_characters_loop
3633 move_characters_endloop:
3634 clc
3636 ; Check collisions with the player.
3638 jsr player_collide
3639 bcs move_characters_collisions
3640 jmp move_characters_exit
3642 move_characters_collisions:
3643 clc
3645 ldy #0
3646 lda ($74),y ; type
3647 cmp #8
3648 bpl move_character_destroy_enemy
3650 ; Unplot the item.
3651 jsr unplot_character
3653 ; Remove it from the item table.
3654 jsr remove_room_item
3656 lda #0 ; remove the item from the character list
3657 ldy #0
3658 sta ($74),y
3660 iny
3661 lda ($74),y ; get the item type
3663 sta $8d ; temporarily store A and increase the score
3664 tax
3665 lda item_scores,x
3666 sta $70
3667 jsr add_score
3668 lda $8d
3670 ; Check the item type.
3671 cmp #8
3672 bmi move_characters_not_health
3674 lda #20
3675 sta $70
3676 jsr add_strength
3677 clc
3679 ldx #2
3680 jsr play_sound
3682 rts
3684 move_characters_not_health:
3685 cmp #5
3686 bmi move_characters_not_treasure
3688 ldx #2
3689 jsr play_sound
3691 clc
3692 rts
3694 move_characters_not_treasure:
3695 cmp #4
3696 bmi move_characters_not_key
3698 ; Key - update the item/player flags byte.
3699 lda $5780
3700 ora #$01
3701 sta $5780
3702 clc
3704 ldx #3
3705 jsr play_sound
3707 rts
3709 move_characters_not_key:
3711 ; Update the player's weapon.
3712 asl
3713 sta $5789
3714 clc
3716 ldx #2
3717 jsr play_sound
3719 rts
3721 move_character_destroy_enemy:
3723 ; Unplot the enemy and replace it with an explosion.
3725 jsr unplot_character
3727 lda #3 ; explosion
3728 ldy #0
3729 sta ($74),y
3731 lda #4
3732 ldy #1
3733 sta ($74),y
3735 jsr plot_character
3737 ; Reduce the player's strength.
3739 ldx #1
3740 jsr play_sound
3742 lda #1
3743 sta $70
3744 jmp reduce_strength ; optimise away the rts
3746 move_characters_exit:
3747 clc
3748 rts
3750 remove_room_item:
3752 ldx $5782 ; current room row number
3753 lda eleven_times_table,x
3754 adc $5783 ; current room column number
3755 tax
3756 lda #$80 ; store a value with the top bit set instead of zero because we
3757 sta $5200,x ; have visited this room if we can collect the object within it
3758 clc
3759 rts
3761 item_scores: .byte $1,$4,$9,$16, $50,$20,$5,$10,$40
3762 score_vdu_bytes: .byte 1,1,31 ; reversed
3763 score_digits: .byte "0123456789"
3765 add_score: ; $70=score to add
3767 sed
3768 lda $5786
3769 adc $70
3770 sta $5786
3771 lda $5787
3772 adc #0
3773 sta $5787
3774 lda $5788
3775 adc #0
3776 sta $5788
3777 cld
3779 write_score:
3781 lda #$86
3782 sta $70
3783 lda #$57
3784 sta $71
3786 ldx #2
3787 write_score_vdu_bytes:
3788 lda score_vdu_bytes,x
3789 jsr $ffee
3790 dex
3791 bpl write_score_vdu_bytes
3793 write_score_digits: ; $70,$71=address of score bytes
3795 ldy #2
3796 write_score_loop:
3798 lda ($70),y
3799 lsr
3800 lsr
3801 lsr
3802 lsr
3803 tax
3804 lda score_digits,x
3805 jsr $ffee
3807 lda ($70),y
3808 and #$0f
3809 tax
3810 lda score_digits,x
3811 jsr $ffee
3813 dey
3814 bpl write_score_loop
3816 clc
3817 rts
3819 strength_units: .byte $00,$88,$cc,$ee
3821 add_strength: ; $70=strength to add
3823 ; Divide the initial strength by 4 to determine which half character to
3824 ; start plotting at, and multiply by 8 to get the address. The net result
3825 ; is to mask off the bottom two bits and shift left once.
3826 lda $5784
3827 and #$fc
3828 sta $71 ; strength rounded down to a multiple of four units
3829 asl
3830 clc
3831 tay
3833 lda $5784
3834 adc $70
3835 cmp #65
3836 bmi add_strength_update
3838 lda #64
3840 add_strength_update:
3841 clc
3842 sta $5784 ; the final strength
3844 sec
3845 sbc $71
3846 clc
3847 tax ; the number of units to add between the rounded original
3848 ; strength and the final strength
3850 lda #$f3 ; the start of the strength bar
3851 sta $72
3852 lda #$59
3853 sta $73
3855 cpx #4
3856 bmi add_strength_loop_extra
3858 add_strength_loop:
3860 clc
3861 lda #$ff
3862 sta ($72),y
3864 tya
3865 adc #8
3866 tay
3868 txa
3869 sec
3870 sbc #4
3871 clc
3872 tax
3874 cmp #4
3875 bpl add_strength_loop
3877 add_strength_loop_extra:
3878 cpx #0
3879 beq add_strength_exit
3881 ; For any remaining units in excess of the multiples of four units, plot
3882 ; the appropriate byte.
3883 lda $5784
3884 and #3
3885 tax
3887 lda strength_units,x
3888 sta ($72),y
3890 add_strength_exit:
3891 clc
3892 rts
3894 reduce_strength: ; $70=strength to remove
3896 lda $5784
3897 tax
3898 sec
3899 sbc $70
3900 bpl reduce_strength_update
3902 lda #0
3904 reduce_strength_update:
3905 clc
3906 sta $5784
3908 ; Divide the final strength by 4 to determine which half character to
3909 ; plot, and multiply by 8 to get the address. The net result is to mask off
3910 ; the bottom two bits and shift left once.
3911 and #$fc
3912 asl
3913 tay
3915 lda #$f3 ; the start of the strength bar
3916 sta $70
3917 lda #$59
3918 sta $71
3920 lda $5784
3921 and #3
3922 tax
3923 lda strength_units,x
3924 sta ($70),y
3926 lda $5784
3927 cmp #0
3928 bne reduce_strength_exit
3930 lda $5780 ; the player ran out of strength
3931 ora #$40
3932 sta $5780
3934 lda #64 ; reset the delay counter
3935 sta $5785
3937 lda #$80 ; unplot the player
3938 sta $74
3939 lda #$52
3940 sta $75
3942 jsr unplot_character
3944 lda #8 ; change the player's direction to the demise animation
3945 sta $5281
3947 jsr plot_character
3948 jmp destroy_enemies ; optimise away the rts
3950 reduce_strength_exit:
3951 clc
3952 rts
3954 destroy_enemies:
3956 lda #$8c
3957 sta $74
3958 lda #$52
3959 sta $75
3961 destroy_enemies_loop:
3963 ldy #0
3964 lda ($74),y
3965 cmp #8
3966 bmi destroy_enemies_not_enemy
3968 jsr unplot_character
3970 lda #3 ; emerge/explosion
3971 ldy #0
3972 sta ($74),y
3974 iny
3975 lda #4 ; explosion
3976 sta ($74),y
3978 jsr plot_character
3979 jmp destroy_enemies_not_emerging_enemy
3981 destroy_enemies_not_enemy:
3982 cmp #3
3983 bne destroy_enemies_not_emerging_enemy
3985 jsr unplot_character
3987 iny ; whether emerging or exploding, ensure that the enemy
3988 lda ($74),y ; is now exploding
3989 ora #4
3990 sta ($74),y
3992 jsr plot_character
3994 destroy_enemies_not_emerging_enemy:
3995 clc
3996 lda $74
3997 adc #6
3998 sta $74
3999 cmp #$a4
4000 bmi destroy_enemies_loop
4002 clc
4003 rts
4005 remove_characters:
4007 ; Clear the character table.
4009 ldx #6
4010 remove_characters_loop:
4011 lda #0
4012 sta $5280,x
4013 txa
4014 adc #6
4015 tax
4016 cpx #$2a
4017 bmi remove_characters_loop
4019 rts
4021 ; The player collision masks use bits to represent where the player is in a
4022 ; tile. See the collisions.txt file for more information.
4024 ; Player is above, enemy is below, checking the overlap in the lower tile.
4025 player_collision_mask_above: .byte $00, $c0, $f0, $fc
4027 projectile_collision_mask_above: .byte $00, $00, $00, $80
4029 ; Player and enemy share the same tile or player is on the tile below.
4030 player_collision_mask_below: .byte $ff, $3f, $0f, $03
4032 projectile_collision_mask_below: .byte $e0, $38, $e0, $03
4034 ; Player is above or on the same tile, enemy is below, checking the overlap in
4035 ; the lower tile.
4036 enemy_collision_mask_above: .byte $f8, $3f, $0f, $03
4038 ; Enemy is above, player is below, checking the overlap in the lower tile.
4039 enemy_collision_mask_below: .byte $00, $00, $c0, $f0
4041 ; Player is to the left, enemy is to the right, checking the overlap in the
4042 ; right hand tile.
4043 player_collision_mask_left:
4044 projectile_collision_mask_left: .byte $00, $00, $00, $08
4046 ; Player and enemy share the same tile or player is on the tile to the right.
4047 player_collision_mask_right:
4048 projectile_collision_mask_right: .byte $0c, $06, $03, $01
4050 ; Player is to the left, enemy is to the right or on the same tile, checking
4051 ; the overlap in the right hand tile.
4052 enemy_collision_mask_left: .byte $0f, $07, $03, $01
4054 ; Enemy is to the left, player is to the right, checking the overlap in the
4055 ; right hand tile.
4056 enemy_collision_mask_right: .byte $00, $08, $0c, $0e
4058 player_collide:
4060 lda $5282 ; player y
4061 sta $8a
4062 lda $5284 ; player x
4063 sta $8b
4065 ldx $5283 ; player dy
4066 lda player_collision_mask_above,x
4067 sta $86
4068 lda player_collision_mask_below,x
4069 sta $88
4070 ldx $5285 ; player dx
4071 lda player_collision_mask_left,x
4072 sta $87
4073 lda player_collision_mask_right,x
4074 sta $89
4076 jmp collide ; optimise away the rts
4078 projectile_collide:
4080 lda $5288 ; projectile y
4081 sta $8a
4082 lda $528a ; projectile x
4083 sta $8b
4085 ldx $5289 ; projectile dy
4086 lda projectile_collision_mask_above,x
4087 sta $86
4088 lda projectile_collision_mask_below,x
4089 sta $88
4090 ldx $528b ; projectile dx
4091 lda projectile_collision_mask_left,x
4092 sta $87
4093 lda projectile_collision_mask_right,x
4094 sta $89
4096 ; Run on into the next routine.
4098 collide:
4100 lda #$8c ; set the character address
4101 sta $74
4102 lda #$52
4103 sta $75
4105 collide_loop:
4107 ldy #0
4108 lda ($74),y ; type
4109 cmp #4
4110 bpl collide_check
4112 jmp collide_next
4114 collide_check:
4116 ldy #2
4117 lda ($74),y ; y
4118 sec
4119 sbc $8a ; y - player/projectile y
4120 beq check_collide_y_equal
4121 cmp #1
4122 beq check_collide_y_greater
4123 cmp #255
4124 beq check_collide_y_less
4126 jmp collide_next
4128 check_collide_y_equal:
4129 ; The enemy is on the same tile as the player/projectile so look at the
4130 ; collision on their common tile.
4131 ldy #3
4132 lda ($74),y ; dy
4133 tax
4134 lda enemy_collision_mask_above,x
4135 and $88 ; player/projectile mask below
4136 bne check_collide_x
4138 jmp collide_next
4140 check_collide_y_greater:
4141 ; The enemy is on the tile below the player/projectile so look at the
4142 ; collision on the enemy's tile.
4143 ldy #3
4144 lda ($74),y ; dy
4145 tax
4146 lda enemy_collision_mask_above,x
4147 and $86 ; player mask above
4148 bne check_collide_x
4150 jmp collide_next
4152 check_collide_y_less:
4153 ; The enemy is on the tile above the player/projectile so look at the
4154 ; collision on the player's tile.
4155 ldy #3
4156 lda ($74),y ; dy
4157 tax
4158 lda enemy_collision_mask_below,x
4159 and $88 ; player mask below
4160 bne check_collide_x
4162 jmp collide_next
4164 check_collide_x:
4165 ldy #4
4166 lda ($74),y ; x
4167 sec
4168 sbc $8b ; x - player/projectile x
4169 beq check_collide_x_equal
4170 cmp #1
4171 beq check_collide_x_greater
4172 cmp #255
4173 beq check_collide_x_less
4175 jmp collide_next
4177 check_collide_x_equal:
4178 ; The enemy is on the same tile as the player/projectile so look at the
4179 ; collision on their common tile.
4180 ldy #5
4181 lda ($74),y ; dx
4182 tax
4183 lda enemy_collision_mask_left,x
4184 and $89 ; player mask right
4185 bne check_collide_destroy
4187 jmp collide_next
4189 check_collide_x_greater:
4190 ; The enemy is the tile to the right of the player/projectile so look
4191 ; at the collision on the enemy's tile.
4192 ldy #5
4193 lda ($74),y ; dx
4194 tax
4195 lda enemy_collision_mask_left,x
4196 and $87 ; player mask left
4197 bne check_collide_destroy
4199 jmp collide_next
4201 check_collide_x_less:
4202 ; The enemy is the tile to the left of the player/projectile so look at
4203 ; the collision on the player's tile.
4204 ldy #5
4205 lda ($74),y ; dx
4206 tax
4207 lda enemy_collision_mask_right,x
4208 and $89 ; player mask right
4209 bne check_collide_destroy
4211 collide_next:
4212 clc
4214 ; Examine the next character.
4215 lda $74
4216 adc #6
4218 cmp #$a4
4219 bpl collide_exit
4220 sta $74
4221 jmp collide_loop
4223 check_collide_destroy:
4225 sec ; set the carry flag to inform the caller that the
4226 rts ; player/projectile should be destroyed
4228 collide_exit:
4229 clc
4230 rts
4232 blank_screen:
4233 lda #1
4234 sta $70
4235 lda #0
4236 sta $71
4237 jsr set_palette
4238 lda #2
4239 sta $70
4240 lda #0
4241 sta $71
4242 jsr set_palette
4243 lda #3
4244 sta $70
4245 lda #0
4246 sta $71
4247 ; Run on into set_palette.
4249 set_palette:
4250 ; $70=logical colour
4251 ; $71=physical colour
4252 lda $70
4253 sta $578b
4254 lda $71
4255 sta $578c
4256 lda #0
4257 sta $578d
4258 sta $578e
4259 sta $578f
4261 lda #$c
4262 ldx #$8b
4263 ldy #$57
4264 jsr $fff1
4265 rts
4267 sounds_low: .byte <explosion_sound, <damage_sound, <item_sound, <key_sound, <note_sound, <emerge_sound
4268 sounds_high: .byte >explosion_sound, >damage_sound, >item_sound, >key_sound, >note_sound, >emerge_sound
4270 explosion_sound: .byte 1,0, 1,0, 60,0, 2,0
4271 damage_sound: .byte 1,0, 2,0, 40,0, 4,0
4272 item_sound: .byte $13,0, 3,0, 32,0, 3,0
4273 key_sound: .byte $13,0, 4,0, 50,0, 5,0
4274 emerge_sound: .byte 2,0, 3,0, 0,0, 2,0
4276 .alias note_sound $5760
4277 .alias note_pitch $5764
4278 .alias note_duration $5766
4280 play_note: ; A=pitch, Y=duration
4282 sta note_pitch
4283 sty note_duration
4284 ldx #4
4285 ; Run on into the next routine.
4287 play_sound: ; X=sound number
4289 lda sounds_high,x
4290 tay
4291 lda sounds_low,x
4292 tax
4293 lda #7
4294 jsr $fff1
4296 rts
4298 copy_title_up:
4300 lda #$00
4301 sta $70
4302 lda #$18
4303 sta $71
4305 lda #$a0
4306 sta $72
4307 lda #$5a
4308 sta $73
4310 ldx #5
4311 ; Run on into the next routine.
4313 copy_title:
4315 copy_title_loop1:
4317 ldy #0
4318 copy_title_loop2:
4320 lda ($70),y
4321 sta ($72),y
4322 iny
4323 cpy #0
4324 bne copy_title_loop2
4326 clc
4327 lda $72
4328 adc #$40
4329 sta $72
4330 lda $73
4331 adc #$01
4332 sta $73
4333 clc
4335 lda $71
4336 adc #$01
4337 sta $71
4338 clc
4340 dex
4341 bpl copy_title_loop1
4343 rts
4345 copy_completed_screen_up:
4347 lda #$00
4348 sta $70
4349 lda #$0f
4350 sta $71
4352 lda #$60
4353 sta $72
4354 lda #$5e
4355 sta $73
4357 ldx #8
4358 jmp copy_title ; optimise away the rts
4360 init:
4361 ; Set up note data.
4362 ldx #7
4363 set_up_note_loop:
4364 lda note_data,x
4365 sta $5760,x
4366 dex
4367 bpl set_up_note_loop
4369 jsr cls ; clear the text window
4371 lda #26 ; unset the text window
4372 jsr $ffee
4374 ; Define the default high scores.
4375 ldy #0
4376 lda #$80
4377 sta $70
4378 lda #$51
4379 sta $71
4380 lda #$16
4381 sta $72
4383 ldx #0
4384 init_define_high_scores_loop:
4386 lda #0
4387 sta ($70),y
4388 iny
4389 lda $72
4390 sta ($70),y
4391 iny
4392 lda #0
4393 sta ($70),y
4395 iny
4396 init_define_high_score_name_loop:
4398 lda high_score_default_name1,x
4399 sta ($70),y
4400 iny
4401 inx
4402 cpx #9
4403 beq init_define_high_scores_next
4404 cpx #18
4405 bne init_define_high_score_name_loop
4407 ldx #0
4408 init_define_high_scores_next:
4410 sed
4411 lda $72
4412 sec
4413 sbc #2
4414 sta $72
4415 cld
4416 clc
4418 cpy #96
4419 bne init_define_high_scores_loop
4421 ; Disable joystick support.
4422 lda #0
4423 sta $577e
4425 rts
4427 note_data: .byte $13,0, 241,255, 0,0, 4,0
4429 high_score_default_name1: .byte "RETRO "
4430 high_score_default_name2: .byte " SOFTWARE"
4432 title_vdu_bytes: .byte 17,2, 31,7,28, "to play"
4433 input_message: .byte 17,2, 31,2,27, "Press SPACE/FIRE"
4434 title_vdu_bytes1: .byte 17,3, 31,1,30, "Copyright (c) 2011"
4435 title_vdu_bytes2: .byte 17,3, 31,1,30, " David Boddie "
4436 title_vdu_bytes3: .byte 17,1, 31,1,30, "for Retro Software"
4437 title_vdu_bytes4: .byte 17,3, 31,1,30, "GNU GPL 3 or later"
4439 set_standard_palette:
4441 lda #1
4442 sta $70
4443 lda #1
4444 sta $71
4445 jsr set_palette
4447 jmp set_core_palette ; optimise away the rts
4449 complete_palette_bytes: .byte 2,4, 3,5, 1,4, 3,3, 2,2
4451 set_complete_palette:
4453 lda #0
4454 sta $80
4455 lda #25
4456 sta $81
4458 set_complete_palette_loop:
4460 jsr wait_for_vsync
4462 dec $81
4463 lda $81
4464 cmp #0
4465 bne set_complete_palette_loop
4467 lda #25
4468 sta $81
4470 ldx $80
4471 lda complete_palette_bytes,x
4472 sta $70
4473 inx
4474 lda complete_palette_bytes,x
4475 sta $71
4476 inx
4477 stx $80
4478 jsr set_palette
4480 lda $80
4481 cmp #10
4482 bne set_complete_palette_loop
4484 rts
4486 set_hidden_palette:
4488 lda #1
4489 sta $70
4490 lda #0
4491 sta $71
4492 jsr set_palette
4494 ; Run on into the next routine.
4496 set_core_palette:
4498 lda #2
4499 sta $70
4500 lda #2
4501 sta $71
4502 jsr set_palette
4504 lda #3
4505 sta $70
4506 lda #3
4507 sta $71
4508 jsr set_palette
4510 rts
4512 show_title:
4514 jsr set_standard_palette
4516 ldx #0
4517 write_title_text_loop:
4518 lda title_vdu_bytes,x
4519 jsr $ffee
4520 inx
4521 cpx #12
4522 bmi write_title_text_loop
4524 jsr show_input_message
4526 ; Show the title.
4527 jsr copy_title_up
4529 ; Show the high scores.
4531 jsr colour1
4533 lda #$80
4534 sta $70
4535 lda #$51
4536 sta $71
4538 lda #8
4539 sta $80
4541 show_title_high_scores_loop:
4543 lda #31
4544 jsr $ffee
4545 lda #2
4546 jsr $ffee
4547 lda $80
4548 adc #2
4549 sta $80
4550 clc
4551 jsr $ffee
4553 jsr write_score_digits
4555 lda #32
4556 jsr $ffee
4558 ldx #8
4559 ldy #3
4560 show_title_high_scores_vdu_loop2:
4562 lda ($70),y
4563 cmp #32
4564 bmi ignore_char
4565 cmp #123
4566 bpl ignore_char
4567 jsr $ffee
4569 ignore_char:
4570 iny
4571 dex
4572 bpl show_title_high_scores_vdu_loop2
4574 lda $70
4575 adc #12
4576 sta $70
4577 cmp #$e0
4578 bne show_title_high_scores_loop
4580 lda #0 ; message counter
4581 sta $72
4583 show_title_wait_loop:
4585 lda #150
4586 sta $5785
4588 ldx $72
4589 ldy #22
4590 show_title_wait_message_loop:
4592 lda title_vdu_bytes1,x
4593 jsr $ffee
4594 inx
4595 dey
4596 bpl show_title_wait_message_loop
4598 cpx #92
4599 beq show_title_wait_reset_offset
4601 txa
4602 sta $72
4603 jmp show_title_wait_inner_loop
4605 show_title_wait_reset_offset:
4606 lda #0
4607 sta $72
4609 show_title_wait_inner_loop:
4610 jsr wait_for_vsync
4612 dec $5785
4613 beq show_title_wait_loop
4615 show_title_wait_loop_no_update:
4616 lda #128
4617 ldx #0
4618 jsr $fff4
4619 cpx #0 ; fire button pressed?
4620 beq show_title_no_joystick
4622 lda #1 ; enable joystick support
4623 sta $577e
4624 jmp show_title_exit
4626 show_title_no_joystick:
4627 ldx #157 ; SPACE
4628 jsr check_key
4629 cpy #255
4630 bne show_title_wait_inner_loop
4632 lda #0 ; disable joystick support
4633 sta $577e
4635 show_title_exit:
4636 clc
4637 rts
4639 show_input_message:
4641 ldx #0
4642 show_input_message_loop:
4644 lda input_message,x
4645 jsr $ffee
4646 inx
4647 cpx #21
4648 bne show_input_message_loop
4650 rts
4652 wait_for_vsync:
4654 lda #19
4655 jmp $fff4 ; optimise away the rts
4657 game_over_vdu_bytes: .byte 28,4,17,15,15, 12, 26, 31,4,15, 17,2, "The journey", 31,9,17, "is over"
4659 delay:
4661 delay_loop:
4663 jsr wait_for_vsync
4664 dec $5785
4665 bne delay_loop
4667 rts
4669 show_game_over:
4671 lda #128
4672 sta $5785
4673 jsr delay
4675 ldx #0
4676 write_game_over_text_loop:
4677 lda game_over_vdu_bytes,x
4678 jsr $ffee
4679 inx
4680 cpx #33
4681 bmi write_game_over_text_loop
4683 lda #192
4684 sta $5785
4685 jsr delay
4687 rts
4689 end_of_level_bytes1: .byte 31,1,3, 17,3, "Exploration bonus", 31,11,5, "x 9"
4690 end_of_level_bytes2: .byte 31,0,28, 17,2, "My journey continues"
4692 show_end_of_level_screen:
4694 ; Draw a decorative room.
4696 jsr make_empty_room
4698 ldx #5
4699 end_of_level_h_walls_loop:
4701 lda #3
4702 sta $57b2,x
4703 sta $57e4,x
4704 dex
4705 bpl end_of_level_h_walls_loop
4707 ldx #30
4708 end_of_level_v_walls_loop:
4710 lda #3
4711 sta $57bc,x
4712 sta $57c1,x
4713 txa
4714 sec
4715 sbc #10
4716 tax
4717 bpl end_of_level_v_walls_loop
4719 jsr plot_room_tiles
4720 jsr set_standard_palette
4722 ldx #0
4723 end_of_level_text_loop1:
4725 lda end_of_level_bytes1,x
4726 jsr $ffee
4727 inx
4728 cpx #28
4729 bne end_of_level_text_loop1
4731 ; Count the number of rooms explored.
4732 ldx #0
4733 lda #0
4734 sta $8d
4735 sta $8e
4736 end_of_level_room_count_loop:
4738 lda $5200,x
4739 and #$80
4740 beq end_of_level_room_count_loop_next
4742 sed
4743 lda $8d
4744 adc #1
4745 sta $8d
4746 lda $8e
4747 adc #0
4748 sta $8e
4749 cld
4750 clc
4752 end_of_level_room_count_loop_next:
4753 inx
4754 cpx #121
4755 bne end_of_level_room_count_loop
4757 ; Position the player so that we can perform an animation.
4758 jsr position_player_set_up_plotting
4760 lda $8d
4761 sta $70
4762 lda $8e
4763 sta $71
4764 jsr write_bonus
4766 lda #0 ; reset motion counter
4767 sta $578e
4769 show_end_of_level_bonus_loop:
4771 jsr wait_for_vsync
4773 clc
4774 lda $578e
4775 and #15
4776 bne end_of_level_no_animation
4778 ; Animate the player.
4780 jsr reset_unplot_buffer
4781 jsr reset_plot_buffer
4783 ; $74,$75 should be unchanged
4784 jsr unplot_character
4786 lda $5281
4787 eor #1
4788 sta $5281
4789 jsr plot_character
4791 jsr plot_buffer
4793 end_of_level_no_animation:
4794 clc
4795 lda $578e
4796 and #3
4797 bne end_of_level_no_countdown
4799 ; Transfer the bonus to the score.
4801 sed
4802 sec
4803 lda $8d
4804 sbc #1
4805 sta $8d
4806 sta $70
4807 lda $8e
4808 sbc #0
4809 sta $8e
4810 sta $71
4811 cld
4812 clc
4814 jsr write_bonus
4816 lda #9
4817 sta $70
4818 jsr add_score
4820 lda $8d
4821 and #$3f
4822 asl
4823 ldy #1
4824 jsr play_note
4826 end_of_level_no_countdown:
4827 inc $578e ; update motion counter
4828 clc
4830 lda $8d
4831 cmp #0
4832 bne show_end_of_level_bonus_loop
4834 lda $8e
4835 cmp #0
4836 bne show_end_of_level_bonus_loop
4838 lda #64 ; initialise delay counter
4839 sta $5785
4840 jsr delay
4842 ldx #0
4843 end_of_level_text_loop2:
4845 lda end_of_level_bytes2,x
4846 jsr $ffee
4847 inx
4848 cpx #25
4849 bne end_of_level_text_loop2
4851 lda $578a
4852 cmp #3
4853 bpl show_end_of_level_screen_exit
4855 lda #192 ; initialise delay counter
4856 sta $5785
4857 jsr delay
4859 show_end_of_level_screen_exit:
4860 rts
4862 level_bonus_vdu_bytes: .byte 5,6,31, 1,17 ; reversed
4864 write_bonus: ; $70,$71=value
4865 ; $72,$73=address of VDU codes
4867 ldx #4
4868 write_bonus_vdu_bytes:
4870 lda level_bonus_vdu_bytes,x
4871 jsr $ffee
4872 dex
4873 bpl write_bonus_vdu_bytes
4875 ldy #1
4876 write_bonus_loop:
4878 tya
4879 tax ; temporary
4881 lda $70,x
4882 sta $80
4883 lsr
4884 lsr
4885 lsr
4886 lsr
4887 tax
4888 lda score_digits,x
4889 jsr $ffee
4891 lda $80
4892 and #$0f
4893 tax
4894 lda score_digits,x
4895 jsr $ffee
4897 dey
4898 bpl write_bonus_loop
4900 clc
4901 rts
4903 position_player_set_up_plotting:
4905 jsr reset_player_position
4906 jsr remove_characters
4908 jsr reset_unplot_buffer
4909 jsr reset_plot_buffer
4911 ; Run on into the next routine.
4913 plot_the_player:
4915 lda #$80 ; plot the player
4916 sta $74
4917 lda #$52
4918 sta $75
4919 jsr plot_character
4921 jsr plot_buffer
4922 rts
4924 complete_game_vdu_bytes1: .byte 12
4925 complete_game_vdu_bytes2: .byte 17,3, 31,2,20, "Congratulations!"
4926 complete_game_vdu_bytes3: .byte 17,2, 31,1,22, "Now journey onward"
4927 complete_game_vdu_bytes4: .byte 17,2, 31,1,24, "to a new adventure"
4929 show_complete_game:
4931 jsr blank_screen
4933 ldx #0
4934 show_complete_game_vdu_loop:
4936 lda complete_game_vdu_bytes1,x
4937 jsr $ffee
4938 inx
4939 cpx #68
4940 bne show_complete_game_vdu_loop
4942 jsr copy_completed_screen_up
4944 jsr set_complete_palette
4946 lda #255
4947 sta $5785
4949 show_complete_game_delay_loop:
4951 jsr wait_for_vsync
4953 dec $5785
4954 bne show_complete_game_no_message
4956 jsr colour1
4957 jsr show_input_message
4959 show_complete_game_no_message:
4961 lda #128
4962 ldx #0
4963 jsr $fff4
4964 cpx #0 ; fire button pressed?
4965 beq show_complete_game_no_joystick
4966 jmp show_complete_game_exit
4968 show_complete_game_no_joystick:
4970 ldx #157
4971 jsr check_key
4972 cpy #255
4973 bne show_complete_game_delay_loop
4975 show_complete_game_exit:
4976 clc
4977 rts
4979 check_high_scores:
4981 ; Start at the bottom of the table, moving scores down as necessary, and
4982 ; write in the current score at the appropriate place.
4984 lda #$86 ; current score
4985 sta $70
4986 lda #$57
4987 sta $71
4989 lda #$80
4990 sta $72
4991 lda #$51
4992 sta $73
4994 check_high_scores_loop:
4996 ldy #2
4997 check_high_scores_digits_loop:
4999 lda ($72),y
5000 cmp ($70),y ; existing score less than current score?
5001 bmi check_high_scores_move_down
5002 beq check_high_scores_digits_next ; keep checking digits if equal
5003 jmp check_high_scores_next
5005 check_high_scores_digits_next:
5006 dey
5007 bpl check_high_scores_digits_loop
5009 check_high_scores_next:
5010 clc
5011 lda $72
5012 adc #12
5013 sta $72
5014 cmp #$e0
5015 bne check_high_scores_loop
5017 ; The player's score didn't make it into the high score table.
5018 rts
5020 check_high_scores_move_down: ; $70,$71=pointer to current score
5021 ; $72,$73=pointer to old score
5023 ; The current score exceeded the existing entry. Make a note of the
5024 ; position in the high score table, insert the player's score, and take
5025 ; the old score
5027 lda $72 ; Record the position in the high score table of the
5028 sta $8d ; player's score.
5029 lda $73
5030 sta $8e
5032 lda #$e0
5033 sta $74
5034 lda #$51
5035 sta $75
5037 ldy #0
5038 insert_blank_player_name_loop:
5040 cpy #3
5041 bpl insert_blank_player_name_score_only
5043 lda ($70),y
5044 jmp insert_blank_player_name_store
5046 insert_blank_player_name_score_only:
5047 lda #32
5049 insert_blank_player_name_store:
5050 sta ($74),y
5051 iny
5052 cpy #12
5053 bne insert_blank_player_name_loop
5055 check_high_scores_move_down_loop:
5057 ldy #0
5058 check_high_scores_copy_score_and_name:
5060 lda ($72),y ; swap the current score with the score in the table
5061 tax
5062 lda ($74),y
5063 sta ($72),y
5064 txa
5065 sta ($74),y
5066 iny
5067 cpy #12
5068 bne check_high_scores_copy_score_and_name
5070 clc
5071 lda $72
5072 adc #12
5073 sta $72
5074 cmp #$e0
5075 bne check_high_scores_move_down_loop
5077 ; Draw a decorative room.
5079 jsr set_hidden_palette
5081 jsr make_empty_room
5083 lda #3
5084 sta $76
5085 sta $77
5086 jsr draw_top_line
5087 jsr draw_bottom_line
5088 jsr draw_left_line
5090 lda #0
5091 sta $77
5092 jsr draw_right_line
5094 jsr plot_room_tiles
5096 ; Add text characters to the room.
5097 jsr colour3
5099 lda #3 ; x
5100 sta $70
5101 lda #6 ; y
5102 sta $71
5104 lda #65
5105 sta $72
5107 ldx #3
5108 plot_text_characters_loop:
5110 jsr print_xy
5112 lda $70
5113 adc #4
5114 sta $70
5116 dex
5117 bpl plot_text_characters_next
5119 lda #3
5120 sta $70
5121 lda $71
5122 adc #3
5123 sta $71
5125 ldx #3
5127 plot_text_characters_next:
5129 inc $72
5130 lda $72
5131 cmp #91
5132 bne plot_text_characters_loop
5134 lda #11
5135 sta $70
5136 lda #95 ; _ representing a space
5137 sta $72
5138 jsr print_xy
5140 lda #15
5141 sta $70
5142 lda #60 ; < representing delete
5143 sta $72
5144 jsr print_xy
5146 ; Put the player in the centre of the room.
5147 jsr position_player_set_up_plotting
5149 lda #0 ; reset motion counter
5150 sta $578e
5152 lda #0 ; not on a character
5153 sta $578d
5155 lda #0 ; reset the level number so that the correct tiles are used
5156 sta $578a
5158 lda #3 ; cursor position in the high score entry held in $8d,$8e
5159 sta $8f
5161 jsr set_standard_palette
5163 ldx #0
5164 high_score_vdu_loop:
5166 lda high_score_vdu_bytes,x
5167 jsr $ffee
5168 inx
5169 cpx #39
5170 bne high_score_vdu_loop
5172 high_score_entry_loop:
5174 jsr reset_unplot_buffer
5175 jsr reset_plot_buffer
5177 jsr move_player
5178 ; Check if the player leaves the room.
5179 bcc high_score_entry_check_position
5180 jmp high_score_entry_after_loop
5182 high_score_entry_check_position:
5184 lda $5285 ; dx
5185 cmp #2
5186 beq high_score_entry_maybe_aligned
5187 jmp high_score_entry_not_aligned
5189 high_score_entry_maybe_aligned:
5191 lda $5282 ; y
5192 tay
5193 cmp #8
5194 bpl high_score_entry_not_aligned
5196 lda $5284 ; x
5197 tax
5198 cmp #9
5199 beq high_score_entry_not_aligned
5200 and #1
5201 beq high_score_entry_not_aligned
5203 lda $5283 ; dy
5204 cmp #2
5205 bmi high_score_entry_aligned
5206 jmp high_score_entry_not_aligned
5208 lda $5282 ; y again (don't apply the touching rule to the bottom
5209 cmp #7 ; row of characters)
5210 beq high_score_entry_not_aligned
5212 iny ; we are really touching the character below
5214 high_score_entry_aligned:
5216 lda $578d
5217 cmp #1
5218 beq high_score_entry_next
5220 ; The player is aligned with a letter.
5221 txa
5222 sec
5223 sbc #1
5224 lsr
5225 sta $7e ; record (x - 1) / 2
5227 tya ; recall y
5228 sec
5229 sbc #1
5230 asl
5231 asl ; (y - 1) * 4
5232 clc
5234 adc $7e ; (y - 1) * 4 + (x - 1) / 2
5235 adc #65
5236 sta $7e ; record the ASCII code
5238 cmp #91
5239 bmi insert_character
5241 cmp #92
5242 beq delete_character
5244 ; Insert a space.
5245 lda #32
5246 sta $7e
5248 insert_character:
5249 lda $8f
5250 cmp #12
5251 bpl high_score_entry_pressed
5253 tay ; insert the character
5254 lda $7e
5255 sta ($8d),y
5256 jsr print_high_score_character
5258 inc $8f
5259 jmp high_score_entry_pressed
5261 delete_character:
5262 lda $8f
5263 cmp #4
5264 bmi high_score_entry_pressed
5266 cmp #12
5267 beq high_score_delete_previous_character
5269 tay
5270 lda #32 ; insert a space
5271 sta ($8d),y
5272 jsr print_high_score_character
5274 high_score_delete_previous_character:
5275 dec $8f
5276 lda $8f
5277 tay ; insert a space
5278 lda #32
5279 sta ($8d),y
5280 jsr print_high_score_character
5282 high_score_entry_pressed:
5283 lda #1
5284 sta $578d
5285 jmp high_score_entry_next
5287 high_score_entry_not_aligned:
5288 lda #0
5289 sta $578d
5291 high_score_entry_next:
5293 jsr wait_for_vsync
5294 jsr plot_buffer
5296 jmp high_score_entry_loop
5298 inc $578e
5299 clc
5301 high_score_entry_after_loop:
5302 clc
5304 jsr cls
5305 jsr set_hidden_palette
5307 rts
5309 high_score_vdu_bytes: .byte 17,1, 31,2,3, "Enter your name!", 17,3, 31,5,30, "> <", 17,1
5311 cls:
5312 lda #12
5313 jsr $ffee
5314 rts
5316 colour1:
5317 lda #17
5318 jsr $ffee
5319 lda #1
5320 jsr $ffee
5321 rts
5323 colour3:
5324 lda #17
5325 jsr $ffee
5326 lda #3
5327 jsr $ffee
5328 rts
5330 print_high_score_character: ; A=ASCII code
5332 clc
5333 sta $72 ; store the character
5334 lda $8f
5335 adc #3
5336 sta $70 ; store the x position of the character
5337 lda #30
5338 sta $71
5339 ; Run on into the next routine.
5341 print_xy:
5343 lda #31
5344 jsr $ffee
5345 lda $70
5346 jsr $ffee
5347 lda $71
5348 jsr $ffee
5349 lda $72
5350 jsr $ffee
5351 rts
5353 disable_sound: ; X=1 (disable); X=0 (enable)
5355 lda #210
5356 ldy #0
5357 jmp $fff4 ; optimise away the rts
5359 status_vdu_bytes: .byte 31,2,0, 17,3, "Score", 31,11,0, 17,2, "Strength", 17,1
5360 ; TAB(1,0), COLOUR 3, "Score", TAB(12,0), COLOUR 2, "Strength", COLOUR 1
5362 start_new_game:
5364 ; Clear the screen.
5365 jsr cls
5367 ; Set the level.
5368 lda #0
5369 sta $578a
5371 ; Set the score.
5372 lda #0
5373 sta $5786
5374 lda #0
5375 sta $5787
5376 lda #0
5377 sta $5788
5379 ; Blank the screen now because it will be blanked before the room is shown
5380 ; and otherwise the strength bar will show briefly.
5381 jsr blank_screen
5383 ; Set the player's strength.
5384 lda #0
5385 sta $5784
5386 lda #64
5387 sta $70
5388 jsr add_strength
5390 ; Set the projectile type.
5391 lda #0
5392 sta $5789
5394 rts
5396 reset_player_position:
5398 lda #1 ; player
5399 sta $5280
5400 lda #6 ; down (first frame)
5401 sta $5281
5402 lda #4 ; y=4
5403 sta $5282
5404 lda #2 ; dy=2
5405 sta $5283
5406 lda #4 ; x=4
5407 sta $5284
5408 lda #3 ; dx=3
5409 sta $5285
5411 rts
5413 start_level:
5415 ; Clear the item/player flags.
5416 lda #0
5417 sta $5780
5419 ; Set current room.
5421 ldx $578a
5422 lda start_rooms_y,x
5423 sta $5782
5424 lda start_rooms_x,x
5425 sta $5783
5427 ; Set the player's position.
5429 jsr reset_player_position
5431 ; Reset the weapon counter.
5432 lda #0
5433 sta $577f
5435 ; Fill the treasure table with objects.
5436 ldx $578a ; level
5437 lda key_rooms,x
5438 sta $80
5440 ldx $578a ; level
5441 lda seeds,x
5442 adc #1
5443 and #31
5444 sta $7c
5445 clc
5446 lda seeds,x
5447 adc #2
5448 and #31
5449 sta $7d
5450 clc
5452 lda $578a ; create an upper limit on the weapon type found in this level
5453 adc #2
5454 sta $5781
5455 clc
5457 lda #$00
5458 sta $8e
5459 lda #$52
5460 sta $8f
5462 ldy #0
5463 start_level_add_treasure_loop:
5465 cpy $80 ; check for the key room
5466 bne start_level_add_treasure_item
5468 lda #5 ; the value to store is type + 1
5469 jmp start_level_add_treasure_store
5471 start_level_add_treasure_item:
5472 clc
5473 jsr unlimited_values
5474 and #$0f
5475 cmp #0
5476 beq start_level_add_treasure_none
5478 clc
5479 sta $8c
5480 tya
5481 adc $8c
5482 and #31
5483 clc
5484 tax
5485 lda treasure_table,x
5487 cmp #4
5488 bmi start_level_add_treasure_weapon
5490 clc
5491 adc #1
5492 jmp start_level_add_treasure_store
5494 start_level_add_treasure_weapon:
5496 ; Only add weapons with types that equal the level number or exceed it
5497 ; by one.
5498 cmp $5781
5499 bcs start_level_add_treasure_none
5501 clc
5502 adc #1 ; store values 0-8 as values 1-9
5503 jmp start_level_add_treasure_store
5505 start_level_add_treasure_none:
5506 clc
5507 lda #0 ; do not put treasure in this room
5509 start_level_add_treasure_store:
5510 clc
5511 sta ($8e),y ; add the item to the table
5513 iny
5514 cpy #121
5515 bmi start_level_add_treasure_loop
5517 ; Write the status text.
5518 ldx #0
5519 write_status_text_loop:
5520 lda status_vdu_bytes,x
5521 jsr $ffee
5522 inx
5523 cpx #25
5524 bmi write_status_text_loop
5526 jsr write_score
5528 clc
5529 rts
5531 main:
5532 jsr init
5534 main_loop:
5536 jsr show_title
5538 jsr start_new_game
5540 level_loop:
5542 jsr start_level
5544 game_loop:
5546 jsr remove_characters
5548 jsr reset_unplot_buffer
5549 jsr reset_plot_buffer
5551 lda $5782 ; current room (y)
5552 sta $78
5553 lda $5783 ; current room (x)
5554 sta $79
5555 jsr plot_room
5556 jsr set_room_palette
5557 jsr create_enemy_positions
5558 jsr add_treasure
5560 jsr plot_the_player
5562 lda #0 ; reset projectile counter
5563 sta $578d
5565 lda #0 ; reset motion counter
5566 sta $578e
5568 lda #63 ; reset generation counter
5569 sta $578f
5571 room_loop:
5572 jsr reset_unplot_buffer
5573 jsr reset_plot_buffer
5575 jsr move_characters
5576 jsr move_projectile
5578 lda $5780 ; is player out of strength ($40), leaving the
5579 and #$c2 ; level (0x80) or completing the game (0x02)?
5580 beq room_loop_player_move
5581 clc
5583 dec $5785 ; leave the loop when the delay
5584 bne room_loop_delay_next
5585 jmp after_room_loop ; counter is about to reset
5587 room_loop_delay_next:
5589 lda $5281 ; leave the loop when the player demise
5590 cmp #11 ; animation has finished
5591 beq room_loop_after_player_move
5592 clc
5594 lda $578e
5595 and #7
5596 bne room_loop_after_player_move
5598 lda $5780 ; skip the animation if leaving the level or
5599 and #$82 ; completing the game
5600 bne room_loop_after_player_move
5602 ; Show the demise animation when appropriate.
5604 lda #$80
5605 sta $74
5606 lda #$52
5607 sta $75
5609 jsr unplot_character
5611 inc $5281
5612 jsr plot_character
5613 jmp room_loop_after_player_move
5615 room_loop_player_move:
5617 ; See if it is time to generate a new enemy.
5618 lda $578f
5619 cmp #0
5620 bne no_emerge_characters
5621 jsr emerge_characters
5623 no_emerge_characters:
5624 clc
5626 jsr check_fire_key
5627 jsr move_player
5628 bcs after_room_loop ; check if we are leaving the level
5630 room_loop_after_player_move:
5631 clc
5633 lda #19
5634 jsr $fff4
5635 jsr plot_buffer
5637 ldx #143 ; Escape key check
5638 jsr check_key
5639 cpy #255
5640 beq main_loop_play_again
5642 ldx #174 ; S key check
5643 jsr check_key
5644 cpy #255
5645 bne no_set_sound
5647 ldx #0
5648 jsr disable_sound
5649 jmp after_sound_checks
5651 no_set_sound:
5653 ldx #239 ; Q key check
5654 jsr check_key
5655 cpy #255
5656 bne after_sound_checks
5658 ldx #1
5659 jsr disable_sound
5661 after_sound_checks:
5663 ldx #200 ; P key check
5664 jsr check_key
5665 cpy #255
5666 bne no_pause
5668 pause_loop:
5670 ldx #201 ; O key check
5671 jsr check_key
5672 cpy #255
5673 bne pause_loop
5675 no_pause:
5676 clc
5678 lda $578d
5679 cmp #0
5680 beq room_loop_no_update_projectile_counter
5682 dec $578d
5684 room_loop_no_update_projectile_counter:
5686 dec $578f ; update generation counter
5688 inc $578e ; update motion counter
5689 clc
5690 jmp room_loop
5692 after_room_loop:
5693 clc
5695 lda $5780
5696 and #$80
5697 bne exit_level
5699 lda $5780
5700 and #$40
5701 bne game_over
5703 lda $5780
5704 and #$02
5705 bne complete_game
5707 jmp game_loop
5709 exit_level:
5711 jsr show_end_of_level_screen
5713 inc $578a
5714 clc
5715 jmp level_loop
5717 game_over:
5718 jsr show_game_over
5719 jmp main_loop_play_again
5721 complete_game:
5722 jsr show_end_of_level_screen
5723 jsr show_complete_game
5724 jmp main_loop_play_again
5726 main_loop_play_again:
5727 jsr cls
5729 ; Check the score against the high scores.
5730 jsr check_high_scores
5732 jmp main_loop
5734 exit:
5735 clc
5736 rts