mirror of
https://github.com/robmcmullen/atrcopy.git
synced 2025-02-13 00:33:28 +00:00
Progress on DOS 33 VTOC using complicated numpy manipulation.
* not complete, and may be easier to understand by using a reorder on the raw bytes rather than trying to convert to 16 bit values and skipping every other
This commit is contained in:
parent
b87335dfa8
commit
fe01a97c1f
@ -9,16 +9,64 @@ log = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
class Dos33VTOC(VTOC):
|
class Dos33VTOC(VTOC):
|
||||||
|
max_tracks = (256 - 0x38) / 4 # 50, but kept here in case sector size changed
|
||||||
|
max_sectors = max_tracks * 16
|
||||||
|
reorder_index = np.tile(np.arange(7, -1, -1), max_tracks * 2) + (np.repeat(np.arange(max_tracks * 2), 8) * 8)
|
||||||
|
|
||||||
def parse_segments(self, segments):
|
def parse_segments(self, segments):
|
||||||
self.vtoc1 = segments[0].data
|
# VTOC stored in groups of 4 bytes starting at 0x38
|
||||||
bits = np.unpackbits(self.vtoc1[0x0a:0x64])
|
# in bits, the sector used data is stored by track:
|
||||||
log.debug("vtoc before: %s" % bits)
|
#
|
||||||
self.sector_map[0:720] = bits
|
# FEDCBA98 76543210 xxxxxxxx xxxxxxxx
|
||||||
|
#
|
||||||
|
# where the x values are ignored (should be zeros). Track 0 info is
|
||||||
|
# found starting at 0x38, track 1 is found at 0x3c, etc.
|
||||||
|
#
|
||||||
|
# Want to convert this to an array that is a list of bits by
|
||||||
|
# track/sector number, i.e.:
|
||||||
|
#
|
||||||
|
# t0s0 t0s1 t0s2 t0s3 t0s4 t0s5 t0s6 t0s7 ... t1s0 t1s1 ... etc
|
||||||
|
#
|
||||||
|
# Problem: the bits are stored backwards, so a straight unpackbits will
|
||||||
|
# produce:
|
||||||
|
#
|
||||||
|
# t0sf t0se t0sd ...
|
||||||
|
#
|
||||||
|
# i.e. each group of 16 bits needs to be reversed.
|
||||||
|
self.vtoc = segments[0].data
|
||||||
|
|
||||||
|
# create a view using little-endian 16 bit values, skipping every other
|
||||||
|
# 16 bit value. This gets us 76543210FEDCBA98 76543210FEDCBA98 ... etc
|
||||||
|
expanded = self.vtoc[0x38:].view(dtype="<u2")
|
||||||
|
used = expanded[0::2]
|
||||||
|
|
||||||
|
# need to operate on a copy of the 16 bit values, because skipping
|
||||||
|
# every 2 and attempting to view as bytes results in a ValueError: "new
|
||||||
|
# type not compatible with array"
|
||||||
|
usedcopy = np.zeros([used.shape[0]], dtype="<u2")
|
||||||
|
usedcopy[:] = used
|
||||||
|
print repr(usedcopy)
|
||||||
|
|
||||||
|
# now convert to bytes, giving us 76543210 FEDCBA98 76543210 FEDCBA98
|
||||||
|
# ... etc, and unpack that to bits giving us a zero or one representing
|
||||||
|
# sectors 7 6 5 4 3 2 1 0 F E D ...
|
||||||
|
usedbytes = usedcopy.view(dtype=np.uint8)
|
||||||
|
bits = np.unpackbits(usedbytes)
|
||||||
|
|
||||||
|
# and now we need to reverse the order of each group of 8 numbers
|
||||||
|
self.sector_map[0:self.max_sectors] = bits[reorder_index]
|
||||||
|
log.debug("vtoc before: %s" % self.sector_map[0:35*16])
|
||||||
|
|
||||||
def calc_bitmap(self):
|
def calc_bitmap(self):
|
||||||
log.debug("vtoc after: %s" % self.sector_map[0:720])
|
log.debug("vtoc after: %s" % self.sector_map[0:35*16])
|
||||||
packed = np.packbits(self.sector_map[0:720])
|
|
||||||
self.vtoc1[0x0a:0x64] = packed
|
# bits inside bytes will be in the right order after this, but the
|
||||||
|
# bytes are still swapped and there are no gaps
|
||||||
|
packed = np.packbits(self.sector_map[self.reorder_index])
|
||||||
|
print packed
|
||||||
|
|
||||||
|
# FIXME
|
||||||
|
self.vtoc[0x38:] = packed
|
||||||
s = WriteableSector(self.bytes_per_sector, self.vtoc1)
|
s = WriteableSector(self.bytes_per_sector, self.vtoc1)
|
||||||
s.sector_num = 360
|
s.sector_num = 360
|
||||||
self.sectors.append(s)
|
self.sectors.append(s)
|
||||||
@ -239,7 +287,9 @@ class Dos33Header(AtrHeader):
|
|||||||
self.header_offset = 0
|
self.header_offset = 0
|
||||||
self.sector_order = range(16)
|
self.sector_order = range(16)
|
||||||
self.vtoc_sector = 17 * 16
|
self.vtoc_sector = 17 * 16
|
||||||
self.max_sectors = 35 * 16
|
self.tracks_per_disk = 0
|
||||||
|
self.sectors_per_track = 0
|
||||||
|
self.max_sectors = -1
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s Disk Image (size=%d (%dx%db)" % (self.file_format, self.image_size, self.max_sectors, self.sector_size)
|
return "%s Disk Image (size=%d (%dx%db)" % (self.file_format, self.image_size, self.max_sectors, self.sector_size)
|
||||||
@ -255,10 +305,13 @@ class Dos33Header(AtrHeader):
|
|||||||
AtrHeader.check_size(self, size)
|
AtrHeader.check_size(self, size)
|
||||||
if size != 143360:
|
if size != 143360:
|
||||||
raise InvalidDiskImage("Incorrect size for DOS 3.3 image")
|
raise InvalidDiskImage("Incorrect size for DOS 3.3 image")
|
||||||
|
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):
|
def sector_is_valid(self, sector):
|
||||||
# DOS 3.3 sectors count from 0
|
# DOS 3.3 sectors count from 0
|
||||||
return sector >= 0 and sector < self.max_sectors
|
return (self.max_sectors < 0) | (sector >= 0 and sector < self.max_sectors)
|
||||||
|
|
||||||
def get_pos(self, sector):
|
def get_pos(self, sector):
|
||||||
if not self.sector_is_valid(sector):
|
if not self.sector_is_valid(sector):
|
||||||
@ -344,11 +397,13 @@ class Dos33DiskImage(DiskImageBase):
|
|||||||
|
|
||||||
def get_vtoc(self):
|
def get_vtoc(self):
|
||||||
data, style = self.get_sectors(self.header.vtoc_sector)
|
data, style = self.get_sectors(self.header.vtoc_sector)
|
||||||
values = data[0:56].view(dtype=self.vtoc_type)[0]
|
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.first_catalog = self.header.sector_from_track(values[1], values[2])
|
||||||
self.assert_valid_sector(self.first_catalog)
|
self.assert_valid_sector(self.first_catalog)
|
||||||
self.total_sectors = int(values['num_tracks']) * int(values['sectors_per_track'])
|
self.total_sectors = int(values['num_tracks']) * int(values['sectors_per_track'])
|
||||||
self.dos_release = values['dos_release']
|
self.dos_release = values['dos_release']
|
||||||
|
self.last_track_num = values['last_track']
|
||||||
|
self.track_alloc_dir = values['track_dir']
|
||||||
|
|
||||||
def get_directory(self, directory=None):
|
def get_directory(self, directory=None):
|
||||||
sector = self.first_catalog
|
sector = self.first_catalog
|
||||||
|
Loading…
x
Reference in New Issue
Block a user