Reverse engineer star blazer game main loop and input system, bring sky blazer disass...
authorNick Downing <nick.downing@lifx.co>
Sun, 21 Jul 2024 07:38:55 +0000 (23:38 -0800)
committerNick Downing <nick.downing@lifx.co>
Sun, 21 Jul 2024 10:26:08 +0000 (02:26 -0800)
13 files changed:
.gitignore
star_blazer/Makefile
star_blazer/equivalence.py [new file with mode: 0755]
star_blazer/equivalence.sh [new file with mode: 0755]
star_blazer/sky_blazer.asm.patch [new file with mode: 0644]
star_blazer/sky_blazer.txt
star_blazer/sky_blazer0_segments.txt
star_blazer/sky_blazer_object_defs.inc
star_blazer/star_blazer.asm.patch
star_blazer/star_blazer.txt
star_blazer/star_blazer_object_defs.inc [moved from star_blazer/object_defs.inc with 99% similarity]
star_blazer/uncomment.sh [new file with mode: 0755]
utils/disasm.py

index 9a4a37d..570fa5b 100644 (file)
@@ -68,6 +68,8 @@
 /star_blazer/shape_index_pixel.inc
 /star_blazer/shape_pixel.json
 /star_blazer/sky_blazer.asm
+/star_blazer/sky_blazer.asm0
+/star_blazer/sky_blazer1.txt
 /star_blazer/sky_blazer_draw_misc.json
 /star_blazer/sky_blazer_draw_misc_table.inc
 /star_blazer/sky_blazer_object.json
index c988657..f316898 100644 (file)
@@ -9,6 +9,7 @@ LOAD_ADDR=0x800
 .PHONY: all
 all: \
 star_blazer.dsk \
+sky_blazer.asm \
 sky_blazer_shape_index.inc \
 sky_blazer_shape_data.inc \
 sky_blazer_object_index.inc \
@@ -154,8 +155,11 @@ sky_blazer_draw_misc.json: sky_blazer.txt sky_blazer0.ihx
 sky_blazer.asm: \
 sky_blazer0.ihx \
 sky_blazer_trace.txt \
-sky_blazer.txt
-       ../utils/disasm.py --trace=sky_blazer_trace.txt sky_blazer.txt $< $@
+sky_blazer.txt \
+sky_blazer.asm.patch
+       ../utils/disasm.py --trace=sky_blazer_trace.txt sky_blazer.txt $< $@ sky_blazer1.txt
+       cp $@ $@0
+       patch $@ <$@.patch
 
 sky_blazer0.ihx: \
 Sky\ Blazer\ (4am\ and\ san\ inc\ crack).nib \
diff --git a/star_blazer/equivalence.py b/star_blazer/equivalence.py
new file mode 100755 (executable)
index 0000000..384a80e
--- /dev/null
@@ -0,0 +1,59 @@
+#!/usr/bin/env python3
+
+import sys
+
+prefixes = {'barr', 'bvar', 'loc', 'sub', 'rts', 'ptr', 'vec'}
+
+lines = list(sys.stdin)
+assert lines[0][:3] == '---'
+assert lines[1][:3] == '+++'
+lines = lines[2:]
+for i in range(len(lines) - 3):
+  if (
+    lines[i][:1] == ' ' and
+      lines[i + 1][:1] == '-' and
+      lines[i + 2][:1] == '+' and
+       lines[i + 3][:1] == ' '
+  ):
+    offset = 0
+
+    old = lines[i + 1][1:].strip()
+    j = old.find(',')
+    if j >= 0:
+      old = old[:j]
+    j = old.find(':')
+    if j >= 0:
+      old = old[:j]
+    j = old.find(' + ')
+    if j >= 0:
+      offset -= int(old[j + 3:], 0)
+      old = old[:j]
+    else:
+      j = old.find(' - ')
+      if j >= 0:
+        offset += int(old[j + 3:], 0)
+        old = old[:j]
+
+    new = lines[i + 2][1:].strip()
+    j = new.find(',')
+    if j >= 0:
+      new = new[:j]
+    j = new.find(':')
+    if j >= 0:
+      new = new[:j]
+    j = new.find(' + ')
+    if j >= 0:
+      offset += int(new[j + 3:], 0)
+      new = new[:j]
+    else:
+      j = new.find(' - ')
+      if j >= 0:
+        offset -= int(new[j + 3:], 0)
+        new = new[:j]
+
+    j = new.find('_')
+    if j >= 0 and new[:j] in prefixes:
+      addr = int(new[j + 1:], 16) + offset
+      print(f's/^#0x....,\\(0x....,{old:s},\\)/0x{addr:04x},\\1/')
+    else:
+      print('old', old, 'new', new, 'offset', offset)
diff --git a/star_blazer/equivalence.sh b/star_blazer/equivalence.sh
new file mode 100755 (executable)
index 0000000..4e23949
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/sh
+./uncomment.sh <star_blazer.asm >a
+./uncomment.sh <sky_blazer.asm >b
+diff --unified a b >c
+./equivalence.py <c >d
+# matches in the zpage tend to be false because of ambiguity
+# therefore, sort in reverse so that matches later in the file have priority
+LC_ALL=C sort -r <d |uniq >e
diff --git a/star_blazer/sky_blazer.asm.patch b/star_blazer/sky_blazer.asm.patch
new file mode 100644 (file)
index 0000000..dded0c0
--- /dev/null
@@ -0,0 +1,1301 @@
+--- sky_blazer.asm0    2024-07-20 23:30:36.964896855 -0800
++++ sky_blazer.asm     2024-07-20 23:34:52.942221251 -0800
+@@ -1,3 +1,10 @@
++UNREACHABLE = 1
++DHGR = 0
++PIXEL_SHAPE = 0
++SHAPE = 1
++OBJECT = 1
++DRAW_MISC = 1
++
+ HIRES_SCREEN = 0x2000                 ; 2000
+ HW_KBD = 0xc000                               ; c000
+ HW_KBDSTRB = 0xc010                   ; c010
+@@ -11,19 +18,48 @@
+ HW_PADDL1 = 0xc065                    ; c065
+ HW_PTRIG = 0xc070                     ; c070
++.if DHGR
++; read
++HW_SETDHIRES = 0xc05e
++HW_SETIOUDIS = 0xc07e
++HW_CLRIOUDIS = 0xc07f
++HW_LC_BANK2_RAM_WP = 0xc080
++HW_LC_BANK2_ROM_WE = 0xc081
++HW_LC_BANK2_ROM_WP = 0xc082
++HW_LC_BANK2_RAM_WE = 0xc083
++HW_LC_BANK1_RAM_WP = 0xc084
++HW_LC_BANK1_ROM_WE = 0xc085
++HW_LC_BANK1_ROM_WP = 0xc086
++HW_LC_BANK1_RAM_WE = 0xc087
++
++; write
++HW_CLR80COL = 0xc000
++HW_SET80COL = 0xc001
++HW_RDMAINRAM = 0xc002
++HW_RDCARDRAM = 0xc003
++HW_WRMAINRAM = 0xc004
++HW_WRCARDRAM = 0xc005
++HW_CLR80VID = 0xc00c
++HW_SET80VID = 0xc00d
++.endif
++
++.include "object_defs.inc"
++
++      .globl  start
++
+       .area   zpage
+       .ds     0x22                    ; 0000
+ vec_init_game:
+-      .ds     2                       ; 0022 r
++      .dw     init_game               ; 0022 r
+ vec_start_game:
+-      .ds     2                       ; 0024 r
++      .dw     start_game              ; 0024 r
+       .ds     2                       ; 0026
+ vec_calculate_object_shape:
+-      .ds     2                       ; 0028 r
++      .dw     calculate_object_shape  ; 0028 r
+       .ds     0x24                    ; 002a
+ vec_draw_misc_from_table:
+-      .ds     2                       ; 004e r
++      .dw     draw_misc_from_table    ; 004e r
+       .ds     0x30                    ; 0050
+ half_dimension:
+       .ds     1                       ; 0080 rw
+@@ -47,12 +83,22 @@
+ draw_y:       .ds     1                       ; 008a rw
+ video_line_ptr:
+       .ds     2                       ; 008b rw
++.if DHGR
++draw_misc_aux_mask:
++      .ds     1
++draw_misc_aux_mask_xor:
++      .ds     1
++.endif
+ draw_misc_mask:
+       .ds     1                       ; 008d rw
+ draw_misc_mask_temp:
+       .ds     1                       ; 008e rw
+ draw_misc_mask_xor:
+       .ds     1                       ; 008f rw
++.if DHGR
++draw_misc_shape_xor:
++      .ds     1
++.endif
+ ; 24-bit register, repurposed for divide routine as
+ ;   accumulator: divisor
+ ;   accumulator + 1: remainder
+@@ -422,20 +468,20 @@
+ ;   object1080_velocity_scale_for_position_(hi|lo)
+ ; returns a = high byte of scaled value
+ get_scaled_object_velocity_x_to_a:
+-      lda     object1080_velocity_y_hi + 0x60,y ; 0b5a r
++      lda     object1080_velocity_x_lo - 0x10,y ;object1080_velocity_y_hi + 0x60,y ; 0b5a r
+       sta     *accumulator            ; 0b5d r
+-      lda     object1080_state + 0x60,y ; 0b5f r
++      lda     object1080_velocity_x_hi - 0x10,y ;object1080_state + 0x60,y ; 0b5f r
+       jmp     loc_0b6d                ; 0b62 r
+ get_scaled_object_velocity_y_to_a:
+-      lda     object1080_velocity_x_lo + 0x60,y ; 0b65 r
++      lda     object1080_velocity_y_lo - 0x10,y ;object1080_velocity_x_lo + 0x60,y ; 0b65 r
+       sta     *accumulator            ; 0b68 r
+-      lda     object1080_velocity_x_hi + 0x60,y ; 0b6a r
++      lda     object1080_velocity_y_hi - 0x10,y ;object1080_velocity_x_hi + 0x60,y ; 0b6a r
+ loc_0b6d:
+       sty     *y_save                 ; 0b6d r
+       sta     *accumulator + 1        ; 0b6f r
+-      lda     object1080_velocity_y_random_range + 0x60,y ; 0b71 r
++      lda     object1080_velocity_scale_for_position_hi - 0x10,y ;object1080_velocity_y_random_range + 0x60,y ; 0b71 r
+       sta     *temp                   ; 0b74 r
+-      lda     object1080_velocity_scale_for_position_hi + 0x60,y ; 0b76 r
++      lda     object1080_velocity_scale_for_position_lo - 0x10,y ;object1080_velocity_scale_for_position_hi + 0x60,y ; 0b76 r
+       ldy     *temp                   ; 0b79 r
+       jsr     multiply_ya_by_accumulator_optimized ; 0b7b r
+       tya                             ; 0b7e r
+@@ -450,46 +496,46 @@
+ copy_object_position_plus_scaled_velocity:
+       jsr     get_scaled_object_velocity_x_to_a ; 0b82 r
+       clc                             ; 0b85 r
+-      adc     object1080_shape + 0x60,y ; 0b86 r
+-      sta     object1080_shape + 0x60,x ; 0b89 r
++      adc     object1080_x_hi - 0x10,y ;object1080_shape + 0x60,y ; 0b86 r
++      sta     object1080_x_hi - 0x10,x ;object1080_shape + 0x60,x ; 0b89 r
+       jsr     get_scaled_object_velocity_y_to_a ; 0b8c r
+       clc                             ; 0b8f r
+-      adc     object1080_x_hi + 0x60,y ; 0b90 r
+-      sta     object1080_x_hi + 0x60,x ; 0b93 r
++      adc     object1080_y_hi - 0x10,y ;object1080_x_hi + 0x60,y ; 0b90 r
++      sta     object1080_y_hi - 0x10,x ;object1080_x_hi + 0x60,x ; 0b93 r
+       rts                             ; 0b96 r
+ copy_object_position_plus_scaled_velocity_rotate_90:
+       jsr     get_scaled_object_velocity_y_to_a ; 0b97 r
+       jsr     neg_a                   ; 0b9a r
+       clc                             ; 0b9d r
+-      adc     object1080_shape + 0x60,y ; 0b9e r
+-      sta     object1080_shape + 0x60,x ; 0ba1 r
++      adc     object1080_x_hi - 0x10,y ;object1080_shape + 0x60,y ; 0b9e r
++      sta     object1080_x_hi - 0x10,x ;object1080_shape + 0x60,x ; 0ba1 r
+       jsr     get_scaled_object_velocity_x_to_a ; 0ba4 r
+       clc                             ; 0ba7 r
+-      adc     object1080_x_hi + 0x60,y ; 0ba8 r
+-      sta     object1080_x_hi + 0x60,x ; 0bab r
++      adc     object1080_y_hi - 0x10,y ;object1080_x_hi + 0x60,y ; 0ba8 r
++      sta     object1080_y_hi - 0x10,x ;object1080_x_hi + 0x60,x ; 0bab r
+       rts                             ; 0bae r
+ copy_object_position_plus_scaled_velocity_rotate_180:
+       jsr     get_scaled_object_velocity_x_to_a ; 0baf r
+       jsr     neg_a                   ; 0bb2 r
+       clc                             ; 0bb5 r
+-      adc     object1080_shape + 0x60,y ; 0bb6 r
+-      sta     object1080_shape + 0x60,x ; 0bb9 r
++      adc     object1080_x_hi - 0x10,y ;object1080_shape + 0x60,y ; 0bb6 r
++      sta     object1080_x_hi - 0x10,x ;object1080_shape + 0x60,x ; 0bb9 r
+       jsr     get_scaled_object_velocity_y_to_a ; 0bbc r
+       jsr     neg_a                   ; 0bbf r
+       clc                             ; 0bc2 r
+-      adc     object1080_x_hi + 0x60,y ; 0bc3 r
+-      sta     object1080_x_hi + 0x60,x ; 0bc6 r
++      adc     object1080_y_hi - 0x10,y ;object1080_x_hi + 0x60,y ; 0bc3 r
++      sta     object1080_y_hi - 0x10,x ;object1080_x_hi + 0x60,x ; 0bc6 r
+       rts                             ; 0bc9 r
+ copy_object_position_plus_scaled_velocity_rotate_270:
+       jsr     get_scaled_object_velocity_y_to_a ; 0bca r
+       clc                             ; 0bcd r
+-      adc     object1080_shape + 0x60,y ; 0bce r
+-      sta     object1080_shape + 0x60,x ; 0bd1 r
++      adc     object1080_x_hi - 0x10,y ;object1080_shape + 0x60,y ; 0bce r
++      sta     object1080_x_hi - 0x10,x ;object1080_shape + 0x60,x ; 0bd1 r
+       jsr     get_scaled_object_velocity_x_to_a ; 0bd4 r
+       jsr     neg_a                   ; 0bd7 r
+       clc                             ; 0bda r
+-      adc     object1080_x_hi + 0x60,y ; 0bdb r
+-      sta     object1080_x_hi + 0x60,x ; 0bde r
++      adc     object1080_y_hi - 0x10,y ;object1080_x_hi + 0x60,y ; 0bdb r
++      sta     object1080_y_hi - 0x10,x ;object1080_x_hi + 0x60,x ; 0bde r
+       rts                             ; 0be1 r
+ ; call with y = object to calculate for
+ ; uses coefficient from the following table:
+@@ -519,27 +565,27 @@
+ ; only the 0 and 180 degrees rotation occurred in the trace
+ copy_scaled_object_velocity:
+       jsr     get_scaled_object_velocity_x_to_ya ; 0c06 r
+-      sta     object1080_velocity_y_hi + 0x60,x ; 0c09 r
++      sta     object1080_velocity_x_lo - 0x10,x ;object1080_velocity_y_hi + 0x60,x ; 0c09 r
+       tya                             ; 0c0c r
+-      sta     object1080_state + 0x60,x ; 0c0d r
++      sta     object1080_velocity_x_hi - 0x10,x ;object1080_state + 0x60,x ; 0c0d r
+       ldy     *y_save                 ; 0c10 r
+       jsr     get_scaled_object_velocity_y_to_ya ; 0c12 r
+-      sta     object1080_velocity_x_lo + 0x60,x ; 0c15 r
++      sta     object1080_velocity_y_lo - 0x10,x ;object1080_velocity_x_lo + 0x60,x ; 0c15 r
+       tya                             ; 0c18 r
+-      sta     object1080_velocity_x_hi + 0x60,x ; 0c19 r
++      sta     object1080_velocity_y_hi - 0x10,x ;object1080_velocity_x_hi + 0x60,x ; 0c19 r
+       ldy     *y_save                 ; 0c1c r
+       rts                             ; 0c1e r
+ copy_scaled_object_velocity_rotate_90:
+       jsr     get_scaled_object_velocity_y_to_ya ; 0c1f r
+       jsr     neg_ya                  ; 0c22 r
+-      sta     object1080_velocity_y_hi + 0x60,x ; 0c25 r
++      sta     object1080_velocity_x_lo - 0x10,x ;object1080_velocity_y_hi + 0x60,x ; 0c25 r
+       tya                             ; 0c28 r
+-      sta     object1080_state + 0x60,x ; 0c29 r
++      sta     object1080_velocity_x_hi - 0x10,x ;object1080_state + 0x60,x ; 0c29 r
+       ldy     *y_save                 ; 0c2c r
+       jsr     get_scaled_object_velocity_x_to_ya ; 0c2e r
+-      sta     object1080_velocity_x_lo + 0x60,x ; 0c31 r
++      sta     object1080_velocity_y_lo - 0x10,x ;object1080_velocity_x_lo + 0x60,x ; 0c31 r
+       tya                             ; 0c34 r
+-      sta     object1080_velocity_x_hi + 0x60,x ; 0c35 r
++      sta     object1080_velocity_y_hi - 0x10,x ;object1080_velocity_x_hi + 0x60,x ; 0c35 r
+       ldy     *y_save                 ; 0c38 r
+       rts                             ; 0c3a r
+ copy_scaled_object_velocity_rotate_180:
+@@ -558,15 +604,15 @@
+       rts                             ; 0c57 -> 0c59 -> 0fcb r s=f1
+ copy_scaled_object_velocity_rotate_270:
+       jsr     get_scaled_object_velocity_y_to_ya ; 0c5a r
+-      sta     object1080_velocity_y_hi + 0x60,x ; 0c5d r
++      sta     object1080_velocity_x_lo - 0x10,x ;object1080_velocity_y_hi + 0x60,x ; 0c5d r
+       tya                             ; 0c60 r
+-      sta     object1080_state + 0x60,x ; 0c61 r
++      sta     object1080_velocity_x_hi - 0x10,x ;object1080_state + 0x60,x ; 0c61 r
+       ldy     *y_save                 ; 0c64 r
+       jsr     get_scaled_object_velocity_x_to_ya ; 0c66 r
+       jsr     neg_ya                  ; 0c69 r
+-      sta     object1080_velocity_x_lo + 0x60,x ; 0c6c r
++      sta     object1080_velocity_y_lo - 0x10,x ;object1080_velocity_x_lo + 0x60,x ; 0c6c r
+       tya                             ; 0c6f r
+-      sta     object1080_velocity_x_hi + 0x60,x ; 0c70 r
++      sta     object1080_velocity_y_hi - 0x10,x ;object1080_velocity_x_hi + 0x60,x ; 0c70 r
+       ldy     *y_save                 ; 0c73 r
+       rts                             ; 0c75 r
+ horizontal_collision:
+@@ -608,8 +654,8 @@
+ horizontal_collision_and_zero:
+       jsr     horizontal_collision    ; 0cc4 r
+       lda     #0x00                   ; 0cc7 r
+-      sta     object1080_velocity_y_hi + 0x60,x ; 0cc9 r
+-      sta     object1080_state + 0x60,x ; 0ccc r
++      sta     object1080_velocity_x_lo - 0x10,x ;object1080_velocity_y_hi + 0x60,x ; 0cc9 r
++      sta     object1080_velocity_x_hi - 0x10,x ;object1080_state + 0x60,x ; 0ccc r
+       rts                             ; 0ccf r
+ vertical_collision_and_zero:
+       jsr     vertical_collision      ; 1015 -> 0cd0 -> 0c9d r s=f6
+@@ -942,9 +988,10 @@
+       bcs     ucode_decimal_set_save  ; 0ebf r
+ ucode_decimal_set_mission_specific_value:
+       ldy     *decimal + 6            ; 0ec1 r
+-      lda     initial_decimal_plus_0xe,y ; 0ec3 r
++      lda     mission_table_decimal_plus_4 - 1,y ;initial_decimal_plus_0xe,y ; 0ec3 r
++ 
+       pha                             ; 0ec6 r
+-      lda     initial_decimal_plus_0xf,y ; 0ec7 r
++      lda     mission_table_decimal_plus_5 - 1,y ;initial_decimal_plus_0xf,y ; 0ec7 r
+       tay                             ; 0eca r
+       pla                             ; 0ecb r
+       bcs     ucode_decimal_set_save  ; 0ecc r
+@@ -1312,7 +1359,7 @@
+       tsx                             ; 1095 -> 1097 -> 1098 r
+       stx     *ucode_sp               ; 1097 -> 1098 -> 109a r
+       ldx     *ucode_x_save           ; 1098 -> 109a -> 109c r
+-      lda     object1080_y1 + 0x60,x  ; 109a -> 109c -> 109f r x=01..7f
++      lda     object1080_state - 0x10,x ;object1080_y1 + 0x60,x       ; 109a -> 109c -> 109f r x=01..7f
+       sta     *ucode_fire_in_state_fn_count ; 109c -> 109f -> 10a1 r
+ ; alternative entry point for execute_ucode_words that comes from scoring?
+ execute_ucode_words_entry:
+@@ -1344,7 +1391,7 @@
+ ;     jsr     execute_object1080_ucode_countdown
+ ;     bpl     rts_15d6
+ execute_ucode_words_done:
+-      lda     object1080_y1 + 0x60,x  ; 1093,10a5,10ba,10c2,10c6 -> 10cd -> 10d0 r x=01..7f
++      lda     object1080_state - 0x10,x ;object1080_y1 + 0x60,x       ; 1093,10a5,10ba,10c2,10c6 -> 10cd -> 10d0 r x=01..7f
+       rts                             ; 10cd -> 10d0 -> 123e,143a,1615,1629,1633,1649,165b,1759 r s=f8..fe,02
+ ; call with the following set up:
+ ;   execute_ucode_words_ptr
+@@ -1865,16 +1912,20 @@
+       bpl     loc_14c9                ; 14a0 -> 14a3 -> 14a5,14c9 r n=0..1
+       iny                             ; 14a3 -> 14a5 -> 14a6 r
+       bne     ucode_test_fire_all_objects_active ; 14a5 -> 14a6 -> 149b r z=0
++.if UNREACHABLE
+       beq     loc_14c9                ; 14a8 r
++.endif
+ ucode_test_fire_all_objects_inactive:
+       lda     (*ucode_collision_or_fire_ptr),y ; 14aa r
+       beq     loc_14c9                ; 14ac r
+       tax                             ; 14ae r
+-      lda     object1080_y1 + 0x60,x  ; 14af r
++      lda     object1080_state - 0x10,x ;object1080_y1 + 0x60,x       ; 14af r
+       bmi     loc_14ca                ; 14b2 r
+       iny                             ; 14b4 r
+       bne     ucode_test_fire_all_objects_inactive ; 14b5 r
++.if UNREACHABLE
+       beq     loc_14c9                ; 14b7 r
++.endif
+ ; opcode is followed by null-terminated list of objects to test
+ ; note: some of these opcodes never executed in the trace
+ ; 0x01 loc_149b test that all objects are active (object1080_state >= 0x80)
+@@ -1907,17 +1958,21 @@
+       bmi     loc_14c9                ; 14d5 -> 14d8 -> 14c9,14da r n=0..1
+       iny                             ; 14d8 -> 14da -> 14db r
+       bne     ucode_test_fire_any_object_active ; 14da -> 14db -> 14d0 r z=0
++.if UNREACHABLE
+       beq     loc_14c9                ; 14dd r
+       rts                             ; 14df r
++.endif
+ ucode_test_fire_any_object_inactive:
+       lda     (*ucode_collision_or_fire_ptr),y ; 14e0 r
+       beq     loc_14c9                ; 14e2 r
+       tax                             ; 14e4 r
+-      lda     object1080_y1 + 0x60,x  ; 14e5 r
++      lda     object1080_state - 0x10,x ;object1080_y1 + 0x60,x       ; 14e5 r
+       bpl     loc_14ca                ; 14e8 r
+       iny                             ; 14ea r
+       bne     ucode_test_fire_any_object_inactive ; 14eb r
++.if UNREACHABLE
+       beq     loc_14c9                ; 14ed r
++.endif
+ test_object_fire_in_state_f0:
+       lda     object6080_fire_count - 0x60,x ; 1668 -> 14ef -> 14f2 r x=60..7f
+       beq     test_object_fire_false  ; 14ef -> 14f2 -> 14f4,153f r z=0..1
+@@ -2308,11 +2363,35 @@
+ ; the entry point to the executable
+ ; in star blazer it had joystick detection code, deleted in sky blazer
+ ; so in sky blazer it just jumps to init_game via vec_init_game
+-start:        jmp     (vec_init_game)         ; -> 17d1 -> 1708 r
++start:
++.if DHGR
++      ; shadow code that needs to run with "sta HW_RDCARDRAM"
++      ; from draw_object to draw_misc_from_table (this is generous)
++SHADOW_PAGES = (draw_misc_from_table - draw_object + 0xff) / 0x100
++SHADOW_START = draw_misc_from_table - SHADOW_PAGES * 0x100
++      lda     #<SHADOW_START
++      sta     *video_line_ptr
++      lda     #>SHADOW_START
++      sta     video_line_ptr + 1 
++      ldx     #SHADOW_PAGES
++      ldy     #<draw_object - SHADOW_START
++      sta     HW_WRCARDRAM
++90$:  lda     (video_line_ptr),y
++      sta     (video_line_ptr),y
++      iny
++      bne     90$
++      inc     video_line_ptr + 1
++      dex
++      bne     90$
++      sta     HW_WRMAINRAM
++.endif
++      jmp     (vec_init_game)         ; -> 17d1 -> 1708 r
++.if UNREACHABLE
+       .db     0x00                    ; 17d4
+       .db     0x00                    ; 17d5
+       .db     0x00                    ; 17d6
+       .db     0x00                    ; 17d7
++.endif
+ ; the next 3 routines were added in sky blazer in space freed up by
+ ; the deletion of the joystick detection code, it seems to have been
+ ; manually patched rather than reassembled as it is not tightly packed
+@@ -2320,7 +2399,9 @@
+       lda     #0xff                   ; 1710 -> 17d8 -> 17da r
+       sta     *stuck_joystick         ; 17d8 -> 17da -> 17dc r
+       jmp     video_init              ; 17da -> 17dc -> 1937 r
++.if UNREACHABLE
+       .db     0x00                    ; 17df
++.endif
+ patch_read_pb0:
+       bit     HW_PB0                  ; 179b -> 17e0 -> 17e3 r
+       bpl     0$                      ; 17e0 -> 17e3 -> 17e5,17ec r n=0..1
+@@ -2338,7 +2419,10 @@
+       sta     hw_spkr_ptr             ; 17f5 r
+       rts                             ; 17f8 r
++; above code is a bit bigger for DHGR so we are past address 0x1800 by here
++.ifeq DHGR
+       .area   text1
++.endif
+ divide_a_by_y:
+       sta     *accumulator + 1        ; 0a90,0aa0,0ab5,0ad5 -> 1800 -> 1802 r
+@@ -2404,10 +2488,12 @@
+       lda     *result + 1             ; 186e r
+       ldy     *result + 2             ; 1870 r
+       rts                             ; 1872 r
++.if UNREACHABLE
+       inc     *random_seed            ; 1873 r
+       bne     4$                      ; 1875 r
+       inc     *random_seed + 1        ; 1877 r
+ 4$:   rts                             ; 1879 r
++.endif
+ random_init:
+       lda     *random_seed            ; 16ae -> 187a -> 187c r
+       ora     #0x01                   ; 187a -> 187c -> 187e r
+@@ -2573,16 +2659,30 @@
+       ldx     #>HIRES_SCREEN          ; 199b -> 199d -> 199f r
+       stx     *video_line_ptr + 1     ; 199d -> 199f -> 19a1 r
+       tay                             ; 199f -> 19a1 -> 19a2 r
+-0$:   sta     (*video_line_ptr),y     ; 19a1,19a5,19aa -> 19a2 -> 19a4 r y=00..ff
++0$:
++.if DHGR
++      sta     HW_WRCARDRAM
++      sta     (*video_line_ptr),y
++      sta     HW_WRMAINRAM
++.endif
++      sta     (*video_line_ptr),y     ; 19a1,19a5,19aa -> 19a2 -> 19a4 r y=00..ff
+       iny                             ; 19a2 -> 19a4 -> 19a5 r
+       bne     0$                      ; 19a4 -> 19a5 -> 19a2,19a7 r z=0..1
+       inc     *video_line_ptr + 1     ; 19a5 -> 19a7 -> 19a9 r
+       dex                             ; 19a7 -> 19a9 -> 19aa r
+       bne     0$                      ; 19a9 -> 19aa -> 19a2,19ac r z=0..1
++.if DHGR
++      lda     HW_CLRIOUDIS
++      sta     HW_CLR80COL
++.endif
+       sta     HW_TXTCLR               ; 19aa -> 19ac -> 19af r
+       sta     HW_MIXCLR               ; 19ac -> 19af -> 19b2 r
+       sta     HW_PAGE1                ; 19af -> 19b2 -> 19b5 r
+       sta     HW_HIRES                ; 19b2 -> 19b5 -> 19b8 r
++.if DHGR
++      lda     HW_SETDHIRES
++      sta     HW_SET80VID
++.endif
+       rts                             ; 19b5 -> 19b8 -> 1713 r s=fe
+ video_clear_rectangle:
+       ldx     *clip_y0                ; 1064 -> 19b9 -> 19bb r
+@@ -2590,8 +2690,20 @@
+       sta     *video_line_ptr         ; 19bb -> 19be -> 19c0 r
+       lda     video_line_table_hi - 0x20,x ; 19be -> 19c0 -> 19c3 r x=28..cf
+       sta     *video_line_ptr + 1     ; 19c0 -> 19c3 -> 19c5 r
++.if DHGR
++      lda     #0
++      sta     HW_WRCARDRAM
++      ldy     *clip_x0
++90$:  sta     (*video_line_ptr),y     ; 19c7,19ce -> 19c9 -> 19cb r y=6c..93
++      iny                             ; 19c9 -> 19cb -> 19cc r
++      cpy     *clip_x1                ; 19cb -> 19cc -> 19ce r y=6d..94
++      bcc     90$                     ; 19cc -> 19ce -> 19c9,19d0 r c=0..1
++      sta     HW_WRMAINRAM
++      ldy     *clip_x0
++.else
+       ldy     *clip_x0                ; 19c3 -> 19c5 -> 19c7 r
+       lda     #0x00                   ; 19c5 -> 19c7 -> 19c9 r
++.endif
+ 1$:   sta     (*video_line_ptr),y     ; 19c7,19ce -> 19c9 -> 19cb r y=6c..93
+       iny                             ; 19c9 -> 19cb -> 19cc r
+       cpy     *clip_x1                ; 19cb -> 19cc -> 19ce r y=6d..94
+@@ -2641,6 +2753,7 @@
+       sta     object1080_y0 - 0x10,x  ; 1a1b -> 1a1e -> 1a21 r x=10..7f
+       adc     #0x01                   ; 1a1e -> 1a21 -> 1a23 r c=0..1 d=0
+       sta     object1080_y1 - 0x10,x  ; 1a21 -> 1a23 -> 1a26 r x=10..7f
++.ifeq PIXEL_SHAPE
+       rts                             ; 1a23 -> 1a26 -> 1076,1179,1602 r s=f2..fa,02
+ pixel_data_table_left:
+       .db     0x83                    ; 1a27 r
+@@ -2723,14 +2836,17 @@
+       lda     object1080_onscreen_shape_ptr_hi - 0x10,x ; 1aa5 -> 1aa7 -> 1aaa r x=20..4f
+       ora     (*video_line_ptr),y     ; 1aa7 -> 1aaa -> 1aac r y=6d..93,02
+       sta     (*video_line_ptr),y     ; 1aaa -> 1aac -> 1aae r y=6d..93,02
++.endif
+ rts_1aae:
+       rts                             ; 1a7b,1a7f,1aa1,1aa5,1aac,1ac1,1ad6 -> 1aae -> 15cd r s=fc
+ draw_object:
+       lda     object1080_onscreen - 0x10,x ; 16a8 -> 1aaf -> 1ab2 r x=14..77
+       bne     rts_1aae                ; 1aaf -> 1ab2 -> 1ab4 r z=1
+       lda     object1080_shape - 0x10,x ; 1ab2 -> 1ab4 -> 1ab7 r x=14..77
++.ifeq PIXEL_SHAPE
+       cmp     #0x08                   ; 1ab4 -> 1ab7 -> 1ab9 r a=01..8b
+       bcc     draw_pixel_object       ; 1ab7 -> 1ab9 -> 1a45,1abb r c=0..1
++.endif
+       lda     object1080_y0 - 0x10,x  ; 1ab9 -> 1abb -> 1abe r x=14..77
+       cmp     object1080_y1 - 0x10,x  ; 1abb -> 1abe -> 1ac1 r a=00..ff x=14..77
+       bcs     rts_1aae                ; 1abe -> 1ac1 -> 1aae,1ac3 r c=0..1
+@@ -2783,7 +2899,12 @@
+       stx     *x_save                 ; 1b32 -> 1b35 -> 1b37 r
+       lda     *draw_y                 ; 1b35 -> 1b37 -> 1b39 r
+       cmp     *clip_y0                ; 1b37 -> 1b39 -> 1b3b r a=00..f9
++.if DHGR
++      bcs     . + 5
++      jmp     8$
++.else
+       bcc     8$                      ; 1b39 -> 1b3b -> 1b3d,1b83 r c=0..1
++.endif
+       lda     *clip_y1                ; 1b3b -> 1b3d -> 1b3f r
+       cmp     *draw_y1                ; 1b3d -> 1b3f -> 1b41 r a=d0
+       bcc     8$                      ; 1b3f -> 1b41 -> 1b43,1b83 r c=0..1
+@@ -2794,16 +2915,59 @@
+       cmp     *draw_x1                ; 1b49 -> 1b4b -> 1b4d r a=94
+       bcc     8$                      ; 1b4b -> 1b4d -> 1b4f,1b83 r c=0..1
+       lda     object1080_onscreen_shape_ptr_lo - 0x10,x ; 1b4d -> 1b4f -> 1b52 r x=14..77
++.if DHGR
++      sta     92$
++.endif
+       sta     7$                      ; 1b4f -> 1b52 -> 1b55 r
++.if DHGR
++      tay
++.endif
+       lda     object1080_onscreen_shape_ptr_hi - 0x10,x ; 1b52 -> 1b55 -> 1b58 r x=14..77
++.if DHGR
++      sta     92$ + 1
++.endif
+       sta     7$ + 1                  ; 1b55 -> 1b58 -> 1b5b r
++.if DHGR
++      sta     HW_WRCARDRAM
++      sty     91$
++      sta     91$ + 1
++      ;sta    HW_WRMAINRAM
++.endif
+       ldx     #0x00                   ; 1b58 -> 1b5b -> 1b5d r
+       ldy     *draw_y                 ; 1b5b -> 1b5d -> 1b5f r
+ 5$:   lda     video_line_table_lo - 0x20,y ; 1b5d,1b7e -> 1b5f -> 1b62 r y=28..cf
+       sta     *video_line_ptr         ; 1b5f -> 1b62 -> 1b64 r
+       lda     video_line_table_hi - 0x20,y ; 1b62 -> 1b64 -> 1b67 r y=28..cf
+       sta     *video_line_ptr + 1     ; 1b64 -> 1b67 -> 1b69 r
++.if DHGR
++      sta     HW_RDCARDRAM
++      sta     HW_WRCARDRAM
++      ldy     *draw_x0
++      stx     *dimension
++90$:  .db     0xbd ; lda NNNN,x
++91$:  .dw     0
++      ora     (*video_line_ptr),y
++      sta     (*video_line_ptr),y
++      inx
++      iny
++      cpy     *draw_x1
++      bcc     90$
++      ldx     *dimension
++      sta     HW_RDMAINRAM
++      sta     HW_WRMAINRAM
++.endif
+       ldy     *draw_x0                ; 1b67 -> 1b69 -> 1b6b r
++.if DHGR ; draw overflow pixel
++      dey
++      bmi     93$
++      .db     0xbd ; lda NNNN,x
++92$:  .dw     0
++      lsr     a
++      and     #0x40
++      ora     (*video_line_ptr),y
++      sta     (*video_line_ptr),y
++93$:  iny
++.endif
+ 6$:   .db     0xbd                    ; 1b69,1b76 -> 1b6b -> 1b6e r "lda bvar_6f9f,x" x=00..39
+ 7$:   .dw     0x6f9f                  ; 1b6c rw
+       ora     (*video_line_ptr),y     ; 1b6b -> 1b6e -> 1b70 r y=6c..93
+@@ -2820,16 +2984,50 @@
+       rts                             ; 1b80 -> 1b82 -> 15cd r s=fc
+ 8$:   inc     object1080_onscreen_clipped - 0x10,x ; 1b3b,1b41,1b47,1b4d -> 1b83 -> 1b86 r x=14..77
+       lda     object1080_onscreen_shape_ptr_lo - 0x10,x ; 1b83 -> 1b86 -> 1b89 r x=14..77
++.if DHGR
++      sta     94$
++.endif
+       sta     11$                     ; 1b86 -> 1b89 -> 1b8c r
++.if DHGR
++      tay
++.endif
+       lda     object1080_onscreen_shape_ptr_hi - 0x10,x ; 1b89 -> 1b8c -> 1b8f r x=14..77
++.if DHGR
++      sta     94$ + 1
++.endif
+       sta     11$ + 1                 ; 1b8c -> 1b8f -> 1b92 r
++.if DHGR
++      sta     HW_WRCARDRAM
++      sty     96$
++      sta     96$ + 1
++      sta     HW_WRMAINRAM
++.endif
+       ldx     #0x00                   ; 1b8f -> 1b92 -> 1b94 r
+       ldy     *draw_y                 ; 1b92 -> 1b94 -> 1b96 r
+-9$:   lda     x_table_times2_mod7_minus_03 + 0xe0,y ; 1b94,1bc7 -> 1b96 -> 1b99 r y=00..fc
++9$:   lda     video_line_table_lo - 0x20,y ;x_table_times2_mod7_minus_03 + 0xe0,y ; 1b94,1bc7 -> 1b96 -> 1b99 r y=11..d8
+       sta     *video_line_ptr         ; 1b96 -> 1b99 -> 1b9b r
+-      lda     video_line_table_lo + 0xa0,y ; 1b99 -> 1b9b -> 1b9e r y=00..fc
++      lda     video_line_table_hi - 0x20,y ;video_line_table_lo + 0xa0,y ; 1b99 -> 1b9b -> 1b9e r y=11..d8
+       sta     *video_line_ptr + 1     ; 1b9b -> 1b9e -> 1ba0 r
+       ldy     *draw_x0                ; 1b9e -> 1ba0 -> 1ba2 r
++.if DHGR ; draw overflow pixel
++      lda     *draw_y
++      cmp     *clip_y0
++      bcc     12$
++      cmp     *clip_y1
++      bcs     12$
++      dey
++      cpy     *clip_x0
++      bcc     95$
++      cpy     *clip_x1
++      bcs     95$
++      .db     0xbd ; lda NNNN,x
++94$:  .dw     0
++      lsr     a
++      and     #0x40
++      ora     (*video_line_ptr),y
++      sta     (*video_line_ptr),y
++95$:  iny
++.endif
+ 10$:  lda     *draw_y                 ; 1ba0,1bbf -> 1ba2 -> 1ba4 r
+       cmp     *clip_y0                ; 1ba2 -> 1ba4 -> 1ba6 r a=00..fc
+       bcc     12$                     ; 1ba4 -> 1ba6 -> 1ba8,1bbb r c=0..1
+@@ -2839,6 +3037,16 @@
+       bcc     12$                     ; 1bac -> 1bae -> 1bb0,1bbb r c=0..1
+       cpy     *clip_x1                ; 1bae -> 1bb0 -> 1bb2 r y=6c..a4
+       bcs     12$                     ; 1bb0 -> 1bb2 -> 1bb4,1bbb r c=0..1
++.if DHGR
++      sta     HW_RDCARDRAM
++      sta     HW_WRCARDRAM
++      .db     0xbd ; lda NNNN,x
++96$:  .dw     0
++      ora     (*video_line_ptr),y
++      sta     (*video_line_ptr),y
++      sta     HW_RDMAINRAM
++      sta     HW_WRMAINRAM
++.endif
+       .db     0xbd                    ; 1bb2 -> 1bb4 -> 1bb7 r "lda 0x6fab,x" x=00..39
+ 11$:  .dw     0x6fab                  ; 1bb5 rw
+       ora     (*video_line_ptr),y     ; 1bb4 -> 1bb7 -> 1bb9 r y=6c..93
+@@ -2852,6 +3060,7 @@
+       cpy     *draw_y1                ; 1bc3 -> 1bc5 -> 1bc7 r y=01..fd
+       bcc     9$                      ; 1bc5 -> 1bc7 -> 1b96,1bc9 r c=0..1
+       ldx     *x_save                 ; 1bc7 -> 1bc9 -> 1bcb r
++.ifeq PIXEL_SHAPE
+       rts                             ; 1bc9 -> 1bcb -> 15cd r s=fc
+ erase_pixel_object:
+       lda     #0x00                   ; 1c12 -> 1bcc -> 1bce r
+@@ -2883,12 +3092,15 @@
+       eor     #0xff                   ; 1c03 -> 1c06 -> 1c08 r
+       and     (*video_line_ptr),y     ; 1c06 -> 1c08 -> 1c0a r y=6d..93,02
+       sta     (*video_line_ptr),y     ; 1c08 -> 1c0a -> 1c0c r y=6d..93,02
++.endif
+ rts_1c0c:
+       rts                             ; 1bd6,1bda,1bfd,1c01,1c0a,1c10 -> 1c0c -> 1076,15cd,16a8 r s=f4..fc,02
+ erase_object:
+       lda     object1080_onscreen - 0x10,x ; 11ba,16a5,16ab -> 1c0d -> 1c10 r x=10..7f
+       beq     rts_1c0c                ; 1c0d -> 1c10 -> 1c0c,1c12 r z=0..1
++.ifeq PIXEL_SHAPE
+       bmi     erase_pixel_object      ; 1c10 -> 1c12 -> 1bcc,1c14 r n=0..1
++.endif
+       lda     #0x00                   ; 1c12 -> 1c14 -> 1c16 r
+       sta     object1080_onscreen - 0x10,x ; 1c14 -> 1c16 -> 1c19 r x=14..77
+       lda     object1080_onscreen_x0 - 0x10,x ; 1c16 -> 1c19 -> 1c1c r x=14..77
+@@ -2903,16 +3115,61 @@
+       stx     *x_save                 ; 1c2d -> 1c30 -> 1c32 r
+       bne     3$                      ; 1c30 -> 1c32 -> 1c34,1c6a r z=0..1
+       lda     object1080_onscreen_shape_ptr_lo - 0x10,x ; 1c32 -> 1c34 -> 1c37 r x=14..77
++.if DHGR
++      sta     92$
++.endif
+       sta     2$                      ; 1c34 -> 1c37 -> 1c3a r
++.if DHGR
++      tay
++.endif
+       lda     object1080_onscreen_shape_ptr_hi - 0x10,x ; 1c37 -> 1c3a -> 1c3d r x=14..77
++.if DHGR
++      sta     92$ + 1
++.endif
+       sta     2$ + 1                  ; 1c3a -> 1c3d -> 1c40 r
++.if DHGR
++      sta     HW_WRCARDRAM
++      sty     91$
++      sta     91$ + 1
++      ;sta    HW_WRMAINRAM
++.endif
+       ldx     #0x00                   ; 1c3d -> 1c40 -> 1c42 r
+       ldy     *draw_y                 ; 1c40 -> 1c42 -> 1c44 r
+ 0$:   lda     video_line_table_lo - 0x20,y ; 1c42,1c65 -> 1c44 -> 1c47 r y=28..cf
+       sta     *video_line_ptr         ; 1c44 -> 1c47 -> 1c49 r
+       lda     video_line_table_hi - 0x20,y ; 1c47 -> 1c49 -> 1c4c r y=28..cf
+       sta     *video_line_ptr + 1     ; 1c49 -> 1c4c -> 1c4e r
++.if DHGR
++      sta     HW_RDCARDRAM
++      sta     HW_WRCARDRAM
++      ldy     *draw_x0
++      stx     *dimension
++90$:  .db     0xbd ; lda NNNN,x
++91$:  .dw     0
++      eor     #0xff
++      and     (*video_line_ptr),y
++      sta     (*video_line_ptr),y
++      inx
++      iny
++      cpy     *draw_x1
++      bcc     90$
++      ldx     *dimension
++      sta     HW_RDMAINRAM
++      sta     HW_WRMAINRAM
++.endif
+       ldy     *draw_x0                ; 1c4c -> 1c4e -> 1c50 r
++.if DHGR ; erase overflow pixel
++      dey
++      bmi     93$
++      .db     0xbd ; lda NNNN,x
++92$:  .dw     0
++      lsr     a
++      and     #0x40
++      eor     #0xff
++      and     (*video_line_ptr),y
++      sta     (*video_line_ptr),y
++93$:  iny
++.endif
+ 1$:   .db     0xbd                    ; 1c4e,1c5d -> 1c50 -> 1c53 r "lda 0x6f93,x" x=00..39
+ 2$:   .dw     0x6f93                  ; 1c51 rw
+       eor     #0xff                   ; 1c50 -> 1c53 -> 1c55 r
+@@ -2929,16 +3186,51 @@
+       ldx     *x_save                 ; 1c65 -> 1c67 -> 1c69 r
+       rts                             ; 1c67 -> 1c69 -> 1076,16a8 r s=f4..fa,02
+ 3$:   lda     object1080_onscreen_shape_ptr_lo - 0x10,x ; 1c32 -> 1c6a -> 1c6d r x=14..77
++.if DHGR
++      sta     94$
++.endif
+       sta     6$                      ; 1c6a -> 1c6d -> 1c70 r
++.if DHGR
++      tay
++.endif
+       lda     object1080_onscreen_shape_ptr_hi - 0x10,x ; 1c6d -> 1c70 -> 1c73 r x=14..77
++.if DHGR
++      sta     94$ + 1
++.endif
+       sta     6$ + 1                  ; 1c70 -> 1c73 -> 1c76 r
++.if DHGR
++      sta     HW_WRCARDRAM
++      sty     96$
++      sta     96$ + 1
++      sta     HW_WRMAINRAM
++.endif
+       ldx     #0x00                   ; 1c73 -> 1c76 -> 1c78 r
+       ldy     *draw_y                 ; 1c76 -> 1c78 -> 1c7a r
+-4$:   lda     x_table_times2_mod7_minus_03 + 0xe0,y ; 1c78,1cad -> 1c7a -> 1c7d r y=00..fc
++4$:   lda     video_line_table_lo - 0x20,y ;x_table_times2_mod7_minus_03 + 0xe0,y ; 1c78,1cad -> 1c7a -> 1c7d r y=11..d8
+       sta     *video_line_ptr         ; 1c7a -> 1c7d -> 1c7f r
+-      lda     video_line_table_lo + 0xa0,y ; 1c7d -> 1c7f -> 1c82 r y=00..fc
++      lda     video_line_table_hi - 0x20,y ;video_line_table_lo + 0xa0,y ; 1c7d -> 1c7f -> 1c82 r y=11..d8
+       sta     *video_line_ptr + 1     ; 1c7f -> 1c82 -> 1c84 r
+       ldy     *draw_x0                ; 1c82 -> 1c84 -> 1c86 r
++.if DHGR ; erase overflow pixel
++      lda     *draw_y
++      cmp     *clip_y0
++      bcc     7$
++      cmp     *clip_y1
++      bcs     7$
++      dey
++      cpy     *clip_x0
++      bcc     95$
++      cpy     *clip_x1
++      bcs     95$
++      .db     0xbd ; lda NNNN,x
++94$:  .dw     0
++      lsr     a
++      and     #0x40
++      eor     #0xff
++      and     (*video_line_ptr),y
++      sta     (*video_line_ptr),y
++95$:  iny
++.endif
+ 5$:   lda     *draw_y                 ; 1c84,1ca5 -> 1c86 -> 1c88 r
+       cmp     *clip_y0                ; 1c86 -> 1c88 -> 1c8a r a=00..fc
+       bcc     7$                      ; 1c88 -> 1c8a -> 1c8c,1ca1 r c=0..1
+@@ -2948,6 +3240,17 @@
+       bcc     7$                      ; 1c90 -> 1c92 -> 1c94,1ca1 r c=0..1
+       cpy     *clip_x1                ; 1c92 -> 1c94 -> 1c96 r y=6c..a4
+       bcs     7$                      ; 1c94 -> 1c96 -> 1c98,1ca1 r c=0..1
++.if DHGR
++      sta     HW_RDCARDRAM
++      sta     HW_WRCARDRAM
++      .db     0xbd ; lda NNNN,x
++96$:  .dw     0
++      eor     #0xff
++      and     (*video_line_ptr),y
++      sta     (*video_line_ptr),y
++      sta     HW_RDMAINRAM
++      sta     HW_WRMAINRAM
++.endif
+       .db     0xbd                    ; 1c96 -> 1c98 -> 1c9b r "lda 0x6fab,x" x=00..39
+ 6$:   .dw     0x6fab                  ; 1c99 rw
+       eor     #0xff                   ; 1c98 -> 1c9b -> 1c9d r
+@@ -2967,9 +3270,24 @@
+       stx     *x_save                 ; 1db0 -> 1cb2 -> 1cb4 r
+       tay                             ; 1cb2 -> 1cb4 -> 1cb5 r
+       lda     shape_data_ptr_lo,y     ; 1cb4 -> 1cb5 -> 1cb8 r y=1c..ff
++.if DHGR
++      sta     93$
++.endif
+       sta     3$                      ; 1cb5 -> 1cb8 -> 1cbb r
++.if DHGR
++      tax
++.endif
+       lda     shape_data_ptr_hi,y     ; 1cb8 -> 1cbb -> 1cbe r y=1c..ff
++.if DHGR
++      sta     93$ + 1
++.endif
+       sta     3$ + 1                  ; 1cbb -> 1cbe -> 1cc1 r
++.if DHGR
++      sta     HW_WRCARDRAM
++      stx     91$
++      sta     91$ + 1
++      sta     HW_WRMAINRAM
++.endif
+       lda     shape_width_bytes,y     ; 1cbe -> 1cc1 -> 1cc4 r y=1c..ff
+       clc                             ; 1cc1 -> 1cc4 -> 1cc5 r
+       adc     *draw_x0                ; 1cc4 -> 1cc5 -> 1cc7 r c=0 d=0
+@@ -2977,6 +3295,11 @@
+       lda     *draw_x0                ; 1cc7 -> 1cc9 -> 1ccb r
+       lsr     a                       ; 1cc9 -> 1ccb -> 1ccc r
+       bcc     0$                      ; 1ccb -> 1ccc -> 1cce,1cd4 r c=0..1
++.if DHGR
++      lda     *draw_misc_aux_mask
++      eor     *draw_misc_aux_mask_xor
++      sta     *draw_misc_aux_mask
++.endif
+       lda     *draw_misc_mask         ; 1ccc -> 1cce -> 1cd0 r
+       eor     *draw_misc_mask_xor     ; 1cce -> 1cd0 -> 1cd2 r
+       sta     *draw_misc_mask         ; 1cd0 -> 1cd2 -> 1cd4 r
+@@ -2992,9 +3315,56 @@
+       lda     video_line_table_hi,y   ; 1ce5 -> 1ce7 -> 1cea r y=00..bc
+       adc     #0x00                   ; 1ce7 -> 1cea -> 1cec r c=0..1 d=0
+       sta     *video_line_ptr + 1     ; 1cea -> 1cec -> 1cee r
++.if DHGR
++      sta     HW_RDCARDRAM
++      sta     HW_WRCARDRAM
++      lda     *draw_misc_aux_mask
++      sta     *draw_misc_mask_temp
++      ldy     *draw_x0
++      stx     *dimension
++90$:  lda     *draw_y
++      cmp     #0xc0
++      bcs     92$
++      cpy     #0x28
++      bcs     92$
++      .db     0xbd ; lda NNNN,x
++91$:  .dw     0
++      and     *draw_misc_mask_temp
++      sta     (*video_line_ptr),y
++92$:  lda     *draw_misc_mask_temp
++      eor     *draw_misc_aux_mask_xor
++      sta     *draw_misc_mask_temp
++      inx
++      iny
++      cpy     *draw_x1
++      bcc     90$
++      ldx     *dimension
++      sta     HW_RDMAINRAM
++      sta     HW_WRMAINRAM
++.endif
+       lda     *draw_misc_mask         ; 1cec -> 1cee -> 1cf0 r
+       sta     *draw_misc_mask_temp    ; 1cee -> 1cf0 -> 1cf2 r
+       ldy     *draw_x0                ; 1cf0 -> 1cf2 -> 1cf4 r
++.if DHGR ; draw overflow pixel
++      lda     *draw_y
++      cmp     #0xc0
++      bcs     95$
++      dey
++      cpy     #0x28
++      bcs     94$
++      .db     0xbd ; lda NNNN,x
++93$:  .dw     0
++      lsr     a
++      and     *draw_misc_mask_temp
++      eor     (*video_line_ptr),y
++      and     #0x40
++      eor     (*video_line_ptr),y
++      sta     (*video_line_ptr),y
++94$:  iny
++95$:  lda     *draw_misc_mask_temp
++      eor     *draw_misc_mask_xor
++      sta     *draw_misc_mask_temp
++.endif
+ 2$:   lda     *draw_y                 ; 1cf2,1d0f -> 1cf4 -> 1cf6 r
+       cmp     #0xc0                   ; 1cf4 -> 1cf6 -> 1cf8 r a=00..bc
+       bcs     4$                      ; 1cf6 -> 1cf8 -> 1cfa r c=0
+@@ -3014,7 +3384,12 @@
+       inc     *draw_y                 ; 1d0f -> 1d11 -> 1d13 r
+       ldy     *draw_y                 ; 1d11 -> 1d13 -> 1d15 r
+       cpy     *draw_y1                ; 1d13 -> 1d15 -> 1d17 r y=01..bd
++.if DHGR
++      bcs     . + 5
++      jmp     1$
++.else
+       bcc     1$                      ; 1d15 -> 1d17 -> 1ce0,1d19 r c=0..1
++.endif
+       ldx     *x_save                 ; 1d17 -> 1d19 -> 1d1b r
+       rts                             ; 1d19 -> 1d1b -> 1db3 r s=ed..f6
+ draw_misc_from_table:
+@@ -3027,7 +3402,7 @@
+       asl     a                       ; 1d23 -> 1d24 -> 1d25 r
+       sta     *draw_misc_ptr          ; 1d24 -> 1d25 -> 1d27 r
+       lda     #0x00                   ; 1d25 -> 1d27 -> 1d29 r
+-      adc     #0x46                   ; 1d27 -> 1d29 -> 1d2b r c=0..1 d=0
++      adc     #>draw_misc_table       ; 1d27 -> 1d29 -> 1d2b r c=0..1 d=0
+       sta     *draw_misc_ptr + 1      ; 1d29 -> 1d2b -> 1d2d r
+       lda     *half_dimension         ; 1d2b -> 1d2d -> 1d2f r
+       lsr     a                       ; 1d2d -> 1d2f -> 1d30 r
+@@ -3036,10 +3411,20 @@
+       lsr     a                       ; 1d31 -> 1d32 -> 1d33 r
+       lsr     a                       ; 1d32 -> 1d33 -> 1d34 r
+       tay                             ; 1d33 -> 1d34 -> 1d35 r
++.if DHGR
++      lda     draw_misc_aux_mask_table,y
++      sta     *draw_misc_aux_mask
++      lda     draw_misc_aux_mask_xor_table,y
++      sta     *draw_misc_aux_mask_xor
++.endif
+       lda     draw_misc_mask_table,y  ; 1d34 -> 1d35 -> 1d38 r y=00..06
+       sta     *draw_misc_mask         ; 1d35 -> 1d38 -> 1d3a r
+       lda     draw_misc_mask_xor_table,y ; 1d38 -> 1d3a -> 1d3d r y=00..06
+       sta     *draw_misc_mask_xor     ; 1d3a -> 1d3d -> 1d3f r
++.if DHGR
++      lda     draw_misc_shape_xor_table,y
++      sta     *draw_misc_shape_xor
++.endif
+       lda     *half_dimension         ; 1d3d -> 1d3f -> 1d41 r
+       and     #0x1f                   ; 1d3f -> 1d41 -> 1d43 r
+       cmp     #0x08                   ; 1d41 -> 1d43 -> 1d45 r a=00..1f
+@@ -3057,6 +3442,14 @@
+       iny                             ; 1d57 -> 1d59 -> 1d5a r
+ 1$:   lda     (*draw_misc_ptr),y      ; 1d59,1d69 -> 1d5a -> 1d5c r y=03..0c
+       beq     2$                      ; 1d5a -> 1d5c -> 1d5e r z=0
++.if DHGR
++      cmp     #0xd0 ; sky
++      bcc     90$
++      cmp     #0xd2 ; blazer + 1
++      bcs     90$
++      eor     *draw_misc_shape_xor
++90$:
++.endif
+       jsr     do_draw_misc            ; 1d5c -> 1d5e -> 1da6 r s=f4..fa,02
+ 2$:   iny                             ; 1db5 -> 1d61 -> 1d62 r
+       cpy     #0x10                   ; 1d61 -> 1d62 -> 1d64 r y=04..0d
+@@ -3112,6 +3505,84 @@
+       ldy     *draw_misc_y_save       ; 1d1b -> 1db3 -> 1db5 r
+ rts_1db5:
+       rts                             ; 1da1,1db3 -> 1db5 -> 1076,1d61,1d7d,1d82,1d87 r s=ef..f8
++.if DHGR
++; bit 0     6 0     6 0     6 0     6  hex
++;     1111111 1111111 1111111 1111111  7f 7f 7f 7f
++;     0000000 0000000 0000000 0000000  00 00 00 00
++;     0110011 0011001 1001100 1100110  66 4c 19 33
++;     1001100 1100110 0110011 0011001  19 33 66 4c
++;     1111111 1111111 1111111 1111111  7f 7f 7f 7f
++;     0011001 1001100 1100110 0110011  4c 19 33 66
++;     1100110 0110011 0011001 1001100  33 66 4c 19
++;     1111111 1111111 1111111 1111111  7f 7f 7f 7f
++draw_misc_aux_mask_table:
++      .db     0x7f
++      .db     0x00
++      .db     0x66
++      .db     0x19
++      .db     0x7f
++      .db     0x4c
++      .db     0x33
++      .db     0x7f
++draw_misc_mask_table:
++.if 1 ; swapped for overflow pixel
++      .db     0x7f
++      .db     0x00
++      .db     0x33
++      .db     0x4c
++      .db     0x7f
++      .db     0x66
++      .db     0x19
++      .db     0x7f
++.else
++      .db     0x7f
++      .db     0x00
++      .db     0x4c
++      .db     0x33
++      .db     0x7f
++      .db     0x19
++      .db     0x66
++      .db     0x7f
++.endif
++draw_misc_aux_mask_xor_table:
++      .db     0x7f ^ 0x7f
++      .db     0x00 ^ 0x00
++      .db     0x19 ^ 0x66
++      .db     0x66 ^ 0x19
++      .db     0x7f ^ 0x7f
++      .db     0x33 ^ 0x4c
++      .db     0x4c ^ 0x33
++      .db     0x7f ^ 0x7f
++draw_misc_mask_xor_table:
++      .db     0x7f ^ 0x7f
++      .db     0x00 ^ 0x00
++      .db     0x33 ^ 0x4c
++      .db     0x4c ^ 0x33
++      .db     0x7f ^ 0x7f
++      .db     0x66 ^ 0x19
++      .db     0x19 ^ 0x66
++      .db     0x7f ^ 0x7f
++; emulate the shifting of the star blazer text with hibit clear
++; done by XORing the value below onto the shape index (d0 or d1)
++draw_misc_shape_xor_table:
++      .db     0
++      .db     0xc8 ^ 0xd0
++      .db     0xc8 ^ 0xd0
++      .db     0xc8 ^ 0xd0
++      .db     0xc8 ^ 0xd0
++      .db     0
++      .db     0
++      .db     0
++.else
++; bit 0     6 0     6  7  hex
++;     1111111 1111111  1  ff ff
++;     0000000 0000000  0  00 00
++;     0101010 1010101  0  2a 55
++;     1010101 0101010  0  55 2a
++;     1111111 1111111  0  7f 7f
++;     0101010 1010101  1  aa d5
++;     1010101 0101010  1  d5 aa
++;     1111111 1111111  1  ff ff
+ draw_misc_mask_table:
+       .db     0xff                    ; 1db6 r
+       .db     0x00                    ; 1db7 r
+@@ -3122,15 +3593,17 @@
+       .db     0xd5                    ; 1dbc r
+       .db     0xff                    ; 1dbd r
+ draw_misc_mask_xor_table:
+-      .db     0x00                    ; 1dbe r
+-      .db     0x00                    ; 1dbf r
+-      .db     0x7f                    ; 1dc0 r
+-      .db     0x7f                    ; 1dc1 r
+-      .db     0x00                    ; 1dc2 r
+-      .db     0x7f                    ; 1dc3 r
+-      .db     0x7f                    ; 1dc4 r
+-      .db     0x00                    ; 1dc5 r
++      .db     0xff ^ 0xff ;0x00                       ; 1dbe r
++      .db     0x00 ^ 0x00 ;0x00                       ; 1dbf r
++      .db     0x55 ^ 0x2a ;0x7f                       ; 1dc0 r
++      .db     0x2a ^ 0x55 ;0x7f                       ; 1dc1 r
++      .db     0x7f ^ 0x7f ;0x00                       ; 1dc2 r
++      .db     0xd5 ^ 0xaa ;0x7f                       ; 1dc3 r
++      .db     0xaa ^ 0xd5 ;0x7f                       ; 1dc4 r
++      .db     0xff ^ 0xff ;0x00                       ; 1dc5 r
++.endif
++; for DHGR the following code will be moved to the end to make room
+       .area   text2
+ do_player_input:
+@@ -3442,6 +3915,15 @@
+       .area   data2
++.if DHGR
++.include "../shape/dhgr_pixel_shape_index.inc"
++.else
++.if PIXEL_SHAPE
++.include "shape_index_pixel.inc"
++.else
++.if SHAPE
++.include "shape_index.inc"
++.else
+ shape_data_ptr_lo:
+       .db     <bvar_5d01              ; 4000 r
+       .db     <bvar_5d01              ; 4001 r
+@@ -4984,6 +5466,12 @@
+       .db     0x01                    ; 45fd r
+       .db     0x01                    ; 45fe r
+       .db     0x04                    ; 45ff r
++.endif
++.endif
++.endif
++.if DRAW_MISC
++.include "draw_misc_table.inc"
++.else
+ ; 0x20 entries of 0x10 bytes
+ draw_misc_table:
+       .db     0x01                    ; 4600 r
+@@ -5498,7 +5986,174 @@
+       .db     0x00                    ; 47fd r
+       .db     0x00                    ; 47fe r
+       .db     0x00                    ; 47ff r
++.endif
++
++.if OBJECT
++; move these to here where they'll overlay data3 and fill in gaps
++; initial fuel (hi 2 digits)
++initial_decimal_plus_9:
++      .db     0x03                    ; 4800 r
++mission_table_clip_x0:
++      .db     0x6c                    ; 4801 r
++      .db     0x6c                    ; 4802 r
++      .db     0x6c                    ; 4803 r
++      .db     0x6c                    ; 4804 r
++      .db     0x6c                    ; 4805 r
++      .db     0x6c                    ; 4806 r
++      .db     0x6c                    ; 4807 r
++      .db     0x6c                    ; 4808 r
++      .db     0x6c                    ; 4809 r
++      .db     0x6c                    ; 480a r
++      .db     0x6c                    ; 480b r
++      .db     0x6c                    ; 480c r
++      .db     0x6c                    ; 480d r
++      .db     0x6c                    ; 480e r
++      .db     0x6c                    ; 480f r
++      .ds     0x70
++; initial fuel (lo 2 digits)
++initial_decimal_plus_8:
++      .db     0x00                    ; 4880 r
++mission_table_clip_x1:
++      .db     0x94                    ; 4881 r
++      .db     0x94                    ; 4882 r
++      .db     0x94                    ; 4883 r
++      .db     0x94                    ; 4884 r
++      .db     0x94                    ; 4885 r
++      .db     0x94                    ; 4886 r
++      .db     0x94                    ; 4887 r
++      .db     0x94                    ; 4888 r
++      .db     0x94                    ; 4889 r
++      .db     0x94                    ; 488a r
++      .db     0x94                    ; 488b r
++      .db     0x94                    ; 488c r
++      .db     0x94                    ; 488d r
++      .db     0x94                    ; 488e r
++      .db     0x94                    ; 488f r
++      .ds     0x70
++; initial bomb (hi 2 digits)
++initial_decimal_plus_0xb:
++      .db     0x00                    ; 4900 r
++mission_table_clip_y0:
++      .db     0x28                    ; 4901 r
++      .db     0x28                    ; 4902 r
++      .db     0x28                    ; 4903 r
++      .db     0x28                    ; 4904 r
++      .db     0x28                    ; 4905 r
++      .db     0x28                    ; 4906 r
++      .db     0x28                    ; 4907 r
++      .db     0x28                    ; 4908 r
++      .db     0x28                    ; 4909 r
++      .db     0x28                    ; 490a r
++      .db     0x28                    ; 490b r
++      .db     0x28                    ; 490c r
++      .db     0x28                    ; 490d r
++      .db     0x28                    ; 490e r
++      .db     0x28                    ; 490f r
++      .ds     0x70
++; initial bomb (lo 2 digits)
++initial_decimal_plus_0xa:
++      .db     0x30                    ; 4980 r
++mission_table_clip_y1:
++      .db     0xd0                    ; 4981 r
++      .db     0xd0                    ; 4982 r
++      .db     0xd0                    ; 4983 r
++      .db     0xd0                    ; 4984 r
++      .db     0xd0                    ; 4985 r
++      .db     0xd0                    ; 4986 r
++      .db     0xd0                    ; 4987 r
++      .db     0xd0                    ; 4988 r
++      .db     0xd0                    ; 4989 r
++      .db     0xd0                    ; 498a r
++      .db     0xd0                    ; 498b r
++      .db     0xd0                    ; 498c r
++      .db     0xd0                    ; 498d r
++      .db     0xd0                    ; 498e r
++      .db     0xd0                    ; 498f r
++      .ds     0x70
++; initial ship left (hi 2 digits)
++initial_decimal_plus_0xd:
++      .db     0x00                    ; 4a00 r
++mission_table_update_object_count:
++      .db     0x20                    ; 4a01 r
++      .db     0x20                    ; 4a02 r
++      .db     0x20                    ; 4a03 r
++      .db     0x20                    ; 4a04 r
++      .db     0x20                    ; 4a05 r
++      .db     0x20                    ; 4a06 r
++      .db     0x20                    ; 4a07 r
++      .db     0x20                    ; 4a08 r
++      .db     0x20                    ; 4a09 r
++      .db     0x20                    ; 4a0a r
++      .db     0x20                    ; 4a0b r
++      .db     0x20                    ; 4a0c r
++      .db     0x20                    ; 4a0d r
++      .db     0x20                    ; 4a0e r
++      .db     0x20                    ; 4a0f r
++      .ds     0x70
++; initial ship left (lo 2 digits)
++initial_decimal_plus_0xc:
++      .db     0x04                    ; 4a80 r
++mission_table_update_sound_count:
++      .db     0x0f                    ; 4a81 r
++      .db     0x0f                    ; 4a82 r
++      .db     0x0f                    ; 4a83 r
++      .db     0x0f                    ; 4a84 r
++      .db     0x0f                    ; 4a85 r
++      .db     0x0f                    ; 4a86 r
++      .db     0x0f                    ; 4a87 r
++      .db     0x0f                    ; 4a88 r
++      .db     0x0f                    ; 4a89 r
++      .db     0x0f                    ; 4a8a r
++      .db     0x0f                    ; 4a8b r
++      .db     0x0f                    ; 4a8c r
++      .db     0x0f                    ; 4a8d r
++      .db     0x0f                    ; 4a8e r
++      .db     0x0f                    ; 4a8f r
++      .ds     0x70
++; initial bonus/1000 (hi 2 digits)
++initial_decimal_plus_0xf:
++      .db     0x00                    ; 4b00 r
++mission_table_decimal_plus_5:
++      .db     0x99                    ; 4b01 r
++      .db     0x99                    ; 4b02 r
++      .db     0x99                    ; 4b03 r
++      .db     0x99                    ; 4b04 r
++      .db     0x99                    ; 4b05 r
++      .db     0x99                    ; 4b06 r
++      .db     0x99                    ; 4b07 r
++      .db     0x99                    ; 4b08 r
++      .db     0x99                    ; 4b09 r
++      .db     0x99                    ; 4b0a r
++      .db     0x99                    ; 4b0b r
++      .db     0x99                    ; 4b0c r
++      .db     0x99                    ; 4b0d r
++      .db     0x99                    ; 4b0e r
++      .db     0x99                    ; 4b0f r
++      .ds     0x70
++; initial bonus/1000 (lo 2 digits)
++initial_decimal_plus_0xe:
++      .db     0x62                    ; 4b80 r
++mission_table_decimal_plus_4:
++      .db     0x99                    ; 4b81 r
++      .db     0x99                    ; 4b82 r
++      .db     0x99                    ; 4b83 r
++      .db     0x99                    ; 4b84 r
++      .db     0x99                    ; 4b85 r
++      .db     0x99                    ; 4b86 r
++      .db     0x99                    ; 4b87 r
++      .db     0x99                    ; 4b88 r
++      .db     0x99                    ; 4b89 r
++      .db     0x99                    ; 4b8a r
++      .db     0x99                    ; 4b8b r
++      .db     0x99                    ; 4b8c r
++      .db     0x99                    ; 4b8d r
++      .db     0x99                    ; 4b8e r
++      .db     0x99                    ; 4b8f r
++
++      .area   data3
++.include "object_index.inc"
++.else
+       .area   data3
+ ; initial fuel (hi 2 digits)
+@@ -7127,7 +7782,8 @@
+       .db     0x00                    ; 4e2d r
+       .db     0x00                    ; 4e2e r
+       .db     0x00                    ; 4e2f r
+-0$:   .db     0x00                    ; 4e30 r
++object1080_velocity_scale_for_position_lo:
++      .db     0x00                    ; 4e30 r
+       .db     0x00                    ; 4e31 r
+       .db     0x00                    ; 4e32 r
+       .db     0x00                    ; 4e33 r
+@@ -9697,9 +10353,19 @@
+       .dw     0x0000                  ; 5bba r
+       .dw     bvar_9b18               ; 5bbc r
+       .dw     0x0000                  ; 5bbe r
++.endif
+       .area   data4
++.if DHGR
++.include "../shape/dhgr_pixel_shape_data_main.inc"
++.else
++.if PIXEL_SHAPE
++.include "shape_data_pixel.inc"
++.else
++.if SHAPE
++.include "shape_data.inc"
++.else
+       .db     0x5c                    ; 5c00
+       .db     0x02                    ; 5c01
+       .db     0x00                    ; 5c02
+@@ -22114,9 +22780,15 @@
+       .db     0xb8                    ; 8bfd
+       .db     0x82                    ; 8bfe
+       .db     0x5d                    ; 8bff
++.endif
++.endif
++.endif
+       .area   data5
++.if OBJECT
++.include "object_data.inc"
++.else
+ bvar_8c00:
+       .db     0x30                    ; 8c00 r
+       .db     0x0f                    ; 8c01
+@@ -26685,6 +27357,14 @@
+       .db     0x78                    ; 9be8
+       .db     0x04                    ; 9be9
+       .db     0x00                    ; 9bea
++.endif
++
++.if DHGR
++      .bank   aux_mem (fsfx=_aux_mem)
++      .area   data6 (bank=aux_mem)
++
++.include "../shape/dhgr_pixel_shape_data_aux.inc"
++.endif
+       .area   udata1
index 50a05e8..cc4b6fc 100644 (file)
@@ -1,5 +1,5 @@
 areas
-0x0000,0x00f3,zpage,uninit
+0x0000,0x00f4,zpage,uninit
 0x0200,0x0002,data0,init
 0x0400,0x03f0,udata0,uninit
 0x0a00,0x0df9,text0,init
@@ -32,68 +32,105 @@ items
 0x008d,0x0001,draw_misc_mask,byte
 0x008e,0x0001,draw_misc_mask_temp,byte
 0x008f,0x0001,draw_misc_mask_xor,byte
-# 24-bit register, repurposed for divide routine as
-#   accumulator: divisor
-#   accumulator + 1: remainder
+; 24-bit register, repurposed for divide routine as
+;   accumulator: divisor
+;   accumulator + 1: remainder
 0x0090,0x0003,accumulator,byte
-# 24-bit register
+; 24-bit register
 0x0094,0x0003,register,byte
-# 24-bit register, repurposed for divide routine as
-#   result: quotient
-#   result + 1: loop count
+; 24-bit register, repurposed for divide routine as
+;   result: quotient
+;   result + 1: loop count
 0x0098,0x0003,result,byte
 0x009c,0x0002,random_seed,word
-0x00a0,0x0001,current_sound,byte # is it really?
+; current position 0..0xf in cyclic_update_sound scan
+0x00a0,0x0001,cyclic_sound,byte
+0x00a1,0x0001,sound_period_save,byte
 0x00a8,0x0002,draw_misc_ptr,word
 0x00aa,0x0001,draw_misc_y_save,byte
 0x00ab,0x0001,draw_misc_y0,byte
 0x00ad,0x0001,draw_misc_count,byte
-# array of 8 * 4-digit numbers in BCD
-#   decimal: score/10
-#   decimal + 2: high score/10
-#   decimal + 4: spare
-#   decimal + 6: mission
-#   decimal + 8: fuel
-#   decimal + 0xa: bomb
-#   decimal + 0xc: ship left
-#   decimal + 0xe: bonus/1000
+; array of 8 * 4-digit numbers in BCD
+;   decimal: score/10
+;   decimal + 2: high score/10
+;   decimal + 4: spare (holds value from mission_table_decimal_plus_[45])
+;   decimal + 6: mission
+;   decimal + 8: fuel
+;   decimal + 0xa: bomb
+;   decimal + 0xc: ship left
+;   decimal + 0xe: bonus/1000
 0x00b0,0x0010,decimal,byte
-# index into microcode for ucode_execute_words
-0x00c0,0x0002,ucode_ptr_c0,word
+; base of microcode for execute_ucode_words, execute_ucode_fire_in_state_fn
+0x00c0,0x0002,execute_ucode_words_ptr,word
 0x00c2,0x0001,ucode_word_object,byte
-0x00c7,0x0001,ucode_object_c7,byte
+; how many times to call cyclic_update_object per game cycle
+0x00c3,0x0001,update_object_count,byte
+0x00c4,0x0001,update_object_countdown,byte
+; how many times to call cyclic_update_sound per game cycle
+0x00c5,0x0001,update_sound_count,byte
+0x00c6,0x0001,update_sound_countdown,byte
+; current position 0x10..0x7f in cyclic_update_object scan
+0x00c7,0x0001,cyclic_object,byte
 0x00c8,0x0001,sp_save,byte
-0x00c9,0x0001,ucode_x_save_c9,byte
-0x00ca,0x0001,ucode_y_save_ca,byte
-# seems to preserve a value from one of:
-#   object6080_b500 (execute_object6080_ucode_fire_in_state_f0)
-#   object6080_b520 (execute_object6080_ucode_fire_in_state_f1)
-#   object6080_b540 (execute_object6080_ucode_fire_in_state_f2)
-#   object6080_b560 (execute_object6080_ucode_fire_in_state_f3)
-# and also used as an index into ucode in ucode_execute_fire_in_state_fn
-0x00cb,0x0001,ucode_state_save,byte
-# seems to contain value from object1080_state
-# and also used as a counter in ucode_execute_fire_in_state_fn
-0x00cc,0x0001,ucode_object_state,byte
+0x00c9,0x0001,ucode_x_save,byte
+0x00ca,0x0001,ucode_y_save,byte
+; for execute_ucode_fire_in_state_fn: offset from execute_ucode_words_ptr,
+; incremented in cyclic fashion, so when a byte of 0 is read it resets to 0
+0x00cb,0x0001,ucode_fire_in_state_fn_index,byte
+; for execute_ucode_fire_in_state_fn: countdown of instructions to execute
+; for execute_ucode_words: keeps the value of object1080_state for current
+; object, to speed up repeated comparisons finding a state-specific section
+0x00cc,0x0001,ucode_fire_in_state_fn_count,byte
 0x00cd,0x0001,ucode_sp,byte
-# index into microcode for ucode_ucode_set_object_shape
-0x00d0,0x0002,ucode_ptr_d0,word # or shape_ptr?
+; base of microcode for ucode_set_object_shape
+0x00d0,0x0002,ucode_set_object_shape_ptr,word
+; used for 24-bit calculations as temp:a including accelerate-by-velocity
+; also used as abs_velocity_x_hi by calculate_direction_nibble
+; and used as counter 0..4 for direction
 0x00d2,0x0002,temp,word
 0x00d4,0x0001,y_save,byte
-0x00e2,0x0001,ucode_x_save_e2,byte
-0x00e3,0x0001,ucode_y_save_e3,byte
-0x00e4,0x0002,homing_ptr,word # is it really?
-# index into microcode for ucode_collision_test, ucode_test_fire_in_state_fn
-0x00e6,0x0002,ucode_ptr_e6,word
-0x00f0,0x0001,demo_mode,byte # 0xff = demo mode, 0x00 = play mode
-# 0xc0 = ctrl-c state (forces joystick control)
-# 0x80 = button pressed
-# 0x40 = ctrl-s state (unknown what this does)
-# 0x20 = pause / single step
-# 0x02 = fire by keyboard
-0x00f1,0x0001,button_state,byte
-# >= 0x80 = key waiting (uses lsr to clear it)
+; used by calculate_direction_nibble
+0x00d5,0x0001,abs_velocity_x_lo,word
+0x00d6,0x0002,abs_velocity_x_mul0pt1875,word
+0x00d8,0x0002,abs_velocity_x_mul0pt6875,word
+0x00da,0x0002,abs_velocity_x_mul1pt5,word
+0x00dc,0x0002,abs_velocity_x_mul5,word
+; temporary save location for index into ucode_homing table
+0x00e1,0x0001,homing_offset_save,byte
+; saves the object number being tested against
+0x00e2,0x0001,ucode_collision_or_fire_x_save,byte
+; saves the index into the microcode table in ucode_collision_or_fire_ptr
+0x00e3,0x0001,ucode_collision_or_fire_y_save,byte
+; used by execute_ucode_homing to store base of ucode_homing table
+0x00e4,0x0002,ucode_homing_ptr,word
+; base of microcode for ucode_collision_test, ucode_test_fire_in_state_fn
+0x00e6,0x0002,ucode_collision_or_fire_ptr,word
+; following 3 variables are used by test_object_collision
+; saves object1080_state value for object, controls which 0xfN section to do,
+; the value is copied to this variable to speed up the repeated comparisons
+0x00e8,0x0001,collision_object_state,byte
+; hi bit saves the cf value that will be returned from test_object_collision,
+; needed because after processing each collision, we continue to test for more
+0x00e9,0x0001,collision_result,byte
+; hi bit says whether we are in the state-specific section, if set it means
+; a new 0xfN section header is end of the state-specific section and we finish
+0x00ea,0x0001,collision_specific,byte
+; 0xff = demo mode, 0x00 = play mode
+0x00f0,0x0001,demo_mode,byte
+; bit 7: enable joystick
+; bit 6: disable sound (never set in sky blazer, uses hw_spkr_ptr instead)
+; bit 5: pause/single-step
+; bit 1: spacebar firing (when set, requests a simulated button press)
+; bit 0: which joystick channel to read (0=x, 1=y, toggles each time)
+0x00f1,0x0001,control_state,byte
+; >= 0x80 = key waiting (uses lsr to clear it)
 0x00f2,0x0001,key_state,byte
+; added in sky blazer
+; bit 7 = 1 on startup, changes to 0 if we ever see button PB0 not pressed,
+; so that the button presses can be disregarded if the button is stuck down
+; (a stuck button would have bypassed the joystick test in star blazer and
+; allowed to use the joystick even if the axes were returning insane values)
+0x00f3,0x0001,stuck_joystick,byte
 0x0200,0x0002,vec_restart,word
 0x0400,0x0070,object1080_onscreen,byte
 0x0480,0x0070,object1080_onscreen_clipped,byte
@@ -109,7 +146,12 @@ items
 0x0a12,0x0001,neg_ya,code
 0x0a21,0x0001,lsr_24bit_by_4,code
 0x0a2b,0x0001,lsr_24bit_by_2,code
-0x0a38,0x0001,get_scaled_accumulator_to_ya,code
+; called with ya = a number from one of these tables:
+;   object1080_velocity_scale_for_position_(hi|lo)
+;   object1080_velocity_scale_(hi|lo)
+; essentially does multiply_ya_by_accumulator, but checks for ya in
+; {0, 0x80, 0x100, 0x200} first in order to do a faster computation
+0x0a38,0x0001,multiply_ya_by_accumulator_optimized,code
 0x0a6a,0x0001,add_ya_to_object_velocity_x,code
 0x0a79,0x0001,add_ya_to_object_velocity_y,code
 0x0a88,0x0001,randomize_object_position,code
@@ -118,74 +160,129 @@ items
 0x0aff,0x0001,copy_object_velocity,code
 0x0b18,0x0001,randomize_object_position_relative,code
 0x0b30,0x0001,randomize_object_velocity_relative,code
-0x0b5a,0x0001,get_object_velocity_x_and_calculate_a,code
-0x0b65,0x0001,get_object_velocity_y_and_calculate_a,code
-0x0b82,0x0001,move_object_pos_pos,code
-0x0b97,0x0001,move_object_neg_pos,code
-0x0baf,0x0001,move_object_neg_neg,code
-0x0bca,0x0001,move_object_pos_neg,code
-0x0be2,0x0001,get_object_velocity_x_and_calculate_ya,code
-0x0bed,0x0001,get_object_velocity_y_and_calculate_ya,code
-0x0c06,0x0001,update_object_velocity,code
-0x0c1f,0x0001,update_object_velocity_rotate_90,code
-0x0c3b,0x0001,update_object_velocity_rotate_180,code
-0x0c5a,0x0001,update_object_velocity_rotate_270,code
+; call with y = object to calculate for
+; uses coefficient from the following table:
+;   object1080_velocity_scale_for_position_(hi|lo)
+; returns a = high byte of scaled value
+0x0b5a,0x0001,get_scaled_object_velocity_x_to_a,code
+0x0b65,0x0001,get_scaled_object_velocity_y_to_a,code
+; call with source object in y, destination object in x
+; uses coefficient from the following table, indexed by y:
+;   object1080_velocity_scale_for_position_(hi|lo)
+; velocity can be rotated through 0, 90, 180, 270 degrees
+; could be used for flinging the explosion debris outwards,
+; but not executed in my trace, so may be an unused feature
+0x0b82,0x0001,copy_object_position_plus_scaled_velocity,code
+0x0b97,0x0001,copy_object_position_plus_scaled_velocity_rotate_90,code
+0x0baf,0x0001,copy_object_position_plus_scaled_velocity_rotate_180,code
+0x0bca,0x0001,copy_object_position_plus_scaled_velocity_rotate_270,code
+; call with y = object to calculate for
+; uses coefficient from the following table:
+;   object1080_velocity_scale_(hi|lo)
+; returns ya = scaled value, y_save = original y value
+0x0be2,0x0001,get_scaled_object_velocity_x_to_ya,code
+0x0bed,0x0001,get_scaled_object_velocity_y_to_ya,code
+; call with source object in y, destination object in x
+; uses coefficient from the following table, indexed by y:
+;   object1080_velocity_scale_(hi|lo)
+; velocity can be rotated through 0, 90, 180, 270 degrees
+; only the 0 and 180 degrees rotation occurred in the trace
+0x0c06,0x0001,copy_scaled_object_velocity,code
+0x0c1f,0x0001,copy_scaled_object_velocity_rotate_90,code
+0x0c3b,0x0001,copy_scaled_object_velocity_rotate_180,code
+0x0c5a,0x0001,copy_scaled_object_velocity_rotate_270,code
 0x0c76,0x0001,horizontal_collision,code
 0x0c9d,0x0001,vertical_collision,code
 0x0cc4,0x0001,horizontal_collision_and_zero,code
 0x0cd0,0x0001,vertical_collision_and_zero,code
 0x0cdc,0x0001,horizontal_collision_and_copy,code
 0x0cec,0x0001,vertical_collision_and_copy,code
-0x0cfc,0x0001,calculate_object_abs_difference0,code
-0x0d06,0x0001,calculate_object_abs_difference2,code
-0x0d10,0x0001,calculate_object_abs_difference1,code
-0x0d1a,0x0001,calculate_object_abs_difference3,code
-0x0d24,0x0001,calculate_object_abs_x_difference,code
-0x0d2e,0x0001,calculate_object_abs_y_difference,code
-0x0d38,0x0001,maybe_copy_one_of_arr_52a0_52e0_5320_5360_to_arr_b480,code
+0x0cfc,0x0001,calculate_object_x_quadratic_countdown,code
+0x0d06,0x0001,calculate_object_y_quadratic_countdown,code
+0x0d10,0x0001,calculate_object_x_cubic_countdown,code
+0x0d1a,0x0001,calculate_object_y_cubic_countdown,code
+0x0d24,0x0001,calculate_object_x_homing_countdown,code
+0x0d2e,0x0001,calculate_object_y_homing_countdown,code
+0x0d38,0x0001,copy_fire_count_init_to_fire_count,code
+; call with:
+;   x = current object
+;   a = value for object1080_animate_countdown
+;   ucode_ptr_d0 = table of shapes to index by direction nibble
+; recomputes object bounds after new shape has been determined
 0x0d5e,0x0001,calculate_object_direction,code
+; call with:
+;   x = current object
+;   a = value for object1080_state (if nonzero)
+; references ucode_animate_shape_ptr table, indexed by current object
+; if there is no table, set shape to 0 (loc_0d66)
+; if value passed in was nonzero (always), set object state first (loc_0db9)
 0x0d6c,0x0001,calculate_object_shape,code
-# example: object1080_ucode_animate_shape_4d_headquarters_radar_icbm
-#              -> implied start of section 0xf0
-#      .db     0x72 headquarters shape
-#      .db     0xf2 -> start of section 0xf2
-#      .db     0x76 icbm shape
-#      .db     0xf1 -> start of section 0xf1
-#      .db     0x73 radar0 shape
-#      .db     0x74 radar1 shape
-#      .db     0x75 radar2 shape
-#      .db     0x74 radar1 shape
-#      .db     0xf9 -> repeating, & 0xf3 for start sentinel (0xf1)
-#      .db     0x00 sentinel
-# object1080_animate_shape_index + 0x4d holds the index into above table
-# loc_0da6 does a post-increment
-# loc_0daf controls wraparound when sentinel >= 0xf0 reached
-#   loc_0dac for 0xff
-#   loc_0db9 for 0xf8..0xfe (repeating, & 0xf3 for the start sentinel)
-#     0xf0..0xf3 value is poked into object1080_state + object, and
-#     something happens when it changes, if object >= 0x60 ... then loc_0dcb
-#   loc_0dcb for 0xf0..0xf7
-#     scan the table from the beginning (except if sentinel was 0xf0)
-#       loc_0ddc when end of table is reached
-#       scan until we find the value at object1080_state + object
-#   loc_0ddc a = table index where start sentinel was found (or end sentinel)
-#     update object1080_animate_shape_index with this index (causes the
-#     wrapping to restart the animation sequence) ... resume at loc_0da6
-# note: the ucode_word routine seems implicated in launching this:
-# 0$:  ldy     object1080_state - 0x10,x
-#      bpl     2$
-#      and     #0x03
-#      ora     #0xf0
-#      jmp     [vec_calculate_object_shape]
+; called from:
+; - reset_object_state
+; - move_object_by_velocity
+; in theory can also be called by calculate_object_shape by fallthru, but this
+; does not happen in the trace, and analysis of all callsites reveals it can't
+; example: object1080_ucode_animate_shape_4d_headquarters_radar_icbm
+;              -> implied start of section 0xf0
+;      .db     0x72 headquarters shape
+;      .db     0xf2 -> start of section 0xf2
+;      .db     0x76 icbm shape
+;      .db     0xf1 -> start of section 0xf1
+;      .db     0x73 radar0 shape
+;      .db     0x74 radar1 shape
+;      .db     0x75 radar2 shape
+;      .db     0x74 radar1 shape
+;      .db     0xf9 -> set the object state to 0xf1 and then restart lookup
+;      .db     0x00 sentinel
+; object1080_animate_shape_index + 0x4d holds the index into above table
+; loc_0da6 does a post-increment
+; loc_0daf controls wraparound when sentinel >= 0xf0 reached
+;   loc_0dac for 0xff
+;     finished, return via compute_object_bounds
+;   loc_0db9 for 0xf8..0xfe
+;     (note this is also the entry point from calculate_object_shape)
+;     set object state with the value & 0xf3
+;     if new state is different than before:
+;       call copy_fire_count_init_to_fire_count (has a table for each state)
+;     then resume at loc_0dcb (scan the table from the beginning)
+;   loc_0dcb for 0xf0..0xf7
+;     scan the table from the beginning (except if sentinel was 0xf0)
+;       loc_0ddc when end of table is reached
+;       scan until we find the value at object1080_state + object
+;   loc_0ddc a = table index where start sentinel was found (or end sentinel)
+;     update object1080_animate_shape_index with this index (causes the
+;     wrapping to restart the animation sequence) ... resume at loc_0da6
+; note: the ucode_word routine seems implicated in launching this:
+; 0$:  ldy     object1080_state - 0x10,x
+;      bpl     2$
+;      and     #0x03
+;      ora     #0xf0
+;      jmp     [vec_calculate_object_shape]
 0x0d81,0x0001,ucode_set_object_shape,code
+; calculate multiples of abs(vel_x)
+; let direction = count of truth of abs(vel_y) >= each multiple
+;   if abs(vel_y) >= 5 abs(vel_x), direction = 4
+;   else if abs(vel_y) >= 1.5 abs(vel_x), direction = 3
+;   else if abs(vel_y) >= 0.6875 abs(vel_x), direction = 2
+;   else if abs(vel_y) >= 0.1875 abs(vel_x), direction = 1
+;   else direction = 0
+; if vel_y is negative, let direction = 0x10 - direction
+; if vel_x is negative, let direction = 8 - direction
+; return y = lower nibble of direction
+; analysis:
+;   0.6875 is an approximation to 1/1.5 = 0.667
+;   0.1875 is an approximation to 1/5 = 0.2
+;   angle breaks are 0, 10.6, 34.5, 56.3, 78.7, 90 deg
+;   approximation to 0, 11.25, 33.75, 56.25, 78.75, 90 deg
+;   tan(56.25) = 1.4966 ~= 1.5, tan(78.75) = 5.0273 ~= 5
 0x0de5,0x0001,calculate_direction_nibble,code
 0x0ebc,0x0001,ucode_decimal_set_0,code
-0x0ec1,0x0001,ucode_decimal_set_score_var_4b80_score_var_4b00_by_mission,code
+0x0ec1,0x0001,ucode_decimal_set_mission_specific_value,code
 0x0ece,0x0001,ucode_decimal_set_1,code
-0x0ed4,0x0001,ucode_decimal_set_score_var_4880_score_var_4800,code
-0x0edc,0x0001,ucode_decimal_set_score_var_4980_score_var_4900,code
-0x0ee4,0x0001,ucode_decimal_set_score_var_4a80_score_var_4a00,code
-0x0eec,0x0001,ucode_decimal_set_score_var_4b80_score_var_4b00,code
+0x0ed4,0x0001,ucode_decimal_set_initial_decimal_4,code
+0x0edc,0x0001,ucode_decimal_set_initial_decimal_5,code
+0x0ee4,0x0001,ucode_decimal_set_initial_decimal_6,code
+0x0eec,0x0001,ucode_decimal_set_initial_decimal_7,code
 0x0ef2,0x0001,ucode_decimal_set_save,code
 0x0ef7,0x0010,ucode_decimal_set_vectors,word,code_m1
 0x0f07,0x0010,ucode_update_bits_4_to_6_vectors,word,code_m1
@@ -200,174 +297,195 @@ items
 0x0fb1,0x0001,adjust_score_for_reset_object,code
 0x0fb9,0x0001,ucode_byte,code
 0x0fdb,0x0001,go_ucode_decimal,code
-# enter with ucode_word_object = 1st byte of ucode pair, a = 2nd byte
-# these values come from do_ucode_word (I think the only external caller)
-# does ldx *ucode_word_object first, so in below, "object" refers to this
-# 1st byte:
-#   < 0x10: go to ucode_escape
-#     if 1st byte bit 0 = 1, only do the rest if demo mode (otherwise continue)
-#     if 1st byte bit 1 = 1, only do the rest if NOT demo mode (otherwise done)
-#     < 0x04: go to 2$
-#       2nd byte:
-#         < 0x20: clear demo mode, set mission from 2nd byte bits 0..3
-#         < 0x30: set demo mode, set mission from 2nd byte bits 0..3
-#         < 0xa0: vector to start game
-#         >= 0xa0: start game demo
-#     < 0x08: go to ucode_decimal, with unusual bcc -> bcc instruction
-#       2nd byte bits 4..7
-#         == 0x30: vector to update a decimal based on 2nd byte bits 0..2
-#      .dw     set_decimal_0 - 1
-#      .dw     set_decimal_0 - 1
-#      .dw     set_decimal_score_var_4b80_score_var_4b00_by_mission - 1
-#      .dw     set_decimal_1 - 1
-#      .dw     set_decimal_score_var_4880_score_var_4800 - 1
-#      .dw     set_decimal_score_var_4980_score_var_4900 - 1
-#      .dw     set_decimal_score_var_4a80_score_var_4a00 - 1
-#      .dw     set_decimal_score_var_4b80_score_var_4b00 - 1
-#         == 0x40: decimal increment
-#           2nd byte bits 0..2 are *2 and give index into decimals array
-#         == 0x50: decimal decrement
-#           2nd byte bits 0..2 are *2 and give index into decimals array
-#         == 0x70: go to 0$
-#           2nd byte bits 0..2 are *2 and give index into decimals array
-#         == 0x20: vector to draw misc from table
-#           2nd byte bits 0..2 are +1 and sent into draw_misc_from_table
-#         otherwise ignored
-#     < 0x0c: go to 6$
-#       2nd byte:
-#         < 0xe1: vector to draw_misc_from_table (title display, etc)
-#         >= 0xe1:
-#           2nd byte bit 0 = 0: vector to restart
-#           2nd byte bit 0 = 1: video clear rectangle
-#     >= 0x0c: 2nd byte is a sound channel? 01..10
-#      store 1st byte into sound_status_ab80[2nd byte - 1]
-#   >= 0x10: 1st byte is object for opcode in 2nd byte
-# 2nd byte:
-#   < 0x08: go to 0$
-#     if object is active, change its shape using 2nd byte bits 0..1
-#   < 0x0e: go to 3$
-#     vector to ucode_08_to_0e_vectors routine based on 2nd byte bits 0..2
-#      .dw     horizontal_collision_and_zero - 1
-#      .dw     vertical_collision_and_zero - 1
-#      .dw     horizontal_collision - 1
-#      .dw     vertical_collision - 1
-#      .dw     horizontal_collision_and_copy - 1
-#      .dw     vertical_collision_and_copy - 1
-#   = 0x0e: go to 1$
-#     decrement object1080_countdown_b190, returns zf=1 terminal count?
-#   != 0x0f: go to ucode_byte
-#     if bit 7 = 0, then only do the rest if the object is inactive
-#     vector to routine based on 2nd byte bits 4..6
-#      .dw     rts_0a11 - 1
-#      .dw     randomize_object_position - 1
-#      .dw     copy_object_position - 1
-#      .dw     randomize_object_position_relative - 1
-#      .dw     move_object_pos_pos - 1
-#      .dw     move_object_neg_pos - 1
-#      .dw     move_object_neg_neg - 1
-#      .dw     move_object_pos_neg - 1
-#     vector to routine based on 2nd byte bits 0..2
-#      .dw     rts_0a11 - 1
-#      .dw     randomize_object_velocity - 1
-#      .dw     copy_object_velocity - 1
-#      .dw     randomize_object_velocity_relative - 1
-#      .dw     update_object_velocity - 1
-#      .dw     update_object_velocity_rotate_90 - 1
-#      .dw     update_object_velocity_rotate_180 - 1
-#      .dw     update_object_velocity_rotate_270 - 1
-#     if bit 3 = 1, and object1080_state[x] != 0:
-#       make object active and compute bounds
-#     else
-#       reset object state
-#   = 0x0f: if object is active, make it inactive and erase it
+; enter with ucode_word_object = 1st byte of ucode pair, a = 2nd byte
+; these values come from do_ucode_word (I think the only external caller)
+; does ldx *ucode_word_object first, so in below, "object" refers to this
+; 1st byte:
+;   < 0x10: go to ucode_escape
+;     if 1st byte bit 0 = 1, only do the rest if demo mode (otherwise continue)
+;     if 1st byte bit 1 = 1, only do the rest if NOT demo mode (otherwise done)
+;     < 0x04: go to 2$
+;       2nd byte:
+;         < 0x20: clear demo mode, set mission from 2nd byte bits 0..3
+;         < 0x30: set demo mode, set mission from 2nd byte bits 0..3
+;         < 0xa0: vector to start game
+;         >= 0xa0: start game demo
+;     < 0x08: go to ucode_decimal, with unusual bcc -> bcc instruction
+;       2nd byte bits 4..7
+;         == 0x30: vector to update a decimal based on 2nd byte bits 0..2
+;      .dw     set_decimal_0 - 1
+;      .dw     set_decimal_0 - 1
+;      .dw     set_decimal_mission_specific_value - 1
+;      .dw     set_decimal_1 - 1
+;      .dw     set_decimal_initial_decimal_4 - 1
+;      .dw     set_decimal_initial_decimal_5 - 1
+;      .dw     set_decimal_initial_decimal_6 - 1
+;      .dw     set_decimal_initial_decimal_7 - 1
+;         == 0x40: decimal increment
+;           2nd byte bits 0..2 are *2 and give index into decimals array
+;         == 0x50: decimal decrement
+;           2nd byte bits 0..2 are *2 and give index into decimals array
+;         == 0x70: go to 0$
+;           2nd byte bits 0..2 are *2 and give index into decimals array
+;         == 0x20: vector to draw misc from table
+;           2nd byte bits 0..2 are +1 and sent into draw_misc_from_table
+;         otherwise ignored
+;     < 0x0c: go to 6$
+;       2nd byte:
+;         < 0xe1: vector to draw_misc_from_table (title display, etc)
+;         >= 0xe1:
+;           2nd byte bit 0 = 0: vector to restart
+;           2nd byte bit 0 = 1: video clear rectangle
+;     >= 0x0c: 2nd byte is a sound channel? 01..10
+;      store 1st byte into sound_status_active[2nd byte - 1]
+;   >= 0x10: 1st byte is object for opcode in 2nd byte
+; 2nd byte:
+;   < 0x08: go to 0$
+;     if object is active: set its state 0xf0..0xf3 using 2nd byte bits 0..1
+;     (done by call set_object_shape which causes its shape to be recalculated)
+;   < 0x0e: go to 3$
+;     vector to ucode_08_to_0e_vectors routine based on 2nd byte bits 0..2
+;      .dw     horizontal_collision_and_zero - 1
+;      .dw     vertical_collision_and_zero - 1
+;      .dw     horizontal_collision - 1
+;      .dw     vertical_collision - 1
+;      .dw     horizontal_collision_and_copy - 1
+;      .dw     vertical_collision_and_copy - 1
+;   = 0x0e: go to 1$
+;     decrement object1080_countdown2, returns zf=1 terminal count?
+;   != 0x0f: go to ucode_byte
+;     if bit 7 = 0, then only do the rest if the object is inactive
+;     vector to routine based on 2nd byte bits 4..6
+;      .dw     rts_0a11 - 1
+;      .dw     randomize_object_position - 1
+;      .dw     copy_object_position - 1
+;      .dw     randomize_object_position_relative - 1
+;      .dw     move_object_pos_pos - 1
+;      .dw     move_object_neg_pos - 1
+;      .dw     move_object_neg_neg - 1
+;      .dw     move_object_pos_neg - 1
+;     vector to routine based on 2nd byte bits 0..2
+;      .dw     rts_0a11 - 1
+;      .dw     randomize_object_velocity - 1
+;      .dw     copy_object_velocity - 1
+;      .dw     randomize_object_velocity_relative - 1
+;      .dw     update_object_velocity - 1
+;      .dw     update_object_velocity_rotate_90 - 1
+;      .dw     update_object_velocity_rotate_180 - 1
+;      .dw     update_object_velocity_rotate_270 - 1
+;     if bit 3 = 1, and object1080_state[x] != 0:
+;       make object active and compute bounds
+;     else
+;       reset object state
+;   = 0x0f: if object is active, make it inactive and erase it
 0x0fdd,0x0001,ucode_word,code
 0x1009,0x0001,vector_to_ucode,code
 0x1016,0x0001,ucode_escape,code
-# enter with a = value for ucode_word_object, ucode_ptr_c0 setup,
-# y = index into table at ucode_ptr_c0 (it will be incremented twice)
-# routine loads first byte from the ucode table and calls ucode_word
+; enter with a = value for ucode_word_object, ucode_ptr_c0 setup,
+; y = index into table at ucode_ptr_c0 (it will be incremented twice)
+; routine loads first byte from the ucode table and calls ucode_word
 0x106a,0x0001,do_ucode_word,code
-0x107c,0x0001,decimal_zero,code
-# zf=1 -> go to loc_10cd
-# otherwise load ucode_object_state from object1080_state,
-# and enter a loop scanning ucode table at ucode_ptr_c0 from index 0,
-# when value read from ucode table is:
-#   == 0x00: go to loc_10cd
-#   >= 0xf0: see if it's the start sentinel in ucode_object_state
-#     if it's not then keep skipping 2 locations until end of table or found
-#     when found, skip 2 locations and check for more commands (0 is end of
-#     table, >= 0xf0 is a different section, otherwise execute + zf=0 repeat
-#   otherwise execute it via do_ucode_word, and check zf return because
-#   zf=1 means terminate the loop at loc_10cd otherwise keep executing loop
-# in summary there seems to be a global section at the start of the table that
-# is always executed, and a specific section to execute based on current state
-0x1093,0x0001,ucode_execute_words,code
+; called from:
+;   adjust_score: with x = 0xa when something happens to score (?)
+;   ucode_decimal_(inc|dec): with x = 8..0xf based on index in decimal[] array
+; executes ucode_mission_init_or_decimal_reached_zero microcode for object in x
+0x107c,0x0001,decimal_reached_zero,code
+; zf=1 -> go to loc_10cd
+; otherwise load ucode_fire_in_state_fn_count from object1080_state,
+; and enter a loop scanning ucode table at ucode_ptr_c0 from index 0,
+; when value read from ucode table is:
+;   == 0x00: go to loc_10cd
+;   >= 0xf0: see if it's the start sentinel in ucode_fire_in_state_fn_count
+;     if it's not then keep skipping 2 locations until end of table or found
+;     when found, skip 2 locations and check for more commands (0 is end of
+;     table, >= 0xf0 is a different section, otherwise execute + zf=0 repeat
+;   otherwise execute it via do_ucode_word, and check zf return because
+;   zf=1 means terminate the loop at loc_10cd otherwise keep executing loop
+; in summary there seems to be a global section at the start of the table that
+; is always executed, and a specific section to execute based on current state
+0x1093,0x0001,execute_ucode_words,code
 0x109c,0x0001,,code_ign # bug? spans ae80 and aef0 tables, don't merge them
-# alternative entry point for ucode_execute_words that comes from scoring?
-0x10a1,0x0001,ucode_execute_words_entry,code
-# returns the current value of object1080_state for the object in x
-# I think this might be to provide the correct flags return?
-0x10cd,0x0001,ucode_execute_words_done,code_ign # bug? spans ae80 and aef0 tables, don't merge them
-# it seems to read values from table at ucode_ptr_c0 with some complicated
-# indirection (value from table = index to use for next read from table?) and
-# it executes them by calling do_ucode_word, this may read adjacent value?
-# ucode_object_state = counter that gets decremented to 0
-# bvar_00cb = start index in table, and is advanced by the routine
-0x10d1,0x0001,ucode_execute_fire_in_state_fn,code
+; alternative entry point for execute_ucode_words that comes from scoring?
+0x10a1,0x0001,execute_ucode_words_entry,code
+; returns the current value of object1080_state for the object in x
+; this is tested by bpl to see if object went inactive, e.g. in update_object:
+;      jsr     execute_object1080_ucode_countdown
+;      bpl     rts_15d6
+0x10cd,0x0001,execute_ucode_words_done,code_ign # bug? spans ae80 and aef0 tables, don't merge them
+; call with the following set up:
+;   execute_ucode_words_ptr
+;   ucode_fire_in_state_fn_index
+;   ucode_fire_in_state_fn_count
+; executes ucode words cyclically until count exhausted
+0x10d1,0x0001,execute_ucode_fire_in_state_fn,code
 0x10ed,0x0001,adjust_score,code
 0x1153,0x0001,reset_decimals,code
 0x1160,0x0001,reset_object_state,code
 0x11a7,0x0001,make_object_active_and_compute_bounds,code
 0x11b2,0x0001,make_object_inactive_and_erase,code
-# called from update_object, when:
-#   object1080_countdown_b120 or object1080_countdown_b190 expires
+; called from update_object, when:
+;   object1080_countdown or object1080_countdown2 expires
 0x11bd,0x0001,execute_object1080_ucode_countdown,code
-# called from update_object, when:
-#   test_object_collision returns cf=1
+; called from update_object, when:
+;   test_object_collision returns cf=1
 0x11cd,0x0001,execute_object1080_ucode_collision,code
-# called from update_object for objects >= 40, when:
-#   object1080_x_hi outside [object4080_x_hi_min, object4080_x_hi_max)
+; called from update_object for objects >= 40, when:
+;   object1080_x_hi outside [object4080_x_hi_min, object4080_x_hi_max)
 0x11dd,0x0001,execute_object4080_ucode_x_outside,code
-# called from update_object for objects >= 40, when:
-#   object1080_y_hi outside [object4080_y_hi_min, object4080_y_hi_max)
+; called from update_object for objects >= 40, when:
+;   object1080_y_hi outside [object4080_y_hi_min, object4080_y_hi_max)
 0x11ed,0x0001,execute_object4080_ucode_y_outside,code
-# called from update_object for objects >= 60, when:
-#   object1080_state == 0xf0
-#   and then test_object_fire_in_state_f0 returns cf=1
-0x11fd,0x0001,execute_object6080_ucode_fire_in_state_f0,code
-# called from update_object for objects >= 60, when:
-#   object1080_state == 0xf1
-#   and then test_object_fire_in_state_f1 returns cf=1
-0x1222,0x0001,execute_object6080_ucode_fire_in_state_f1,code
-# called from update_object for objects >= 60, when:
-#   object1080_state == 0xf2
-#   and then test_object_fire_in_state_f2 returns cf=1
-0x1247,0x0001,execute_object6080_ucode_fire_in_state_f2,code
-# called from update_object for objects >= 60, when:
-#   object1080_state == 0xf3
-#   and then test_object_fire_in_state_f3 returns cf=1
-0x126c,0x0001,execute_object6080_ucode_fire_in_state_f3,code
-# called from accelerate_object_towards_another
-# seems to have a chance to intervene in the homing logic
-0x1291,0x0001,execute_object6080_ucode_homing,code
+; called from update_object for objects >= 60, when:
+;   object1080_state == 0xf0
+;   and then test_object_fire_in_state_f0 returns cf=1
+0x11fd,0x0001,execute_ucode_fire_in_state_f0,code
+; called from update_object for objects >= 60, when:
+;   object1080_state == 0xf1
+;   and then test_object_fire_in_state_f1 returns cf=1
+0x1222,0x0001,execute_ucode_fire_in_state_f1,code
+; called from update_object for objects >= 60, when:
+;   object1080_state == 0xf2
+;   and then test_object_fire_in_state_f2 returns cf=1
+0x1247,0x0001,execute_ucode_fire_in_state_f2,code
+; called from update_object for objects >= 60, when:
+;   object1080_state == 0xf3
+;   and then test_object_fire_in_state_f3 returns cf=1
+0x126c,0x0001,execute_ucode_fire_in_state_f3,code
+; called from accelerate_object_towards_another
+; call with x = current object, reads the ucode_homing table for object x
+; table contains object numbers which are tested in order for whether active
+; (i.e. bit 7 is set in the object1080_state field of the object being tested)
+; returns y = active object number, or 0 if none (and zf as appropriate)
+; the general section is tested first, followed by a state-specific section
+; e.g. object x is in state f2, it will only check the general and f2 section
+0x1291,0x0001,execute_ucode_homing,code
+; call with x = current object, performs the x and y homing countdowns
+; when x or y acceleration is to occur, does the following steps:
+; - reset the x or y coming countdown by redoing the abs computation
+; - call execute_ucode_homing to choose the object to home to
+; - if found, calculate x or y difference and adjust x or y velocity by this
+;   (sense of adjustment is controllable and presumably the scale is 1/256)
 0x12e1,0x0001,accelerate_object_towards_another,code
 0x133f,0x0001,sign_extend_a_to_ya_asl_by_4,code
-0x1350,0x0001,accelerate_object_somehow,code
+0x1350,0x0001,accelerate_object_by_constant,code
 0x1388,0x0001,move_object_by_velocity,code
+; call with x = object whose collisions are to be tested
+; looks up microcode table from object1080_ucode_collision_test_ptr
+; the table contains byte values of objects to be tested against
+; there is a general section followed by state-specific 0xfN sections
 0x13d0,0x0001,test_object_collision,code
-0x1447,0x0001,accelerate_object_anyhow,code
+0x1447,0x0001,accelerate_object_by_velocity,code
 0x149b,0x0001,ucode_test_fire_all_objects_active,code
 0x14aa,0x0001,ucode_test_fire_all_objects_inactive,code
-# opcode is followed by null-terminated list of objects to test
-# note: some of these opcodes never executed in the trace
-# references to object1080_y1 + 0x60 should be object1080_state - 0x10
-# 0x01 loc_149b test that all objects are active (object1080_state >= 0x80)
-# 0x02 loc_14aa test that all objects are inactive (object1080_state < 0x80)
-# 0x03 loc_14d0 test that any object is active (object1080_state >= 0x80)
-# 0x04 loc_14e0 test that any object is inactive (object1080_state >= 0x80)
-# otherwise fall into:
-# loc_14c9: cf=0
-# loc_14ca: return cf (cf=1 from cmp equality), a=object1080_state (for zf?)
+; opcode is followed by null-terminated list of objects to test
+; note: some of these opcodes never executed in the trace
+; 0x01 loc_149b test that all objects are active (object1080_state >= 0x80)
+; 0x02 loc_14aa test that all objects are inactive (object1080_state < 0x80)
+; 0x03 loc_14d0 test that any object is active (object1080_state >= 0x80)
+; 0x04 loc_14e0 test that any object is inactive (object1080_state >= 0x80)
+; otherwise fall into:
+; loc_14c9: cf=0
+; loc_14ca: return cf (cf=1 from cmp equality), a=object1080_state (for zf?)
 0x14b9,0x0001,ucode_test_object_fire,code
 0x14d0,0x0001,ucode_test_fire_any_object_active,code
 0x14e0,0x0001,ucode_test_fire_any_object_inactive,code
@@ -379,34 +497,78 @@ items
 0x1549,0x0001,test_object_fire_in_state_f2,code
 0x1569,0x0001,test_object_fire_in_state_f3,code
 0x1589,0x0001,objects_init,code
-0x1595,0x0001,objects_init_entry,code
+0x1595,0x0001,objects_reinit,code
+; maybe update object whose number is in cyclic_object
+; then increment cyclic_object so it cycles through 0x10..0x7f
+; cf=1 return indicates it is time to check the keyboard
+0x15b2,0x0001,cyclic_update_object,code
 0x15d7,0x0001,update_object_player,code
 0x15ee,0x0001,update_object,code
 0x15ff,0x0001,update_object_entry,code
-0x16ae,0x0001,all_init,code
-# takes mission number in x, does not set mission if x = 0
+0x16ae,0x0001,init_mission,code
+; takes mission number in x, does not set mission if x = 0
 0x16f1,0x0001,clear_demo_set_mission,code
-# takes mission number in x, does not set mission if x = 0
+; takes mission number in x, does not set mission if x = 0
 0x16f7,0x0001,set_demo_set_mission,code
 0x16fd,0x0001,inc_mission,code
 0x1708,0x0001,init_game,code,,10000 # suppress local for patch
 0x1719,0x0001,start_game_demo,code
 0x171b,0x0001,start_game,code,,10000 # suppress local for patch
-0x1750,0x0001,test_key,code
-0x1797,0x0001,read_buttons,code
+; in the below, 0$ is outer game loop, 4$ is inner game loop
+; 0$: cancel previous keyboard input
+; 1$: if new keyboard input is present:
+;   move incoming key to key_state (high bit set = key present)
+;   strobe keyboard interface to clear it
+;   check for control characters, may restart game via vec_start_game
+; 2$: if in demo mode:
+;   call test_start_game, may start game via vec_start_game
+; 3$: if in single-step mode:
+;   if no key present, return to 1$
+; 4$: if sound enabled:
+;   make "update_sound_count" repeated calls to cyclic_update_sound
+; 6$: make "update_object_count" repeated calls to cyclic_update_object
+;   (this handles all of the in-game display updating as a side effect)
+;   if any of these calls return cf=1, abort the loop and return to 0$
+;   otherwise, upon completion of the loop, return to 4$
+0x1750,0x0001,start_mission,code
+; if joystick button or spacebar is pressed, start game via vec_start_game
+; clears single-step mode and sets joystick mode according to input source
+0x1797,0x0001,test_start_game,code
 0x17b1,0x0001,not_demo_vector_to_start_game,code
+; ctrl-r (0x92): restart game via vec_start_game (clears single-step mode)
+; ctrl-c (0x83): toggle bit 7 of control_state (enable joystick)
+; ctrl-s (0x93): toggle bit 6 of control_state (disable sound)
+; esc (0x9b): toggle bit 5 of control_state (pause/single-step)
 0x17b6,0x0001,check_control_characters,code
+; the entry point to the executable
+; in star blazer it had joystick detection code, deleted in sky blazer
+; so in sky blazer it just jumps to init_game via vec_init_game
 0x17d1,0x0001,start,code
+; the next 3 routines were added in sky blazer in space freed up by
+; the deletion of the joystick detection code, it seems to have been
+; manually patched rather than reassembled as it is not tightly packed
+0x17d8,0x0001,patch_video_init,code
+0x17e0,0x0001,patch_read_pb0,code
+0x17f0,0x0001,patch_toggle_sound,code
 0x1800,0x0001,divide_a_by_y,code
 0x1829,0x0001,multiply_ya_by_accumulator,code
 0x1873,0x0001,,code # unreachable
 0x187a,0x0001,random_init,code
 0x1881,0x0001,random_byte,code
 0x18a2,0x0001,sound_init,code
-0x18b0,0x0001,next_sound,code
+0x18b0,0x0001,cyclic_update_sound,code
+0x18bf,0x0001,update_sound,code
+; toggles in sky blazer, HW_SPKR (sound on) or HW_TAPEOUT (sound off)
+; apparently this is to equalize the execution speed when sound is off
+0x18ed,0x0001,hw_spkr_ptr,word
+0x1917,0x0001,update_sound_reset,code
+; enter here when there are still more repeats of the tone to be played back
+0x1929,0x0001,update_sound_repeat,code
 0x1937,0x0001,video_init,code
 0x1999,0x0001,restart,code
 0x19b9,0x0001,video_clear_rectangle,code
+; selects 0th, 1st or 2nd third of the screen in hi-res graphics memory layout
+0x19d6,0x0003,times_40_table,byte
 0x19da,0x0001,compute_object_bounds,code
 0x1a27,0x0007,pixel_data_table_left,byte
 0x1a2e,0x0007,pixel_data_table_right,byte
@@ -438,8 +600,28 @@ items
 0x1da6,0x0001,do_draw_misc,code
 0x1db6,0x0008,draw_misc_mask_table,byte
 0x1dbe,0x0008,draw_misc_mask_xor_table,byte
-# returns cf=1 if firing (random for demo mode)
+0x1e00,0x0001,do_player_input,byte
+; returns cf=1 if firing (random for demo mode)
 0x1e03,0x0001,test_player_fire,code
+0x1e23,0x0001,spacebar_firing,code
+; if in demo mode, generates a random player input
+; otherwise tests the keyboard, joystick, joystick buttons
+0x1e2a,0x0001,player_input,byte
+0x1f80,0x0010,sound_table_repeat_countdown,byte
+; read-only lookup table for initial sound period
+0x1f90,0x0010,sound_table_period,byte
+; read-only lookup table for sound period change before each repeat
+0x1fa0,0x0010,sound_table_period_delta,byte
+; read-only lookup table for sound period that triggers reset to initial values
+0x1fb0,0x0010,sound_table_period_limit,byte
+; read-only lookup table for initial sound duration
+0x1fc0,0x0010,sound_table_duration,byte
+; read-only lookup table for sound duration change before each repeat
+0x1fd0,0x0010,sound_table_duration_delta,byte
+; read-only lookup table for initial sound delay between each repeat
+0x1fe0,0x0010,sound_table_delay,byte
+; read-only lookup table for sound delay change before each repeat
+0x1ff0,0x0010,sound_table_delay_delta,byte
 0x2000,0x2000,HIRES_SCREEN,byte
 0x4000,0x0100,shape_data_ptr_lo,byte,byte
 0x4100,0x0100,shape_data_ptr_hi,byte,byte
@@ -447,40 +629,53 @@ items
 0x4300,0x0100,shape_height,byte
 0x4400,0x0100,shape_size_bytes,byte
 0x4500,0x0100,shape_width,byte
-# 0x20 entries of 0x10 bytes
+; 0x20 entries of 0x10 bytes
 0x4600,0x0200,draw_misc_table,byte,,10000 # suppress local for patch
-0x4800,0x0001,score_var_4800,byte
-0x4801,0x000f,score_table_4801,byte
-0x4810,0x0070,object1080_countdown_b120_init,byte
-0x4880,0x0001,score_var_4880,byte
-0x4881,0x000f,score_table_4881,byte
-0x4890,0x0070,object1080_countdown_b190_init,byte
-0x4900,0x0001,score_var_4900,byte
-0x4901,0x000f,score_table_4901,byte
-0x4910,0x0070,object1080_animate0,byte
-0x4980,0x0001,score_var_4980,byte
-0x4981,0x000f,score_table_4981,byte
-0x4990,0x0070,object1080_animate1,byte
-0x4a00,0x0001,score_var_4a00,byte
-0x4a01,0x000f,score_table_4a01,byte
-# 0x4a10 spare
-0x4a80,0x0001,score_var_4a80,byte
-0x4a81,0x000f,score_table_4a81,byte
-# 0x4a90 spare
-0x4b00,0x0001,score_var_4b00,byte
-0x4b01,0x000f,score_table_4b01,byte
-0x4b10,0x0070,object1080_4b10,byte
-0x4b80,0x0001,score_var_4b80,byte
-0x4b81,0x000f,score_table_4b81,byte
-0x4b90,0x0070,object1080_4b90,byte
+; initial fuel (hi 2 digits)
+0x4800,0x0001,initial_decimal_plus_9,byte
+0x4801,0x000f,mission_table_clip_x0,byte
+0x4810,0x0070,object1080_countdown_init,byte
+; initial fuel (lo 2 digits)
+0x4880,0x0001,initial_decimal_plus_8,byte
+0x4881,0x000f,mission_table_clip_x1,byte
+0x4890,0x0070,object1080_countdown2_init,byte
+; initial bomb (hi 2 digits)
+0x4900,0x0001,initial_decimal_plus_0xb,byte
+0x4901,0x000f,mission_table_clip_y0,byte
+0x4910,0x0070,object1080_animate_countdown_init,byte
+; initial bomb (lo 2 digits)
+0x4980,0x0001,initial_decimal_plus_0xa,byte
+0x4981,0x000f,mission_table_clip_y1,byte
+; non-zero for missiles, means shape is based on direction
+0x4990,0x0070,object1080_animate_by_direction,byte
+; initial ship left (hi 2 digits)
+0x4a00,0x0001,initial_decimal_plus_0xd,byte
+0x4a01,0x000f,mission_table_update_object_count,byte
+; 0x4a10 spare
+; initial ship left (lo 2 digits)
+0x4a80,0x0001,initial_decimal_plus_0xc,byte
+0x4a81,0x000f,mission_table_update_sound_count,byte
+; 0x4a90 spare
+; initial bonus/1000 (hi 2 digits)
+0x4b00,0x0001,initial_decimal_plus_0xf,byte
+0x4b01,0x000f,mission_table_decimal_plus_5,byte
+0x4b10,0x0070,object1080_score,byte
+; initial bonus/1000 (lo 2 digits)
+0x4b80,0x0001,initial_decimal_plus_0xe,byte
+0x4b81,0x000f,mission_table_decimal_plus_4,byte
+; used by cyclic_update_object
+; if object is active it gets updated
+; otherwise a delay loop runs controlled by this
+; probably to control game speed and sound generation
+0x4b90,0x0070,object1080_dummy_update,byte
 0x4c00,0x0070,object1080_velocity_x_random_base,byte
 0x4c70,0x0070,object1080_velocity_x_random_range,byte
 0x4ce0,0x0070,object1080_velocity_y_random_base,byte
 0x4d50,0x0070,object1080_velocity_y_random_range,byte
-# 0x4dc0 spare
-0x4ed0,0x0030,object4070_4ed0,byte # might be bigger
-# 0x4f00 spare
-0x4f40,0x0040,object4080_4f40,byte
+0x4dc0,0x0070,object1080_velocity_scale_for_position_hi,byte
+0x4e30,0x0070,object1080_velocity_scale_for_position_lo,byte
+0x4ea0,0x0070,object1080_velocity_scale_hi,byte
+0x4f10,0x0070,object1080_velocity_scale_lo,byte
 0x4f80,0x0040,object4080_x_random_base,byte
 0x4fc0,0x0040,object4080_x_random_range,byte
 0x5000,0x0040,object4080_x_hi_min,byte
@@ -489,28 +684,74 @@ items
 0x50c0,0x0040,object4080_y_random_range,byte
 0x5100,0x0040,object4080_y_hi_min,byte
 0x5140,0x0040,object4080_y_hi_max,byte
-0x5180,0x0030,object5080_x_difference,byte
-0x51b0,0x0030,object5080_y_difference,byte
-0x5240,0x0030,object5080_difference_5240,byte
-0x5270,0x0030,object5080_difference_5270,byte
-0x52a0,0x0030,object5080_difference_52a0,byte
-0x52d0,0x0030,object5080_difference_52d0,byte
+; read-only table used for homing movements
+; sign controls homing sense (- towards, + away from)
+; absolute value controls how often x acceleration happens
+; -1 for missile
+; -4 for helicopter_enemy_plane
+; -4 for tank
+; other objects do not home in the x direction
+0x5180,0x0030,object5080_x_homing_sense,byte
+; read-only table used for homing movements
+; sign controls homing sense (- towards, + away from)
+; absolute value controls how often y acceleration happens
+; -3 for bird
+; -1 for missile
+; -12,-8,-4,-10,-6 for helicopter_enemy_plane
+; other objects do not home in the y direction
+0x51b0,0x0030,object5080_y_homing_sense,byte
+; read-only table used for quadratic movements
+; frequency and direction of x acceleration by constant
+0x5240,0x0030,object5080_x_quadratic_sense,byte
+; read-only table used for cubic movements
+; frequency and direction of x acceleration by velocity
+; note: positive used for bullets (means it will get slower)
+; note: negative used for missiles (means it will get faster;
+; used in conjunction with homing so not exactly a cubic path)
+0x5270,0x0030,object5080_x_cubic_sense,byte
+; read-only table used for quadratic movements
+; frequency and direction of y acceleration by constant
+0x52a0,0x0030,object5080_y_quadratic_sense,byte
+; read-only table used for cubic movements
+; frequency and direction of y acceleration by velocity
+; note: negative used for missiles (means it will get faster;
+; used in conjunction with homing so not exactly a cubic path)
+0x52d0,0x0030,object5080_y_cubic_sense,byte
 0x5300,0x0020,object6080_fire_count_init_in_state_f0,byte
-# used from execute_object6080_ucode_fire_in_state_f0
-0x5320,0x0020,object6080_5320,byte
+; read-only table accessed by execute_ucode_fire_in_state_f0
+; how many instructions execute_ucode_fire_in_state_fn will execute
+0x5320,0x0020,object6080_ucode_fire_in_state_f0_count,byte
 0x5340,0x0020,object6080_fire_count_init_in_state_f1,byte
-# used from execute_object6080_ucode_fire_in_state_f1
-0x5360,0x0020,object6080_5360,byte
+; read-only table accessed by execute_ucode_fire_in_state_f1
+; how many instructions execute_ucode_fire_in_state_fn will execute
+0x5360,0x0020,object6080_ucode_fire_in_state_f1_count,byte
 0x5380,0x0020,object6080_fire_count_init_in_state_f2,byte
-# used from execute_object6080_ucode_fire_in_state_f2
-0x53a0,0x0020,object6080_53a0,byte
+; read-only table accessed by execute_ucode_fire_in_state_f2
+; how many instructions execute_ucode_fire_in_state_fn will execute
+0x53a0,0x0020,object6080_ucode_fire_in_state_f2_count,byte
 0x53c0,0x0020,object6080_fire_count_init_in_state_f3,byte
-# used from execute_object6080_ucode_fire_in_state_f2
-0x53e0,0x0020,object6080_53e0,byte
-# the partitioning below is approximate and just tries to cover everything
+; read-only table accessed by execute_ucode_fire_in_state_f3
+; how many instructions execute_ucode_fire_in_state_fn will execute
+0x53e0,0x0020,object6080_ucode_fire_in_state_f3_count,byte
+; the partitioning below is approximate and just tries to cover everything
 0x5400,0x0020,,word
 0x5420,0x00e0,object1080_ucode_animate_shape_ptr,word
-0x5500,0x0020,object0010_ucode_init_or_zero_ptr,word
+; objects 0..0xf have special purposes in the game
+; (actually not really objects, but it is convenient to treat them as such)
+; 0 does not have microcode
+; 1..5 have microcode: the initialization code for each mission
+; 6 has microcode: draws "great performance", "bonus"
+; 7 has microcode: draws "great performance", "game over"
+; 8..0xf have microcode to execute when each decimal[] is decremented to 0
+;   8 for decimal = score/10: does not have microcode
+;   9 for decimal + 2 = high score/10: does not have microcode
+;   0xa for decimal + 4 = spare: runs when something happens to score (?)
+;   0xb for decimal + 6 = mission: does not have microcode
+;   0xc for decimal + 8 = fuel: has microcode
+;   0xd for decimal + 0xa = bomb: has microcode
+;   0xe for decimal + 0xc = ship left: has microcode
+;   0xf for decimal + 0xe = bonus/1000: has microcode
+0x5500,0x0020,object0010_ucode_mission_init_or_decimal_reached_zero_ptr,word
 0x5520,0x00e0,object1080_ucode_countdown_ptr,word
 0x5600,0x0020,,word
 0x5620,0x00e0,object1080_ucode_collision_test_ptr,word
@@ -529,21 +770,26 @@ items
 0x5b00,0x0040,object6080_ucode_fire_in_state_f2_ptr,word
 0x5b40,0x0040,object6080_ucode_test_fire_in_state_f3_ptr,word
 0x5b80,0x0040,object6080_ucode_fire_in_state_f3_ptr,word
-# 0x5bc0 padding
-# 0x5c00 shape data
-# 0x8c08 padding
-# 0x8e00 ucode data
-# 0x9ded end of image
+; 0x5bc0 padding
+; 0x5c00 shape data
+; 0x8c08 padding
+; 0x8e00 ucode data
+; 0x9ded end of image
 0xa800,0x0001,x_table_times2_div7_plus_5b,byte
 0xa900,0x0001,x_table_times2_mod7_minus_03,byte
 0xaa00,0x0001,video_line_table_lo,byte
 0xaac0,0x0001,video_line_table_hi,byte
-0xab80,0x0001,sound_status_ab80,byte
-# ab90?
-0xaba0,0x0001,sound_status_aba0,byte
-0xabb0,0x0001,sound_status_abb0,byte
-0xabc0,0x0001,sound_status_abc0,byte
-0xabd0,0x0001,sound_status_abd0,byte
+; 0 => sound is not playing
+; positive => sound is to be initialized
+; negative => sound is playing
+0xab80,0x0001,sound_status_active,byte
+; countdown for how many times the sound plays a tone before terminating
+0xab90,0x0001,sound_status_repeat_countdown,byte
+0xaba0,0x0001,sound_status_period,byte
+0xabb0,0x0001,sound_status_duration,byte
+0xabc0,0x0001,sound_status_delay,byte
+; countdown for how many update calls until next repeat of the sound plays
+0xabd0,0x0001,sound_status_delay_countdown,byte
 0xabe0,0x0070,object1080_shape,byte
 0xac50,0x0070,object1080_x_hi,byte
 0xacc0,0x0070,object1080_y_hi,byte
@@ -551,51 +797,78 @@ items
 0xada0,0x0070,object1080_x1,byte
 0xae10,0x0070,object1080_y0,byte
 0xae80,0x0070,object1080_y1,byte
-# often a value 0xf0..0xf3 to identify relevant section in ucode table,
-# but I think it has other purposes too (bit 7 may mean object is active?)
+; positive => object is disabled
+; negative => object is enabled, in state 0xf0..0xf3
+; the object can be enabled/disabled in various places:
+; - objects_init: zeros object1080_state
+; - objects_reinit: clears hi bit of object1080_state
+; - make_object_active_and_compute_bounds: sets hi bit of object1080_state
+;   (presumably this relies on some earlier code to set the 0xf0..0xf3 state)
+; - make_object_inactive_and_erase: clears hi bit of object1080_state
+; the state 0xf0..0xf3 can be changed in the following ways:
+; - loc_0daf: comes from microcode value 0xf8..0xfb in animate shape table
+; - loc_0db9: calling calculate_object_shape, passing a non-zero value in a
+; - reset_object_state (from microcode instruction): sets it back to 0xf0
 0xaef0,0x0070,object1080_state,byte
 0xaf60,0x0070,object1080_velocity_x_hi,byte
 0xafd0,0x0070,object1080_velocity_y_hi,byte
 0xb040,0x0070,object1080_velocity_x_lo,byte
 0xb0b0,0x0070,object1080_velocity_y_lo,byte
-0xb120,0x0070,object1080_countdown_b120,byte
-0xb190,0x0070,object1080_countdown_b190,byte
+0xb120,0x0070,object1080_countdown,byte
+0xb190,0x0070,object1080_countdown2,byte
 0xb200,0x0070,object1080_x_lo,byte
 0xb270,0x0070,object1080_y_lo,byte
-0xb2e0,0x0070,object1080_animate2,byte
+; countdown to when move_object_by_velocity calls set_object_shape
+0xb2e0,0x0070,object1080_animate_countdown,byte
 0xb350,0x0070,object1080_animate_shape_index,byte
-0xb3c0,0x0030,object5080_abs_x_difference,byte
-0xb3f0,0x0030,object5080_abs_y_difference,byte
-# accelerate_object_somehow
-# used as a countdown for whether x should be accelerated by +/- 0x4c
-0xb420,0x0030,object5080_abs_difference_b420,byte
-# accelerate_object_somehow
-# used as a countdown for whether y should be accelerated by +/- 0x40
-0xb450,0x0030,object5080_abs_difference_b450,byte
-# accelerate_object_anyhow
-# used as a countdown for whether x should be accelerated by calculated value
-0xb480,0x0030,object5080_abs_difference_b480,byte
-# accelerate_object_anyhow
-# used as a countdown for whether y should be accelerated by calculated value
-0xb4b0,0x0030,object5080_abs_difference_b4b0,byte
+; initialized with the abs value of object5080_x_homing_sense
+; when = 0, it means object does not home in x direction
+; when > 0, it is the countdown until next x acceleration
+; (each time it reaches 0 it is reset from the abs computation)
+0xb3c0,0x0030,object5080_x_homing_countdown,byte
+; initialized with the abs value of object5080_y_homing_sense
+; when = 0, it means object does not home in y direction
+; when > 0, it is the countdown until next y acceleration
+; (each time it reaches 0 it is reset from the abs computation)
+0xb3f0,0x0030,object5080_y_homing_countdown,byte
+; accelerate_object_by_constant
+; used as a countdown for whether x should be accelerated by +/- 0x4c
+; makes player fly away, tank drive away, etc
+0xb420,0x0030,object5080_x_quadratic_countdown,byte
+; accelerate_object_by_constant
+; used as a countdown for whether y should be accelerated by +/- 0x40
+; makes player fly away/fall to the ground, etc
+0xb450,0x0030,object5080_y_quadratic_countdown,byte
+; accelerate_object_by_velocity
+; used as a countdown for whether x should be accelerated by x velocity
+; (divided by 1024?) -- should result in a cubic movement
+0xb480,0x0030,object5080_x_cubic_countdown,byte
+; accelerate_object_by_velocity
+; used as a countdown for whether y should be accelerated by y velocity
+; (divided by 1024?) -- should result in a cubic movement
+0xb4b0,0x0030,object5080_y_cubic_countdown,byte
 0xb4e0,0x0020,object6080_fire_count,byte
-# used from execute_object6080_ucode_fire_in_state_f0
-0xb500,0x0020,object6080_b500,byte
-# used from execute_object6080_ucode_fire_in_state_f1
-0xb520,0x0020,object6080_b520,byte
-# used from execute_object6080_ucode_fire_in_state_f2
-0xb540,0x0020,object6080_b540,byte
-# used from execute_object6080_ucode_fire_in_state_f3
-0xb560,0x0020,object6080_b560,byte
+; used from execute_ucode_fire_in_state_f0
+; offset to next instruction execute_ucode_fire_in_state_fn will execute
+0xb500,0x0020,object6080_ucode_fire_in_state_f0_index,byte
+; used from execute_ucode_fire_in_state_f1
+; offset to next instruction execute_ucode_fire_in_state_fn will execute
+0xb520,0x0020,object6080_ucode_fire_in_state_f1_index,byte
+; used from execute_ucode_fire_in_state_f2
+; offset to next instruction execute_ucode_fire_in_state_fn will execute
+0xb540,0x0020,object6080_ucode_fire_in_state_f2_index,byte
+; used from execute_ucode_fire_in_state_f3
+; offset to next instruction execute_ucode_fire_in_state_fn will execute
+0xb560,0x0020,object6080_ucode_fire_in_state_f3_index,byte
 0xc000,0x0001,HW_KBD,byte
 0xc010,0x0001,HW_KBDSTRB,byte
+0xc020,0x0001,HW_TAPEOUT,byte
 0xc030,0x0001,HW_SPKR,byte
 0xc050,0x0001,HW_TXTCLR,byte
 0xc052,0x0001,HW_MIXCLR,byte
 0xc054,0x0001,HW_PAGE1,byte
 0xc057,0x0001,HW_HIRES,byte
 0xc061,0x0001,HW_PB0,byte
-0xc062,0x0001,HW_PB1,byte
 0xc065,0x0001,HW_PADDL1,byte
 0xc070,0x0001,HW_PTRIG,byte
 
@@ -737,6 +1010,7 @@ shapes
 0xff,blank
 
 objects
+0x00,spare
 0x01,init_mission_1
 0x02,init_mission_2
 0x03,init_mission_3
@@ -744,11 +1018,14 @@ objects
 0x05,init_mission_5
 0x06,draw_great_performance_bonus
 0x07,draw_great_performance_game_over
-0x0a,set_mission_7
-0x0c,draw_empty_fuel
-0x0d,init_ship
-0x0e,draw_high_score
-0x0f,draw_bonus
+0x08,spare
+0x09,spare
+0x0a,something_happened_to_score
+0x0b,spare
+0x0c,fuel_exhausted
+0x0d,bomb_exhausted
+0x0e,ship_left_exhausted
+0x0f,bonus_exhausted
 0x10,draw_fuel_bomb
 0x11,draw_ship_left
 0x12,draw_high_score_copyright
index 01fd99c..988d233 100644 (file)
@@ -9,7 +9,5 @@
 [0x1f80, 0x2000)
 [0x4000, 0x4a10)
 [0x4a80, 0x4a90)
-[0x4b00, 0x4dc0)
-[0x4ed0, 0x4f00)
-[0x4f40, 0x8c00)
+[0x4b00, 0x8c00)
 [0x8c00, 0x9beb)
index b13ef3e..d82e022 100644 (file)
@@ -265,10 +265,10 @@ SECTION_F0 = 0xf0
 SECTION_F1 = 0xf1
 SECTION_F2 = 0xf2
 SECTION_F3 = 0xf3
-SECTION_F8_REPEAT = 0xf8
-SECTION_F9_REPEAT = 0xf9
-SECTION_FA_REPEAT = 0xfa
-SECTION_FB_REPEAT = 0xfb
+SECTION_F8_SET_STATE_F0 = 0xf8
+SECTION_F9_SET_STATE_F1 = 0xf9
+SECTION_FA_SET_STATE_F2 = 0xfa
+SECTION_FB_SET_STATE_F3 = 0xfb
 SECTION_FF = 0xff
 
 ; word-wide sections
@@ -321,17 +321,17 @@ UCODE_DECIMAL_ADJUST = 0x7000
 
 ; decimal set
 UCODE_DECIMAL_SET_0 = 0x100
-UCODE_DECIMAL_SET_SCORE_VAR_4B80_SCORE_VAR_4B00_BY_MISSION = 0x200
+UCODE_DECIMAL_SET_MISSION_SPECIFIC_VALUE = 0x200
 UCODE_DECIMAL_SET_1 = 0x300
-UCODE_DECIMAL_SET_SCORE_VAR_4880_SCORE_VAR_4800 = 0x400
-UCODE_DECIMAL_SET_SCORE_VAR_4980_SCORE_VAR_4900 = 0x500
-UCODE_DECIMAL_SET_SCORE_VAR_4A80_SCORE_VAR_4A00 = 0x600
-UCODE_DECIMAL_SET_SCORE_VAR_4B80_SCORE_VAR_4B00 = 0x700
+UCODE_DECIMAL_SET_INITIAL_DECIMAL_4 = 0x400
+UCODE_DECIMAL_SET_INITIAL_DECIMAL_5 = 0x500
+UCODE_DECIMAL_SET_INITIAL_DECIMAL_6 = 0x600
+UCODE_DECIMAL_SET_INITIAL_DECIMAL_7 = 0x700
 
 ; decimal other
 UCODE_DECIMAL_0_SCORE = 0x0000
 UCODE_DECIMAL_1_HIGH_SCORE = 0x0100
-UCODE_DECIMAL_2 = 0x0200
+UCODE_DECIMAL_2_SPARE = 0x0200
 UCODE_DECIMAL_3_MISSION = 0x0300
 UCODE_DECIMAL_4_FUEL = 0x0400
 UCODE_DECIMAL_5_BOMB = 0x0500
@@ -345,7 +345,7 @@ UCODE_DRAW_MISC_CLEAR_RECTANGLE = 0xe100
 ; draw misc bits 0 to 4
 UCODE_DRAW_MISC_DECIMAL_0_SCORE = 0x0000
 UCODE_DRAW_MISC_DECIMAL_1_HIGH_SCORE = 0x0100
-UCODE_DRAW_MISC_DECIMAL_2 = 0x0200
+UCODE_DRAW_MISC_DECIMAL_2_SPARE = 0x0200
 UCODE_DRAW_MISC_DECIMAL_3_MISSION = 0x0300
 UCODE_DRAW_MISC_DECIMAL_4_FUEL = 0x0400
 UCODE_DRAW_MISC_DECIMAL_5_BOMB = 0x0500
@@ -402,27 +402,39 @@ UCODE_SOUND_EFFECT_D_EXPLOSION = 0x0d00
 UCODE_SOUND_EFFECT_E_EXPLOSION = 0x0e00
 UCODE_SOUND_EFFECT_F_EXPLOSION = 0x0f00
 
-; the following occur by themselves
+; the following take an object number >= 0x10 in the low byte
+; (if the object number would be < 0x10 then it's an escape as above)
 
+; the following occur by themselves (not a bitmap):
+
+; 0x0000 does not occur because it would indicate the end of the microcode?
+; 0x0400, 0x0500, 0x0600, 0x0700: synonyms for 0x0000, 0x0100, 0x0200, 0x0300
 ; byte
+UCODE_IF_ACTIVE_SET_STATE_F1 = 0x0100
+UCODE_IF_ACTIVE_SET_STATE_F2 = 0x0200
+UCODE_IF_ACTIVE_SET_STATE_F3 = 0x0300
+UCODE_IF_ACTIVE_SET_STATE_F0 = 0x0400
 UCODE_HORIZONTAL_COLLISION_AND_ZERO = 0x0800
 UCODE_VERTICAL_COLLISION_AND_ZERO = 0x0900
 UCODE_HORIZONTAL_COLLISION = 0x0a00
 UCODE_VERTICAL_COLLISION = 0x0b00
 UCODE_HORIZONTAL_COLLISION_AND_COPY = 0x0c00
 UCODE_VERTICAL_COLLISION_AND_COPY = 0x0d00
+UCODE_DECREMENT_COUNTDOWN2 = 0x0e00
 UCODE_INACTIVATE_OBJECT = 0x0f00
 
-; the following are used with UCODE_UPDATE_OBJECT(_IF_INACTIVE)
+; the following occur as a bitmap, used with UCODE_UPDATE_OBJECT(_IF_INACTIVE)
+; for UCODE_UPDATE_OBJECT_IF_INACTIVE, one of the *POSITION* bits must be set,
+; otherwise the opcode would be < 0x1000 (the values that occur by themselves)
 
 ; update bits 0 to 2
 UCODE_RANDOMIZE_OBJECT_VELOCITY = 0x0100
 UCODE_COPY_OBJECT_VELOCITY = 0x0200
 UCODE_RANDOMIZE_OBJECT_VELOCITY_RELATIVE = 0x0300
-UCODE_UPDATE_OBJECT_VELOCITY = 0x0400
-UCODE_UPDATE_OBJECT_VELOCITY_ROTATE_90 = 0x0500
-UCODE_UPDATE_OBJECT_VELOCITY_ROTATE_180 = 0x0600
-UCODE_UPDATE_OBJECT_VELOCITY_ROTATE_270 = 0x0700
+UCODE_COPY_SCALED_OBJECT_VELOCITY = 0x0400
+UCODE_COPY_SCALED_OBJECT_VELOCITY_ROTATE_90 = 0x0500
+UCODE_COPY_SCALED_OBJECT_VELOCITY_ROTATE_180 = 0x0600
+UCODE_COPY_SCALED_OBJECT_VELOCITY_ROTATE_270 = 0x0700
 
 ; update bit 3
 UCODE_RESET_OBJECT = 0x0000
@@ -432,10 +444,10 @@ UCODE_ACTIVATE_OBJECT = 0x0800
 UCODE_RANDOMIZE_OBJECT_POSITION = 0x1000
 UCODE_COPY_OBJECT_POSITION = 0x2000
 UCODE_RANDOMIZE_OBJECT_POSITION_RELATIVE = 0x3000
-UCODE_MOVE_OBJECT_POS_POS = 0x4000
-UCODE_MOVE_OBJECT_NEG_POS = 0x5000
-UCODE_MOVE_OBJECT_NEG_NEG = 0x6000
-UCODE_MOVE_OBJECT_POS_NEG = 0x7000
+UCODE_COPY_OBJECT_POSITION_PLUS_SCALED_VELOCITY = 0x4000
+UCODE_COPY_OBJECT_POSITION_PLUS_SCALED_VELOCITY_ROTATE_90 = 0x5000
+UCODE_COPY_OBJECT_POSITION_PLUS_SCALED_VELOCITY_ROTATE_180 = 0x6000
+UCODE_COPY_OBJECT_POSITION_PLUS_SCALED_VELOCITY_ROTATE_270 = 0x7000
 
 ; update bit 7
 UCODE_UPDATE_OBJECT_IF_INACTIVE = 0x0000
index d04c215..9753e7b 100644 (file)
@@ -1,5 +1,5 @@
---- star_blazer.asm0   2024-07-19 00:00:54.594263249 +1000
-+++ star_blazer.asm    2024-07-19 00:01:14.178307255 +1000
+--- star_blazer.asm0   2024-07-20 22:51:05.009210965 -0800
++++ star_blazer.asm    2024-07-20 22:51:49.064421478 -0800
 @@ -1,3 +1,10 @@
 +UNREACHABLE = 1
 +DHGR = 0
        rts                             ; 0ccf r
  vertical_collision_and_zero:
        jsr     vertical_collision      ; 1015 -> 0cd0 -> 0c9d r s=f5
-@@ -925,9 +971,10 @@
+@@ -936,9 +982,10 @@
        bcs     ucode_decimal_set_save  ; 0ebf r
  ucode_decimal_set_mission_specific_value:
        ldy     *decimal + 6            ; 0ec1 r
        tay                             ; 0eca r
        pla                             ; 0ecb r
        bcs     ucode_decimal_set_save  ; 0ecc r
-@@ -1294,7 +1341,7 @@
+@@ -1306,7 +1353,7 @@
        tsx                             ; 1095 -> 1097 -> 1098 r
        stx     *ucode_sp               ; 1097 -> 1098 -> 109a r
        ldx     *ucode_x_save           ; 1098 -> 109a -> 109c r
        sta     *ucode_fire_in_state_fn_count ; 109c -> 109f -> 10a1 r
  ; alternative entry point for execute_ucode_words that comes from scoring?
  execute_ucode_words_entry:
-@@ -1326,7 +1373,7 @@
+@@ -1338,7 +1385,7 @@
  ;     jsr     execute_object1080_ucode_countdown
  ;     bpl     rts_15d6
  execute_ucode_words_done:
        rts                             ; 10cd -> 10d0 -> 123e,143a,1615,1629,1633,1649,165b,1759 r s=f7..fd,02
  ; call with the following set up:
  ;   execute_ucode_words_ptr
-@@ -1847,16 +1894,20 @@
+@@ -1859,16 +1906,20 @@
        bpl     loc_14c9                ; 14a0 -> 14a3 -> 14a5,14c9 r n=0..1
        iny                             ; 14a3 -> 14a5 -> 14a6 r
        bne     ucode_test_fire_all_objects_active ; 14a5 -> 14a6 -> 149b r z=0
  ; opcode is followed by null-terminated list of objects to test
  ; note: some of these opcodes never executed in the trace
  ; 0x01 loc_149b test that all objects are active (object1080_state >= 0x80)
-@@ -1889,17 +1940,21 @@
+@@ -1901,17 +1952,21 @@
        bmi     loc_14c9                ; 14d5 -> 14d8 -> 14da r n=0
        iny                             ; 14d8 -> 14da -> 14db r
        bne     ucode_test_fire_any_object_active ; 14da -> 14db -> 14d0 r z=0
  test_object_fire_in_state_f0:
        lda     object6080_fire_count - 0x60,x ; 1668 -> 14ef -> 14f2 r x=60..7f
        beq     test_object_fire_false  ; 14ef -> 14f2 -> 14f4,153f r z=0..1
-@@ -2263,10 +2318,35 @@
-       sta     *button_state           ; 17ce r
- rts_17d0:
-       rts                             ; 17ab,17ca -> 17d0 -> 1768,176f r s=fd
+@@ -2304,10 +2359,35 @@
+ ; if invalid joystick input detected, permanently disable joystick
+ ; (but this test can be bypassed by pressing either joystick button)
+ ; then jumps to init_game via vec_init_game
 -start:        lda     HW_PB0                  ; -> 17d1 -> 17d4 r
 +start:
 +.if DHGR
        ldx     #0x01                   ; 17db r
  0$:   jsr     ROM_PREAD               ; 17dd r
        cpy     #0xff                   ; 17e0 r
-@@ -2277,9 +2357,17 @@
-       sta     bvar_179e               ; 17e9 r
-       sta     bvar_17a3               ; 17ec r
-       sta     bvar_1e0e               ; 17ef r
+@@ -2318,9 +2398,17 @@
+       sta     disable_joystick0       ; 17e9 r
+       sta     disable_joystick1       ; 17ec r
+       sta     disable_joystick2       ; 17ef r
 -1$:   jmp     (vec_init_game)         ; 17d9 -> 17f2 -> 1708 r
 +1$:
 +.if 0 ;DHGR ; language card
  
  divide_a_by_y:
        sta     *accumulator + 1        ; 0a90,0aa0,0ab5,0ad5 -> 1800 -> 1802 r
-@@ -2345,10 +2433,12 @@
+@@ -2386,10 +2474,12 @@
        lda     *result + 1             ; 186e r
        ldy     *result + 2             ; 1870 r
        rts                             ; 1872 r
  random_init:
        lda     *random_seed            ; 16ae -> 187a -> 187c r
        ora     #0x01                   ; 187a -> 187c -> 187e r
-@@ -2508,16 +2598,30 @@
+@@ -2549,16 +2639,30 @@
        ldx     #>HIRES_SCREEN          ; 199b -> 199d -> 199f r
        stx     *video_line_ptr + 1     ; 199d -> 199f -> 19a1 r
        tay                             ; 199f -> 19a1 -> 19a2 r
        rts                             ; 19b5 -> 19b8 -> 1713 r s=fd
  video_clear_rectangle:
        ldx     *clip_y0                ; 1064 -> 19b9 -> 19bb r
-@@ -2525,8 +2629,20 @@
+@@ -2566,8 +2670,20 @@
        sta     *video_line_ptr         ; 19bb -> 19be -> 19c0 r
        lda     video_line_table_hi - 0x20,x ; 19be -> 19c0 -> 19c3 r x=28..cf
        sta     *video_line_ptr + 1     ; 19c0 -> 19c3 -> 19c5 r
  1$:   sta     (*video_line_ptr),y     ; 19c7,19ce -> 19c9 -> 19cb r y=6c..93
        iny                             ; 19c9 -> 19cb -> 19cc r
        cpy     *clip_x1                ; 19cb -> 19cc -> 19ce r y=6d..94
-@@ -2576,6 +2692,7 @@
+@@ -2617,6 +2733,7 @@
        sta     object1080_y0 - 0x10,x  ; 1a1b -> 1a1e -> 1a21 r x=10..7f
        adc     #0x01                   ; 1a1e -> 1a21 -> 1a23 r c=0..1 d=0
        sta     object1080_y1 - 0x10,x  ; 1a21 -> 1a23 -> 1a26 r x=10..7f
        rts                             ; 1a23 -> 1a26 -> 1076,1179,1602 r s=f1..f9,02
  pixel_data_table_left:
        .db     0x83                    ; 1a27 r
-@@ -2658,14 +2775,17 @@
+@@ -2699,14 +2816,17 @@
        lda     object1080_onscreen_shape_ptr_hi - 0x10,x ; 1aa5 -> 1aa7 -> 1aaa r x=20..4f
        ora     (*video_line_ptr),y     ; 1aa7 -> 1aaa -> 1aac r y=6d..93,02
        sta     (*video_line_ptr),y     ; 1aaa -> 1aac -> 1aae r y=6d..93,02
        lda     object1080_y0 - 0x10,x  ; 1ab9 -> 1abb -> 1abe r x=14..77
        cmp     object1080_y1 - 0x10,x  ; 1abb -> 1abe -> 1ac1 r a=11..d4 x=14..77
        bcs     rts_1aae                ; 1abe -> 1ac1 -> 1ac3 r c=0
-@@ -2718,7 +2838,12 @@
+@@ -2759,7 +2879,12 @@
        stx     *x_save                 ; 1b32 -> 1b35 -> 1b37 r
        lda     *draw_y                 ; 1b35 -> 1b37 -> 1b39 r
        cmp     *clip_y0                ; 1b37 -> 1b39 -> 1b3b r a=11..d4
        lda     *clip_y1                ; 1b3b -> 1b3d -> 1b3f r
        cmp     *draw_y1                ; 1b3d -> 1b3f -> 1b41 r a=d0
        bcc     8$                      ; 1b3f -> 1b41 -> 1b43,1b83 r c=0..1
-@@ -2729,16 +2854,59 @@
+@@ -2770,16 +2895,59 @@
        cmp     *draw_x1                ; 1b49 -> 1b4b -> 1b4d r a=94
        bcc     8$                      ; 1b4b -> 1b4d -> 1b4f,1b83 r c=0..1
        lda     object1080_onscreen_shape_ptr_lo - 0x10,x ; 1b4d -> 1b4f -> 1b52 r x=14..77
  6$:   .db     0xbd                    ; 1b69,1b76 -> 1b6b -> 1b6e r "lda bvar_6f9f,x" x=00..39
  7$:   .dw     0x6f9f                  ; 1b6c rw
        ora     (*video_line_ptr),y     ; 1b6b -> 1b6e -> 1b70 r y=6c..93
-@@ -2755,16 +2923,50 @@
+@@ -2796,16 +2964,50 @@
        rts                             ; 1b80 -> 1b82 -> 15cd r s=fb
  8$:   inc     object1080_onscreen_clipped - 0x10,x ; 1b3b,1b41,1b47,1b4d -> 1b83 -> 1b86 r x=14..77
        lda     object1080_onscreen_shape_ptr_lo - 0x10,x ; 1b83 -> 1b86 -> 1b89 r x=14..77
  10$:  lda     *draw_y                 ; 1ba0,1bbf -> 1ba2 -> 1ba4 r
        cmp     *clip_y0                ; 1ba2 -> 1ba4 -> 1ba6 r a=11..d8
        bcc     12$                     ; 1ba4 -> 1ba6 -> 1ba8,1bbb r c=0..1
-@@ -2774,6 +2976,16 @@
+@@ -2815,6 +3017,16 @@
        bcc     12$                     ; 1bac -> 1bae -> 1bb0,1bbb r c=0..1
        cpy     *clip_x1                ; 1bae -> 1bb0 -> 1bb2 r y=6c..a4
        bcs     12$                     ; 1bb0 -> 1bb2 -> 1bb4,1bbb r c=0..1
        .db     0xbd                    ; 1bb2 -> 1bb4 -> 1bb7 r "lda 0x6fab,x" x=00..39
  11$:  .dw     0x6fab                  ; 1bb5 rw
        ora     (*video_line_ptr),y     ; 1bb4 -> 1bb7 -> 1bb9 r y=6c..93
-@@ -2787,6 +2999,7 @@
+@@ -2828,6 +3040,7 @@
        cpy     *draw_y1                ; 1bc3 -> 1bc5 -> 1bc7 r y=12..d9
        bcc     9$                      ; 1bc5 -> 1bc7 -> 1b96,1bc9 r c=0..1
        ldx     *x_save                 ; 1bc7 -> 1bc9 -> 1bcb r
        rts                             ; 1bc9 -> 1bcb -> 15cd r s=fb
  erase_pixel_object:
        lda     #0x00                   ; 1c12 -> 1bcc -> 1bce r
-@@ -2818,12 +3031,15 @@
+@@ -2859,12 +3072,15 @@
        eor     #0xff                   ; 1c03 -> 1c06 -> 1c08 r
        and     (*video_line_ptr),y     ; 1c06 -> 1c08 -> 1c0a r y=6d..93,02
        sta     (*video_line_ptr),y     ; 1c08 -> 1c0a -> 1c0c r y=6d..93,02
        lda     #0x00                   ; 1c12 -> 1c14 -> 1c16 r
        sta     object1080_onscreen - 0x10,x ; 1c14 -> 1c16 -> 1c19 r x=14..77
        lda     object1080_onscreen_x0 - 0x10,x ; 1c16 -> 1c19 -> 1c1c r x=14..77
-@@ -2838,16 +3054,61 @@
+@@ -2879,16 +3095,61 @@
        stx     *x_save                 ; 1c2d -> 1c30 -> 1c32 r
        bne     3$                      ; 1c30 -> 1c32 -> 1c34,1c6a r z=0..1
        lda     object1080_onscreen_shape_ptr_lo - 0x10,x ; 1c32 -> 1c34 -> 1c37 r x=14..77
  1$:   .db     0xbd                    ; 1c4e,1c5d -> 1c50 -> 1c53 r "lda 0x6f93,x" x=00..39
  2$:   .dw     0x6f93                  ; 1c51 rw
        eor     #0xff                   ; 1c50 -> 1c53 -> 1c55 r
-@@ -2864,16 +3125,51 @@
+@@ -2905,16 +3166,51 @@
        ldx     *x_save                 ; 1c65 -> 1c67 -> 1c69 r
        rts                             ; 1c67 -> 1c69 -> 1076,16a8 r s=f3..f9,02
  3$:   lda     object1080_onscreen_shape_ptr_lo - 0x10,x ; 1c32 -> 1c6a -> 1c6d r x=14..77
  5$:   lda     *draw_y                 ; 1c84,1ca5 -> 1c86 -> 1c88 r
        cmp     *clip_y0                ; 1c86 -> 1c88 -> 1c8a r a=11..d8
        bcc     7$                      ; 1c88 -> 1c8a -> 1c8c,1ca1 r c=0..1
-@@ -2883,6 +3179,17 @@
+@@ -2924,6 +3220,17 @@
        bcc     7$                      ; 1c90 -> 1c92 -> 1c94,1ca1 r c=0..1
        cpy     *clip_x1                ; 1c92 -> 1c94 -> 1c96 r y=6c..a4
        bcs     7$                      ; 1c94 -> 1c96 -> 1c98,1ca1 r c=0..1
        .db     0xbd                    ; 1c96 -> 1c98 -> 1c9b r "lda 0x6fab,x" x=00..39
  6$:   .dw     0x6fab                  ; 1c99 rw
        eor     #0xff                   ; 1c98 -> 1c9b -> 1c9d r
-@@ -2902,9 +3209,24 @@
+@@ -2943,9 +3250,24 @@
        stx     *x_save                 ; 1db0 -> 1cb2 -> 1cb4 r
        tay                             ; 1cb2 -> 1cb4 -> 1cb5 r
        lda     shape_data_ptr_lo,y     ; 1cb4 -> 1cb5 -> 1cb8 r y=16..ff
        lda     shape_width_bytes,y     ; 1cbe -> 1cc1 -> 1cc4 r y=16..ff
        clc                             ; 1cc1 -> 1cc4 -> 1cc5 r
        adc     *draw_x0                ; 1cc4 -> 1cc5 -> 1cc7 r c=0 d=0
-@@ -2912,6 +3234,11 @@
+@@ -2953,6 +3275,11 @@
        lda     *draw_x0                ; 1cc7 -> 1cc9 -> 1ccb r
        lsr     a                       ; 1cc9 -> 1ccb -> 1ccc r
        bcc     0$                      ; 1ccb -> 1ccc -> 1cce,1cd4 r c=0..1
        lda     *draw_misc_mask         ; 1ccc -> 1cce -> 1cd0 r
        eor     *draw_misc_mask_xor     ; 1cce -> 1cd0 -> 1cd2 r
        sta     *draw_misc_mask         ; 1cd0 -> 1cd2 -> 1cd4 r
-@@ -2927,9 +3254,56 @@
+@@ -2968,9 +3295,56 @@
        lda     video_line_table_hi,y   ; 1ce5 -> 1ce7 -> 1cea r y=00..bc
        adc     #0x00                   ; 1ce7 -> 1cea -> 1cec r c=0..1 d=0
        sta     *video_line_ptr + 1     ; 1cea -> 1cec -> 1cee r
  2$:   lda     *draw_y                 ; 1cf2,1d0f -> 1cf4 -> 1cf6 r
        cmp     #0xc0                   ; 1cf4 -> 1cf6 -> 1cf8 r a=00..bc
        bcs     4$                      ; 1cf6 -> 1cf8 -> 1cfa r c=0
-@@ -2949,7 +3323,12 @@
+@@ -2990,7 +3364,12 @@
        inc     *draw_y                 ; 1d0f -> 1d11 -> 1d13 r
        ldy     *draw_y                 ; 1d11 -> 1d13 -> 1d15 r
        cpy     *draw_y1                ; 1d13 -> 1d15 -> 1d17 r y=01..bd
        ldx     *x_save                 ; 1d17 -> 1d19 -> 1d1b r
        rts                             ; 1d19 -> 1d1b -> 1db3 r s=ec..f5
  draw_misc_from_table:
-@@ -2962,7 +3341,7 @@
+@@ -3003,7 +3382,7 @@
        asl     a                       ; 1d23 -> 1d24 -> 1d25 r
        sta     *draw_misc_ptr          ; 1d24 -> 1d25 -> 1d27 r
        lda     #0x00                   ; 1d25 -> 1d27 -> 1d29 r
        sta     *draw_misc_ptr + 1      ; 1d29 -> 1d2b -> 1d2d r
        lda     *half_dimension         ; 1d2b -> 1d2d -> 1d2f r
        lsr     a                       ; 1d2d -> 1d2f -> 1d30 r
-@@ -2971,10 +3350,20 @@
+@@ -3012,10 +3391,20 @@
        lsr     a                       ; 1d31 -> 1d32 -> 1d33 r
        lsr     a                       ; 1d32 -> 1d33 -> 1d34 r
        tay                             ; 1d33 -> 1d34 -> 1d35 r
        lda     *half_dimension         ; 1d3d -> 1d3f -> 1d41 r
        and     #0x1f                   ; 1d3f -> 1d41 -> 1d43 r
        cmp     #0x08                   ; 1d41 -> 1d43 -> 1d45 r a=00..1f
-@@ -2992,6 +3381,14 @@
+@@ -3033,6 +3422,14 @@
        iny                             ; 1d57 -> 1d59 -> 1d5a r
  1$:   lda     (*draw_misc_ptr),y      ; 1d59,1d69 -> 1d5a -> 1d5c r y=03..0c
        beq     2$                      ; 1d5a -> 1d5c -> 1d5e,1d61 r z=0..1
        jsr     do_draw_misc            ; 1d5c -> 1d5e -> 1da6 r s=f3..f9,02
  2$:   iny                             ; 1d5c,1db5 -> 1d61 -> 1d62 r
        cpy     #0x10                   ; 1d61 -> 1d62 -> 1d64 r y=04..0d
-@@ -3047,6 +3444,84 @@
+@@ -3088,6 +3485,84 @@
        ldy     *draw_misc_y_save       ; 1d1b -> 1db3 -> 1db5 r
  rts_1db5:
        rts                             ; 1da1,1db3 -> 1db5 -> 1076,1d61,1d7d,1d82,1d87 r s=ee..f7
  draw_misc_mask_table:
        .db     0xff                    ; 1db6 r
        .db     0x00                    ; 1db7 r
-@@ -3057,15 +3532,17 @@
+@@ -3098,15 +3573,17 @@
        .db     0xd5                    ; 1dbc r
        .db     0xff                    ; 1dbd r
  draw_misc_mask_xor_table:
        .area   text2
  
  do_player_input:
-@@ -3378,6 +3855,15 @@
+@@ -3420,6 +3897,15 @@
  
        .area   data2
  
  shape_data_ptr_lo:
        .db     <bvar_5d01              ; 4000 r
        .db     <bvar_5d01              ; 4001 r
-@@ -4920,6 +5406,12 @@
+@@ -4962,6 +5448,12 @@
        .db     0x01                    ; 45fd r
        .db     0x01                    ; 45fe r
        .db     0x04                    ; 45ff r
  ; 0x20 entries of 0x10 bytes
  draw_misc_table:
        .db     0x01                    ; 4600 r
-@@ -5434,7 +5926,174 @@
+@@ -5476,7 +5968,174 @@
        .db     0x00                    ; 47fd r
        .db     0x00                    ; 47fe r
        .db     0x00                    ; 47ff r
        .area   data3
  
  ; initial fuel (hi 2 digits)
-@@ -7063,7 +7722,8 @@
+@@ -7105,7 +7764,8 @@
        .db     0x00                    ; 4e2d r
        .db     0x00                    ; 4e2e r
        .db     0x00                    ; 4e2f r
        .db     0x00                    ; 4e31 r
        .db     0x00                    ; 4e32 r
        .db     0x00                    ; 4e33 r
-@@ -9633,9 +10293,19 @@
+@@ -9675,9 +10335,19 @@
        .dw     0x0000                  ; 5bba r
        .dw     bvar_9d1d               ; 5bbc r
        .dw     0x0000                  ; 5bbe r
        .db     0x5c                    ; 5c00
        .db     0x02                    ; 5c01
        .db     0x00                    ; 5c02
-@@ -22061,9 +22731,15 @@
+@@ -22103,9 +22773,15 @@
        .db     0xe0                    ; 8c05
        .db     0x83                    ; 8c06
        .db     0x9e                    ; 8c07
  bvar_8e00:
        .db     0x30                    ; 8e00 r
        .db     0x0f                    ; 8e01
-@@ -26634,6 +27310,14 @@
+@@ -26676,6 +27352,14 @@
        .db     0x7c                    ; 9dea
        .db     0x98                    ; 9deb
        .db     0x00                    ; 9dec
index 146bbbc..ee0e835 100644 (file)
@@ -117,12 +117,12 @@ items
 0x00ea,0x0001,collision_specific,byte
 ; 0xff = demo mode, 0x00 = play mode
 0x00f0,0x0001,demo_mode,byte
-; 0xc0 = ctrl-c state (forces joystick control)
-; 0x80 = button pressed
-; 0x40 = ctrl-s state (unknown what this does)
-; 0x20 = pause / single step
-; 0x02 = fire by keyboard
-0x00f1,0x0001,button_state,byte
+; bit 7: enable joystick
+; bit 6: disable sound
+; bit 5: pause/single-step
+; bit 1: spacebar firing (when set, requests a simulated button press)
+; bit 0: which joystick channel to read (0=x, 1=y, toggles each time)
+0x00f1,0x0001,control_state,byte
 ; >= 0x80 = key waiting (uses lsr to clear it)
 0x00f2,0x0001,key_state,byte
 0x0200,0x0002,vec_restart,word
@@ -494,6 +494,7 @@ items
 0x1595,0x0001,objects_reinit,code
 ; maybe update object whose number is in cyclic_object
 ; then increment cyclic_object so it cycles through 0x10..0x7f
+; cf=1 return indicates it is time to check the keyboard
 0x15b2,0x0001,cyclic_update_object,code
 0x15d7,0x0001,update_object_player,code
 0x15ee,0x0001,update_object,code
@@ -507,10 +508,40 @@ items
 0x1708,0x0001,init_game,code,,10000 # suppress local for patch
 0x1719,0x0001,start_game_demo,code
 0x171b,0x0001,start_game,code,,10000 # suppress local for patch
+; in the below, 0$ is outer game loop, 4$ is inner game loop
+; 0$: cancel previous keyboard input
+; 1$: if new keyboard input is present:
+;   move incoming key to key_state (high bit set = key present)
+;   strobe keyboard interface to clear it
+;   check for control characters, may restart game via vec_start_game
+; 2$: if in demo mode:
+;   call test_start_game, may start game via vec_start_game
+; 3$: if in single-step mode:
+;   if no key present, return to 1$
+; 4$: if sound enabled:
+;   make "update_sound_count" repeated calls to cyclic_update_sound
+; 6$: make "update_object_count" repeated calls to cyclic_update_object
+;   (this handles all of the in-game display updating as a side effect)
+;   if any of these calls return cf=1, abort the loop and return to 0$
+;   otherwise, upon completion of the loop, return to 4$
 0x1750,0x0001,start_mission,code
-0x1797,0x0001,read_buttons,code
+; if joystick button or spacebar is pressed, start game via vec_start_game
+; clears single-step mode and sets joystick mode according to input source
+0x1797,0x0001,test_start_game,code
+; overwritten with 0x24 (bit zp) if invalid joystick input detected at startup
+0x179e,0x0001,disable_joystick0,code
+; overwritten with 0x24 (bit zp) if invalid joystick input detected at startup
+0x17a3,0x0001,disable_joystick1,code
 0x17b1,0x0001,not_demo_vector_to_start_game,code
+; ctrl-r (0x92): restart game via vec_start_game (clears single-step mode)
+; ctrl-c (0x83): toggle bit 7 of control_state (enable joystick)
+; ctrl-s (0x93): toggle bit 6 of control_state (disable sound)
+; esc (0x9b): toggle bit 5 of control_state (pause/single-step)
 0x17b6,0x0001,check_control_characters,code
+; the entry point to the executable
+; if invalid joystick input detected, permanently disable joystick
+; (but this test can be bypassed by pressing either joystick button)
+; then jumps to init_game via vec_init_game
 0x17d1,0x0001,start,code
 0x1800,0x0001,divide_a_by_y,code
 0x1829,0x0001,multiply_ya_by_accumulator,code
@@ -562,6 +593,9 @@ items
 0x1e00,0x0001,do_player_input,byte
 ; returns cf=1 if firing (random for demo mode)
 0x1e03,0x0001,test_player_fire,code
+; overwritten with 0x24 (bit zp) if invalid joystick input detected at startup
+0x1e0e,0x0001,disable_joystick2,code
+0x1e23,0x0001,spacebar_firing,code
 ; if in demo mode, generates a random player input
 ; otherwise tests the keyboard, joystick, joystick buttons
 0x1e2a,0x0001,player_input,byte
similarity index 99%
rename from star_blazer/object_defs.inc
rename to star_blazer/star_blazer_object_defs.inc
index 2f52a86..6dced2f 100644 (file)
@@ -410,13 +410,13 @@ UCODE_SOUND_EFFECT_F_EXPLOSION = 0x0f00
 
 ; the following occur by themselves (not a bitmap):
 
-; UCODE_IF_ACTIVE_SET_STATE_F0 doesn't seem to occur, use RESET_OBJECT instead?
+; 0x0000 does not occur because it would indicate the end of the microcode?
 ; 0x0400, 0x0500, 0x0600, 0x0700: synonyms for 0x0000, 0x0100, 0x0200, 0x0300
 ; byte
-UCODE_IF_ACTIVE_SET_STATE_F0 = 0x0000
 UCODE_IF_ACTIVE_SET_STATE_F1 = 0x0100
 UCODE_IF_ACTIVE_SET_STATE_F2 = 0x0200
 UCODE_IF_ACTIVE_SET_STATE_F3 = 0x0300
+UCODE_IF_ACTIVE_SET_STATE_F0 = 0x0400
 UCODE_HORIZONTAL_COLLISION_AND_ZERO = 0x0800
 UCODE_VERTICAL_COLLISION_AND_ZERO = 0x0900
 UCODE_HORIZONTAL_COLLISION = 0x0a00
diff --git a/star_blazer/uncomment.sh b/star_blazer/uncomment.sh
new file mode 100755 (executable)
index 0000000..b491806
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+# use like this:
+#   ./uncomment.sh <galaxian.asm >a
+#   ./uncomment.sh <alien_typhoon.asm >b
+#   diff --unified a b >c
+
+sed -e 's/[ \t]*;.*//; s/[0-9]\+\$/$/; s/:\t/:\n\t/' |\
+sed -e 's/^\(\t...\)\(\t[^0-9#*]\)/\1\n\t\2/; s/^\(\t...\t\*\)/\1\n\t\t/'
index e7eb9b1..b898b59 100755 (executable)
@@ -385,6 +385,7 @@ def add_item(
   # code items should only ever be the opcode
   # if more than 1 byte then something has gone wrong
   # the stack trace lets us see what was being disassembled
+  #print('xxx', hex(addr))
   assert info.size == 1 or info.type < ITEM_CODE
 
   # if the combined item is different, replace/insert it