mirror of
https://github.com/robmcmullen/atrcopy.git
synced 2024-11-29 11:51:14 +00:00
Added BaseHeader for superclass
This commit is contained in:
parent
04edbed853
commit
35c13bb9d5
@ -8,7 +8,74 @@ import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AtrHeader(object):
|
||||
class BaseHeader(object):
|
||||
file_format = "generic" # text descriptor of file format
|
||||
|
||||
def __init__(self, sector_size=256, initial_sectors=0, vtoc_sector=0, starting_sector_label=0):
|
||||
self.image_size = 0
|
||||
self.sector_size = sector_size
|
||||
self.initial_sector_size = 0
|
||||
self.num_initial_sectors = 0
|
||||
self.crc = 0
|
||||
self.unused = 0
|
||||
self.flags = 0
|
||||
self.header_offset = 0
|
||||
self.starting_sector_label = starting_sector_label
|
||||
self.max_sectors = 0 # number of sectors, -1 is unlimited
|
||||
self.tracks_per_disk = 0
|
||||
self.sectors_per_track = 0
|
||||
self.first_vtoc = vtoc_sector
|
||||
self.num_vtoc = 1
|
||||
self.extra_vtoc = []
|
||||
self.first_directory = 0
|
||||
self.num_directory = 0
|
||||
|
||||
def __len__(self):
|
||||
return self.header_offset
|
||||
|
||||
def to_array(self):
|
||||
header_bytes = np.zeros([self.header_offset], dtype=np.uint8)
|
||||
self.encode(header_bytes)
|
||||
return header_bytes
|
||||
|
||||
def encode(self, header_bytes):
|
||||
"""Subclasses should override this to put the byte values into the
|
||||
header.
|
||||
"""
|
||||
return
|
||||
|
||||
def sector_is_valid(self, sector):
|
||||
return (self.max_sectors < 0) | (sector >= self.starting_sector_label and sector < (self.max_sectors + self.starting_sector_label))
|
||||
|
||||
def get_pos(self, sector):
|
||||
"""Get index (into the raw data of the disk image) of start of sector
|
||||
|
||||
This base class method assumes the sectors are one after another, in
|
||||
order starting from the beginning of the raw data.
|
||||
"""
|
||||
if not self.sector_is_valid(sector):
|
||||
raise ByteNotInFile166("Sector %d out of range" % sector)
|
||||
pos = sector * self.sector_size + self.header_offset
|
||||
size = self.sector_size
|
||||
return pos, size
|
||||
|
||||
def sector_from_track(self, track, sector):
|
||||
return (track * self.sectors_per_track) + sector
|
||||
|
||||
def track_from_sector(self, sector):
|
||||
track, sector = divmod(sector, self.sectors_per_track)
|
||||
return track, sector
|
||||
|
||||
def check_size(self, size):
|
||||
raise InvalidDiskImage("BaseHeader subclasses need custom checks for size")
|
||||
|
||||
def strict_check(self, image):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
|
||||
class AtrHeader(BaseHeader):
|
||||
# ATR Format described in http://www.atarimax.com/jindroush.atari.org/afmtatr.html
|
||||
format = np.dtype([
|
||||
('wMagic', '<u2'),
|
||||
@ -22,16 +89,7 @@ class AtrHeader(object):
|
||||
file_format = "ATR"
|
||||
|
||||
def __init__(self, bytes=None, sector_size=128, initial_sectors=3, create=False):
|
||||
self.image_size = 0
|
||||
self.sector_size = sector_size
|
||||
self.crc = 0
|
||||
self.unused = 0
|
||||
self.flags = 0
|
||||
self.header_offset = 0
|
||||
self.starting_sector_label = 1
|
||||
self.initial_sector_size = sector_size
|
||||
self.num_initial_sectors = initial_sectors
|
||||
self.max_sectors = 0
|
||||
BaseHeader.__init__(self, sector_size, initial_sectors, 360)
|
||||
if create:
|
||||
self.header_offset = 16
|
||||
self.check_size(0)
|
||||
@ -54,11 +112,7 @@ class AtrHeader(object):
|
||||
def __str__(self):
|
||||
return "%s Disk Image (size=%d (%dx%db), crc=%d flags=%d unused=%d)" % (self.file_format, self.image_size, self.max_sectors, self.sector_size, self.crc, self.flags, self.unused)
|
||||
|
||||
def __len__(self):
|
||||
return self.header_offset
|
||||
|
||||
def to_array(self):
|
||||
raw = np.zeros([16], dtype=np.uint8)
|
||||
def encode(self, raw):
|
||||
values = raw.view(dtype=self.format)[0]
|
||||
values[0] = 0x296
|
||||
paragraphs = self.image_size / 16
|
||||
@ -89,15 +143,15 @@ class AtrHeader(object):
|
||||
self.num_initial_sectors = 3
|
||||
else:
|
||||
self.image_size = size
|
||||
self.first_vtoc = 360
|
||||
self.num_vtoc = 1
|
||||
self.first_directory = 361
|
||||
self.num_directory = 8
|
||||
self.tracks_per_disk = 40
|
||||
self.sectors_per_track = 18
|
||||
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
|
||||
|
||||
def get_pos(self, sector):
|
||||
if not self.sector_is_valid(sector):
|
||||
raise ByteNotInFile166("Sector %d out of range" % sector)
|
||||
|
@ -1,7 +1,7 @@
|
||||
import numpy as np
|
||||
|
||||
from errors import *
|
||||
from diskimages import AtrHeader, DiskImageBase, Directory, VTOC, WriteableSector, BaseSectorList
|
||||
from diskimages import BaseHeader, DiskImageBase, Directory, VTOC, WriteableSector, BaseSectorList
|
||||
from segments import DefaultSegment, EmptySegment, ObjSegment, RawTrackSectorSegment, SegmentSaver
|
||||
|
||||
import logging
|
||||
@ -279,59 +279,30 @@ class Dos33Dirent(object):
|
||||
self.deleted = False
|
||||
|
||||
|
||||
class Dos33Header(AtrHeader):
|
||||
class Dos33Header(BaseHeader):
|
||||
file_format = "DOS 3.3"
|
||||
|
||||
def __init__(self):
|
||||
AtrHeader.__init__(self, None, 256, 0)
|
||||
self.starting_sector_label = 0
|
||||
self.header_offset = 0
|
||||
self.sector_order = range(16)
|
||||
self.vtoc_sector = 17 * 16
|
||||
self.tracks_per_disk = 0
|
||||
self.sectors_per_track = 0
|
||||
self.max_sectors = -1
|
||||
BaseHeader.__init__(self, 256)
|
||||
|
||||
def __str__(self):
|
||||
return "%s Disk Image (size=%d (%dx%db)" % (self.file_format, self.image_size, self.max_sectors, self.sector_size)
|
||||
|
||||
def __len__(self):
|
||||
return 0
|
||||
|
||||
def to_array(self):
|
||||
raw = np.zeros([0], dtype=np.uint8)
|
||||
return raw
|
||||
|
||||
def check_size(self, size):
|
||||
AtrHeader.check_size(self, size)
|
||||
if size != 143360:
|
||||
raise InvalidDiskImage("Incorrect size for DOS 3.3 image")
|
||||
self.first_vtoc = 17 * 16
|
||||
self.num_vtoc = 1
|
||||
self.first_directory = self.first_vtoc + 15
|
||||
self.num_directory = 8
|
||||
self.tracks_per_disk = 35
|
||||
self.sectors_per_track = 16
|
||||
self.max_sectors = self.tracks_per_disk * self.sectors_per_track
|
||||
|
||||
def sector_is_valid(self, sector):
|
||||
# DOS 3.3 sectors count from 0
|
||||
return (self.max_sectors < 0) | (sector >= 0 and sector < self.max_sectors)
|
||||
|
||||
def get_pos(self, sector):
|
||||
if not self.sector_is_valid(sector):
|
||||
raise ByteNotInFile166("Sector %d out of range" % sector)
|
||||
pos = sector * self.sector_size
|
||||
size = self.sector_size
|
||||
return pos, size
|
||||
|
||||
def sector_from_track(self, track, sector):
|
||||
return track * 16 + sector
|
||||
|
||||
def track_from_sector(self, sector):
|
||||
track, sector = divmod(sector, 16)
|
||||
return track, sector
|
||||
|
||||
|
||||
class Dos33DiskImage(DiskImageBase):
|
||||
def __init__(self, rawdata, filename=""):
|
||||
self.first_catalog = 0
|
||||
self.first_directory = 0
|
||||
DiskImageBase.__init__(self, rawdata, filename)
|
||||
|
||||
def __str__(self):
|
||||
@ -367,10 +338,10 @@ class Dos33DiskImage(DiskImageBase):
|
||||
if (magic == [1, 56, 176, 3]).all():
|
||||
raise InvalidDiskImage("ProDOS format found; not DOS 3.3 image")
|
||||
swap_order = False
|
||||
data, style = self.get_sectors(self.header.vtoc_sector)
|
||||
data, style = self.get_sectors(self.header.first_vtoc)
|
||||
if data[3] == 3:
|
||||
if data[1] < 35 and data[2] < 16:
|
||||
data, style = self.get_sectors(self.header.vtoc_sector + 14)
|
||||
data, style = self.get_sectors(self.header.first_vtoc + 14)
|
||||
if data[2] != 13:
|
||||
swap_order = True
|
||||
else:
|
||||
@ -397,17 +368,18 @@ class Dos33DiskImage(DiskImageBase):
|
||||
])
|
||||
|
||||
def get_vtoc(self):
|
||||
data, style = self.get_sectors(self.header.vtoc_sector)
|
||||
data, style = self.get_sectors(self.header.first_vtoc)
|
||||
values = data[0:self.vtoc_type.itemsize].view(dtype=self.vtoc_type)[0]
|
||||
self.first_catalog = self.header.sector_from_track(values[1], values[2])
|
||||
self.assert_valid_sector(self.first_catalog)
|
||||
self.total_sectors = int(values['num_tracks']) * int(values['sectors_per_track'])
|
||||
self.first_directory = self.header.sector_from_track(values['cat_track'], values['cat_sector'])
|
||||
self.sector_size = int(values['bytes_per_sector'])
|
||||
self.max_sectors = int(values['num_tracks']) * int(values['sectors_per_track'])
|
||||
self.dos_release = values['dos_release']
|
||||
self.last_track_num = values['last_track']
|
||||
self.track_alloc_dir = values['track_dir']
|
||||
self.assert_valid_sector(self.first_directory)
|
||||
|
||||
def get_directory(self, directory=None):
|
||||
sector = self.first_catalog
|
||||
sector = self.first_directory
|
||||
num = 0
|
||||
files = []
|
||||
while sector > 0:
|
||||
@ -451,8 +423,8 @@ class Dos33DiskImage(DiskImageBase):
|
||||
r = self.rawdata
|
||||
segments = []
|
||||
addr = 0
|
||||
start, count = self.get_contiguous_sectors(self.header.vtoc_sector, 1)
|
||||
segment = RawTrackSectorSegment(r[start:start+count], self.header.vtoc_sector, 1, count, 0, 0, self.header.sector_size, name="VTOC")
|
||||
start, count = self.get_contiguous_sectors(self.header.first_vtoc, 1)
|
||||
segment = RawTrackSectorSegment(r[start:start+count], self.header.first_vtoc, 1, count, 0, 0, self.header.sector_size, name="VTOC")
|
||||
segments.append(segment)
|
||||
return segments
|
||||
|
||||
@ -460,7 +432,7 @@ class Dos33DiskImage(DiskImageBase):
|
||||
byte_order = []
|
||||
r = self.rawdata
|
||||
segments = []
|
||||
sector = self.first_catalog
|
||||
sector = self.first_directory
|
||||
while sector > 0:
|
||||
self.assert_valid_sector(sector)
|
||||
print "reading catalog sector", sector
|
||||
@ -474,7 +446,7 @@ class Dos33DiskImage(DiskImageBase):
|
||||
|
||||
def get_next_directory_sector(self, sector):
|
||||
if sector == -1:
|
||||
sector = self.first_catalog
|
||||
sector = self.first_directory
|
||||
print "reading catalog sector", sector
|
||||
self.assert_valid_sector(sector)
|
||||
raw, _, _ = self.get_raw_bytes(sector)
|
||||
|
Loading…
Reference in New Issue
Block a user