Added strict/relaxed checking to allow autoload scanning to match as narrowly as possible

* added cart image names from atari800 source
This commit is contained in:
Rob McMullen 2016-06-02 16:59:59 -07:00
parent be7dd609c7
commit 7500aafce1
4 changed files with 121 additions and 75 deletions

View File

@ -153,6 +153,12 @@ class AtariDosFile(object):
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

View File

@ -7,6 +7,10 @@ from segments import SegmentData, EmptySegment, ObjSegment
from diskimages import DiskImageBase
from utils import to_numpy
import logging
log = logging.getLogger(__name__)
# From atari800 source
known_cart_types = [
# (note: all size units in KB)
@ -19,74 +23,74 @@ known_cart_types = [
# banked size
# banked offset (for bank zero)
# banked address
(0, "", 0,),
(1, "Standard 8K", 8, 8, 0, 0xa000),
(2, "Standard 16K", 16, 16, 0, 0x8000),
(3, "OSS 16K", 16, 4, 12, 0xb000, 4, 0, 0xa000),
(4, "5200 32K", 32, 32, 0, 0x4000),
(5, "DB 32K", 32,),
(6, "5200 EE 16K", 16,),
(7, "5200 BBSB 40K", 40,),
(8, "WILL 64K", 64,),
(9, "EXP_64K", 64,),
(10, "DIAMOND_64K", 64,),
(11, "SDX_64K", 64,),
(12, "XEGS_32K", 32, 8, 24, 0xa000, 8, 0, 0x8000),
(13, "XEGS_64_07K", 64, 8, 56, 0xa000, 8, 0, 0x8000),
(14, "XEGS_128K", 128, 8, 120, 0xa000, 8, 0, 0x8000),
(15, "OSS_M091_16K", 16,),
(16, "5200_NS_16K", 16,),
(17, "ATRAX_128K", 128,),
(18, "BBSB_40K", 40,),
(19, "5200_8K", 8, 8, 0, 0x8000),
(20, "5200_4K", 4, 4, 0, 0x8000),
(21, "RIGHT_8K", 8,),
(22, "WILL_32K", 32,),
(23, "XEGS_256K", 256, 8, 248, 0xa000, 8, 0, 0x8000),
(24, "XEGS_512K", 512, 8, 504, 0xa000, 8, 0, 0x8000),
(25, "XEGS_1024K", 1024, 8, 1016, 0xa000, 8, 0, 0x8000 ),
(26, "MEGA_16K", 16,),
(27, "MEGA_32K", 32,),
(28, "MEGA_64K", 64,),
(29, "MEGA_128K", 128,),
(30, "MEGA_256K", 256,),
(31, "MEGA_512K", 512,),
(32, "MEGA_1024K", 1024,),
(33, "SWXEGS_32K", 32, 8, 24, 0xa000, 8, 0, 0x8000),
(34, "SWXEGS_64K", 64, 8, 56, 0xa000, 8, 0, 0x8000),
(35, "SWXEGS_128K", 128, 8, 120, 0xa000, 8, 0, 0x8000),
(36, "SWXEGS_256K", 256, 8, 248, 0xa000, 8, 0, 0x8000),
(37, "SWXEGS_512K", 512, 8, 504, 0xa000, 8, 0, 0x8000),
(38, "SWXEGS_1024K", 1024, 8, 1016, 0xa000, 8, 0, 0x8000 ),
(39, "PHOENIX_8K", 8,),
(40, "BLIZZARD_16K", 16, 16, 0, 0x8000),
(41, "ATMAX_128K", 128,),
(42, "ATMAX_1024K", 1024,),
(43, "SDX_128K", 128,),
(44, "OSS_8K", 8,),
(45, "OSS_043M_16K", 16, 4, 12, 0xb000, 4, 0, 0xa000),
(46, "BLIZZARD_4K", 4,),
(47, "AST_32K", 32,),
(48, "ATRAX_SDX_64K", 64,),
(49, "ATRAX_SDX_128K", 128,),
(50, "TURBOSOFT_64K", 64,),
(51, "TURBOSOFT_128K", 128,),
(52, "ULTRACART_32K", 32,),
(53, "LOW_BANK_8K", 8, 8, 0, 0x8000),
(54, "SIC_128K", 128,),
(55, "SIC_256K", 256,),
(56, "SIC_512K", 512,),
(57, "Standard 2K", 2, 2, 0, 0xb800),
(58, "Standard 4K", 4, 4, 0, 0xb000),
(59, "Right 4K", 4, 4, 4, 0, 0x9000),
(60, "TURBO_HIT_32K", 32,),
(61, "MEGA_2048K", 2048,),
(62, "THECART_128MK", 128*1024,),
(63, "MEGA_4096K", 4096,),
(64, "MEGA_2048K", 2048,),
(65, "THECART_32MK", 32*1024,),
(66, "THECART_64MK", 64*1024,),
(67, "XEGS_64_8FK", 64),
(0, "", 0,),
(1, "Standard 8 KB", 8, 8, 0, 0xa000),
(2, "Standard 16 KB", 16, 16, 0, 0x8000),
(3, "OSS two chip (034M) 16 KB", 16, 4, 12, 0xb000, 4, 0, 0xa000),
(4, "Standard 32 KB 5200", 32, 32, 0, 0x4000),
(5, "DB 32 KB", 32,),
(6, "Two chip 16 KB 5200", 16,),
(7, "Bounty Bob 40 KB 5200", 40,),
(8, "Williams 64 KB", 64,),
(9, "Express 64 KB", 64,),
(10, "Diamond 64 KB", 64,),
(11, "SpartaDOS X 64 KB", 64,),
(12, "XEGS 32 KB", 32, 8, 24, 0xa000, 8, 0, 0x8000),
(13, "XEGS (banks 0-7) 64 KB", 64, 8, 56, 0xa000, 8, 0, 0x8000),
(14, "XEGS 128 KB", 128, 8, 120, 0xa000, 8, 0, 0x8000),
(15, "OSS one chip 16 KB", 16,),
(16, "One chip 16 KB 5200", 16,),
(17, "Atrax 128 KB", 128,),
(18, "Bounty Bob 40 KB", 40,),
(19, "Standard 8 KB 5200", 8, 8, 0, 0x8000),
(20, "Standard 4 KB 5200", 4, 4, 0, 0x8000),
(21, "Right slot 8 KB", 8,),
(22, "Williams 32 KB", 32,),
(23, "XEGS 256 KB", 256, 8, 248, 0xa000, 8, 0, 0x8000),
(24, "XEGS 512 KB", 512, 8, 504, 0xa000, 8, 0, 0x8000),
(25, "XEGS 1 MB", 1024, 8, 1016, 0xa000, 8, 0, 0x8000 ),
(26, "MegaCart 16 KB", 16,),
(27, "MegaCart 32 KB", 32,),
(28, "MegaCart 64 KB", 64,),
(29, "MegaCart 128 KB", 128,),
(30, "MegaCart 256 KB", 256,),
(31, "MegaCart 512 KB", 512,),
(32, "MegaCart 1 MB", 1024,),
(33, "Switchable XEGS 32 KB", 32, 8, 24, 0xa000, 8, 0, 0x8000),
(34, "Switchable XEGS 64 KB", 64, 8, 56, 0xa000, 8, 0, 0x8000),
(35, "Switchable XEGS 128 KB", 128, 8, 120, 0xa000, 8, 0, 0x8000),
(36, "Switchable XEGS 256 KB", 256, 8, 248, 0xa000, 8, 0, 0x8000),
(37, "Switchable XEGS 512 KB", 512, 8, 504, 0xa000, 8, 0, 0x8000),
(38, "Switchable XEGS 1 MB", 1024, 8, 1016, 0xa000, 8, 0, 0x8000 ),
(39, "Phoenix 8 KB", 8,),
(40, "Blizzard 16 KB", 16, 16, 0, 0x8000),
(41, "Atarimax 128 KB Flash", 128,),
(42, "Atarimax 1 MB Flash", 1024,),
(43, "SpartaDOS X 128 KB", 128,),
(44, "OSS 8 KB", 8,),
(45, "OSS two chip (043M) 16 KB", 16, 4, 12, 0xb000, 4, 0, 0xa000),
(46, "Blizzard 4 KB", 4,),
(47, "AST 32 KB", 32,),
(48, "Atrax SDX 64 KB", 64,),
(49, "Atrax SDX 128 KB", 128,),
(50, "Turbosoft 64 KB", 64,),
(51, "Turbosoft 128 KB", 128,),
(52, "Ultracart 32 KB", 32,),
(53, "Low bank 8 KB", 8, 8, 0, 0x8000),
(54, "SIC! 128 KB", 128,),
(55, "SIC! 256 KB", 256,),
(56, "SIC! 512 KB", 512,),
(57, "Standard 2 KB", 2, 2, 0, 0xb800),
(58, "Standard 4 KB", 4, 4, 0, 0xb000),
(59, "Right slot 4 KB", 4, 4, 4, 0, 0x9000),
(60, "Blizzard 32 KB", 32,),
(61, "MegaMax 2 MB", 2048,),
(62, "The!Cart 128 MB", 128*1024,),
(63, "Flash MegaCart 4 MB", 4096,),
(64, "MegaCart 2 MB", 2048,),
(65, "The!Cart 32 MB", 32*1024,),
(66, "The!Cart 64 MB", 64*1024,),
(67, "XEGS (banks 8-15) 64 KB", 64, 8, 56, 0xa000, 8, 0, 0x8000),
]
def get_known_carts():
@ -156,11 +160,11 @@ class A8CartHeader(object):
return raw
def set_type(self, cart_type):
print "TYPE", cart_type
self.cart_type = cart_type
c = known_cart_types[cart_type]
self.cart_name = c[1]
self.cart_size = c[2]
self.main_size = self.cart_size
if len(c) >= 6:
self.main_size, self.main_offset, self.main_origin = c[3:6]
if len(c) >= 9:
@ -197,15 +201,23 @@ class AtariCartImage(DiskImageBase):
except InvalidCartHeader:
self.header = A8CartHeader()
self.header.set_type(self.cart_type)
def strict_check(self):
if self.header.cart_type != self.cart_type:
raise InvalidDiskImage("Cart type doesn't match type defined in header")
def relaxed_check(self):
if self.header.cart_type != self.cart_type:
# force the header to be the specified cart type
self.header = A8CartHeader()
self.header.set_type(self.cart_type)
def check_size(self):
if self.header is None:
return
k, rem = divmod((len(self) - len(self.header)), 1024)
c = known_cart_types[self.cart_type]
print "checking %s:" % c[1], k, rem, c[2]
log.debug("checking %s:" % c[1], k, rem, c[2])
if rem > 0:
raise InvalidDiskImage("Cart not multiple of 1K")
if k != c[2]:
@ -227,7 +239,6 @@ class AtariCartImage(DiskImageBase):
return [s]
def get_banked_segments(self):
print "HI", self.header.banks
segments = []
r = self.rawdata
for i, offset in enumerate(self.header.banks):

View File

@ -87,6 +87,9 @@ class AtrHeader(object):
self.sector_size = 128
initial_bytes = self.initial_sector_size * self.num_initial_sectors
self.max_sectors = ((self.image_size - initial_bytes) / self.sector_size) + self.num_initial_sectors
def strict_check(self, image):
pass
def sector_is_valid(self, sector):
return sector > 0 and sector <= self.max_sectors
@ -117,6 +120,12 @@ class XfdHeader(AtrHeader):
raw = np.zeros([0], dtype=np.uint8)
return raw
def strict_check(self, image):
size = len(image)
if size in [92160, 133120, 183936, 184320]:
return
raise InvalidDiskImage("Uncommon size of XFD file")
class DiskImageBase(object):
def __init__(self, rawdata, filename=""):
@ -159,6 +168,16 @@ class DiskImageBase(object):
self.get_vtoc()
self.get_directory()
self.check_sane()
def strict_check(self):
"""Perform the strictest of checks to verify the data is valid """
self.header.strict_check(self)
def relaxed_check(self):
"""Conform as much as possible to get the data to work with this
format.
"""
pass
@classmethod
def new_header(cls, diskimage, format="ATR"):

View File

@ -13,15 +13,17 @@ class SegmentParser(object):
menu_name = ""
image_type = None
def __init__(self, segment_data):
def __init__(self, segment_data, strict=False):
self.image = None
self.segments = []
self.strict = strict
self.parse(segment_data)
def parse(self, r):
self.segments.append(DefaultSegment(r, 0))
try:
self.image = self.get_image(r)
self.check_image()
self.image.parse_segments()
except AtrError:
raise InvalidSegmentParser
@ -30,6 +32,15 @@ class SegmentParser(object):
def get_image(self, r):
return self.image_type(r)
def check_image(self):
if self.strict:
try:
self.image.strict_check()
except AtrError:
raise InvalidSegmentParser
else:
self.image.relaxed_check()
class DefaultSegmentParser(SegmentParser):
menu_name = "Raw Data"
@ -78,7 +89,7 @@ def guess_parser_for_mime(mime, r):
found = None
for parser in parsers:
try:
found = parser(r)
found = parser(r, True)
break
except InvalidSegmentParser:
pass
@ -112,7 +123,6 @@ mime_parse_order = [
grouped_carts = get_known_carts()
sizes = sorted(grouped_carts.keys())
print sizes
for k in sizes:
if k >= 1024:
key = "application/vnd.atari8bit.%dmb_cart" % (k / 1024)