mirror of
https://github.com/robmcmullen/atrcopy.git
synced 2024-09-26 22:56:44 +00:00
Refs #1: added detection of DCM images
This commit is contained in:
parent
1a7381b865
commit
7659499fdb
@ -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 .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 .spartados import SpartaDosDiskImage
|
||||||
from .cartridge import A8CartHeader, AtariCartImage
|
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 .magic import guess_detail_for_mime
|
||||||
from .utils import to_numpy, text_to_int
|
from .utils import to_numpy, text_to_int
|
||||||
|
|
||||||
@ -60,6 +60,11 @@ def find_diskimage(filename):
|
|||||||
print("Loading file %s" % filename)
|
print("Loading file %s" % filename)
|
||||||
rawdata = SegmentData(fh.read())
|
rawdata = SegmentData(fh.read())
|
||||||
parser = None
|
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:
|
for mime in mime_parse_order:
|
||||||
if options.verbose:
|
if options.verbose:
|
||||||
print("Trying MIME type %s" % mime)
|
print("Trying MIME type %s" % mime)
|
||||||
|
12
atrcopy/container.py
Normal file
12
atrcopy/container.py
Normal 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
41
atrcopy/dcm.py
Normal 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")
|
@ -65,3 +65,11 @@ class NotEnoughSpaceOnDisk(AtrError):
|
|||||||
|
|
||||||
class FileNotFound(AtrError):
|
class FileNotFound(AtrError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class UnsupportedContainer(AtrError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidContainer(AtrError):
|
||||||
|
pass
|
||||||
|
@ -10,6 +10,7 @@ from .dos33 import Dos33DiskImage, ProdosDiskImage, Dos33BinFile
|
|||||||
from .standard_delivery import StandardDeliveryImage
|
from .standard_delivery import StandardDeliveryImage
|
||||||
from . import errors
|
from . import errors
|
||||||
from .magic import guess_detail_for_mime
|
from .magic import guess_detail_for_mime
|
||||||
|
from .dcm import DCMContainer
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -157,6 +158,22 @@ class ProdosSegmentParser(SegmentParser):
|
|||||||
image_type = ProdosDiskImage
|
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):
|
def guess_parser_for_mime(mime, r, verbose=False):
|
||||||
parsers = mime_parsers[mime]
|
parsers = mime_parsers[mime]
|
||||||
found = None
|
found = None
|
||||||
@ -182,6 +199,9 @@ def guess_parser_for_system(mime_base, r):
|
|||||||
|
|
||||||
|
|
||||||
def iter_parsers(r):
|
def iter_parsers(r):
|
||||||
|
container = guess_container(r.data)
|
||||||
|
if container is not None:
|
||||||
|
r = container.unpacked
|
||||||
for mime in mime_parse_order:
|
for mime in mime_parse_order:
|
||||||
p = guess_parser_for_mime(mime, r)
|
p = guess_parser_for_mime(mime, r)
|
||||||
if p is not None:
|
if p is not None:
|
||||||
|
Loading…
Reference in New Issue
Block a user