- Add mufflon C source (gitignored, auto-downloaded by make) - Add tools/nuf_to_asm.py for converting .nuf to oscar64 assembly - Add Makefile targets: nufli, nufli-clean, ensure-mufflon - Generate NUFLI .asm/.h files for all 5 screens - Add NUFLI integration plan to tasks.md
80 lines
2.5 KiB
Python
80 lines
2.5 KiB
Python
#!/usr/bin/env python3
|
|
"""Convert NUFLI .nuf binary to oscar64-compatible assembly/include files.
|
|
|
|
Usage:
|
|
python3 nuf_to_asm.py input.nuf output_base
|
|
|
|
Output files:
|
|
output_base.asm - Assembly data file
|
|
output_base.h - C header with extern declarations
|
|
"""
|
|
|
|
import argparse
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
|
|
def nuf_to_asm(nuf_data, output_base):
|
|
"""Convert NUFLI binary to assembly data."""
|
|
out_path = Path(output_base)
|
|
|
|
# Skip 2-byte load address header
|
|
data = nuf_data[2:]
|
|
|
|
# Assembly data file
|
|
with open(out_path.with_suffix('.asm'), 'w') as f:
|
|
f.write("; NUFLI image data - generated by nuf_to_asm.py\n")
|
|
f.write("; Load at $2000, display with SYS 12288 ($3000)\n")
|
|
f.write(f"; Total size: {len(data)} bytes\n\n")
|
|
f.write(".segment \"NUFLI_DATA\"\n\n")
|
|
|
|
# Export the data
|
|
f.write(".export _nufli_data\n")
|
|
f.write(".export _nufli_size\n\n")
|
|
|
|
f.write("_nufli_data:\n")
|
|
|
|
# Write data in rows of 16 bytes
|
|
for i in range(0, len(data), 16):
|
|
chunk = data[i:i+16]
|
|
hex_bytes = ', '.join(f'${b:02x}' for b in chunk)
|
|
f.write(f" .byte {hex_bytes}\n")
|
|
|
|
f.write(f"\n_nufli_size = {len(data)}\n")
|
|
|
|
# C header file
|
|
with open(out_path.with_suffix('.h'), 'w') as f:
|
|
f.write("/* NUFLI image data - generated by nuf_to_asm.py */\n")
|
|
f.write(f"#ifndef {out_path.name.upper().replace('.', '_')}_H\n")
|
|
f.write(f"#define {out_path.name.upper().replace('.', '_')}_H\n\n")
|
|
f.write(f"/* NUFLI data size: {len(data)} bytes */\n")
|
|
f.write(f"extern const unsigned char nufli_data[{len(data)}];\n")
|
|
f.write(f"extern const unsigned int nufli_size;\n\n")
|
|
f.write("/* Display NUFLI image */\n")
|
|
f.write("void nufli_display(void);\n\n")
|
|
f.write("#endif\n")
|
|
|
|
print(f"Wrote {out_path.with_suffix('.asm')} ({len(data)} bytes)")
|
|
print(f"Wrote {out_path.with_suffix('.h')}")
|
|
|
|
|
|
def main(argv=None):
|
|
ap = argparse.ArgumentParser(
|
|
description="Convert NUFLI .nuf binary to oscar64 assembly"
|
|
)
|
|
ap.add_argument("input", help="Input .nuf file")
|
|
ap.add_argument("output_base", help="Output base path (no extension)")
|
|
args = ap.parse_args(argv)
|
|
|
|
in_path = Path(args.input)
|
|
if not in_path.exists():
|
|
print(f"Error: {in_path} not found", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
data = in_path.read_bytes()
|
|
nuf_to_asm(data, args.output_base)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|