# also y coordinate temporary storage
0x0017,0x0001,draw_temp,byte
0x0020,0x0001,draw_x_save,byte
+# high score in 4-digit BCD
+0x0023,0x0002,high_score,byte
+# cleared when keyboard input occurs
+# I think it controls demo mode, 0 for play mode
+0x0025,0x0001,demo_mode,byte
+# score in 4-digit BCD
+0x0029,0x0002,score,byte
+0x0036,0x0001,starfield_count,byte
+# ships in 2-digit BCD
+0x0069,0x0001,ships,byte
+# wins in 2-digit BCD
+0x0072,0x0001,wins,byte
0x2000,0x0028,VIDEO_LINE_00,byte
0x2028,0x0028,VIDEO_LINE_40,byte
0x2050,0x0028,VIDEO_LINE_80,byte
0x3f80,0x0028,VIDEO_LINE_3F,byte
0x3fa8,0x0028,VIDEO_LINE_7F,byte
0x3fd0,0x0028,VIDEO_LINE_BF,byte
-0x486e,0x0001,velocity_y,byte
-0x4870,0x0001,velocity_x_lo,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
+0x486e,0x0001,y_velocity,byte
+0x4870,0x0001,x_velocity_lo,byte
+0x4886,0x0001,high_score_init,byte
+0x48aa,0x0001,starfield_count_init,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
+0x48de,0x0010,title_display_delay,byte
+0x48ee,0x0010,title_display_y,byte
+0x48fe,0x0010,title_display_x,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,0x0001,draw_misc_data,byte
-0x8a80,0x0080,draw_misc_data_ptr_lo,byte
-0x8b00,0x0080,draw_misc_data_ptr_hi,byte
-0x8b80,0x0080,draw_misc_width_bytes,byte
-0x8c00,0x0080,draw_misc_height,byte
+0x7e80,0x0001,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
0x8cf1,0x0008,y_8cf1,byte
0x8d01,0x0008,velocity_hi_8d01,byte
0x8d11,0x0008,x_hi_8d11,byte
0x8d21,0x0008,x_lo_8d21,byte
+0x8d31,0x0028,star_y,byte
+0x8df1,0x0028,star_shape_left,byte
+0x8e51,0x0028,star_shape_right,byte
+0x8eb1,0x0028,star_y_velocity,byte
0x8f71,0x0001,y_8f71,byte
+0x8f79,0x0028,move_starfield_table,byte
0x8fe1,0x0001,x_8fe1,byte
0x9028,0x0012,y_9028,byte
0x90a8,0x0012,x_90a8,byte
+0x937c,0x0001,init_bvar_0019,byte
+# see screen_size
+0x93a4,0x0004,screen_offset,byte
# initialize clip_rect, clear screen, set hires
0x93a8,0x0001,video_init,code
0x93be,0x0001,,code_ign # self-modifying code assembled with garbage word
0x94e5,0x0001,,code_ign # accessing video_line_table before clipping y
0x94fe,0x0001,,code_ign # self-modifying code assembled with garbage word
0x94ff,0x0002,,word
-0x951c,0x0002,draw_misc_data_ptr_base,word
+0x951c,0x0002,misc_shape_data_ptr_base,word
# draws over previous video contents
# a = shape to draw
# draw_x1 = x0 for drawing and is advanced by routine
0x9577,0x00c0,video_line_table_lo,byte,byte,10000
0x9637,0x00c0,video_line_table_hi,byte,byte,10000
0x9707,0x0001,start,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
+# 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
+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
0x9ef7,0x0001,physics_9ef7,code
0x9f22,0x0001,physics_9f22,code
0x9f5b,0x0001,add_velocity_to_position,code
-0x9f7d,0x0001,add_velocity_x_to_position,code
+0x9f7d,0x0001,add_x_velocity_to_position,code
0x9f88,0x0001,move_shape_9f88,code
-0x9fcf,0x0001,move_shape_01,code
-0xa018,0x0001,move_shape_02,code
+0x9fcf,0x0001,move_missile,code
+0xa018,0x0001,move_shell,code
0xa0f4,0x0001,clip_xy,code
-0xa10d,0x0001,move_shape_00,code
+0xa10d,0x0001,move_ship,code
0xa12e,0x0001,move_shape_a12e,code
# returns a = x, y = y
0xa156,0x0001,get_new_position,code
0xa205,0x0001,get_old_position,code
0xa22e,0x0001,move_shape_a22e,code
0xa264,0x0001,erase_shape_a264,code
-0xa281,0x0001,erase_shape_01,code
-0xa2a6,0x0001,erase_shape_02,code
-0xa2cb,0x0001,draw_misc_a2cb,code
-0xa332,0x0001,draw_misc_a332,code
-0xa354,0x0001,draw_misc_a345,code
-0xa376,0x0001,do_draw_digit_pair,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
+0xa332,0x0001,draw_ships,code
+0xa354,0x0001,draw_wins,code
+0xa376,0x0001,set_base_draw_digit_pair,code
0xa379,0x0001,draw_digit_pair,code
-0xa389,0x0001,do_draw_digit,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
0xc000,0x0001,HW_KBD,byte
0xc010,0x0001,HW_KBDSTRB,byte
0xc030,0x0001,HW_SPKR,byte
0xc062,0x0001,HW_PB1,byte
0xc065,0x0001,HW_PADDL1,byte
0xc070,0x0001,HW_PTRIG,byte
+
+shape_names
+0x00,ship
+0x01,missile
+0x02,shell
+0x04,ship_explosion
+0x05,ship_explosion
+0x06,ship_explosion
+0x07,ship_explosion
+0x08,alien_foot
+0x09,alien_foot
+0x0a,alien_foot
+0x0b,alien_foot
+0x0c,alien_foot
+0x0d,alien_foot
+0x0e,alien_foot
+0x0f,alien_foot
+0x10,alien_explosion
+0x11,alien_explosion
+0x12,alien_explosion
+0x13,alien_explosion
+0x14,alien_foot
+0x15,alien_foot
+0x16,alien_foot
+0x17,alien_foot
+0x18,text_100
+0x19,text_200
+0x1a,text_300
+0x1b,text_500
+0x28,alien_head
+0x29,alien_head
+0x2a,alien_head
+0x3c,alien_head
+0x3d,alien_head
+0x3e,alien_head
+0x50,flagship
+0x51,flagship
+0x52,flagship
+
+misc_shape_names
+0x00,signature
+0x02,text_score
+0x03,text_score_0
+0x04,text_hiscore
+0x05,text_hiscore_0
+0x06,text_ships
+0x07,text_ships_blank
+0x08,text_wins
+0x09,text_wins_blank
+0x14,text_0
+0x15,text_1
+0x16,text_2
+0x17,text_3
+0x18,text_4
+0x19,text_5
+0x1a,text_6
+0x1b,text_7
+0x1c,text_8
+0x1d,text_9
+0x1e,text_0
+0x1f,text_1
+0x20,text_2
+0x21,text_3
+0x22,text_4
+0x23,text_5
+0x24,text_6
+0x25,text_7
+0x26,text_8
+0x27,text_9
+0x28,ships_0
+0x29,ships_1
+0x2a,ships_2
+0x2b,ships_3
+0x32,blank
+0x3c,flags_0
+0x3d,flags_1
+0x3e,flags_2
+0x3f,flags_3
+0x40,flags_4
+0x41,flags_5
+0x42,flags_6
+0x43,flags_7
+0x44,flags_8
+0x45,flags_9
+0x46,flags_00
+0x47,flags_10
+0x48,flags_20
+0x49,flags_30
+0x4a,flags_40
+0x4b,flags_50
+0x4c,flags_60
+0x4d,flags_70
+0x4e,flags_80
+0x4f,flags_90
+0x50,text_galaxian
+0x51,text_by
+0x52,text_tony_suzuki
+0x53,text_copyright_1980
+0x54,text_star_craft
+0x55,text_tokyo
+0x56,text_points
+0x57,flagship
+0x58,text_random_or_50
+0x59,alien
+0x5a,text_50_or_30
+0x5b,alien
+0x5c,text_30_or_10
+0x5d,text_special_add_1_ship_at_3000_pts
+0x64,bullet
print('reading addrs')
shape_tables = {}
shape_data_ptr_base = -1
-draw_misc_tables = {}
-draw_misc_data_ptr_base = -1
-shapes = {}
+misc_shape_tables = {}
+misc_shape_data_ptr_base = -1
+shape_names = {}
+misc_shape_names = {}
with open(addrs_txt) as fin:
def get_line():
while True:
if _type == 'byte':
if name[:6] == 'shape_':
shape_tables[name[6:]] = (addr, size // 0x80)
- elif name[:10] == 'draw_misc_':
- draw_misc_tables[name[10:]] = (addr, size // 0x80)
+ elif name[:11] == 'misc_shape_':
+ misc_shape_tables[name[11:]] = (addr, size // 0x80)
elif _type == 'word':
if name == 'shape_data_ptr_base':
shape_data_ptr_base = addr
- elif name == 'draw_misc_data_ptr_base':
- draw_misc_data_ptr_base = addr
+ elif name == 'misc_shape_data_ptr_base':
+ misc_shape_data_ptr_base = addr
fields = get_line()
continue
- if section == 'shapes':
+ if section == 'shape_names':
fields = get_line()
while len(fields) >= 2:
assert len(fields) == 2
index = int(fields[0], 0)
name = fields[1]
- shapes[index] = name
+ shape_names[index] = name
+ fields = get_line()
+ continue
+
+ if section == 'misc_shape_names':
+ fields = get_line()
+ while len(fields) >= 2:
+ assert len(fields) == 2
+ index = int(fields[0], 0)
+ name = fields[1]
+ misc_shape_names[index] = name
fields = get_line()
continue
while len(fields) >= 2:
fields = get_line()
assert shape_data_ptr_base != -1
-assert draw_misc_data_ptr_base != -1
+assert misc_shape_data_ptr_base != -1
print('reading ihx')
intelhex = IntelHex(in_ihx)
print(f'[{segments[i]:04x}, {segments[i + 1]:04x})')
print('extracting')
-data = []
-for i in range(0x100):
- name = f'shape_{i:02x}' if i < 0x80 else f'draw_misc_{i - 0x80:02x}'
- if i in shapes:
- name += '_' + shapes[i]
- data.append({'name': name})
+shapes = []
+for base, prefix, names in [
+ (0, 'shape', shape_names),
+ (0x80, 'misc_shape', misc_shape_names)
+]:
+ for i in range(0x80):
+ name = f'{prefix:s}_{i:02x}'
+ if i in names:
+ name += '_' + names[i]
+ shapes.append({'name': name})
-for base, tables in [(0, shape_tables), (0x80, draw_misc_tables)]:
+for base, tables in [
+ (0, shape_tables),
+ (0x80, misc_shape_tables)
+]:
i = 0
tables1 = list(tables.items())
while i < len(tables1):
(intelhex[data_ptr_hi + j + k * 0x80] << 8)
for k in range(shifts)
]
- data[base + j][table] = [f'0x{k:04x}' for k in value]
+ shapes[base + j][table] = [f'0x{k:04x}' for k in value]
i += 2
else:
table, (data_ptr, shifts) = tables1[i]
intelhex[data_ptr + j + k * 0x80]
for k in range(shifts)
]
- data[base + j][table] = [str(k) for k in value]
+ shapes[base + j][table] = [str(k) for k in value]
i += 1
for base, data_ptr_base in [
),
(
0x80,
- intelhex[draw_misc_data_ptr_base] |
- (intelhex[draw_misc_data_ptr_base + 1] << 8)
+ intelhex[misc_shape_data_ptr_base] |
+ (intelhex[misc_shape_data_ptr_base + 1] << 8)
)
]:
for i in range(0x80):
- height = int(data[base + i]['height'][0], 0)
- width_bytes = [int(j, 0) for j in data[base + i]['width_bytes']]
- data_ptr = [int(j, 0) for j in data[base + i]['data_ptr']]
+ height = int(shapes[base + i]['height'][0], 0)
+ width_bytes = [int(j, 0) for j in shapes[base + i]['width_bytes']]
+ data_ptr = [int(j, 0) for j in shapes[base + i]['data_ptr']]
# only try to extract if data is sensible
- data1 = None
+ data = None
if (
height >= 1 and
height < 46 and
all([j >= 1 and j < 40 for j in width_bytes]) and
all([j < 0x1000 for j in data_ptr])
):
- data1 = [
+ data = [
[
[
f'0x{intelhex[data_ptr_base + data_ptr[j] + k * width_bytes[j] + l]:02x}'
]
for j in range(len(width_bytes))
]
- data[base + i]['data'] = data1
+ shapes[base + i]['data'] = data
print('writing json')
with open(out_json, 'w') as fout:
- json.dump(data, fout, indent = 2)
+ json.dump(shapes, fout, indent = 2)