import zipfile import numpy as np from . import errors 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.bufferedio if zipfile.is_zipfile(fh): with zipfile.ZipFile(fh) as zf: self.check_zip_size(zf) self.create_rawdata(zf) else: raise errors.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, 16) if r > 0: raise errors.InvalidDiskImage("zip entry not 16 byte multiple") def create_rawdata(self, zf): roms = [] segment_info = [] offset = 0 for item in zf.infolist(): rom = np.frombuffer(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))