Refs #1: added detection of DCM images

This commit is contained in:
Rob McMullen 2018-06-24 17:21:47 -07:00
parent 1a7381b865
commit 7659499fdb
5 changed files with 87 additions and 1 deletions

View File

@ -20,7 +20,7 @@ from .kboot import KBootImage, add_xexboot_header
from .segments import SegmentData, SegmentSaver, DefaultSegment, EmptySegment, ObjSegment, RawSectorsSegment, SegmentedFileSegment, user_bit_mask, match_bit_mask, comment_bit_mask, data_style, selected_bit_mask, diff_bit_mask, not_user_bit_mask, interleave_segments, SegmentList, get_style_mask, get_style_bits
from .spartados import SpartaDosDiskImage
from .cartridge import A8CartHeader, AtariCartImage
from .parsers import SegmentParser, DefaultSegmentParser, guess_parser_for_mime, guess_parser_for_system, iter_parsers, iter_known_segment_parsers, mime_parse_order, parsers_for_filename
from .parsers import SegmentParser, DefaultSegmentParser, guess_parser_for_mime, guess_parser_for_system, guess_container, iter_known_segment_parsers, mime_parse_order, parsers_for_filename
from .magic import guess_detail_for_mime
from .utils import to_numpy, text_to_int
@ -60,6 +60,11 @@ def find_diskimage(filename):
print("Loading file %s" % filename)
rawdata = SegmentData(fh.read())
parser = None
try:
unpacked = guess_container(rawdata.data)
except errors.UnsupportedContainer as e:
print(f"{filename}: {e}")
return None
for mime in mime_parse_order:
if options.verbose:
print("Trying MIME type %s" % mime)

12
atrcopy/container.py Normal file
View File

@ -0,0 +1,12 @@
import numpy as np
from . import errors
from .segments import SegmentData
class DiskImageContainer:
def __init__(self, data):
self.unpacked = self.unpack_raw_data(data)
def unpack_raw_data(self, data):
pass

41
atrcopy/dcm.py Normal file
View File

@ -0,0 +1,41 @@
import numpy as np
from . import errors
from .container import DiskImageContainer
from .segments import SegmentData
class DCMContainer(DiskImageContainer):
valid_densities = {
0: (720, 128),
1: (720, 256),
2: (1040, 128),
}
def get_next(self):
try:
data = self.raw[self.index]
except IndexError:
raise errors.InvalidContainer
else:
self.index += 1
return data
def unpack_raw_data(self, data):
self.index = 0
self.count = len(data)
self.raw = data
archive_type = self.get_next()
if archive_type == 0xf9 or archive_type == 0xfa:
archive_flags = self.get_next()
if archive_flags & 0x1f != 1:
if archive_type == 0xf9:
raise errors.InvalidContainer("DCM multi-file archive combined in the wrong order")
else:
raise errors.InvalidContainer("Expected pass one of DCM archive first")
density_flag = (archive_flags >> 5) & 3
if density_flag not in self.valid_densities:
raise errors.InvalidContainer(f"Unsupported density flag {density_flag} in DCM")
else:
raise errors.InvalidContainer("Not a DCM file")
raise errors.UnsupportedContainer("DCM archives are not yet supported")

View File

@ -65,3 +65,11 @@ class NotEnoughSpaceOnDisk(AtrError):
class FileNotFound(AtrError):
pass
class UnsupportedContainer(AtrError):
pass
class InvalidContainer(AtrError):
pass

View File

@ -10,6 +10,7 @@ from .dos33 import Dos33DiskImage, ProdosDiskImage, Dos33BinFile
from .standard_delivery import StandardDeliveryImage
from . import errors
from .magic import guess_detail_for_mime
from .dcm import DCMContainer
import logging
log = logging.getLogger(__name__)
@ -157,6 +158,22 @@ class ProdosSegmentParser(SegmentParser):
image_type = ProdosDiskImage
known_containers = [
DCMContainer,
]
def guess_container(r):
for c in known_containers:
try:
found = c(r)
except errors.InvalidContainer:
continue
else:
return found
return None
def guess_parser_for_mime(mime, r, verbose=False):
parsers = mime_parsers[mime]
found = None
@ -182,6 +199,9 @@ def guess_parser_for_system(mime_base, r):
def iter_parsers(r):
container = guess_container(r.data)
if container is not None:
r = container.unpacked
for mime in mime_parse_order:
p = guess_parser_for_mime(mime, r)
if p is not None: