*.rel
*.rst
*.seed
+/disasm/shape.json
+/disasm/shape_data.inc
+/disasm/shape_index.inc
+/disasm/shape_data_pixel.inc
+/disasm/shape_index_pixel.inc
+/disasm/shape_pixel.json
/disasm/star_blazer.asm
/disasm/star_blazer.asm0
/disasm/star_blazer.dsk
../shape/dhgr_pixel_shape_index.inc \
../shape/dhgr_pixel_shape_data_main.inc \
../shape/dhgr_pixel_shape_data_aux.inc \
-../shape/pixel_shape_index.inc \
-../shape/pixel_shape_data.inc \
-../shape/shape_index.inc \
-../shape/shape_data.inc \
+shape_index_pixel.inc \
+shape_data_pixel.inc \
+shape_index.inc \
+shape_data.inc \
ucode_defs.inc \
ucode_data.inc
${AS6500} -3 -l -o $<
+shape_index_pixel.inc shape_data_pixel.inc: star_blazer.txt shape_pixel.json
+ ./shape_compile.py $^ shape_index_pixel.inc shape_data_pixel.inc
+
+shape_pixel.json: star_blazer.txt ../loader/star_blazer.ihx
+ ./shape_extract.py --pixel $^ $@
+
+shape_index.inc shape_data.inc: star_blazer.txt shape.json
+ ./shape_compile.py $^ shape_index.inc shape_data.inc
+
+shape.json: star_blazer.txt ../loader/star_blazer.ihx
+ ./shape_extract.py $^ $@
+
ucode_data.inc: star_blazer.asm
sed -ne '/^ucode1080_countdown_30_pixel:/,/; 9dec/p' $< |\
./ucode_disasm.py >$@
*.rel \
*.rst \
star_blazer.asm \
-star_blazer.dsk
+star_blazer.dsk \
+shape_index_pixel.inc \
+shape_data_pixel.inc \
+shape_pixel.json \
+shape_index.inc \
+shape_data.inc \
+shape.json
--- /dev/null
+#!/usr/bin/env python3
+
+import json
+import sys
+from intelhex import IntelHex
+
+EXIT_SUCCESS = 0
+EXIT_FAILURE = 1
+
+if len(sys.argv) < 5:
+ print(f'usage: {sys.argv[0]:s} addrs.txt in.json out_index.inc out_data.inc')
+ sys.exit(EXIT_FAILURE)
+addrs_txt = sys.argv[1]
+in_json = sys.argv[2]
+out_index_inc = sys.argv[3]
+out_data_inc = sys.argv[4]
+
+print('reading addrs')
+shape_tables = {}
+with open(addrs_txt, 'r') as fin:
+ def get_line():
+ while True:
+ line = fin.readline()
+ if len(line) == 0:
+ return []
+ i = line.find('#')
+ if i >= 0:
+ line = line[:i]
+ fields = line.strip().split(',')
+ if fields != ['']:
+ #print('fields', fields)
+ return fields
+
+ fields = get_line()
+ while len(fields):
+ assert len(fields) == 1
+ section = fields[0]
+ print(section)
+
+ if section == 'items':
+ fields = get_line()
+ while len(fields) >= 2:
+ assert len(fields) >= 4
+ addr = int(fields[0], 0)
+ name = fields[2]
+ _type = fields[3]
+ if _type == 'byte' and name[:6] == 'shape_':
+ shape_tables[name[6:]] = addr
+ fields = get_line()
+ continue
+
+ # unknown section, skip
+ fields = get_line()
+ while len(fields) >= 2:
+ fields = get_line()
+
+print('reading json')
+with open(in_json) as fin:
+ data = json.load(fin)
+
+print('writing index')
+
+with open(out_index_inc, 'w') as fout:
+ for table, addr in shape_tables.items():
+ fout.write(f'shape_{table:s}:\n')
+
+ prefix = ''
+ if table[-3:] == '_lo':
+ prefix = '<'
+ table = table[:-3]
+ elif table[-3:] == '_hi':
+ prefix = '>'
+ table = table[:-3]
+
+ table_data = [data[i][table] for i in range(0x100)]
+ if table == 'data_ptr' or table == 'size_bytes':
+ for i in range(0x100):
+ name = data[i]['name']
+ if name is not None:
+ size_bytes = int(data[i]['size_bytes'], 0)
+ if table == 'data_ptr':
+ table_data[i] = 'shape_' + name
+ if size_bytes:
+ width_bytes = int(data[i]['width_bytes'], 0)
+ height = int(data[i]['height'], 0)
+ assert size_bytes == width_bytes * height
+ if table == 'data_ptr':
+ table_data[i] += f' + 3 * {width_bytes:d} * {height:d}'
+ else:
+ table_data[i] = f'{width_bytes:d} * {height:d}'
+ fout.write(''.join([f'\t.db\t{prefix:s}{i:s}\n' for i in table_data]))
+
+print('writing data')
+
+# preserve ordering from the original executable, based on data_ptr
+order = sorted(
+ [
+ (int(data[i]['data_ptr'], 0), i)
+ for i in range(0x100)
+ if data[i]['name'] is not None
+ ]
+)
+
+with open(out_data_inc, 'w') as fout:
+ for i in range(len(order)):
+ addr, index = order[i]
+ name = data[index]['name']
+ fout.write(f'shape_{name:s}:\n')
+
+ # check for reuse of same shape data in original executable
+ # if so, don't bother outputting the shape data, use next one
+ if i + 1 < len(order):
+ addr1, index1 = order[i + 1]
+ if addr1 == addr and data[index1]['data'] == data[index]['data']:
+ continue
+
+ fout.write(
+ ''.join(
+ [
+ ''.join(['\t.db\t{0:s}\n'.format(', '.join(j)) for j in i]) + '\n'
+ for i in data[index]['data']
+ ]
+ )
+ )
--- /dev/null
+#!/usr/bin/env python3
+
+import json
+import sys
+from intelhex import IntelHex
+
+EXIT_SUCCESS = 0
+EXIT_FAILURE = 1
+
+pixel = False
+if len(sys.argv) >= 2 and sys.argv[1] == '--pixel':
+ pixel = True
+ del sys.argv[1]
+if len(sys.argv) < 4:
+ print(f'usage: {sys.argv[0]:s} [--pixel] addrs.txt in.ihx out.json')
+ sys.exit(EXIT_FAILURE)
+addrs_txt = sys.argv[1]
+in_ihx = sys.argv[2]
+out_json = sys.argv[3]
+
+print('reading addrs')
+shape_tables = {}
+pixel_tables = {}
+shapes = {}
+with open(addrs_txt, 'r') as fin:
+ def get_line():
+ while True:
+ line = fin.readline()
+ if len(line) == 0:
+ return []
+ i = line.find('#')
+ if i >= 0:
+ line = line[:i]
+ fields = line.strip().split(',')
+ if fields != ['']:
+ #print('fields', fields)
+ return fields
+
+ fields = get_line()
+ while len(fields):
+ assert len(fields) == 1
+ section = fields[0]
+ print(section)
+
+ if section == 'items':
+ fields = get_line()
+ while len(fields) >= 2:
+ assert len(fields) >= 4
+ addr = int(fields[0], 0)
+ name = fields[2]
+ _type = fields[3]
+ if _type == 'byte':
+ if name[:6] == 'shape_':
+ shape_tables[name[6:]] = addr
+ elif name[:6] == 'pixel_':
+ pixel_tables[name[6:]] = addr
+ fields = get_line()
+ continue
+
+ if section == 'shapes':
+ fields = get_line()
+ while len(fields) >= 2:
+ assert len(fields) == 2
+ index = int(fields[0], 0)
+ name = fields[1]
+ # shape < 8 is a single pixel masked by the shape number
+ # ignore these lines in addrs file unless --pixel requested
+ if index >= 8 or pixel:
+ shapes[index] = name
+ fields = get_line()
+ continue
+
+ # unknown section, skip
+ fields = get_line()
+ while len(fields) >= 2:
+ fields = get_line()
+
+print('reading ihx')
+intelhex = IntelHex(in_ihx)
+segments = [j for i in intelhex.segments() for j in i]
+for i in range(0, len(segments), 2):
+ print(f'[{segments[i]:04x}, {segments[i + 1]:04x})')
+
+print('extracting')
+data = [{'name': None} for i in range(0x100)]
+
+i = 0
+shape_tables1 = list(shape_tables.items())
+while i < len(shape_tables1):
+ if (
+ i + 2 <= len(shape_tables1) and
+ shape_tables1[i][0][-3:] == '_lo' and
+ shape_tables1[i + 1][0][-3:] == '_hi'
+ ):
+ table, addr_lo = shape_tables1[i]
+ _, addr_hi = shape_tables1[i + 1]
+ table = table[:-3]
+ for j in range(0x100):
+ value = intelhex[addr_lo + j] | (intelhex[addr_hi + j] << 8)
+ data[j][table] = f'0x{value:04x}'
+ i += 2
+ else:
+ table, addr = shape_tables1[i]
+ for j in range(0x100):
+ value = intelhex[addr + j]
+ data[j][table] = str(value)
+ i += 1
+
+# do this here so that item ordering is nicer in the json file
+for i in range(0x100):
+ data[i]['data'] = None
+
+for index, name in shapes.items():
+ data[index]['name'] = f'{index:02x}_{name:s}'
+
+ # shape < 8 is a single pixel masked by the shape number
+ # transform the special data tables for pixel drawing into ordinary data
+ if index < 8:
+ data[index]['data_ptr'] = '0x0000' # make them be compiled first
+ data[index]['width_bytes'] = '2'
+ data[index]['height'] = '1'
+ data[index]['size_bytes'] = '2'
+ data[index]['width'] = '1'
+
+ data_table_left = pixel_tables['data_table_left']
+ data_table_right = pixel_tables['data_table_right']
+ mask_table_left = pixel_tables['mask_table_left']
+ mask_table_right = pixel_tables['mask_table_right']
+ value = [
+ [
+ [
+ f'0x{intelhex[data_table_left + ((i * 2) % 7)] & intelhex[mask_table_left + index]:02x}',
+ f'0x{intelhex[data_table_right + ((i * 2) % 7)] & intelhex[mask_table_right + index]:02x}'
+ ]
+ ]
+ for i in range(7)
+ ]
+ else:
+ addr = int(data[index]['data_ptr'], 0)
+ height = int(data[index]['height'], 0)
+ width_bytes = int(data[index]['width_bytes'], 0)
+ size_bytes = int(data[index]['size_bytes'], 0)
+ value = [
+ [
+ [
+ f'0x{intelhex[addr + (i - 3) * size_bytes + j * width_bytes + k]:02x}'
+ for k in range(width_bytes)
+ ]
+ for j in range(height)
+ ]
+ for i in range(7 if size_bytes else 1)
+ ]
+ data[index]['data'] = value
+
+print('writing json')
+with open(out_json, 'w') as fout:
+ json.dump(data, fout, indent = 2)
---- star_blazer.asm0 2022-06-25 13:01:14.395901396 +1000
-+++ star_blazer.asm 2022-06-25 13:03:26.391899763 +1000
+--- star_blazer.asm0 2022-06-25 14:50:24.743820370 +1000
++++ star_blazer.asm 2022-06-25 15:16:37.251800919 +1000
@@ -1,3 +1,9 @@
+UNREACHABLE = 1
+DHGR = 0
+PIXEL_SHAPE = 0
-+SHAPE = 0
++SHAPE = 1
+UCODE = 0
+
HIRES_SCREEN = 0x2000 ; 2000
+.include "../shape/dhgr_pixel_shape_index.inc"
+.else
+.if PIXEL_SHAPE
-+.include "../shape/pixel_shape_index.inc"
++.include "shape_index_pixel.inc"
+.else
+.if SHAPE
-+.include "../shape/shape_index.inc"
++.include "shape_index.inc"
+.else
shape_data_ptr_lo:
- .db <0x5d01 ; 4000 r
- .db <0x5d01 ; 4001 r
+ .db <bvar_5d01 ; 4000 r
+ .db <bvar_5d01 ; 4001 r
@@ -4625,6 +5097,9 @@
.db 0x01 ; 45fd r
.db 0x01 ; 45fe r
+.include "../shape/dhgr_pixel_shape_data_main.inc"
+.else
+.if PIXEL_SHAPE
-+.include "../shape/pixel_shape_data.inc"
++.include "shape_data_pixel.inc"
+.else
+.if SHAPE
-+.include "../shape/shape_data.inc"
++.include "shape_data.inc"
+.else
.db 0x5c ; 5c00
.db 0x02 ; 5c01
.db 0x00 ; 5c02
-@@ -21567,9 +22051,15 @@
+@@ -21696,9 +22180,15 @@
.db 0xe0 ; 8c05
.db 0x83 ; 8c06
.db 0x9e ; 8c07
bvar_8e00:
.db 0x30 ; 8e00 r
.db 0x0f ; 8e01
-@@ -26140,6 +26630,13 @@
+@@ -26269,6 +26759,13 @@
.db 0x7c ; 9dea
.db 0x98 ; 9deb
.db 0x00 ; 9dec