mirror of
https://github.com/robmcmullen/atrcopy.git
synced 2024-11-29 11:51:14 +00:00
Added Apple BSAVE file parser
* added object file parsing into assembled files * updated docs
This commit is contained in:
parent
e91c14d1f9
commit
e06a82e611
76
README.rst
76
README.rst
@ -7,6 +7,11 @@ images.
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
``atrcopy`` 4.0 introduces a new command line argument structure based on
|
||||
subcommands, much like ``git`` uses ``git pull``, ``git clone``, ``git
|
||||
branch``, etc. Upgrading to 4.0 will require modification of scripts that use
|
||||
``atrcopy`` 3.x-style command line arguments.
|
||||
|
||||
Starting with ``atrcopy`` 2.0, `numpy <http://www.numpy.org/>`_ is required. It
|
||||
will be automatically installed when installing ``atrcopy`` with::
|
||||
|
||||
@ -118,7 +123,8 @@ abbreviated as shown here::
|
||||
happened
|
||||
|
||||
|
||||
Help for available options for each command is available using::
|
||||
Help for available options for each command is available without specifying a
|
||||
disk image, using a command line like::
|
||||
|
||||
atrcopy COMMAND --help
|
||||
|
||||
@ -178,9 +184,10 @@ Extract all files::
|
||||
extracting File #4 (.2.u.*) 162 COPY32 COM 056 -> COPY32.COM
|
||||
extracting File #5 (.2.u.*) 218 DISKFIX COM 057 -> DISKFIX.COM
|
||||
|
||||
Extract all, renaming to lower case on the host file system::
|
||||
Extract all, using the abbreviated commandn and renaming to lower case on the
|
||||
host file system::
|
||||
|
||||
$ atrcopy DOS_25.ATR extract --all -l
|
||||
$ atrcopy DOS_25.ATR x --all -l
|
||||
DOS_25.ATR: ATR Disk Image (size=133120 (1040x128b), crc=0 flags=0 unused=0) Atari DOS Format: 1010 usable sectors (739 free), 6 files
|
||||
extracting File #0 (.2.u.*) 004 DOS SYS 037 -> dos.sys
|
||||
extracting File #1 (.2.u.*) 041 DUP SYS 042 -> dup.sys
|
||||
@ -242,31 +249,6 @@ The simple assembler included in ``atrcopy`` can create binary programs by
|
||||
connecting binary data together in a single file and specifying a start address
|
||||
so it can be executed by the system's binary run command.
|
||||
|
||||
The following command links together a hires image loaded at 2000 hex (the
|
||||
first hires screen) and code at 6000 hex (that was assembled using an external
|
||||
program, in this case the assembler from the cc65 project) and sets a start
|
||||
address of 6000 hex. (Note that all the addresses are implicitly hex values.)
|
||||
Because the Apple ][ binary format is limited to a single contiguous block of
|
||||
data with a start address of the first byte of data loaded, ``atrcopy`` will fill
|
||||
the gaps between any segments that aren't contiguous with zeros. If the start
|
||||
address is not the first byte of the first specified segment, a mini-segment
|
||||
will be included at the beginning that jumps to the specified ``brun`` address
|
||||
(shown here as the segment from 1ffd - 2000). Note the gap between 4000 and
|
||||
6000 hex will be filled with zeros::
|
||||
|
||||
$ atrcopy game.dsk create dos33autobrun
|
||||
using dos33autobrun template: Apple ][ DOS 3.3 (140K) standard RWTS, HGR, BRUN a file named AUTOBRUN
|
||||
created game.dsk: DOS 3.3 Disk Image (size=143360 (560x256b)
|
||||
File #0 ( A) 002 HELLO 003 001
|
||||
|
||||
$ atrcopy game.dsk asm -b title.bin@2000 game[4:]@6000 --brun 6000 -f -o AUTOBRUN
|
||||
game.dsk: DOS 3.3 Disk Image (size=143360 (560x256b)
|
||||
setting data for $1ffd - $2000 at index $0004
|
||||
setting data for $2000 - $4000 at index $0007
|
||||
setting data for $6000 - $6ef3 at index $4007
|
||||
total file size: $4efa (20218) bytes
|
||||
copying AUTOBRUN to game.dsk
|
||||
|
||||
It is also possible to assemble text files that use the MAC/65 syntax, because
|
||||
support for `pyatasm <https://pypi.python.org/pypi/pyatasm>`_ is built-in (but
|
||||
optional). MAC/65 is a macro assembler originally designed for the Atari 8-bit
|
||||
@ -274,6 +256,44 @@ machines but since it produces 6502 code it can be used to compile for any
|
||||
machine that uses the 6502: Apple, Commodore, etc.
|
||||
|
||||
|
||||
Creating DOS 3.3 Binaries
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
For this example, the goal is to produce a single binary file that combines a
|
||||
hi-res image ``title.bin`` loaded at 2000 hex (the first hi-res screen) and
|
||||
code at 6000 hex from the binary file ``game``, with a start address of 6000
|
||||
hex.
|
||||
|
||||
The binary file ``game`` was assembled using the assembler from the
|
||||
`cc65<https://github.com/cc65/cc65>`_ project, using the command::
|
||||
|
||||
cl65 -t apple2 --cpu 6502 --start-addr 0x6000 -o game game.s
|
||||
|
||||
Because the Apple ][ binary format is limited to a single contiguous block of
|
||||
data with a start address of the first byte of data loaded, ``atrcopy`` will
|
||||
fill the gaps between any segments that aren't contiguous with zeros. If the
|
||||
start address is not the first byte of the first specified segment, a small
|
||||
segment will be included at the beginning that jumps to the specified ``brun``
|
||||
address (shown here as the segment from 1ffd - 2000). Note the gap between 4000
|
||||
and 6000 hex will be filled with zeros::
|
||||
|
||||
$ atrcopy game.dsk create dos33autobrun
|
||||
using dos33autobrun template:
|
||||
Apple ][ DOS 3.3 (140K) disk image for binary program development: HELLO sets
|
||||
fullscreen HGR and calls BRUN on user-supplied AUTOBRUN binary file
|
||||
created game.dsk: DOS 3.3 Disk Image (size=143360 (560x256b)
|
||||
File #0 ( A) 002 HELLO 003 001
|
||||
|
||||
$ atrcopy game.dsk asm -d title.bin@2000 -b game --brun 6000 -f -o AUTOBRUN
|
||||
game.dsk: DOS 3.3 Disk Image (size=143360 (560x256b)
|
||||
adding BSAVE data $6000-$6ef3 ($0ef3 @ $0004) from game
|
||||
setting data for $1ffd - $2000 at index $0004
|
||||
setting data for $2000 - $4000 at index $0007
|
||||
setting data for $6000 - $6ef3 at index $4007
|
||||
total file size: $4efa (20218) bytes
|
||||
copying AUTOBRUN to game.dsk
|
||||
|
||||
|
||||
Example on Mac OS X
|
||||
-------------------
|
||||
|
||||
|
@ -175,7 +175,7 @@ def crc_files(image, files):
|
||||
print("%s: %08x" % (dirent.filename, crc))
|
||||
|
||||
|
||||
def assemble(image, source_files, data_files, run_addr=""):
|
||||
def assemble(image, source_files, data_files, obj_files, run_addr=""):
|
||||
if source_files:
|
||||
try:
|
||||
import pyatasm
|
||||
@ -218,6 +218,13 @@ def assemble(image, source_files, data_files, run_addr=""):
|
||||
data = fh.read()[subset]
|
||||
s = segments.add_segment(data, first)
|
||||
log.debug("read data for %s" % s.name)
|
||||
for name in obj_files:
|
||||
parser = find_diskimage(name)
|
||||
if parser and parser.image:
|
||||
for s in parser.segments:
|
||||
if s.start_addr > 0:
|
||||
print "adding %s from %s" % (s, name)
|
||||
segments.add_segment(s.data, s.start_addr)
|
||||
if options.verbose:
|
||||
for s in segments:
|
||||
print "%s - %04x)" % (str(s)[:-1], s.start_addr + len(s))
|
||||
@ -418,7 +425,8 @@ def run():
|
||||
assembly_parser = subparsers.add_parser(command, help="Create a new binary file in the disk image", aliases=command_aliases[command])
|
||||
assembly_parser.add_argument("-f", "--force", action="store_true", default=False, help="allow file overwrites in the disk image")
|
||||
assembly_parser.add_argument("-s", "--asm", nargs="*", action="append", help="source file(s) to assemble using pyatasm")
|
||||
assembly_parser.add_argument("-d","-b", "--data", nargs="*", action="append", help="binary data file(s) to add to assembly, specify as file@addr. Only a portion of the file may be included; specify the subset using standard python slice notation: file[subset]@addr")
|
||||
assembly_parser.add_argument("-d","--data", nargs="*", action="append", help="binary data file(s) to add to assembly, specify as file@addr. Only a portion of the file may be included; specify the subset using standard python slice notation: file[subset]@addr")
|
||||
assembly_parser.add_argument("-b", "--obj", "--bload", nargs="*", action="append", help="binary file(s) to add to assembly, either executables or labeled memory dumps (e.g. BSAVE on Apple ][), parsing each file's binary segments to add to the resulting disk image at the load address for each segment")
|
||||
assembly_parser.add_argument("-r", "--run-addr", "--brun", action="store", default="", help="run address of binary file if not the first byte of the first segment")
|
||||
assembly_parser.add_argument("-o", "--output", action="store", default="", required=True, help="output file name in disk image")
|
||||
|
||||
@ -522,7 +530,8 @@ def run():
|
||||
elif command == "assemble":
|
||||
asm = options.asm[0] if options.asm else []
|
||||
data = options.data[0] if options.data else []
|
||||
assemble(parser.image, asm, data, options.run_addr)
|
||||
obj = options.obj[0] if options.obj else []
|
||||
assemble(parser.image, asm, data, obj, options.run_addr)
|
||||
elif command == "segments":
|
||||
print "\n".join([str(a) for a in parser.segments])
|
||||
else:
|
||||
|
@ -625,6 +625,48 @@ class Dos33DiskImage(DiskImageBase):
|
||||
return image, 'B'
|
||||
|
||||
|
||||
class Dos33BinFile(object):
|
||||
"""Parse a binary chunk into segments according to the DOS 3.3 binary
|
||||
dump format
|
||||
"""
|
||||
|
||||
def __init__(self, rawdata):
|
||||
self.rawdata = rawdata
|
||||
self.size = len(rawdata)
|
||||
self.segments = []
|
||||
self.files = []
|
||||
|
||||
def __str__(self):
|
||||
return "\n".join(str(s) for s in self.segments) + "\n"
|
||||
|
||||
def strict_check(self):
|
||||
pass
|
||||
|
||||
def relaxed_check(self):
|
||||
pass
|
||||
|
||||
def parse_segments(self):
|
||||
r = self.rawdata
|
||||
b = r.get_data()
|
||||
s = r.get_style()
|
||||
pos = 0
|
||||
style_pos = 0
|
||||
first = True
|
||||
log.debug("Initial parsing: size=%d" % self.size)
|
||||
if len(b[pos:pos + 4]) == 4:
|
||||
start, count = b[pos:pos + 4].view(dtype='<u2')
|
||||
s[pos:pos + 4] = get_style_bits(data=True)
|
||||
data = b[pos + 4:pos + 4 + count]
|
||||
if len(data) == count:
|
||||
name = "BSAVE data" % start
|
||||
else:
|
||||
name = "Incomplete data: expected %04x, loaded %04x" % (count, len(data))
|
||||
self.segments.append(ObjSegment(r[pos + 4:pos + 4 + count], pos, pos + 4, start, start + len(data), name))
|
||||
|
||||
else:
|
||||
self.segments.append(ObjSegment(r[pos:pos + 4], 0, 0, 0, len(b[pos:pos + 4]), "Short Segment Header"))
|
||||
|
||||
|
||||
class ProdosHeader(Dos33Header):
|
||||
file_format = "ProDOS"
|
||||
|
||||
|
@ -6,7 +6,7 @@ from ataridos import AtariDosDiskImage, BootDiskImage, AtariDosFile, XexContaine
|
||||
from spartados import SpartaDosDiskImage
|
||||
from cartridge import AtariCartImage, get_known_carts
|
||||
from mame import MameZipImage
|
||||
from dos33 import Dos33DiskImage, ProdosDiskImage
|
||||
from dos33 import Dos33DiskImage, ProdosDiskImage, Dos33BinFile
|
||||
from errors import *
|
||||
|
||||
import logging
|
||||
@ -130,6 +130,11 @@ class Dos33SegmentParser(SegmentParser):
|
||||
image_type = Dos33DiskImage
|
||||
|
||||
|
||||
class Dos33BinSegmentParser(SegmentParser):
|
||||
menu_name = "BIN (Apple ][ executable)"
|
||||
image_type = Dos33BinFile
|
||||
|
||||
|
||||
class ProdosSegmentParser(SegmentParser):
|
||||
menu_name = "ProDOS Disk Image"
|
||||
image_type = ProdosDiskImage
|
||||
@ -187,6 +192,9 @@ mime_parsers = {
|
||||
Dos33SegmentParser,
|
||||
ProdosSegmentParser,
|
||||
],
|
||||
"application/vnd.apple2.bin": [
|
||||
Dos33BinSegmentParser,
|
||||
],
|
||||
}
|
||||
|
||||
mime_parse_order = [
|
||||
@ -196,6 +204,7 @@ mime_parse_order = [
|
||||
"application/vnd.atari8bit.5200_cart",
|
||||
"application/vnd.mame_rom",
|
||||
"application/vnd.apple2.dsk",
|
||||
"application/vnd.apple2.bin",
|
||||
]
|
||||
|
||||
pretty_mime = {
|
||||
@ -205,6 +214,7 @@ pretty_mime = {
|
||||
"application/vnd.atari8bit.5200_cart":"Atari 5200 Cartridge",
|
||||
"application/vnd.mame_rom": "MAME",
|
||||
"application/vnd.apple2.dsk": "Apple ][ Disk Image",
|
||||
"application/vnd.apple2.bin": "Apple ][ Binary",
|
||||
}
|
||||
|
||||
grouped_carts = get_known_carts()
|
||||
|
Loading…
Reference in New Issue
Block a user