-
Notifications
You must be signed in to change notification settings - Fork 1
/
thrust.6502
10424 lines (8633 loc) · 290 KB
/
thrust.6502
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
\ *****************************************************************************
\ *****************************************************************************
\ * Thrust
\ * By Jeremey C. Smith
\ *
\ * Source disassembly & documentation by Kieran HJ Connell, February 2016
\ * Initial disassembly created using BeebDis by Phill Harvey-Smith
\ * Verified to compile using BeebAsm by Rich Talbot-Watkins
\ * With thanks to jms2 for his original Thrust disassembly notes and
\ * Matt Godbolt for his encouragement for me to get this released!
\ *
\ * Notes:
\ * Original $.THRUST3 executable had to first be decrypted -> (Thrust4)
\ * Relocated from load address $1A00 to executation address $A60 -> (Thrust5)
\ * Relocation code modified slightly as no longer encrypted -> (Thrust6)
\ * Source documented and annotated for first release --> (Thrust7)
\ * Subsequent corrections & documentation --> (Thrust8)
\ *
\ * _LO & _HI used to identify low byte & high byte of 16-bit values & pointers
\ *
\ * Most calculations are in Q7.8 fixed-point arithmetic although y values are
\ * stored in Q10.8 as each world can be several screens deep. Some physics
\ * calculations are performed Q7.16 in x to provide additional precision.
\ * _FRAC & _INT are used to identify the fraction and integer components of a
\ * fixed-point variable. _FRAC_LO is used to signify an additional byte of
\ * precision at the low end whilst _INT_HI is used for additional upper bits.
\ *
\ * TO DO:
\ * - Properly document each function and how each routine actually works
\ * - Identify remaining zero page variables
\ * - Extract constants and globals from immediates
\ * - Sleep
\ *****************************************************************************
\ *****************************************************************************
NATIVE_ADDR = &A60 ; address at which code will run
RELOAD_ADDR = &1A00 ; address at which code will load
OFFSET = RELOAD_ADDR - NATIVE_ADDR
\ ******************************************************************************
\ ******************************************************************************
\ * Constants
\ ******************************************************************************
\ ******************************************************************************
SCREEN_BASE_ADDR = $3C80
SCREEN_WIDTH_CHARS = 72
SCREEN_CHAR_ROW_BYTES = (SCREEN_WIDTH_CHARS * 8)
SCREEN_START_ADDR = SCREEN_BASE_ADDR + SCREEN_CHAR_ROW_BYTES * 2 ; first two rows are status bar
ASCII_beep = $07
ASCII_space = $20
ASCII_escape = $1B
ASCII_0 = $30
ASCII_9 = $39
ASCII_a = $61
ASCII_z = $7A
ASCII_delete = $7F
INKEY_spacebar = $9D
INKEY_ctrl = $FE
INKEY_capslock = $BF
INKEY_shift = $FF
INKEY_return = $B6
INKEY_escape = $8F
INKEY_copy = $96
INKEY_Q = $EF
INKEY_S = $AE
OBJECT_gun_up_right = $0
OBJECT_gun_down_right = $1
OBJECT_gun_up_left = $2
OBJECT_gun_down_left = $3
OBJECT_fuel = $4
OBJECT_pod_stand = $5
OBJECT_generator = $6
OBJECT_door_switch_right = $7
OBJECT_door_switch_left = $8
PARTICLE_flag = $80 ; particle can be replaced
PARTICLE_lifetime_bullet = $28
PARTICLE_lifetime_generator = $0A
PARTICLE_lifetime_star = $1E
PARTICLE_table_max = $1F
PARTICLE_type_player_bullet = $00
PARTICLE_type_debris = $01 ; shoot generator
PARTICLE_type_star = $02
PARTICLE_type_hostile_bullet = $03
\ ******************************************************************************
\ ******************************************************************************
\ * Zero Page - variables
\ ******************************************************************************
\ ******************************************************************************
L0000 = $0000
window_xpos_INT = $0000 ; x position of window into world coordinates that is drawn on screen
demo_mode_flag = $0001 ; 0 = real game, non-zero = demo mode
planet_explode_anim = $0002 ; initialised to $F and decrements to 0
window_ypos_INT = $0003 ; y position of window into world coordinates that is drawn on screen
window_ypos_EXT = $0004 ; "
window_scroll_x = $0005 ; *think* this is the scroll offset in x for the window
window_scroll_y = $0006 ; *think* this is the scroll offset in y for the window
midpoint_xpos_FRAC_LO = $0007 ; fractional part - additional lower 8 bits
midpoint_xpos_FRAC = $0008 ; calculated as player_pos + nearest_obj_pos / 2
midpoint_xpos_INT = $0009 ; all physics calculations are performed on the mid-point
midpoint_ypos_FRAC = $000A ; once the ship and pod are attached
midpoint_ypos_INT = $000B ; integer part
midpoint_ypos_INT_HI = $000C ; integer part - additional upper 8 bits
ship_angle = $000D ; $00 = up, $10 = down, $1F = max angle
old_plot_ship_at_ptr = $000E ; remembers plot_ship_at_ptr
old_plot_ship_at_ptr_HI = $000F ; "
old_plot_ship_L0075 = $0010 ; remembers plot_ship_L0075
old_plot_ship_sprite_number = $0011 ; remembers plot_ship_sprite_number
force_vectorx_FRAC_LO = $0012 ;
force_vectorx_FRAC = $0013 ;
force_vectorx_INT = $0014 ;
force_vectory_FRAC = $0015 ; set to gravity_FRAC in ship_input_thrust_calculate_force
force_vectory_INT = $0016 ; set to gravity_INT in ship_input_thrust_calculate_force
pod_sprite_plotted_flag = $0017 ; set to 1 as plot_pod_sprite is called
ship_sprite_plotted_flag = $0018 ;
level_tick_counter = $0019 ; increments every tick loop
vsync_count = $001A ; increments every vsync event
angle_var_A_accumulate = $001B ; accumulates angle_var_A
angle_var_B_accumulate = $001C ; accumulates angle_var_B
angle_ship_to_pod = $001D ; AND #$1F - number of angles in table
angle_var_A = $001E ; these all appear to accumulate to calculate accurate angle of midpoint vector
angle_var_B = $001F ; essentially the rotational physics simulation
angle_var_C = $0020 ;
pod_attached_flag_1 = $0022 ; set to non-zero at top of attach_pod_to_ship function
midpoint_deltax_FRAC = $0023 ; add midpoint_delta to midpoint to get ship_position
midpoint_deltax_INT = $0024 ; subtract midpoint_delta from midpoint to get pod_position
midpoint_deltay_FRAC = $0025 ; " (fractional part)
midpoint_deltay_INT = $0026 ; " (integer part)
shield_tractor_pressed = $0027 ; non-zero when space is pressed
sheild_tractor_flag = $0028 ; may still be zero when space is pressed!
plot_ship_collision_detected = $002A ; set in plot_ship function
plot_pod_collision_detected = $002B ; set in plot_pod_sprite function
player_pressed_fire = $002C ; non-zero when fire key is pressed
bullet_index = $002D ; can only have 4 bullets active at one time
player_ypos_FRAC = $002E ; calculated by adding midpoint_delta to midpoint_position
player_ypos_INT = $002F ; "
player_ypos_INT_HI = $0030 ; "
old_midpoint_xpos_FRAC_LO = $0031 ; remembers temp_midpoint_xpos_FRAC_LO
player_xpos_FRAC = $0032 ; (as above)
player_xpos_INT = $0033 ; (as above)
player_velocityy_FRAC = $0034 ; calculated in calculate_player_position_from_midpoint
player_velocityy_INT = $0035 ; used to add player velocity to bullets when firing
player_velocityy_INT_HI = $0036 ; "
diff_midpoint_xpos_FRAC_LO = $0037 ; **UNUSED** ?
player_velocityx_FRAC = $0038 ; (as above)
player_velocityx_INT = $0039 ; (as above)
rnd_A = $003A ; used by rnd function
rnd_B = $003B ; used by rnd function
collecting_fuel_flag = $003C ; set to 1 if using tractor beam near fuel object
generator_recharge_counter = $003D ; number of ticks to recharge generator
generator_recharge_increase = $003E ; increase in time between recharges after each hit
old_plot_pod_sprite_at_ptr = $003F ;
old_plot_pod_sprite_at_ptr_HI = $0040 ;
old_plot_pod_L0076 = $0041 ;
player_ship_destroyed_flag = $0042 ; set to $FF during init, 0 or 1 at other times
level_ended_flag = $0043 ; set to 0 each tick, set to $FF in one place - suspect collision / death?
pod_destroying_player_timer = $0044 ; set to $FF during init, otherwise counts down during explode?
pod_line_exists_flag = $0045 ; related to tractor_beam_started_flag
old_draw_line_start_x = $0046 ; remembers draw_line_start_x
old_draw_line_end_x = $0047 ; remembers draw_line_end_x
old_draw_line_start_y = $0048 ; remembers draw_line_start_y
old_draw_line_end_y = $0049 ; remembers draw_line_end_y
line_drawn_flag = $004A ; 0 or $FF set in draw_new_line, unset in erase_old_line
midpoint_window_xpos_INT = $004B ; calculated in update_window_and_terrain_tables
midpoint_window_ypos_INT = $004C ; "
midpoint_deltax_FRAC_LO = $004D ; "
ship_window_xpos_FRAC = $004E ; calculated in update_shield_tractor_draw_ship_and_pod
ship_window_xpos_INT = $004F ; *think* these are relative to the window position
ship_window_ypos_INT = $0050 ; i.e. screen coordinates not world
pod_window_xpos_FRAC = $0051 ; *think* these are relative to the window position
pod_window_xpos_INT = $0052 ; i.e. screen coordinates not world
pod_window_ypos_INT = $0053 ; "
top_nibble_index = $0054 ; initialised to $E (14) and decremented by 2, used to index lookup_top_nibble
fuel_beam_position_flag = $0055 ; set & unset in tick_fuel_pickup_draw_beams
fuel_value_updated_flag = $0056 ; when zero indicates fuel value needs to be updated on screen
fuel_just_ran_out_flag = $0057 ; set moment player runs out of fuel
old_player_xpos_FRAC = $0058 ; remembers player_xpos_FRAC
old_player_xpos_INT = $0059 ; remembers player_xpos_INT
old_player_ypos_INT = $005A ; remembers player_ypos_INT
old_player_ypos_INT_HI = $005B ; remembers player_ypos_INT_HI
pod_xpos_FRAC = $005C ; calculated in calculate_pod_pos
pod_xpos_INT = $005D ; "
pod_ypos_FRAC = $005E ; "
pod_ypos_INT_HI = $005F ; "
sound_timer = $0060 ; counts down to stop sounds from playing on top of each other
level_tick_state = $0061 ; set to 1 when paused, 0 when running, $FF when initialising
char_write_ptr_LO = $0062 ; address fonts are plotted to the screen
char_write_ptr_HI = $0063 ; "
nearest_obj_xpos_FRAC = $0064 ; calculated in calculate_object_plot_addr
nearest_obj_xpos_INT = $0065 ; "
nearest_obj_ypos_INT = $0066 ; "
nearest_obj_ypos_INT_HI = $0067 ; "
tractor_beam_started_flag = $0068 ; related to pod_line_exists_flag
countdown_timer_ticks = $0069 ; used to time between countdown timer seconds
planet_countdown_timer = $006A ; set to $FF or $A on countdown
door_switch_counter_A = $006B ; used in level door logic
door_switch_counter_B = $006C ; "
\ ******************************************************************************
\ ******************************************************************************
\ * Zero Page - temporary variables - often reused
\ ******************************************************************************
\ ******************************************************************************
boot_read_ptr = $0070 ; in bootstrap code
value_LO = $0070 ; in bootstrap code
temp_midpoint_xpos_FRAC_LO = $0070
terrain_y_count_inner = $0070
plot_sprite_at_ptr = $0070
calc_force_vectory_FRAC = $0070
pixels_ptr_pixel_byte = $0070
plot_pod_L0070 = $0070 ; **NEEDS TO BE IDENTIFIED**
plot_ship_L0070 = $0070 ; **NEEDS TO BE IDENTIFIED**
value_HI = $0071 ; in bootstrap code
terrain_y_count_outer = $0071
calc_force_vectory_INT = $0071
plot_ship_at_y_offset = $0071
new_ship_xpos_FRAC = $0071
attach_pod_L0071 = $0071 ; **NEEDS TO BE IDENTIFIED**
draw_line_L0071 = $0071 ; only appears once - is this unused or another variable?
particles_L0071 = $0071 ; **NEEDS TO BE IDENTIFIED**
plot_pod_L0071 = $0071 ; **NEEDS TO BE IDENTIFIED**
boot_write_ptr = $0072 ; in bootstrap code
terrain_draw_start_x = $0072
terrain_draw_ptr = $0072
plot_static_sprite_L0072 = $0072
calc_force_vectorx_FRAC = $0072
plot_ship_at_ptr = $0072 ; address LO
new_ship_xpos_INT = $0072
plot_pixels_ptr = $0072
attach_pod_L0072 = $0072 ; **NEEDS TO BE IDENTIFIED**
particles_L0072 = $0072 ; **NEEDS TO BE IDENTIFIED**
plot_pod_L0072 = $0072 ; **NEEDS TO BE IDENTIFIED**
tractor_beam_L0072 = $0072 ; **NEEDS TO BE IDENTIFIED**
calc_force_vectorx_INT = $0073
attach_pod_L0073 = $0073
plot_pod_sprite_L0073 = $0073
new_ship_ypos_FRAC = $0073
obj_vis_L0073 = $0073 ; **NEEDS TO BE IDENTIFIED**
terrain_draw_wall_index = $0074
attach_pod_L0074 = $0074
pod_sprite_ptr_LO = $0074
new_ship_ypos_INT = $0074
particle_write_ptr = $0074
pixels_ptr_mask_index = $0074
obj_vis_L0074 = $0074 ; **NEEDS TO BE IDENTIFIED**
pod_sprite_ptr_HI = $0075
plot_ship_L0075 = $0075 ; **NEEDS TO BE IDENTIFIED**
attach_pod_L0075 = $0075 ; **NEEDS TO BE IDENTIFIED**
calc_player_ypos_INT_HI = $0075 ; **NEEDS TO BE IDENTIFIED**
draw_line_L0075 = $0075 ; **NEEDS TO BE IDENTIFIED**
obj_vis_L0075 = $0075 ; **NEEDS TO BE IDENTIFIED**
terrain_draw_addr_LO = $0076
plot_ship_sprite_number = $0076 ; which ship sprite to plot (0 - $10) or shield ($11)
explosion_dx_FRAC = $0076
particle_pixel_byte = $0076
rnd_AND_3 = $0076
score_value = $0076
attach_pod_L0076 = $0076 ; **NEEDS TO BE IDENTIFIED**
draw_line_L0076 = $0076 ; **NEEDS TO BE IDENTIFIED**
obj_vis_L0076 = $0076 ; **NEEDS TO BE IDENTIFIED**
plot_pod_L0076 = $0076 ; **NEEDS TO BE IDENTIFIED**
terrain_draw_addr_HI = $0077 ; stores HI byte of address to draw landscape at
plot_pod_sprite_at_ptr = $0077
explosion_dx_INT = $0077
calc_ship_window_xpos_INT = $0077
attach_pod_L0077 = $0077 ; **NEEDS TO BE IDENTIFIED**
obj_vis_L0077 = $0077 ; **NEEDS TO BE IDENTIFIED**
particles_L0077 = $0077 ; **NEEDS TO BE IDENTIFIED**
terrain_xpos_1_clipped = $0078
explosion_dy_FRAC = $0078
draw_line_L0078 = $0078
ship_thrust_x_INT = $0078
attach_pod_L0078 = $0078 ; **NEEDS TO BE IDENTIFIED**
obj_vis_L0078 = $0078 ; **NEEDS TO BE IDENTIFIED**
terrain_xpos_2_clipped = $0079
ship_window_ypos_FRAC = $0079
explosion_dy_INT = $0079
pixels_ptr_temp_L0079 = $0079
obj_vis_L0079 = $0079 ; **NEEDS TO BE IDENTIFIED**
particles_L0079 = $0079 ; **NEEDS TO BE IDENTIFIED**
plot_pod_L0079 = $0079 ; **NEEDS TO BE IDENTIFIED**
ship_thrust_L0079 = $0079 ; **NEEDS TO BE IDENTIFIED**
plot_ship_index = $007A
current_object = $007A
ship_thrust_x_FRAC = $007A
attach_pod_L007A = $007A ; **NEEDS TO BE IDENTIFIED**
plot_pod_L007A = $007A ; **NEEDS TO BE IDENTIFIED**
pod_vector_L007A = $007A ; **NEEDS TO BE IDENTIFIED**
terrain_draw_table_index = $007B
obj_plot_sprite_at_ptr = $007B
prev_angle_var_B = $007B
calc_ship_delta_FRAC = $007B
particles_flag1 = $007B
attach_pod_L007B = $007B ; **NEEDS TO BE IDENTIFIED**
plot_pod_L007B = $007B ; **NEEDS TO BE IDENTIFIED**
teleport_L007B = $007B ; **NEEDS TO BE IDENTIFIED**
prev_angle_var_C = $007C
calc_ship_delta_INT = $007C
particle_byte_mask = $007C
plot_pod_sprite_y_offset = $007C
attach_pod_L007C = $007C ; **NEEDS TO BE IDENTIFIED**
prev_angle_var_A = $007D
particle_masked_pixels = $007D
current_obj_xpos_INT = $007D
temp_angle_ship_to_pod = $007E
player_to_particle_deltay_INT = $007E
current_obj_ypos_INT = $007E
ship_thrust_L007E = $007E ; **NEEDS TO BE IDENTIFIED**
calc_force_vectorx_FRAC_LO = $007F
explosion_particle_count = $007F
current_obj_ypos_EXT = $007F
old_brkv = $0080
relocate_src_ptr = $0080 ; in relocation code
time_out_vsync_count = $0080
high_score_ptr_A = $0080 ; new high score only
clear_screen_ptr = $0080
level_reset_ptr = $0080
plot_string_ptr = $0080
window_deltax_INT = $0080 ; calculated in update_window_and_terrain_tables
add_score_thousands = $0080
old_plot_pixels_ptr = $0080
update_objects_flag = $0080
current_object_width = $0081
door_logic_L0081 = $0081 ; **NEEDS TO BE IDENTIFIED**
relocate_dest_ptr = $0082 ; in relocation code
high_score_ptr_B = $0082 ; new high score only
level_reset_ptr2 = $0082
current_object_height = $0082
plot_high_score_number = $0082
teleport_effect_L0082 = $0082 ; **NEEDS TO BE IDENTIFIED**
object_type = $0083
teleport_effect_L0083 = $0083
high_score_counter = $0084 ; new high score only
level_reset_size = $0084
old_pixels_ptr_mask_index = $0084
gun_param_L0084 = $0084 ; **NEEDS TO BE IDENTIFIED**
current_obj_visible_flag = $0085
high_score_ptr_C = $0085
gun_param_L0086 = $0086 ; **NEEDS TO BE IDENTIFIED**
teleport_L0086 = $0086 ; **NEEDS TO BE IDENTIFIED**
score_accumulation = $0087
teleport_appear_or_disappear = $0087 ; $00 = appear, $FF = disappear
explosion_xpos_FRAC = $0088
draw_line_start_x = $0088
attach_pod_L0088 = $0088 ; **NEEDS TO BE IDENTIFIED**
draw_line_start_y = $0089
explosion_xpos_INT = $0089
attach_pod_L0089 = $0089 ; **NEEDS TO BE IDENTIFIED**
draw_line_end_x = $008A
explosion_ypos_INT = $008A
attach_pod_L008A = $008A ; **NEEDS TO BE IDENTIFIED**
draw_line_end_y = $008B
explosion_ypos_INT_HI = $008B
attach_pod_L008B = $008B ; **NEEDS TO BE IDENTIFIED**
plot_line_pixels_byte = $008C
explosion_angle = $008C
attach_pod_L008C = $008C ; **NEEDS TO BE IDENTIFIED**
explosion_particle_type = $008D
attach_pod_L008E = $008E ; **NEEDS TO BE IDENTIFIED**
attach_pod_L008F = $008F ; **NEEDS TO BE IDENTIFIED**
\ ******************************************************************************
\ ******************************************************************************
\ * Zero Page - variables
\ ******************************************************************************
\ ******************************************************************************
extra_string_counter = $009B ; counter to write extra strings?
extra_string_index = $009C ; index into array of extra strings?
terrain_data_x_increment_ptr = $009D ; pointer to terrain x increment data for level
terrain_data_count_ptr = $009F ; pointer to terrain count data for level
irq1_timer1_signal = $00A1 ; set to 0 at vsync and 1 when timer1 triggers
mute_sound_flag = $00A2 ; set to non-zero to mute sound
hostile_gun_shoot_probability = $00A3 ; probability that a gun will shoot
UNUSED_game_flag = $00A4 ; set to $FF or $00 - unused?
invisible_landscape_flag = $00A5 ; game var init 0 - inverted start of each level
gravity_INT = $00A6 ; gravity vector for level (integer part)
gravity_FRAC = $00A7 ; " (fractional part)
\ ******************************************************************************
\ ******************************************************************************
IRQ1_RETURN_A = $00FC ; OS IRQ handler
\ ******************************************************************************
\ ******************************************************************************
\ * Page &100 - High score table + score data + sound params
\ ******************************************************************************
\ ******************************************************************************
high_score_table = $0100
score_A = $0180 ; score stored as three byte BCD number
score_B = $0181 ; so max score is 999,999
score_C = $0182
old_irq1v = $0190
sound_params_enter_orbit = $0192 ; found some spare bytes!
\ ******************************************************************************
\ ******************************************************************************
\ * Page &200 - OS Vectors
\ ******************************************************************************
\ ******************************************************************************
USERV = $0200
BRKV = $0202
IRQ1V = $0204
L0205 = $0205
IRQ2V = $0206
CLIV = $0208
BYTEV = $020A
WORDV = $020C
WRCHV = $020E
L020F = $020F
RDCHV = $0210
FILEV = $0212
ARGSV = $0214
BGETV = $0216
BPUTV = $0218
GBPBV = $021A
FINDV = $021C
FSCV = $021E
EVENTV = $0220
UPTV = $0222
NETV = $0224
VDUV = $0226
KEYV = $0228
INSV = $022A
REMV = $022C
CNPV = $022E
INDV1 = $0230
INDV2 = $0232
INDV3 = $0234
\ ******************************************************************************
\ ******************************************************************************
\ * Page &400 - Relocated game entry code and game boot data tables
\ ******************************************************************************
\ ******************************************************************************
game_entry = $0400
palette_table = $048F
crtc_regs = $04A0
interlace_status_bit = $04A8
\ ******************************************************************************
\ ******************************************************************************
\ * Page &300 - &5FF - Terrain run-time data
\ ******************************************************************************
\ ******************************************************************************
terrain_draw_table_1 = $02EF ; 11 bytes
terrain_draw_table_2 = $0300 ; 94 bytes
terrain_draw_table_3 = $035E ; 11 bytes
terrain_draw_table_4 = $036F ; 145 bytes
terrain_left_wall = $0400
terrain_right_wall = $0500
\ ******************************************************************************
\ ******************************************************************************
\ * Page &600 - &7BF - Particle system run-time data
\ ******************************************************************************
\ ******************************************************************************
particles_xpos_FRAC = $0600
particles_xpos_INT = $0620
particles_ypos_FRAC = $0640
particles_ypos_INT = $0660
particles_ypos_INT_HI = $0680
particles_dx_FRAC = $06A0
particles_dx_INT = $06C0
particles_dy_FRAC = $06E0
particles_dy_INT = $0700
particles_lifetime = $0720
particles_scraddr_LO = $0740
particles_scraddr_HI = $0760
particles_pixels_byte = $0780
particles_type = $07A0
\ ******************************************************************************
\ ******************************************************************************
\ * Page &7C0 - Sound parameters
\ ******************************************************************************
\ ******************************************************************************
sound_params_page = $0700
sound_params_countdown = $07C0
sound_params_own_gun = $07C8
sound_params_explosion_1 = $07D0
sound_params_explosion_2 = $07D8
sound_params_hostile_gun = $07E0
sound_params_collect_1 = $07E8
sound_params_collect_2 = $07F0
sound_params_engine = $07F8
sound_param_engine_pitch = $07FC ; $2 or $5
\ ******************************************************************************
\ ******************************************************************************
\ * Page &880 - Lookup table angle to vector Y values
\ ******************************************************************************
\ ******************************************************************************
angle_to_y_FRAC = $0880
angle_to_y_INT = $08A0
\ ******************************************************************************
\ ******************************************************************************
\ * Page &900 - In-game messages and strings
\ ******************************************************************************
\ ******************************************************************************
in_game_messages = $0900
string_game_over = $0900 ; in_game_messages + message_game_over - in_game_messages_relocated
string_top_8_thrusters = $090D
string_congratulations = $0924
string_enter_name = $0937
string_press_spacebar = $0951
string_out_of_fuel = $096D
\ ******************************************************************************
\ ******************************************************************************
\ * Page &880 - Lookup table angle to vector X values
\ ******************************************************************************
\ ******************************************************************************
angle_to_x_FRAC = $0980
angle_to_x_INT = $09A0
\ ******************************************************************************
\ ******************************************************************************
\ * Page &9C0 - Lookup table for multiplication by 8 (LO & HI bytes)
\ ******************************************************************************
\ ******************************************************************************
mult_by_8_LO = $09C0
mult_by_8_HI = $0A10
\ ******************************************************************************
\ ******************************************************************************
\ * Hardware registers & OS Functions
\ ******************************************************************************
\ ******************************************************************************
SHEILA_6845_Register = $FE00
SHEILA_6845_Value = $FE01
SHEILA_Video_ULA = $FE20
SHEILA_PaletteReg = $FE21
SHEILA_System_VIA_Register_B = $FE40
SHEILA_System_VIA_Register_A = $FE41
SHEILA_System_VIA_Data_Dir = $FE43
SHEILA_System_VIA_Interrupt_Flag = $FE4D
SHEILA_System_VIA_Interrupt_Enable = $FE4E
SHEILA_System_VIA_Register_A_NH = $FE4F
SHEILA_User_VIA_Timer1_Low_Order = $FE64
SHEILA_User_VIA_Timer1_High_Order = $FE65
SHEILA_User_VIA_Aux_Ctrl_Reg = $FE6B
SHEILA_User_VIA_Interrupt_Flag = $FE6D
SHEILA_User_VIA_Interrupt_Enable = $FE6E
OSWRSC = $FFB3
DEFVEC = $FFB6
OSRDSC = $FFB9
OSEVEN = $FFBF
GSINIT = $FFC2
GSREAD = $FFC5
NVRDCH = $FFC8
NNWRCH = $FFCB
OSFIND = $FFCE
OSGBPB = $FFD1
OSBPUT = $FFD4
OSBGET = $FFD7
OSARGS = $FFDA
OSFILE = $FFDD
OSRDCH = $FFE0
OSASCI = $FFE3
OSNEWL = $FFE7
OSWRCH = $FFEE
OSWORD = $FFF1
OSBYTE = $FFF4
OSCLI = $FFF7
LFFFF = $FFFF
\ ******************************************************************************
\ ******************************************************************************
\ * Start of code
\ ******************************************************************************
\ ******************************************************************************
ORG NATIVE_ADDR
;GUARD SCREEN_BASE_ADDR
.START
\ ******************************************************************************
\ * Message strings
\ ******************************************************************************
.end_of_level_messages ; bytes 0,1? byte 2=font byte mask, byte 3 onwards = text
\\ {
.string_mission
EQUB $D0,$55,$FF
EQUS "Mission " ; terminated by following $FF
.string_in
EQUB $FF,$00,$FF
EQUS "In" ; terminated by following $FF
.string_complete
EQUB $FF,$00,$FF
EQUS "Complete"
EQUB $FF
.string_bonus
EQUB $D0,$5C,$0F
EQUS "Bonus " ; terminated by following $FF
.string_failed
EQUB $FF,$00,$FF
EQUS "Failed"
EQUB $FF
.string_no_bonus
EQUB $E0,$5C,$0F
EQUS "No Bonus"
EQUB $FF
.string_planet_destroyed
EQUB $20,$4F,$F0
EQUS "Planet Destroyed"
EQUB $FF
.string_reverse_gravity
EQUB $A0,$53,$0F
EQUS "Reverse Gravity"
EQUB $FF
.string_invisible_landscape
EQUB $80,$53,$0F
EQUS "Invisible Landscape"
EQUB $FF
.string_i_love_space
EQUB $00,$58,$FF
EQUS " I love space"
EQUB $FF
.string_physics_is_fun
EQUB $00,$58,$FF
EQUS "Physics is fun"
EQUB $FF
.string_support_hotol
EQUB $00,$58,$FF
EQUS " Support Hotol" ; https://en.wikipedia.org/wiki/HOTOL
EQUB $FF
\\ }
\ ******************************************************************************
\ * Pixel masks for MODE 1
\ ******************************************************************************
.pixel_masks_1
EQUB $88,$44,$22,$11
.pixel_masks_2
EQUB $80,$40,$20,$10
.pixel_masks_3
EQUB $08,$04,$02,$01
\ ******************************************************************************
\ * Pointers to ship sprite data
\ ******************************************************************************
.ship_sprite_ptr_table_LO
{
EQUB LO(ship_sprite_0_data)
EQUB LO(ship_sprite_1_data)
EQUB LO(ship_sprite_2_data)
EQUB LO(ship_sprite_3_data)
EQUB LO(ship_sprite_4_data)
EQUB LO(ship_sprite_5_data)
EQUB LO(ship_sprite_6_data)
EQUB LO(ship_sprite_7_data)
EQUB LO(ship_sprite_8_data)
EQUB LO(ship_sprite_9_data)
EQUB LO(ship_sprite_10_data)
EQUB LO(ship_sprite_11_data)
EQUB LO(ship_sprite_12_data)
EQUB LO(ship_sprite_13_data)
EQUB LO(ship_sprite_14_data)
EQUB LO(ship_sprite_15_data)
EQUB LO(ship_sprite_16_data)
EQUB LO(sheild_sprite_data)
}
.ship_sprite_ptr_table_HI
{
EQUB HI(ship_sprite_0_data)
EQUB HI(ship_sprite_1_data)
EQUB HI(ship_sprite_2_data)
EQUB HI(ship_sprite_3_data)
EQUB HI(ship_sprite_4_data)
EQUB HI(ship_sprite_5_data)
EQUB HI(ship_sprite_6_data)
EQUB HI(ship_sprite_7_data)
EQUB HI(ship_sprite_8_data)
EQUB HI(ship_sprite_9_data)
EQUB HI(ship_sprite_10_data)
EQUB HI(ship_sprite_11_data)
EQUB HI(ship_sprite_12_data)
EQUB HI(ship_sprite_13_data)
EQUB HI(ship_sprite_14_data)
EQUB HI(ship_sprite_15_data)
EQUB HI(ship_sprite_16_data)
EQUB HI(sheild_sprite_data)
}
\ ******************************************************************************
\ ******************************************************************************
\ * Landscape / terrain system
\ ******************************************************************************
\ ******************************************************************************
\ ******************************************************************************
\ * Function: landscape_draw
\ * Description: <>
\ ******************************************************************************
.landscape_draw
\\ {
LDA #$00
STA terrain_draw_table_index
LDA #$49 ; 73 - why?
CLC
ADC terrain_window_y_index
STA terrain_draw_wall_index
LDA #$02 ; start at scanline 2
STA terrain_draw_addr_LO
LDA #HI(SCREEN_START_ADDR)
STA terrain_draw_addr_HI
LDX window_xpos_INT
DEX
STX window_xpos_2 ; **MODIFIES CODE**
STX window_xpos_1 ; **MODIFIES CODE**
CLC
.landscape_draw_loop
LDY terrain_draw_wall_index ; starts at terrain_window_y_index + $49
LDA terrain_left_wall,Y
.sbc_window_xpos_1
SBC #$00 ; **SELF-MODIFIED CODE **
window_xpos_1 = sbc_window_xpos_1+1
BCS terrain_xpos_1_greater_than_zero
LDA #$00 ; clamp to 0
JMP terrain_xpos_1_less_than_screen_width
.terrain_xpos_1_greater_than_zero
CMP #SCREEN_WIDTH_CHARS
BCC terrain_xpos_1_less_than_screen_width
LDA #SCREEN_WIDTH_CHARS ; clamp to screen width (chars)
.terrain_xpos_1_less_than_screen_width
STA terrain_xpos_1_clipped
LDY terrain_draw_table_index
SEC
SBC terrain_draw_table_2,Y ; number of columns to draw = xpos1 - table2
BCS terrain_width_1_greater_than_zero
EOR #$FF ; negate width to make positive
TAX ; number of columns to draw
INX ; +1
LDA terrain_xpos_1_clipped
STA terrain_draw_table_2,Y ; update table_2 for next time?
TAY ; start X column
JMP draw_terrain_xpos_1 ; draw a line of terrain
.terrain_width_1_greater_than_zero
CLC
BEQ landscape_draw_part_2 ; nothing to draw
TAX ; number of columns to draw
LDA terrain_draw_table_2,Y
STA terrain_draw_start_x ; start X column
LDA terrain_xpos_1_clipped
STA terrain_draw_table_2,Y ; update table_2 for next time?
LDY terrain_draw_start_x ; start X column
.draw_terrain_xpos_1
JSR draw_terrain
.landscape_draw_part_2
LDY terrain_draw_wall_index
LDA terrain_right_wall,Y
.sbc_window_xpos_2
SBC #$00 ; **SELF-MODIFIED CODE **
window_xpos_2 = sbc_window_xpos_2+1
BCS terrain_xpos_2_greater_than_zero
LDA #$00 ; clamp to 0
JMP terrain_xpos_2_less_than_screen_width
.terrain_xpos_2_greater_than_zero
CMP #SCREEN_WIDTH_CHARS ; clamp to screen width
BCC terrain_xpos_2_less_than_screen_width
LDA #SCREEN_WIDTH_CHARS
.terrain_xpos_2_less_than_screen_width
STA terrain_xpos_2_clipped
LDY terrain_draw_table_index
SEC
SBC terrain_draw_table_4,Y
BCS terrain_width_2_greater_than_zero
EOR #$FF ; negate width to make positive
TAX ; number columns to draw
INX ; +1
LDA terrain_xpos_2_clipped
STA terrain_draw_table_4,Y
TAY ; start X column
JMP draw_terrain_xpos_2
.terrain_width_2_greater_than_zero
CLC
BEQ landscape_increment_index ; nothing to draw
TAX ; number columns to draw
LDA terrain_draw_table_4,Y
STA terrain_draw_start_x ; start X column
LDA terrain_xpos_2_clipped
STA terrain_draw_table_4,Y ; update table 4?
LDY terrain_draw_start_x ; start X column
.draw_terrain_xpos_2
JSR draw_terrain
.landscape_increment_index
INC terrain_draw_wall_index
INC terrain_draw_table_index
.landscape_increment_draw_addr
LDA terrain_draw_addr_LO
ADC #$02 ; only draw every other line
STA terrain_draw_addr_LO
AND #$07
BEQ landscape_draw_next_character_row
JMP landscape_draw_loop
.landscape_draw_next_character_row
LDA terrain_draw_addr_LO
ADC #LO(SCREEN_CHAR_ROW_BYTES - 8)
STA terrain_draw_addr_LO
LDA terrain_draw_addr_HI
ADC #HI(SCREEN_CHAR_ROW_BYTES - 8) ; move down a character row
STA terrain_draw_addr_HI
BMI landscape_draw_return
JMP landscape_draw_loop
.landscape_draw_return
RTS
\\ }
\ ******************************************************************************
\ * Function: initialise_landscape
\ * Description: <>
\ ******************************************************************************
.initialise_landscape
{
LDX #$01
STX terrain_left_wall_2_index
STX terrain_right_wall_2_index
DEX
STX terrain_window_y_index
STX terrain_left_wall_1_xpos
STX terrain_left_wall_2_xpos
STX terrain_left_wall_1_index
STX terrain_right_wall_1_index
DEX
STX terrain_left_wall_1_counter
STX terrain_right_wall_1_counter
STX terrain_right_wall_1_xpos
STX terrain_right_wall_2_xpos
STX terrain_left_wall_2_counter
STX terrain_right_wall_2_counter
LDA window_ypos_INT
STA terrain_y_count_inner
LDA window_ypos_EXT
STA terrain_y_count_outer
INC terrain_y_count_inner
INC terrain_y_count_outer
INC terrain_y_count_outer
BNE terrain_y_count_outer_not_zero
.initialise_landscape_loop ; $C37
JSR terrain_process_accumulate_xpos
.terrain_y_count_outer_not_zero
DEC terrain_y_count_inner
BNE initialise_landscape_loop
DEC terrain_y_count_outer
BNE initialise_landscape_loop
RTS
}
\ ******************************************************************************
\ * Functions: terrain_process_subtract_xpos, terrain_process_accumulate_xpos
\ * Description: updates all triples, terrain_left_wall & terrain_right_wall
\ ******************************************************************************
.terrain_call_process_fn
JMP terrain_call_process_fn_JMP_LO ; **SELF-MODIFIED CODE **
terrain_call_process_fn_JMP_LO = terrain_call_process_fn+1
terrain_call_process_fn_JMP_HI = terrain_call_process_fn+2
.terrain_process_subtract_xpos
{
LDA #LO(terrain_subtract_xpos_fn)
STA terrain_call_process_fn_JMP_LO ; **MODIFIES CODE**
LDA #HI(terrain_subtract_xpos_fn)
STA terrain_call_process_fn_JMP_HI ; **MODIFIES CODE**
DEC terrain_window_y_index
JSR terrain_process
RTS
}
.terrain_process_accumulate_xpos
{
LDA #LO(terrain_accumulate_xpos_fn)
STA terrain_call_process_fn_JMP_LO ; **MODIFIES CODE**
LDA #HI(terrain_accumulate_xpos_fn)
STA terrain_call_process_fn_JMP_HI ; **MODIFIES CODE**
INC terrain_window_y_index
}
\\ Fall through!
.terrain_process
{
\\ Set pointers to data tables A & B
LDA terrain_left_wall_counter_LO
STA terrain_data_count_ptr
LDA terrain_left_wall_counter_HI
STA terrain_data_count_ptr+1
LDA terrain_left_wall_increment_LO
STA terrain_data_x_increment_ptr
LDA terrain_left_wall_increment_HI
STA terrain_data_x_increment_ptr+1
\\ Load first triple
LDA terrain_left_wall_1_xpos
LDX terrain_left_wall_1_counter
LDY terrain_left_wall_1_index
\\ Process triple