Work out Alien Rain equivalence, this time using very rough equivalence.(sh|py)
authorNick Downing <nick@ndcode.org>
Thu, 30 Jun 2022 14:24:16 +0000 (00:24 +1000)
committerNick Downing <nick@ndcode.org>
Thu, 30 Jun 2022 14:24:16 +0000 (00:24 +1000)
galaxian/alien_rain.txt
galaxian/equivalence.py [new file with mode: 0755]
galaxian/equivalence.sh [new file with mode: 0755]
galaxian/galaxian.txt
galaxian/uncomment.sh
utils/disasm.py

index 8f9f176..88eb271 100644 (file)
@@ -1,7 +1,8 @@
 areas
 0x0000,0x0100,zpage,uninit
 0x0400,0x0280,text0,init
-0x1000,0x9580,text1,init
+0x1000,0x1000,text1,init
+0x4000,0x6580,text2,init
 
 items
 # draw_erase_x0: for drawing
@@ -44,94 +45,96 @@ items
 0x001f,0x0001,gal_bvar_001f,byte
 0x0020,0x0001,draw_x_save,byte
 # high score in 4-digit BCD
-0x0023,0x0002,high_score,byte
+0x0024,0x0002,high_score,byte
 # cleared when keyboard input occurs
 # I think it controls demo mode, 0 for play mode
-0x0025,0x0001,demo_mode,byte
+0x0026,0x0001,demo_mode,byte
 # I think this controls awarding of bonus ships
-0x0026,0x0001,score_threshold,byte
-0x0027,0x0001,gal_bvar_0027,byte
+0x0027,0x0001,score_threshold,byte
+0x0028,0x0001,gal_bvar_0027,byte
 # is it an array?
-0x0028,0x0001,gal_bvar_0028,byte
+0x0029,0x0001,gal_bvar_0028,byte
 # score in 4-digit BCD
-0x0029,0x0002,score,byte
-0x002b,0x0001,gal_bvar_002b,byte
-0x002c,0x0001,gal_bvar_002c,byte
-0x002d,0x0001,gal_bvar_002d,byte
-0x002e,0x0001,gal_barr_002e,byte
-0x0036,0x0001,starfield_count,byte
+0x002a,0x0002,score,byte
+0x002c,0x0001,gal_bvar_002b,byte
+0x002d,0x0001,gal_bvar_002c,byte
+0x002e,0x0001,gal_bvar_002d,byte
+0x002f,0x0001,gal_barr_002e,byte
+0x0037,0x0001,starfield_count,byte
 # sizes have not been looked at yet
-0x0037,0x0001,gal_barr_0037,byte
-0x003f,0x0001,gal_barr_003f,byte
-0x0047,0x0001,gal_barr_0047,byte
-0x004f,0x0001,gal_barr_004f,byte
-0x0057,0x0001,gal_barr_0057,byte
-0x005f,0x0001,gal_bvar_005f,byte
+0x0038,0x0001,gal_barr_0037,byte
+0x0040,0x0001,gal_barr_003f,byte
+0x0048,0x0001,gal_barr_0047,byte
+0x0050,0x0001,gal_barr_004f,byte
+0x0058,0x0001,gal_barr_0057,byte
+0x0060,0x0001,gal_bvar_005f,byte
 # used by AI routine in demo mode
 # might be simulated paddle reading (17..f3)
-0x0060,0x0001,simulated_paddle,byte
-0x0061,0x0001,gal_bvar_0061,byte
-0x0062,0x0001,gal_bvar_0062,byte
-0x0063,0x0001,gal_bvar_0063,byte
+0x0061,0x0001,simulated_paddle,byte
+0x0062,0x0001,gal_bvar_0061,byte
+0x0063,0x0001,gal_bvar_0062,byte
+0x0064,0x0001,gal_bvar_0063,byte
 # something to do with ship collision test
-0x0064,0x0001,ship_collision_test_0064,byte
-0x0067,0x0001,ship_x,byte
-0x0068,0x0001,gal_bvar_0068,byte
+0x0065,0x0001,ship_collision_test_0064,byte
+0x0068,0x0001,ship_x,byte
+0x0069,0x0001,gal_bvar_0068,byte
 # ships in 2-digit BCD
-0x0069,0x0001,ships,byte
-0x006a,0x0001,active_aliens,byte
-0x006b,0x0001,gal_bvar_006b,byte
-0x006c,0x0001,gal_bvar_006c,byte
+0x006a,0x0001,ships,byte
+0x006b,0x0001,active_aliens,byte
+0x006c,0x0001,gal_bvar_006b,byte
+0x006d,0x0001,gal_bvar_006c,byte
 # something to do with ship collision test
-0x006d,0x0001,ship_active,byte
-0x006e,0x0001,gal_bvar_006e,byte
-0x006f,0x0001,gal_bvar_006f,byte
+0x006e,0x0001,ship_active,byte
+0x006f,0x0001,gal_bvar_006e,byte
+0x0070,0x0001,gal_bvar_006f,byte
+0x0072,0x0001,gal_bvar_0070,byte
 # gets set to value of bvar_48a0 when win awarded
 # does it cause a new phalanx of aliens to appear?
-0x0071,0x0001,new_level_flag,byte
+0x0073,0x0001,new_level_flag,byte
 # wins in 2-digit BCD
-0x0072,0x0001,wins,byte
+0x0074,0x0001,wins,byte
 # bit 7 set when formation exceeds its bounds
-0x0073,0x0001,fire_shell_flag,byte
+0x0075,0x0001,fire_shell_flag,byte
 # value of (x, y) which is outside formation bounds
 # probably used to determine new direction of movement
-0x0074,0x0001,formation_outside_x,byte
-0x0075,0x0001,formation_outside_y,byte
-0x0076,0x0001,gal_bvar_0076,byte
-0x0078,0x0001,gal_bvar_0078,byte
-0x0079,0x0001,gal_bvar_0079,byte
-0x007a,0x0001,gal_bvar_007a,byte
-0x007b,0x0001,gal_bvar_007b,byte
-0x007c,0x0001,gal_bvar_007c,byte
+0x0076,0x0001,formation_outside_x,byte
+0x0077,0x0001,formation_outside_y,byte
+0x0078,0x0001,gal_bvar_0076,byte
+0x007a,0x0001,gal_bvar_0078,byte
+0x007b,0x0001,gal_bvar_0079,byte
+0x007c,0x0001,gal_bvar_007a,byte
+0x007d,0x0001,gal_bvar_007b,byte
+0x007e,0x0001,gal_bvar_007c,byte
 # set to monotonic_492e[difficulty_level]
 # sometimes incremented when processing an alien,
 # this depends on monotonic_491e[difficulty_level]
-0x007d,0x0001,gal_bvar_007d,byte
+0x007f,0x0001,gal_bvar_007d,byte
 # it increments up to a maximum of 0x0f
 # is it to do with the formation shape or difficulty level?
-0x007e,0x0001,difficulty_level,byte
-0x007f,0x0001,gal_bvar_007f,byte
-0x0080,0x0001,gal_bvar_0080,byte
+0x0080,0x0001,difficulty_level,byte
+0x0081,0x0001,gal_bvar_007f,byte
+0x0082,0x0001,gal_bvar_0080,byte
 # shell will only fire if low 2 bits = 0
 # it is then incremented, to fire every 4 cycles?
-0x0081,0x0001,fire_shell_count,byte
+0x0083,0x0001,fire_shell_count,byte
+0x0084,0x0001,gal_bvar_0082,byte
 # used in vector_alien_to_ship
-0x0083,0x0001,half_alien_x,byte
-0x0084,0x0001,half_alien_y,byte
-0x0085,0x0001,gal_bvar_0085,byte
+0x0085,0x0001,half_alien_x,byte
+0x0086,0x0001,half_alien_y,byte
+0x0087,0x0001,gal_bvar_0085,byte
 # stores bounding rectangle
 # object_(xy)(01): for alien
 # object_(xy)(01) + 1: for ship
-0x0086,0x0002,object_y0,byte
-0x0088,0x0002,object_y1,byte
-0x008a,0x0002,object_x0,byte
-0x008c,0x0002,object_x1,byte
-0x008e,0x0001,gal_bvar_008e,byte
+0x0088,0x0002,object_y0,byte
+0x008a,0x0002,object_y1,byte
+0x008c,0x0002,object_x0,byte
+0x008e,0x0002,object_x1,byte
+0x0090,0x0001,gal_bvar_008e,byte
 # saves x reg during calculation
-0x0091,0x0001,score_x_save,byte
+0x0093,0x0001,score_x_save,byte
 # something to do with ship collision test
-0x0092,0x0001,ship_collision_test_0092,byte
-0x0093,0x0001,gal_bvar_0093,byte
+0x0094,0x0001,ship_collision_test_0092,byte
+0x0095,0x0001,gal_bvar_0093,byte
 # sizes have not been examined yet
 0x00a9,0x0001,gal_barr_00a9,byte
 0x00b1,0x0008,shell_active,byte
@@ -139,6 +142,10 @@ items
 # there seem to be aliens 0x01 (maybe 0x00) to 0x12
 # or maybe entry 0 is used for currently processing alien
 0x00c0,0x0040,alien_status,byte
+0x0420,0x0080,misc_shape_data_ptr_lo,byte
+0x04a0,0x0080,misc_shape_data_ptr_hi,byte
+0x0520,0x0080,misc_shape_width_bytes,byte
+0x05a0,0x0080,misc_shape_height,byte
 0x2000,0x0028,VIDEO_LINE_00,byte
 0x2028,0x0028,VIDEO_LINE_40,byte
 0x2050,0x0028,VIDEO_LINE_80,byte
@@ -331,206 +338,205 @@ items
 0x3f80,0x0028,VIDEO_LINE_3F,byte
 0x3fa8,0x0028,VIDEO_LINE_7F,byte
 0x3fd0,0x0028,VIDEO_LINE_BF,byte
-#0x4854,0x0001,wins_y,byte
-#0x4856,0x0001,wins_x,byte
-#0x4858,0x0001,ships_y,byte
-#0x485a,0x0001,ships_x,byte
-#0x485c,0x0001,high_score_y,byte
-#0x485e,0x0001,high_score_x,byte
-#0x4860,0x0001,score_y,byte
-#0x4862,0x0001,score_x,byte
-#0x4864,0x0001,formation_centre_y,byte
-#0x4866,0x0001,formation_centre_x,byte
-#0x4868,0x0001,alien_orientation_init,byte
-#0x486a,0x0001,formation_y_init,byte
-#0x486c,0x0001,formation_x_init,byte
-#0x486e,0x0001,shell_y_velocity,byte
-#0x4870,0x0001,shell_x_velocity_fraction,byte
-#0x4872,0x0001,missile_y_velocity,byte
-#0x4876,0x0001,ship_y,byte
-## at initialization:
-## gal_bvar_0078 = val_bvar_4880
-## gal_bvar_0079 = -val_bvar_4880
-#0x4880,0x0001,gal_bvar_4880,byte
-## at initalization:
-## gal_bvar_007f = 0xff shifted right until < gal_bvar_4882
-#0x4882,0x0001,gal_bvar_4882,byte
-#0x4884,0x0001,gal_bvar_4884,byte
-#0x4886,0x0001,high_score_init,byte
-## not quite sure what this does, see read_paddle routine
-#0x4888,0x0001,ship_x_threshold,byte
-#0x488a,0x0001,gal_bvar_488a,byte
-#0x488c,0x0001,gal_bvar_488c,byte
-#0x488e,0x0001,gal_bvar_488e,byte
-#0x4890,0x0001,ship_x_max,byte
-#0x4892,0x0001,ship_x_min,byte
-#0x4894,0x0001,gal_bvar_4894,byte
-#0x489a,0x0001,gal_bvar_489a,byte
-## something to do with ship collision test
-#0x489c,0x0001,ship_collision_test_threshold,byte
-#0x489e,0x0001,gal_bvar_006c_init,byte
-#0x48a0,0x0001,gal_bvar_48a0,byte
-#0x48a2,0x0001,gal_bvar_48a2,byte
-## ships won't be redrawn if they exceed this
-#0x48a4,0x0001,max_displayed_ships,byte
-#0x48aa,0x0001,starfield_count_init,byte
-#0x48ac,0x0001,gal_bvar_48ac,byte
-#0x48ae,0x0001,active_aliens_init,byte
-#0x48b0,0x0001,gal_bvar_48b0,byte
-## used for clearing the screen in the beginning
-## seems to be x0, x1, y0, y1
-## it will be offset by the centre values x = 0x6c, y = 0x20
-#0x48b2,0x0004,screen_size,byte
-#0x48b6,0x0001,shell_bounds_x0,byte
-#0x48b7,0x0001,shell_bounds_x1,byte
-#0x48b8,0x0001,shell_bounds_y0,byte
-#0x48b9,0x0001,shell_bounds_y1,byte
-#0x48ba,0x0001,missile_bounds_x0,byte
-#0x48bb,0x0001,missile_bounds_x1,byte
-#0x48bc,0x0001,missile_bounds_y0,byte
-#0x48bd,0x0001,missile_bounds_y1,byte
-## formation inner bounds?
-## used to determine if alien should be moved in formation
-#0x48c2,0x0001,formation_inner_x0,byte
-#0x48c3,0x0001,formation_inner_x1,byte
-#0x48c4,0x0001,formation_inner_y0,byte
-#0x48c5,0x0001,formation_inner_y1,byte
-## formation outer bounds?
-## used to determine if formation should change direction?
-#0x48c6,0x0001,formation_outer_x0,byte
-#0x48c7,0x0001,formation_outer_x1,byte
-#0x48c8,0x0001,formation_outer_y0,byte
-#0x48c9,0x0001,formation_outer_y1,byte
-## added to score, presumably when alien is destroyed
+0x473e,0x0001,wins_y,byte
+0x4740,0x0001,wins_x,byte
+0x4742,0x0001,ships_y,byte
+0x4744,0x0001,ships_x,byte
+0x4746,0x0001,high_score_y,byte
+0x4748,0x0001,high_score_x,byte
+0x474a,0x0001,score_y,byte
+0x474c,0x0001,score_x,byte
+0x474e,0x0001,formation_centre_y,byte
+0x4750,0x0001,formation_centre_x,byte
+0x4752,0x0001,alien_orientation_init,byte
+0x4754,0x0001,formation_y_init,byte
+0x4756,0x0001,formation_x_init,byte
+0x4758,0x0001,shell_y_velocity,byte
+0x475a,0x0001,shell_x_velocity_fraction,byte
+0x475c,0x0001,missile_y_velocity,byte
+0x4760,0x0001,ship_y,byte
+# at initialization:
+# gal_bvar_0078 = val_bvar_4880
+# gal_bvar_0079 = -val_bvar_4880
+0x476a,0x0001,gal_bvar_4880,byte
+# at initalization:
+# gal_bvar_007f = 0xff shifted right until < gal_bvar_4882
+0x476c,0x0001,gal_bvar_4882,byte
+0x476e,0x0001,gal_bvar_4884,byte
+0x4770,0x0001,high_score_init,byte
+# not quite sure what this does, see read_paddle routine
+0x4772,0x0001,ship_x_threshold,byte
+0x4774,0x0001,gal_bvar_488a,byte
+0x4776,0x0001,gal_bvar_488c,byte
+0x4778,0x0001,gal_bvar_488e,byte
+0x477a,0x0001,ship_x_max,byte
+0x477c,0x0001,ship_x_min,byte
+0x477e,0x0001,gal_bvar_4894,byte
+0x4784,0x0001,gal_bvar_489a,byte
+# something to do with ship collision test
+0x4786,0x0001,ship_collision_test_threshold,byte
+0x4788,0x0001,gal_bvar_006c_init,byte
+0x478a,0x0001,gal_bvar_48a0,byte
+0x478c,0x0001,gal_bvar_48a2,byte
+# ships won't be redrawn if they exceed this
+0x478e,0x0001,max_displayed_ships,byte
+0x4794,0x0001,starfield_count_init,byte
+0x4796,0x0001,gal_bvar_48ac,byte
+0x4798,0x0001,active_aliens_init,byte
+0x479a,0x0001,gal_bvar_48b0,byte
+# used for clearing the screen in the beginning
+# seems to be x0, x1, y0, y1
+# it will be offset by the centre values x = 0x6c, y = 0x20
+0x479c,0x0004,screen_size,byte
+0x47a0,0x0001,shell_bounds_x0,byte
+0x47a1,0x0001,shell_bounds_x1,byte
+0x47a2,0x0001,shell_bounds_y0,byte
+0x47a3,0x0001,shell_bounds_y1,byte
+0x47a4,0x0001,missile_bounds_x0,byte
+0x47a5,0x0001,missile_bounds_x1,byte
+0x47a6,0x0001,missile_bounds_y0,byte
+0x47a7,0x0001,missile_bounds_y1,byte
+0x47a8,0x0001,gal_bvar_48be,byte
+0x47a9,0x0001,gal_bvar_48bf,byte
+# formation inner bounds?
+# used to determine if alien should be moved in formation
+0x47ac,0x0001,formation_inner_x0,byte
+0x47ad,0x0001,formation_inner_x1,byte
+0x47ae,0x0001,formation_inner_y0,byte
+0x47af,0x0001,formation_inner_y1,byte
+# formation outer bounds?
+# used to determine if formation should change direction?
+0x47b0,0x0001,formation_outer_x0,byte
+0x47b1,0x0001,formation_outer_x1,byte
+0x47b2,0x0001,formation_outer_y0,byte
+0x47b3,0x0001,formation_outer_y1,byte
+# added to score, presumably when alien is destroyed
 #0x48ca,0x0004,points_table,byte
-## sizes have not been examined yet
-#0x48ce,0x0001,gal_barr_48ce,byte
-#0x48de,0x0010,title_display_delay,byte
-#0x48ee,0x0010,title_display_y,byte
-#0x48fe,0x0010,title_display_x,byte
-## mysterious monotonic sequences
-## testing active_aliens >= monotonic_490e[difficulty_level]
-#0x490e,0x0010,monotonic_490e,byte
-#0x491e,0x0010,monotonic_491e,byte
-#0x492e,0x0010,monotonic_492e,byte
-## 0493e might be part of preceding or following table?
-## next one is filled with 0x46, 0x4d, 0x53 seemingly randomly
-## see also code at 0x9768 (main loop) -- comparing with these values
-#0x493f,0x0040,barr_493f,byte
-## then zeros... padding?
+# sizes have not been examined yet
+0x47b8,0x0001,gal_barr_48ce,byte
+0x47c8,0x0010,title_display_delay,byte
+0x47d8,0x0010,title_display_y,byte
+0x47e8,0x0010,title_display_x,byte
+# mysterious monotonic sequences
+# testing active_aliens >= monotonic_490e[difficulty_level]
+0x47f8,0x0010,monotonic_490e,byte
+0x4808,0x0010,monotonic_491e,byte
+0x4818,0x0010,monotonic_492e,byte
+# 0493e might be part of preceding or following table?
+# next one is filled with 0x46, 0x4d, 0x53 seemingly randomly
+# see also code at 0x9768 (main loop) -- comparing with these values
+0x4829,0x0040,gal_barr_493f,byte
+# then zeros... padding?
 #0x49c0,0x0040,alien_49c0,byte
-#0x4a00,0x0040,alien_4a00,byte
-#0x4a40,0x0040,alien_formation_y,byte
-#0x4a80,0x0040,alien_formation_x,byte
-#0x4ac0,0x0040,alien_4ac0,byte
-#0x4b00,0x0040,alien_4b00,byte
-#0x4b40,0x0040,alien_4b41,byte
-#0x4b80,0x0040,alien_4b81,byte
-## I think this is used when the alien is diving
-## the basic shape, it gets adjusted for orientation
-#0x4c00,0x0040,alien_shape_4c00,byte
-## these seem to be 8 bytes apart, maybe for shells?
-#0x4c40,0x0001,gal_barr_4c40,byte
-#0x4c48,0x0001,gal_barr_4c48,byte
-#0x4c50,0x0001,gal_barr_4c50,byte
-#0x4c58,0x0001,gal_barr_4c58,byte
-#0x4c60,0x0001,gal_barr_4c60,byte
-#0x4c68,0x0001,gal_barr_4c68,byte
-#0x4c70,0x0001,gal_barr_4c70,byte
-#0x4c78,0x0001,gal_barr_4c78,byte
-## identity[x] = x, used for ship x position
-## seems to be needed because the ship_x value is from paddle
-## therefore the table could be used to calibrate the paddle
-#0x4c80,0x0100,identity,byte
-#0x4d81,0x0001,gal_barr_4d81,byte
-## size of 0x400 as there are 4 different alien kinds
-## each has its own page of values for the alien shape
-## I think there might be separate tables for head and foot
-## all values 0..2, added to shape to select orientation
-#0x4e80,0x0400,ptr_9ef1_table,byte
-## all values -4..6, ???
-#0x5280,0x0400,ptr_9f18_table,byte
-## all values -0x28..0x28, ???
-#0x5680,0x0400,ptr_9efe_table,byte
-#0x5a80,0x1800,shape_data,byte
-#0x7280,0x0380,shape_data_ptr_lo,byte
-#0x7600,0x0380,shape_data_ptr_hi,byte
-#0x7980,0x0380,shape_width_bytes,byte
-#0x7d80,0x0080,shape_height,byte
-#0x7e80,0x0c00,misc_shape_data,byte
-#0x8a80,0x0080,misc_shape_data_ptr_lo,byte
-#0x8b00,0x0080,misc_shape_data_ptr_hi,byte
-#0x8b80,0x0080,misc_shape_width_bytes,byte
-#0x8c00,0x0080,misc_shape_height,byte
-#0x8c81,0x0028,star_x,byte
-## sizes have not been examined yet
-#0x8ce1,0x0001,gal_barr_8ce1,byte
-#0x8cf1,0x0008,shell_y,byte
-#0x8d01,0x0008,shell_x_velocity,byte
-#0x8d11,0x0008,shell_x,byte
-#0x8d21,0x0008,shell_x_fraction,byte
-#0x8d31,0x0028,star_y,byte
-## sizes have not been examined yet
-#0x8d91,0x0001,gal_barr_8d91,byte
-#0x8df1,0x0028,star_shape_left,byte
-#0x8e51,0x0028,star_shape_right,byte
-#0x8eb1,0x0028,star_y_velocity,byte
-## sizes have not been examined yet
-#0x8f11,0x0001,gal_barr_8f11,byte
-#0x8f71,0x0001,missile_y,byte
-#0x8f79,0x0028,move_starfield_table,byte
-## sizes have not been examined yet
-#0x8fd9,0x0001,gal_barr_8fd9,byte
-#0x8fe1,0x0001,missile_x,byte
-## a value 0x00..0xff which I think is the angle
-## it is applied to one of the ptr_9ef1_table pages
-#0x8fe8,0x0040,alien_orientation,byte
-## 0th entry is used to hold the y value of the formation
-#0x9028,0x0040,alien_y,byte
-#0x9068,0x0040,alien_9068,byte
-## 0th entry is used to hold the x value of the formation
-#0x90a8,0x0040,alien_x,byte
-#0x90e8,0x0040,alien_90e8,byte
-## I think this gets used when the alien is in formation
-## it will be transformed in several ways to animate a foot
+0x48ea,0x0040,alien_4a00,byte
+0x492a,0x0040,alien_formation_y,byte
+0x496a,0x0040,alien_formation_x,byte
+0x49aa,0x0040,alien_4ac0,byte
+0x49ea,0x0040,alien_4b00,byte
+0x4a2a,0x0040,alien_4b41,byte
+0x4a6a,0x0040,alien_4b81,byte
+# I think this is used when the alien is diving
+# the basic shape, it gets adjusted for orientation
+0x4aea,0x0040,alien_shape_4c00,byte
+# these seem to be 8 bytes apart, maybe for shells?
+0x4b2a,0x0001,gal_barr_4c40,byte
+0x4b32,0x0001,gal_barr_4c48,byte
+0x4b3a,0x0001,gal_barr_4c50,byte
+0x4b42,0x0001,gal_barr_4c58,byte
+0x4b4a,0x0001,gal_barr_4c60,byte
+0x4b52,0x0001,gal_barr_4c68,byte
+0x4b5a,0x0001,gal_barr_4c70,byte
+0x4b62,0x0001,gal_barr_4c78,byte
+# identity[x] = x, used for ship x position
+# seems to be needed because the ship_x value is from paddle
+# therefore the table could be used to calibrate the paddle
+0x4b6a,0x0100,identity,byte
+0x4c6b,0x0001,gal_barr_4d81,byte
+# size of 0x400 as there are 4 different alien kinds
+# each has its own page of values for the alien shape
+# I think there might be separate tables for head and foot
+# all values 0..2, added to shape to select orientation
+0x4d6a,0x0400,ptr_9ef1_table,byte
+# all values -4..6, ???
+0x516a,0x0400,ptr_9f18_table,byte
+# all values -0x28..0x28, ???
+0x556a,0x0400,ptr_9efe_table,byte
+0x596a,0x1800,shape_data,byte
+0x716a,0x0380,shape_data_ptr_lo,byte
+0x74ea,0x0380,shape_data_ptr_hi,byte
+0x786a,0x0380,shape_width_bytes,byte
+0x7c6a,0x0080,shape_height,byte
+0x7d6a,0x0c00,misc_shape_data,byte
+0x8b6b,0x0028,star_x,byte
+# sizes have not been examined yet
+0x8dd1,0x0001,gal_barr_8ce1,byte
+0x8de1,0x0008,shell_y,byte
+0x8df1,0x0008,shell_x_velocity,byte
+0x8e01,0x0008,shell_x,byte
+0x8e11,0x0008,shell_x_fraction,byte
+0x8e21,0x0028,star_y,byte
+# sizes have not been examined yet
+0x8e81,0x0001,gal_barr_8d91,byte
+0x8ee1,0x0028,star_shape_left,byte
+0x8f41,0x0028,star_shape_right,byte
+0x8fa1,0x0028,star_y_velocity,byte
+# sizes have not been examined yet
+0x9001,0x0001,gal_barr_8f11,byte
+0x9061,0x0001,missile_y,byte
+0x9069,0x0028,move_starfield_table,byte
+# sizes have not been examined yet
+0x90c9,0x0001,gal_barr_8fd9,byte
+0x90d1,0x0001,missile_x,byte
+# a value 0x00..0xff which I think is the angle
+# it is applied to one of the ptr_9ef1_table pages
+0x90d8,0x0040,alien_orientation,byte
+# 0th entry is used to hold the y value of the formation
+0x9118,0x0040,alien_y,byte
+0x9158,0x0040,alien_9068,byte
+# 0th entry is used to hold the x value of the formation
+0x9198,0x0040,alien_x,byte
+0x91d8,0x0040,alien_90e8,byte
+# I think this gets used when the alien is in formation
+# it will be transformed in several ways to animate a foot
 #0x9128,0x0040,alien_shape_9128,byte
-## value from here selects a series of page-sized lookup tables
-## ptr_9ef1 <- ptr_9ef1_base + alien_kind[alien] * 0x100
-## ptr_9efe <- ptr_9efe_base + alien_kind[alien] * 0x100
-## ptr_9f18 <- ptr_9f18_base + alien_kind[alien] * 0x100
-#0x9168,0x0040,alien_kind,byte
-#0x91a8,0x0040,alien_91a8,byte
-## seems to be a counter, low 2 bits used to animate the foot
-## also gets compared against gal_bvar_488e, some kind of threshold?
-#0x91e8,0x0040,alien_animate,byte
-## flag which is nonzero to draw a foot? or does it have other uses?
-#0x9228,0x0040,alien_9228,byte
-#0x932b,0x0001,gal_sub_932b,code
-#0x937c,0x0001,init_bvar_0019,byte
-## copies a large number of variables from one set to another
-## also does some +3 and +variable, is it computing bounds?
-#0x9383,0x0001,copy_variables,code
-## see screen_size
-#0x93a4,0x0004,screen_offset,byte
-## initialize clip_rect, clear screen, set hires
-#0x93a8,0x0001,video_init,code
+# value from here selects a series of page-sized lookup tables
+# ptr_9ef1 <- ptr_9ef1_base + alien_kind[alien] * 0x100
+# ptr_9efe <- ptr_9efe_base + alien_kind[alien] * 0x100
+# ptr_9f18 <- ptr_9f18_base + alien_kind[alien] * 0x100
+0x9258,0x0040,alien_kind,byte
+0x9298,0x0040,alien_91a8,byte
+# seems to be a counter, low 2 bits used to animate the foot
+# also gets compared against gal_bvar_488e, some kind of threshold?
+0x92d8,0x0040,alien_animate,byte
+# flag which is nonzero to draw a foot? or does it have other uses?
+0x9318,0x0040,alien_9228,byte
+0x936f,0x0001,gal_sub_932b,code
+0x93b6,0x0001,gal_sub_9372,code
+0x93c0,0x0001,init_bvar_0019,byte
+# copies a large number of variables from one set to another
+# also does some +3 and +variable, is it computing bounds?
+0x93c7,0x0001,copy_variables,code
+# see screen_size
+0x93e8,0x0004,screen_offset,byte
+# initialize clip_rect, clear screen, set hires
+0x93ec,0x0001,video_init,code
 #0x93be,0x0001,,code_ign # self-modifying code assembled with garbage word
 #0x93bf,0x0002,,word
-## clears rectangle described by clip_rect
-#0x93d4,0x0001,video_clear_rect,code
+# clears rectangle described by clip_rect
+0x9418,0x0001,video_clear_rect,code
 0x941a,0x0001,,code_ign # accessing video_line_table before clipping y
 0x9422,0x0001,,code_ign # accessing video_line_table before clipping y
-## returns a = quotient, y = remainder, cf = 0
-#0x93f6,0x0001,div_a_by_7,code
-## the value from shape_data_ptr_lo/hi is relative to this value
-#0x9414,0x0002,shape_data_ptr_base,word,byte
-#0x9416,0x0007,x2_mod7_table,byte
-#0x941d,0x0007,x2_div7_table,byte
-## these contain the pointer for shift count 0, shape 0
-## the byte accessed will be base + shift count * 0x80 + shape
-#0x9424,0x0002,shape_data_ptr_lo_base,word,byte
-#0x9426,0x0002,shape_data_ptr_hi_base,word,byte
-#0x9428,0x0002,shape_width_bytes_base,word,byte
+# returns a = quotient, y = remainder, cf = 0
+0x943a,0x0001,div_a_by_7,code
+# the value from shape_data_ptr_lo/hi is relative to this value
+0x9458,0x0002,shape_data_ptr_base,word,byte
+0x945a,0x0007,x2_mod7_table,byte
+0x9461,0x0007,x2_div7_table,byte
+# these contain the pointer for shift count 0, shape 0
+# the byte accessed will be base + shift count * 0x80 + shape
+0x9468,0x0002,shape_data_ptr_lo_base,word,byte
+0x946a,0x0002,shape_data_ptr_hi_base,word,byte
+0x946c,0x0002,shape_width_bytes_base,word,byte
 # takes x = 0 draw, x = 1 erase
 # reads draw_erase_(x0|y0|shape)
 # sets up draw_(x0|x1|y0|y1)
@@ -565,154 +571,156 @@ items
 0x95bb,0x00c0,video_line_table_lo,byte,byte,10000
 0x967b,0x00c0,video_line_table_hi,byte,byte,10000
 0x9788,0x0001,start,code
-#0x9751,0x0001,process_all,code
-## initializes zpage, and probably other init, and draws something
-#0x9780,0x0001,zpage_init,code
-#0x9784,0x0001,,code_ign # zeroing zpage, don't merge cleared variables
+# initializes zpage, and probably other init, and draws something
+0x981a,0x0001,zpage_init,code
+0x981e,0x0001,,code_ign # zeroing zpage, don't merge cleared variables
+# is this unreachable now?
 #0x979f,0x0001,gal_sub_979f,code
-#0x97be,0x0001,gal_sub_97be,code
-#0x97c5,0x0001,gal_sub_97c5,code
-#0x97fc,0x0001,gal_sub_97fc,code
-#0x980b,0x0001,gal_loc_980b,code
-#0x9815,0x0001,gal_rts_9815,code
-#0x9816,0x0001,gal_sub_9816,code
-#0x9820,0x0001,gal_loc_9820,code_ign # garbage word
-#0x9821,0x0002,gal_ptr_9821,word
-## sizes have not been exained yet
-#0x982e,0x0001,gal_barr_982e,byte
-#0x9836,0x0001,gal_barr_9836,byte
-## used for colouring the starfield
-#0x983e,0x0001,star_mask_table_left,byte
-#0x9842,0x0001,star_mask_table_right,byte
-## called when star goes off screen at y = 0xe0
-## randomize the x position for restart at y = 0x20
-#0x9846,0x0001,regenerate_star,byte
-#0x9859,0x0001,gal_sub_9859,code
-#0x989e,0x0001,move_starfield,code
-#0x98e0,0x0001,,code_ign # accessing video_line_table before clipping y
-#0x98e5,0x0001,,code_ign # accessing video_line_table before clipping y
-#0x990a,0x0001,,code_ign # accessing video_line_table before clipping y
-#0x990f,0x0001,,code_ign # accessing video_line_table before clipping y
-#0x9934,0x0001,gal_sub_9934,code
-#0x9960,0x0001,gal_sub_9960,code
-## if in demo mode, goes to an AI routine at 0x99bf
-#0x99aa,0x0001,read_paddle,code
-#0x99da,0x0001,process_ship,code
-#0x9a5d,0x0001,init_missile,code
-#0x9a6a,0x0001,process_missile,code
-#0x9a99,0x0001,process_ship_fire,code
-## lookup tables for determining alien shape
-## their size is 0x100 * number of possible alien_kind values
-#0x9ad7,0x0002,ptr_9ef1_base,word,byte
-#0x9ad9,0x0002,ptr_9efe_base,word,byte
-#0x9adb,0x0002,ptr_9f18_base,word,byte
-#0x9add,0x0001,init_game,code
-## 0x9b2b is nop, I think it should be "beq activate_aliens"
-#0x9b2d,0x0001,maybe_activate_aliens,code
-#0x9b34,0x0001,activate_aliens,code
-#0x9b93,0x0001,zero_bvar_006b_bvar_0076_bvar_0080_fire_shell_flag,code
-#0x9b9e,0x0001,check_formation_bounds,code
-#0x9bdc,0x0001,move_alien_in_formation,code
-#0x9bfe,0x0001,init_alien,code
-#0x9c10,0x0001,copy_alien,code
-## only if ship is active
-## then stores something in alien_9068
-#0x9c6b,0x0001,maybe_vector_alien_to_ship,code
-#0x9c85,0x0001,gal_sub_9c85,code
-#0x9ca1,0x0001,gal_sub_9ca1,code
-## this is probably called when we start to process a certain alien
-## it sets lookup tables that are used for animating the shape and other things
-#0x9cb1,0x0001,setup_alien_kind,code
-#0x9ccb,0x0001,gal_sub_9ccb,code
-## stores gal_bvar_0076 in alien_9068 for all aliens and the 0th entry
-#0x9d88,0x0001,set_all_alien_9068,code
-## moves the alien depending on its status and then does other processing
-#0x9d9e,0x0001,process_alien,code
-#0x9e14,0x0001,inactivate_shell,code
-## enter with x = shell index
-## maybe fire the given shell, then move it and other processing
-#0x9e28,0x0001,process_shell,code
-#0x9e61,0x0001,maybe_fire_shell,code
-## shell has a slight x velocity towards player
-## enter with a = x component of vector from alien to ship
-## makes it positive, processes it, reapplies the sign
-#0x9ea6,0x0001,calculate_shell_velocity_x,code
-## enter with a, y = alien_x / 2, alien_y / 2
-## returns a, y = signed vector from alien to ship
-#0x9ecb,0x0001,vector_alien_to_ship,code
-## enter with y = x coordinate
-## lets a = x via identity transformation, gets y
-#0x9ee5,0x0001,get_ship_top_centre,code
-## it calculates the shape from alien_orientation
-#0x9eec,0x0001,get_alien_shape,code
-#0x9ef1,0x0002,gal_ptr_9ef1,word
-## something to do with the alien orientation
-#0x9ef7,0x0001,physics_9ef7,code
-#0x9efe,0x0002,gal_ptr_9efe,word
-#0x9f18,0x0001,gal_ptr_9f18,word
-## something to do with the alien orientation
-## is it moving it based on cos(angle) and sin(angle)?
-#0x9f22,0x0001,physics_9f22,code
-#0x9f5b,0x0001,move_shell_by_velocity,code
-#0x9f7d,0x0001,move_missile_by_velocity,code
-#0x9f88,0x0001,move_alien_shape_9f88,code
-#0x9fcf,0x0001,move_missile,code
-#0xa018,0x0001,move_shell,code
-## set up object0 as a shell or an alien first
-## returns whether collision occurred (in zf and a)
-#0xa061,0x0001,ship_collision_test,code
-#0xa098,0x0001,maybe_award_points,code
-## calculates object_(xy)(01)[object]
-## object 0 is alien, object 1 is ship
-## enter with a = centre x, y = top y, score_temp = 1/2 width (height is 7)
-#0xa0d3,0x0001,calculate_bounds0,code
-#0xa0d9,0x0001,calculate_bounds1,code
-#0xa0dd,0x0001,calculate_bounds_entry,code
-#0xa0f4,0x0001,collision_test,code
-#0xa10d,0x0001,move_ship,code
-#0xa12e,0x0001,move_ship_entry0,code
-#0xa147,0x0001,move_ship_entry1,code
-## returns a = ship_x (via identity transformation) - 4, y = ship_y
-#0xa156,0x0001,get_ship_top_left,code
-#0xa15f,0x0001,get_shape_a15f,code
-#0xa166,0x0001,gal_rts_a166,code
-#0xa167,0x0001,do_erase_shape,code
-## might also be doing collision detection?
-#0xa173,0x0001,award_points,code
-## returns a = alien_x[x] - 3, y = alien_y[x]
-#0xa205,0x0001,get_alien_top_left,code
-## it can calculate a foot or an explosion shape
-## it can also return a value from a table directly
-#0xa20f,0x0001,get_alien_part_shape,code
-#0xa22d,0x0001,gal_rts_a22d,code
-#0xa22e,0x0001,move_alien_shape_a22e,code
-## called at the end of award_points routine
-#0xa255,0x0001,move_alien_shape_a22e_entry,code
-## called when an alien is killed and needs to be erased
-## decrements active_aliens, awards a win if decremented to zero
-#0xa264,0x0001,erase_shape_a264,code
-#0xa281,0x0001,erase_missile,code
-#0xa2a6,0x0001,erase_shell,code
-## draws "score" followed by 4 digits followed by "0"
-## also updates high score if new score exceeds high score
-#0xa2cb,0x0001,draw_score,code
-## draws "high score" followed by 4 digits followed by "0"
-#0xa30c,0x0001,draw_high_score,code
-#0xa331,0x0001,gal_rts_a331,code
-#0xa332,0x0001,draw_ships,code
-#0xa354,0x0001,draw_wins,code
-#0xa376,0x0001,set_base_draw_digit_pair,code
-#0xa379,0x0001,draw_digit_pair,code
-#0xa385,0x0001,set_base_draw_hi_digit,code
-#0xa389,0x0001,set_base_draw_digit,code
-#0xa38c,0x0001,draw_digit,code
-#0xa390,0x0001,draw_digit_base,byte
-## a = x (saved to draw_x1), y = y (saved to draw_erase_y0)
-#0xa394,0x0001,set_cursor,byte
-## draws shapes draw_misc_50 through 5f at title_display_x, title_display_y
-#0xa399,0x0001,title_display,byte
-## does x * 0x1000 loops, can be cut short by keyboard input
-#0xa3db,0x0001,delay_x,byte
+0x988c,0x0001,gal_sub_97be,code
+0x9893,0x0001,gal_sub_97c5,code
+0x98ca,0x0001,gal_sub_97fc,code
+0x98d9,0x0001,gal_loc_980b,code
+0x98e3,0x0001,gal_rts_9815,code
+0x98e4,0x0001,gal_sub_9816,code
+0x98ee,0x0001,gal_loc_9820,code_ign # garbage word
+0x98ef,0x0002,gal_ptr_9821,word
+# sizes have not been exained yet
+0x98fc,0x0001,gal_barr_982e,byte
+0x9904,0x0001,gal_barr_9836,byte
+# used for colouring the starfield
+0x990c,0x0001,star_mask_table_left,byte
+0x9910,0x0001,star_mask_table_right,byte
+# called when star goes off screen at y = 0xe0
+# randomize the x position for restart at y = 0x20
+0x9914,0x0001,regenerate_star,byte
+0x9927,0x0001,gal_sub_9859,code
+0x996c,0x0001,move_starfield,code
+0x99ae,0x0001,,code_ign # accessing video_line_table before clipping y
+0x99b3,0x0001,,code_ign # accessing video_line_table before clipping y
+0x99d8,0x0001,,code_ign # accessing video_line_table before clipping y
+0x99dd,0x0001,,code_ign # accessing video_line_table before clipping y
+0x9a02,0x0001,gal_sub_9934,code
+0x9a2e,0x0001,gal_sub_9960,code
+# if in demo mode, goes to an AI routine at 0x99bf
+0x9a78,0x0001,read_paddle,code
+0x9acc,0x0001,process_ship,code
+0x9b4f,0x0001,init_missile,code
+0x9b5c,0x0001,process_missile,code
+0x9b8b,0x0001,process_ship_fire,code
+# lookup tables for determining alien shape
+# their size is 0x100 * number of possible alien_kind values
+0x9bcd,0x0002,ptr_9ef1_base,word,byte
+0x9bcf,0x0002,ptr_9efe_base,word,byte
+0x9bd1,0x0002,ptr_9f18_base,word,byte
+0x9bd3,0x0001,init_game,code
+# 0x9c21 is nop, I think it should be "beq activate_aliens"
+0x9c23,0x0001,maybe_activate_aliens,code
+0x9c2a,0x0001,activate_aliens,code
+0x9c89,0x0001,zero_bvar_006b_bvar_0076_bvar_0080_fire_shell_flag,code
+0x9c94,0x0001,check_formation_bounds,code
+0x9cd2,0x0001,move_alien_in_formation,code
+0x9cf4,0x0001,init_alien,code
+0x9d06,0x0001,copy_alien,code
+# only if ship is active
+# then stores something in alien_9068
+0x9d61,0x0001,maybe_vector_alien_to_ship,code
+0x9d7b,0x0001,gal_sub_9c85,code
+0x9d97,0x0001,gal_sub_9ca1,code
+# this is probably called when we start to process a certain alien
+# it sets lookup tables that are used for animating the shape and other things
+0x9da7,0x0001,setup_alien_kind,code
+0x9dc1,0x0001,gal_sub_9ccb,code
+0x9e3d,0x0001,gal_sub_9d4a,code
+# stores gal_bvar_0076 in alien_9068 for all aliens and the 0th entry
+0x9e7b,0x0001,set_all_alien_9068,code
+# moves the alien depending on its status and then does other processing
+0x9e91,0x0001,process_alien,code
+0x9f18,0x0001,inactivate_shell,code
+# enter with x = shell index
+# maybe fire the given shell, then move it and other processing
+0x9f2c,0x0001,process_shell,code
+0x9f65,0x0001,maybe_fire_shell,code
+# shell has a slight x velocity towards player
+# enter with a = x component of vector from alien to ship
+# makes it positive, processes it, reapplies the sign
+0x9faa,0x0001,calculate_shell_velocity_x,code
+# enter with a, y = alien_x / 2, alien_y / 2
+# returns a, y = signed vector from alien to ship
+0x9fcf,0x0001,vector_alien_to_ship,code
+# enter with y = x coordinate
+# lets a = x via identity transformation, gets y
+0x9fe9,0x0001,get_ship_top_centre,code
+# it calculates the shape from alien_orientation
+0x9ff0,0x0001,get_alien_shape,code
+0x9ff5,0x0002,gal_ptr_9ef1,word
+# something to do with the alien orientation
+0x9ffb,0x0001,physics_9ef7,code
+0xa002,0x0002,gal_ptr_9efe,word
+0xa01c,0x0001,gal_ptr_9f18,word
+# something to do with the alien orientation
+# is it moving it based on cos(angle) and sin(angle)?
+0xa026,0x0001,physics_9f22,code
+0xa05f,0x0001,move_shell_by_velocity,code
+0xa081,0x0001,move_missile_by_velocity,code
+0xa08c,0x0001,move_alien_shape_9f88,code
+0xa0d3,0x0001,move_missile,code
+0xa11c,0x0001,move_shell,code
+# set up object0 as a shell or an alien first
+# returns whether collision occurred (in zf and a)
+0xa165,0x0001,ship_collision_test,code
+0xa19c,0x0001,maybe_award_points,code
+# calculates object_(xy)(01)[object]
+# object 0 is alien, object 1 is ship
+# enter with a = centre x, y = top y, score_temp = 1/2 width (height is 7)
+0xa1d7,0x0001,calculate_bounds0,code
+0xa1dd,0x0001,calculate_bounds1,code
+0xa1e1,0x0001,calculate_bounds_entry,code
+0xa1f8,0x0001,collision_test,code
+0xa211,0x0001,move_ship,code
+0xa232,0x0001,move_ship_entry0,code
+0xa24b,0x0001,move_ship_entry1,code
+# returns a = ship_x (via identity transformation) - 4, y = ship_y
+0xa25a,0x0001,get_ship_top_left,code
+0xa263,0x0001,get_shape_a15f,code
+0xa26a,0x0001,gal_rts_a166,code
+0xa26b,0x0001,do_erase_shape,code
+# might also be doing collision detection?
+0xa277,0x0001,award_points,code
+# returns a = alien_x[x] - 3, y = alien_y[x]
+0xa300,0x0001,get_alien_top_left,code
+# it can calculate a foot or an explosion shape
+# it can also return a value from a table directly
+0xa30a,0x0001,get_alien_part_shape,code
+0xa328,0x0001,gal_rts_a22d,code
+0xa329,0x0001,move_alien_shape_a22e,code
+# called at the end of award_points routine
+0xa350,0x0001,move_alien_shape_a22e_entry,code
+# called when an alien is killed and needs to be erased
+# decrements active_aliens, awards a win if decremented to zero
+0xa35f,0x0001,erase_shape_a264,code
+0xa37c,0x0001,erase_missile,code
+0xa3a1,0x0001,erase_shell,code
+# draws "score" followed by 4 digits followed by "0"
+# also updates high score if new score exceeds high score
+0xa3c6,0x0001,draw_score,code
+# draws "high score" followed by 4 digits followed by "0"
+0xa407,0x0001,draw_high_score,code
+0xa42c,0x0001,gal_rts_a331,code
+0xa42d,0x0001,draw_ships,code
+0xa456,0x0001,draw_wins,code
+0xa478,0x0001,set_base_draw_digit_pair,code
+0xa47b,0x0001,draw_digit_pair,code
+0xa487,0x0001,set_base_draw_hi_digit,code
+0xa48b,0x0001,set_base_draw_digit,code
+0xa48e,0x0001,draw_digit,code
+0xa492,0x0001,draw_digit_base,byte
+# a = x (saved to draw_x1), y = y (saved to draw_erase_y0)
+0xa496,0x0001,set_cursor,byte
+# draws shapes draw_misc_50 through 5f at title_display_x, title_display_y
+0xa49b,0x0001,title_display,byte
+# does x * 0x1000 loops, can be cut short by keyboard input
+0xa4dd,0x0001,delay_x,byte
+0xa4f7,0x0001,process_all,code
 0xc000,0x0001,HW_KBD,byte
 0xc010,0x0001,HW_KBDSTRB,byte
 0xc030,0x0001,HW_SPKR,byte
@@ -765,7 +773,7 @@ shape_names
 0x52,flagship
 
 misc_shape_names
-0x00,signature
+0x00, # garbage (empty name prevents extraction)
 0x02,text_score
 0x03,text_score_0
 0x04,text_hiscore
@@ -798,8 +806,12 @@ misc_shape_names
 0x29,ships_1
 0x2a,ships_2
 0x2b,ships_3
-0x2e, # garbage (empty name prevents extraction)
+0x2d, # garbage (empty name prevents extraction)
+0x2f, # garbage (empty name prevents extraction)
+0x30, # garbage (empty name prevents extraction)
 0x32,blank
+0x33, # garbage (empty name prevents extraction)
+0x35, # garbage (empty name prevents extraction)
 0x3c,flags_0
 0x3d,flags_1
 0x3e,flags_2
@@ -834,5 +846,6 @@ misc_shape_names
 0x5b,alien
 0x5c,text_30_or_10
 0x5d,text_special_add_1_ship_at_3000_pts
-0x64, # garbage (empty name prevents extraction)
-0x76, # garbage (empty name prevents extraction)
+0x5e,instructions_left
+0x5f,instructions_right
+0x78, # garbage (empty name prevents extraction)
diff --git a/galaxian/equivalence.py b/galaxian/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/galaxian/equivalence.sh b/galaxian/equivalence.sh
new file mode 100755 (executable)
index 0000000..208febe
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/sh
+./uncomment.sh <galaxian.asm >a
+./uncomment.sh <alien_rain.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
index c50c031..99b0a80 100644 (file)
@@ -85,6 +85,7 @@ items
 0x006d,0x0001,ship_active,byte
 0x006e,0x0001,gal_bvar_006e,byte
 0x006f,0x0001,gal_bvar_006f,byte
+0x0070,0x0001,gal_bvar_0070,byte
 # gets set to value of bvar_48a0 when win awarded
 # does it cause a new phalanx of aliens to appear?
 0x0071,0x0001,new_level_flag,byte
@@ -114,6 +115,7 @@ items
 # shell will only fire if low 2 bits = 0
 # it is then incremented, to fire every 4 cycles?
 0x0081,0x0001,fire_shell_count,byte
+0x0082,0x0001,gal_bvar_0082,byte
 # used in vector_alien_to_ship
 0x0083,0x0001,half_alien_x,byte
 0x0084,0x0001,half_alien_y,byte
@@ -388,6 +390,8 @@ items
 0x48bb,0x0001,missile_bounds_x1,byte
 0x48bc,0x0001,missile_bounds_y0,byte
 0x48bd,0x0001,missile_bounds_y1,byte
+0x48be,0x0001,gal_bvar_48be,byte
+0x48bf,0x0001,gal_bvar_48bf,byte
 # formation inner bounds?
 # used to determine if alien should be moved in formation
 0x48c2,0x0001,formation_inner_x0,byte
@@ -415,7 +419,7 @@ items
 # 0493e might be part of preceding or following table?
 # next one is filled with 0x46, 0x4d, 0x53 seemingly randomly
 # see also code at 0x9768 (main loop) -- comparing with these values
-0x493f,0x0040,barr_493f,byte
+0x493f,0x0040,gal_barr_493f,byte
 # then zeros... padding?
 0x49c0,0x0040,alien_49c0,byte
 0x4a00,0x0040,alien_4a00,byte
@@ -505,6 +509,7 @@ items
 # flag which is nonzero to draw a foot? or does it have other uses?
 0x9228,0x0040,alien_9228,byte
 0x932b,0x0001,gal_sub_932b,code
+0x9372,0x0001,gal_sub_9372,code
 0x937c,0x0001,init_bvar_0019,byte
 # copies a large number of variables from one set to another
 # also does some +3 and +variable, is it computing bounds?
@@ -623,6 +628,7 @@ items
 # it sets lookup tables that are used for animating the shape and other things
 0x9cb1,0x0001,setup_alien_kind,code
 0x9ccb,0x0001,gal_sub_9ccb,code
+0x9d4a,0x0001,gal_sub_9d4a,code
 # stores gal_bvar_0076 in alien_9068 for all aliens and the 0th entry
 0x9d88,0x0001,set_all_alien_9068,code
 # moves the alien depending on its status and then does other processing
index 41647e5..b491806 100755 (executable)
@@ -5,5 +5,5 @@
 #   ./uncomment.sh <alien_typhoon.asm >b
 #   diff --unified a b >c
 
-sed -e 's/[ \t]*;.*//; s/:\t/:\n\t/' |\
+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 4230f1c..d99d871 100755 (executable)
@@ -210,7 +210,7 @@ with open(addrs_txt) as fin:
           assert len(mate) == 2
 
         # enable this to see which address is out of order
-        #print(hex(addr))
+        print(hex(addr))
         assert (
           len(item_addr) == 0 or
             addr >= item_addr[-1] + item_info[-1].size
@@ -742,7 +742,7 @@ op_control_transfer = {
   'beq',
   'bra'
 }
-op_no_fall_through = {'jmp', 'rts'}
+op_no_fall_through = {'jmp', 'rts', 'brk'}
 def disasm_code(addr):
   # disassemble the next 6 instructions
   i = addr
@@ -775,6 +775,9 @@ def disasm_code(addr):
       if match is not None:
         disasm_code_macro2(addrs, match)
 
+  # enable this when code item with size > 1 causes abort
+  #print(hex(addr), instr)
+
   # recognize and reformat addressing modes
   if len(instr) >= 2:
     match = re_direct.match(instr[1])
@@ -783,8 +786,6 @@ def disasm_code(addr):
     else:
       match = re_direct_xy.match(instr[1])
       if match is not None:
-        # use this when code item with size > 1 causes abort
-        #print(hex(addr), instr)
         disasm_code_direct_xy(addr, n, instr, match)
       else:
         match = re_indirect.match(instr[1])