Added MAME segment parsing from Omnivore

This commit is contained in:
Rob McMullen 2016-06-03 12:40:48 -07:00
parent d8b100fd95
commit f969d27e43
4 changed files with 95 additions and 2 deletions

View File

@ -14,7 +14,7 @@ from kboot import KBootImage, add_xexboot_header
from segments import SegmentData, SegmentSaver, DefaultSegment, EmptySegment, ObjSegment, RawSectorsSegment, user_bit_mask, match_bit_mask, comment_bit_mask, data_bit_mask, selected_bit_mask, diff_bit_mask, not_user_bit_mask, interleave_segments
from spartados import SpartaDosDiskImage
from cartridge import A8CartHeader
from parsers import SegmentParser, DefaultSegmentParser, guess_parser_for_mime, guess_parser_for_system, iter_known_segment_parsers, mime_parse_order
from parsers import SegmentParser, DefaultSegmentParser, guess_parser_for_mime, guess_parser_for_system, iter_parsers, iter_known_segment_parsers, mime_parse_order
from utils import to_numpy

65
atrcopy/mame.py Normal file
View File

@ -0,0 +1,65 @@
import zipfile
import numpy as np
from errors import *
from segments import SegmentData, EmptySegment, ObjSegment
from diskimages import DiskImageBase
from utils import to_numpy
import logging
log = logging.getLogger(__name__)
class MameZipImage(DiskImageBase):
def __init__(self, rawdata, filename=""):
self.zipdata = rawdata
fh = self.zipdata.stringio
if zipfile.is_zipfile(fh):
with zipfile.ZipFile(fh) as zf:
self.check_zip_size(zf)
self.create_rawdata(zf)
else:
raise InvalidDiskImage("Not a MAME zip file")
DiskImageBase.__init__(self, self.rawdata, filename)
def __str__(self):
return "MAME Zip file, %d ROMs, orig_size=%d, uncompressed=%d" % (len(self.zip_segment_info), len(self.zipdata), len(self.rawdata))
def setup(self):
self.check_size()
def strict_check(self):
pass
def relaxed_check(self):
pass
def check_zip_size(self, zf):
for item in zf.infolist():
_, r = divmod(item.file_size, 256)
if r > 0:
raise InvalidDiskImage("zip entry not 256 byte multiple")
def create_rawdata(self, zf):
roms = []
segment_info = []
offset = 0
for item in zf.infolist():
rom = np.fromstring(zf.open(item).read(), dtype=np.uint8)
roms.append(rom)
segment_info.append((offset, item.file_size, item.filename, item.CRC))
offset += item.file_size
data = np.concatenate(roms)
self.zip_segment_info = segment_info
self.rawdata = SegmentData(data)
def check_size(self):
pass
def parse_segments(self):
r = self.rawdata
self.segments = []
for offset, size, name, crc in self.zip_segment_info:
end = offset + size
self.segments.append(ObjSegment(r[offset:end], 0, offset, offset, end, name=name))

View File

@ -6,6 +6,7 @@ from kboot import KBootImage
from ataridos import AtariDosDiskImage, AtariDosFile
from spartados import SpartaDosDiskImage
from cartridge import AtariCartImage, get_known_carts
from mame import MameZipImage
from errors import *
@ -84,6 +85,11 @@ class AtariCartSegmentParser(SegmentParser):
return self.image_type(r, self.cart_type)
class MameZipParser(SegmentParser):
menu_name = "MAME ROM Zipfile"
image_type = MameZipImage
def guess_parser_for_mime(mime, r):
parsers = mime_parsers[mime]
found = None
@ -103,6 +109,13 @@ def guess_parser_for_system(mime_base, r):
return mime, p
return None, None
def iter_parsers(r):
for mime in mime_parse_order:
p = guess_parser_for_mime(mime, r)
if p is not None:
return mime, p
return None, None
mime_parsers = {
"application/vnd.atari8bit.atr": [
@ -114,20 +127,27 @@ mime_parsers = {
"application/vnd.atari8bit.xex": [
XexSegmentParser,
],
"application/vnd.mame_rom": [
MameZipParser,
],
}
mime_parse_order = [
"application/vnd.atari8bit.atr",
"application/vnd.atari8bit.xex",
"CARTS", # Will get filled in below
"application/vnd.mame_rom",
]
pretty_mime = {
"application/vnd.atari8bit.atr": "Atari 8-bit Disk Image",
"application/vnd.atari8bit.xex": "Atari 8-bit Executable",
"application/vnd.mame_rom": "MAME"
}
grouped_carts = get_known_carts()
sizes = sorted(grouped_carts.keys())
cart_order = []
for k in sizes:
if k > 128:
key = "application/vnd.atari8bit.large_cart"
@ -136,13 +156,15 @@ for k in sizes:
key = "application/vnd.atari8bit.%dkb_cart" % k
pretty = "Atari 8-bit %dKB Cartridge" % k
if key not in mime_parsers:
mime_parse_order.append(key)
cart_order.append(key)
pretty_mime[key] = pretty
mime_parsers[key] = []
for c in grouped_carts[k]:
t = c[0]
kclass = type("AtariCartSegmentParser%d" % t, (AtariCartSegmentParser,), {'cart_type': t, 'cart_info': c, 'menu_name': "%s Cartridge" % c[1]})
mime_parsers[key].append(kclass)
i = mime_parse_order.index("CARTS")
mime_parse_order[i:i+1] = cart_order
known_segment_parsers = [DefaultSegmentParser]

View File

@ -1,4 +1,5 @@
import bisect
import cStringIO
import numpy as np
@ -95,6 +96,11 @@ class SegmentData(object):
def __len__(self):
return len(self.data)
@property
def stringio(self):
buf = cStringIO.StringIO(self.data[:])
return buf
def get_data(self):
return self.data