Improve shape extraction, extract and name Alien Typhoon shapes
authorNick Downing <nick@ndcode.org>
Wed, 29 Jun 2022 05:03:52 +0000 (15:03 +1000)
committerNick Downing <nick@ndcode.org>
Wed, 29 Jun 2022 08:48:13 +0000 (18:48 +1000)
.gitignore
galaxian/Makefile
galaxian/alien_typhoon.txt
galaxian/galaxian.txt
galaxian/shape_extract.py
galaxian/shape_extract_png.py

index bc18aed..0b11135 100644 (file)
@@ -15,6 +15,8 @@
 /emu_65c02/cg_default/*.png
 /emu_65c02/cg_default/*.ppm
 /galaxian/alien_typhoon.asm
+/galaxian/alien_typhoon_shape.json
+/galaxian/alien_typhoon_shape.png
 /galaxian/galaxian.asm
 /galaxian/galaxian_shape.json
 /galaxian/galaxian_shape.png
index 9d881d9..02ae9a5 100644 (file)
@@ -9,6 +9,7 @@ LOAD_ADDR=0x800
 all: \
 galaxian_shape.png \
 galaxian.asm \
+alien_typhoon_shape.png \
 alien_typhoon.asm \
 
 galaxian_shape.png: galaxian_shape.json
@@ -23,6 +24,12 @@ galaxian.txt \
 ../loader/galaxian.ihx
        ../utils/disasm.py --trace=$^ $@ </dev/null
 
+alien_typhoon_shape.png: alien_typhoon_shape.json
+       ./shape_extract_png.py $^ $@
+
+alien_typhoon_shape.json: alien_typhoon.txt ../loader/alien_typhoon.ihx
+       ./shape_extract.py $^ $@
+
 alien_typhoon.asm: \
 alien_typhoon_trace.txt \
 alien_typhoon.txt \
@@ -44,4 +51,6 @@ clean:
 galaxian_shape.png \
 galaxian_shape.json \
 galaxian.asm \
+alien_typhoon_shape.png \
+alien_typhoon_shape.json \
 alien_typhoon.asm
index be8d15a..7495e0f 100644 (file)
@@ -434,9 +434,9 @@ items
 0x5046,0x0001,gal_bvar_5280,byte
 # something strange with 5281
 0x5446,0x0001,gal_bvar_5680,byte
-# sizes have not been examined yet
-0x5746,0x0001,shape_data,byte
-0x6f46,0x0001,misc_shape_data,byte
+0x5746,0x1800,shape_data,byte
+0x6f46,0x1b85,misc_shape_data,byte
+# until sub_8acb
 0x8ad7,0x0001,gal_sub_932b,code
 0x8b2b,0x0001,init_bvar_0019,byte
 0x8b32,0x0001,gal_sub_9383,code
@@ -640,6 +640,7 @@ shape_names
 0x00,ship
 0x01,missile
 0x02,shell
+0x03,ship
 0x04,ship_explosion
 0x05,ship_explosion
 0x06,ship_explosion
@@ -664,6 +665,9 @@ shape_names
 0x19,text_200
 0x1a,text_300
 0x1b,text_500
+0x1e,alien_head
+0x1f,alien_head
+0x20,alien_head
 0x28,alien_head
 0x29,alien_head
 0x2a,alien_head
@@ -675,7 +679,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
@@ -708,7 +712,12 @@ misc_shape_names
 0x29,ships_1
 0x2a,ships_2
 0x2b,ships_3
+0x2d, # garbage (empty name prevents extraction)
+0x2f, # garbage (empty name prevents extraction)
+0x30,blank
 0x32,blank
+0x33, # garbage (empty name prevents extraction)
+0x35, # garbage (empty name prevents extraction)
 0x3c,flags_0
 0x3d,flags_1
 0x3e,flags_2
@@ -729,18 +738,23 @@ misc_shape_names
 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
+0x50,text_alien
+0x51,text_typhoon
+0x52,text_by
+0x53,text_tony_suzuki
+0x54,text_copyright_1981
+0x55,text_star_craft
+0x56,text_tokyo
+0x58,text_points
+0x59,flagship
+0x5a,text_random_or_50
 0x5b,alien
-0x5c,text_30_or_10
-0x5d,text_special_add_1_ship_at_3000_pts
-0x64,bullet
+0x5c,text_80_or_40
+0x5d,alien
+0x5e,text_60_or_30
+0x5f,alien
+0x60,text_40_or_20
+0x62,text_special_add_1_ship_at_5000_pts
+0x64,instructions_left
+0x65,instructions_right
+0x78, # garbage (empty name prevents extraction)
index e9d7d86..40ec964 100644 (file)
@@ -380,14 +380,12 @@ items
 0x5280,0x0001,gal_bvar_5280,byte
 0x5281,0x0001,gal_barr_5281,byte
 0x5680,0x0001,gal_bvar_5680,byte
-# sizes have not been examined yet
-0x5a80,0x0001,shape_data,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
-# sizes have not been examined yet
-0x7e80,0x0001,misc_shape_data,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
@@ -680,6 +678,7 @@ misc_shape_names
 0x29,ships_1
 0x2a,ships_2
 0x2b,ships_3
+0x2e, # garbage (empty name prevents extraction)
 0x32,blank
 0x3c,flags_0
 0x3d,flags_1
@@ -715,4 +714,5 @@ misc_shape_names
 0x5b,alien
 0x5c,text_30_or_10
 0x5d,text_special_add_1_ship_at_3000_pts
-0x64,bullet
+0x64, # garbage (empty name prevents extraction)
+0x76, # garbage (empty name prevents extraction)
index e908e82..8c000da 100755 (executable)
@@ -16,10 +16,12 @@ in_ihx = sys.argv[2]
 out_json = sys.argv[3]
 
 print('reading addrs')
+shape_data_addr = -1
+shape_data_size = -1
 shape_tables = {}
-shape_data_ptr_base = -1
+misc_shape_data_addr = -1
+misc_shape_data_size = -1
 misc_shape_tables = {}
-misc_shape_data_ptr_base = -1
 shape_names = {}
 misc_shape_names = {}
 with open(addrs_txt) as fin:
@@ -51,15 +53,16 @@ with open(addrs_txt) as fin:
         name = fields[2]
         _type = fields[3]
         if _type == 'byte':
-          if name[:6] == 'shape_':
+          if name == 'shape_data':
+            shape_data_addr = addr
+            shape_data_size = size
+          elif name[:6] == 'shape_':
             shape_tables[name[6:]] = (addr, size // 0x80)
+          elif name == 'misc_shape_data':
+            misc_shape_data_addr = addr
+            misc_shape_data_size = size
           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 == 'misc_shape_data_ptr_base':
-            misc_shape_data_ptr_base = addr
         fields = get_line()
       continue
 
@@ -87,8 +90,8 @@ with open(addrs_txt) as fin:
     fields = get_line()
     while len(fields) >= 2:
       fields = get_line()
-assert shape_data_ptr_base != -1
-assert misc_shape_data_ptr_base != -1
+assert shape_data_addr != -1
+assert misc_shape_data_addr != -1
 
 print('reading ihx')
 intelhex = IntelHex(in_ihx)
@@ -104,7 +107,7 @@ for base, prefix, names in [
 ]:
   for i in range(0x80):
     name = f'{prefix:s}_{i:02x}'
-    if i in names:
+    if i in names and len(names[i]):
       name += '_' + names[i]
     shapes.append({'name': name})
 
@@ -141,17 +144,9 @@ for base, tables in [
         shapes[base + j][table] = [str(k) for k in value]
       i += 1
 
-for base, data_ptr_base in [
-  (
-    0,
-    intelhex[shape_data_ptr_base] |
-      (intelhex[shape_data_ptr_base + 1] << 8)
-  ),
-  (
-    0x80,
-    intelhex[misc_shape_data_ptr_base] |
-      (intelhex[misc_shape_data_ptr_base + 1] << 8)
-  )
+for base, data_addr, data_size, names in [
+  (0, shape_data_addr, shape_data_size, shape_names),
+  (0x80, misc_shape_data_addr, misc_shape_data_size, misc_shape_names)
 ]:
   for i in range(0x80):
     height = int(shapes[base + i]['height'][0], 0)
@@ -159,17 +154,20 @@ for base, data_ptr_base in [
     data_ptr = [int(j, 0) for j in shapes[base + i]['data_ptr']]
 
     # only try to extract if data is sensible
+    # empty name prevents extraction (as a manual way to suppress
+    # garbage shapes if our checks here do not detect the garbage)
     data = None
     if (
-      height >= 1 and
-        height < 46 and
+      (i not in names or len(names[i])) and
+        height >= 1 and
+        height < 192 and
         all([j >= 1 and j < 40 for j in width_bytes]) and
-        all([j < 0x1000 for j in data_ptr])
+        all([j < data_size for j in data_ptr])
     ):
       data = [
         [
           [
-            f'0x{intelhex[data_ptr_base + data_ptr[j] + k * width_bytes[j] + l]:02x}'
+            f'0x{intelhex[data_addr + data_ptr[j] + k * width_bytes[j] + l]:02x}'
             for l in range(width_bytes[j])
           ]
           for k in range(height)
index 2115270..c99d874 100755 (executable)
@@ -9,7 +9,7 @@ EXIT_SUCCESS = 0
 EXIT_FAILURE = 1
 
 PITCH_X = 256
-PITCH_Y = 64
+PITCH_Y = 128
 
 # see palette.py
 PALETTE = numpy.array(
@@ -47,6 +47,8 @@ with open(in_json) as fin:
 image_out = numpy.zeros((PITCH_Y * 32, PITCH_X * 8), numpy.uint8)
 
 for i in range(0x100):
+  # enable this when hibit test detects garbage
+  #print('i', hex(i))
   j = i & 7
   k = i >> 3
   x = j * PITCH_X