import numpy as np from . import errors from .ataridos import AtariDosDirent, AtariDosDiskImage, XexSegment from .segments import DefaultSegment, EmptySegment, ObjSegment, RawSectorsSegment, SegmentSaver import logging log = logging.getLogger(__name__) class SpartaDosDirent(AtariDosDirent): format = np.dtype([ ('status', 'u1'), ('sector', ' 0 self.hidden = (flag&0x10) > 0 self.archived = (flag&0x100) > 0 self.in_use = (flag&0b1000) > 0 self.deleted = (flag&0b10000) > 0 self.is_dir = (flag&0b100000) > 0 self.opened_output = (flag&0b10000000) > 0 self.starting_sector = int(values[1]) self.basename = bytes(values[4]).rstrip() if self.is_dir: self.ext = b"" else: self.ext = bytes(values[5]).rstrip() self.length = 256*256*values[3] + values[2] self.date_array = tuple(data[17:20]) self.time_array = tuple(data[20:23]) self.is_sane = self.sanity_check(image) def sanity_check(self, image): if not self.in_use: return True if not image.header.sector_is_valid(self.starting_sector): return False return True @property def str_timestamp(self): str_date = "%d/%d/%d" % self.date_array str_time = "%d:%d:%d" % self.time_array return "%s %s" % (str_date, str_time) def start_read(self, image): if not self.is_sane: log.debug("Invalid directory entry '%s', starting_sector=%s" % (str(self), self.starting_sector)) raise errors.InvalidDirent("Invalid directory entry '%s'" % str(self)) self.sector_map = image.get_sector_map(self.starting_sector) self.sector_map_index = 0 self.length_remaining = self.length def read_sector(self, image): sector = self.sector_map[self.sector_map_index] if sector == 0: return None, True, 0, self.length_remaining raw, pos, size = image.get_raw_bytes(sector) num_data_bytes = min(self.length_remaining, size) self.length_remaining -= num_data_bytes self.sector_map_index += 1 return raw[0:num_data_bytes], sector == 0, pos, num_data_bytes class SpartaDosDiskImage(AtariDosDiskImage): def __init__(self, *args, **kwargs): self.first_bitmap = 0 self.num_bitmap = 0 self.root_dir = 0 self.root_dir_dirent = None self.fs_version = 0 AtariDosDiskImage.__init__(self, *args, **kwargs) def __str__(self): return "%s Sparta DOS Format: %d usable sectors (%d free), %d files" % (self.header, self.total_sectors, self.unused_sectors, len(self.files)) boot_record_type = np.dtype([ ('unused', 'u1'), ('num_boot', 'u1'), ('boot_addr', ' 0: sectors = ObjSegment(r, 0, 0, addr, addr + len(r), name="Boot Sectors") code = ObjSegment(r[43:], 0, 0, addr + 43, addr + len(r), name="Boot Code") segments.extend([header, code]) return segments def get_vtoc_segments(self): r = self.rawdata segments = [] addr = 0 start, count = self.get_contiguous_sectors(self.first_bitmap, self.num_bitmap) if self.sector_size == 512: num_boot = 1 boot_size = 512 else: num_boot = 3 boot_size = 128 segment = RawSectorsSegment(r[start:start+count], self.first_bitmap, self.num_bitmap, count, 0, 0, self.sector_size, name="Bitmap") segments.append(segment) return segments def get_sector_map(self, sector): m = None while sector > 0: b, _ = self.get_sectors(sector) sector, prev = b[0:4].view(dtype=' 0: name = "%s %d@%d %s" % (dirent.filename, dirent.length, dirent.starting_sector, dirent.str_timestamp) verbose_name = "%s (%d bytes, sector map@%d) %s %s" % (dirent.filename, dirent.length, dirent.starting_sector, dirent.verbose_info, dirent.str_timestamp) raw = self.rawdata.get_indexed(byte_order) segment = DefaultSegment(raw, name=name, verbose_name=verbose_name) else: segment = EmptySegment(self.rawdata, name=dirent.filename, error=dirent.str_timestamp) return segment