diff options
author | Juan J. MartÃnez <jjm@usebox.net> | 2022-09-16 11:08:35 +0000 |
---|---|---|
committer | Juan J. MartÃnez <jjm@usebox.net> | 2022-09-16 11:08:35 +0000 |
commit | de06bed752f82eb5fad659f9945261fbff185241 (patch) | |
tree | 23d7fdb24453a3a1378f81d021567616492bbdbd /tools/mkcas.py | |
parent | 290c74b70661bcde314f73fde2be888e5aed47e0 (diff) | |
parent | 1ef0d697a62eff28115d6642c850ba4d01ef6a89 (diff) | |
download | ubox-msx-lib-de06bed752f82eb5fad659f9945261fbff185241.tar.gz ubox-msx-lib-de06bed752f82eb5fad659f9945261fbff185241.zip |
Merge branch 'cas-support' into 'main'
Added CAS support to the example game
See merge request reidrac/ubox-msx-lib!32
Diffstat (limited to 'tools/mkcas.py')
-rwxr-xr-x | tools/mkcas.py | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/tools/mkcas.py b/tools/mkcas.py new file mode 100755 index 0000000..267270d --- /dev/null +++ b/tools/mkcas.py @@ -0,0 +1,164 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020-2022 by Juan J. Martinez <jjm@usebox.net> +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +__version__ = "1.1" + +import os +from argparse import ArgumentParser + +DEF_ADDR = 0x4000 +TYPES = ("binary", "basic", "ascii", "custom-header", "custom") +TYPE_BLOCK = { + "binary": bytes((0xD0 for _ in range(10))), + "basic": bytes((0xD3 for _ in range(10))), + "ascii": bytes((0xEA for _ in range(10))), +} + +BLOCK_ID = bytes((0x1F, 0xA6, 0xDE, 0xBA, 0xCC, 0x13, 0x7D, 0x74)) + + +def write_word(fd, word): + fd.write(bytes((word & 0xFF, word >> 8))) + + +def auto_int(value): + return int(value, 0) + + +def main(): + + parser = ArgumentParser( + description="Make a CAS file for the MSX", + epilog="Copyright (C) 2020-2022 Juan J Martinez <jjm@usebox.net>", + ) + + parser.add_argument( + "--version", action="version", version="%(prog)s " + __version__ + ) + parser.add_argument( + "-a", + "--add", + dest="add", + action="store_true", + help="append to the existing CAS file instead of creating a new one", + ) + parser.add_argument( + "--name", + dest="name", + default=None, + type=str, + help="name to use for the file (limit 6 chars, defaults to the file name)", + ) + parser.add_argument( + "--addr", + dest="addr", + default=DEF_ADDR, + type=auto_int, + help="address to load if binary file (default: 0x%04x)" % DEF_ADDR, + ) + parser.add_argument( + "--exec", + dest="exec", + default=DEF_ADDR, + type=auto_int, + help="address to exec if binary file (default: 0x%04x)" % DEF_ADDR, + ) + + parser.add_argument("output", help="target .CAS file") + parser.add_argument("type", help="file type", choices=TYPES) + parser.add_argument("file", help="input file") + + args = parser.parse_args() + + if args.add: + flags = "ab" + else: + flags = "wb" + + with open(args.output, flags) as out: + + if args.name: + name = args.name + else: + name = os.path.basename(args.file) + + with open(args.file, "rb") as inf: + data = inf.read() + + out.write(BLOCK_ID) + + if args.type == "ascii": + + out.write(TYPE_BLOCK[args.type]) + out.write(name[:6].ljust(6).encode("ascii")) + + for b in range(0, len(data), 256): + out.write(BLOCK_ID) + out.write(data[b : b + 256]) + + padding = 256 - (len(data) % 256) + if padding == 256: + out.write(BLOCK_ID) + out.write(bytes((0x1A for _ in range(padding)))) + + elif args.type == "basic": + + out.write(TYPE_BLOCK[args.type]) + out.write(name[:6].ljust(6).encode("ascii")) + out.write(BLOCK_ID) + out.write(data) + + elif args.type == "binary": + + addr = args.addr + exec_addr = args.exec + end_addr = addr + len(data) - 1 + + if end_addr > 0xFFFF: + parser.error("Binary doesn't fit in memory") + + out.write(TYPE_BLOCK[args.type]) + out.write(name[:6].ljust(6).encode("ascii")) + + out.write(BLOCK_ID) + write_word(out, addr) + write_word(out, end_addr) + write_word(out, exec_addr) + + out.write(data) + + elif args.type == "custom-header": + + addr = args.addr + length = len(data) + + write_word(out, addr) + write_word(out, length) + out.write(data) + + else: + # custom + out.write(data) + + +if __name__ == "__main__": + main() |