--- /dev/null
+--- 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
+
areas
-0x0000,0x00f3,zpage,uninit
+0x0000,0x00f4,zpage,uninit
0x0200,0x0002,data0,init
0x0400,0x03f0,udata0,uninit
0x0a00,0x0df9,text0,init
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
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
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
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
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
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
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
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
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
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
0xff,blank
objects
+0x00,spare
0x01,init_mission_1
0x02,init_mission_2
0x03,init_mission_3
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