mirror of
https://github.com/robmcmullen/atrcopy.git
synced 2024-06-10 21:29:39 +00:00
WIP on DOS 3.3 support
This commit is contained in:
parent
7151739ad3
commit
d851a06ae1
|
@ -55,7 +55,7 @@ class AtariDosDirectory(Directory):
|
||||||
log.debug("encoded dirent: %s" % data)
|
log.debug("encoded dirent: %s" % data)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def set_sector_numbers(self):
|
def set_sector_numbers(self, image):
|
||||||
num = 361
|
num = 361
|
||||||
for sector in self.sectors:
|
for sector in self.sectors:
|
||||||
sector.sector_num = num
|
sector.sector_num = num
|
||||||
|
@ -137,7 +137,7 @@ class AtariDosDirent(object):
|
||||||
self.is_sane = self.sanity_check(image)
|
self.is_sane = self.sanity_check(image)
|
||||||
|
|
||||||
def encode_dirent(self):
|
def encode_dirent(self):
|
||||||
data = np.zeros([16], dtype=np.uint8)
|
data = np.zeros([self.format.itemsize], dtype=np.uint8)
|
||||||
values = data.view(dtype=self.format)[0]
|
values = data.view(dtype=self.format)[0]
|
||||||
flag = (1 * int(self.opened_output)) | (2 * int(self.dos_2)) | (4 * int(self.mydos)) | (0x10 * int(self.is_dir)) | (0x20 * int(self.locked)) | (0x40 * int(self.in_use)) | (0x80 * int(self.deleted))
|
flag = (1 * int(self.opened_output)) | (2 * int(self.dos_2)) | (4 * int(self.mydos)) | (0x10 * int(self.is_dir)) | (0x20 * int(self.locked)) | (0x40 * int(self.in_use)) | (0x80 * int(self.deleted))
|
||||||
values[0] = flag
|
values[0] = flag
|
||||||
|
|
|
@ -401,7 +401,7 @@ class DiskImageBase(object):
|
||||||
sector_list = self.sector_list_class(self.bytes_per_sector, self.payload_bytes_per_sector, data, self.writeable_sector_class)
|
sector_list = self.sector_list_class(self.bytes_per_sector, self.payload_bytes_per_sector, data, self.writeable_sector_class)
|
||||||
vtoc_segments = self.get_vtoc_segments()
|
vtoc_segments = self.get_vtoc_segments()
|
||||||
vtoc = self.vtoc_class(self.bytes_per_sector, vtoc_segments)
|
vtoc = self.vtoc_class(self.bytes_per_sector, vtoc_segments)
|
||||||
directory.save_dirent(dirent, vtoc, sector_list)
|
directory.save_dirent(self, dirent, vtoc, sector_list)
|
||||||
self.write_sector_list(sector_list)
|
self.write_sector_list(sector_list)
|
||||||
self.write_sector_list(vtoc)
|
self.write_sector_list(vtoc)
|
||||||
self.write_sector_list(directory)
|
self.write_sector_list(directory)
|
||||||
|
@ -427,7 +427,7 @@ class DiskImageBase(object):
|
||||||
sector_list = dirent.get_sector_list(self)
|
sector_list = dirent.get_sector_list(self)
|
||||||
vtoc_segments = self.get_vtoc_segments()
|
vtoc_segments = self.get_vtoc_segments()
|
||||||
vtoc = self.vtoc_class(self.bytes_per_sector, vtoc_segments)
|
vtoc = self.vtoc_class(self.bytes_per_sector, vtoc_segments)
|
||||||
directory.remove_dirent(dirent, vtoc, sector_list)
|
directory.remove_dirent(self, dirent, vtoc, sector_list)
|
||||||
self.write_sector_list(sector_list)
|
self.write_sector_list(sector_list)
|
||||||
self.write_sector_list(vtoc)
|
self.write_sector_list(vtoc)
|
||||||
self.write_sector_list(directory)
|
self.write_sector_list(directory)
|
||||||
|
@ -554,10 +554,10 @@ class Directory(BaseSectorList):
|
||||||
return dirent
|
return dirent
|
||||||
raise FileNotFound("%s not found on disk" % filename)
|
raise FileNotFound("%s not found on disk" % filename)
|
||||||
|
|
||||||
def save_dirent(self, dirent, vtoc, sector_list):
|
def save_dirent(self, image, dirent, vtoc, sector_list):
|
||||||
self.place_sector_list(dirent, vtoc, sector_list)
|
self.place_sector_list(dirent, vtoc, sector_list)
|
||||||
dirent.update_sector_info(sector_list)
|
dirent.update_sector_info(sector_list)
|
||||||
self.calc_sectors()
|
self.calc_sectors(image)
|
||||||
|
|
||||||
def place_sector_list(self, dirent, vtoc, sector_list):
|
def place_sector_list(self, dirent, vtoc, sector_list):
|
||||||
""" Map out the sectors and link the sectors together
|
""" Map out the sectors and link the sectors together
|
||||||
|
@ -583,18 +583,18 @@ class Directory(BaseSectorList):
|
||||||
last_sector.next_sector_num = 0
|
last_sector.next_sector_num = 0
|
||||||
sector_list.file_length = file_length
|
sector_list.file_length = file_length
|
||||||
|
|
||||||
def remove_dirent(self, dirent, vtoc, sector_list):
|
def remove_dirent(self, image, dirent, vtoc, sector_list):
|
||||||
vtoc.free_sector_list(sector_list)
|
vtoc.free_sector_list(sector_list)
|
||||||
dirent.mark_deleted()
|
dirent.mark_deleted()
|
||||||
self.calc_sectors()
|
self.calc_sectors(image)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def dirent_class(self):
|
def dirent_class(self):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def calc_sectors(self):
|
def calc_sectors(self, image):
|
||||||
self.sectors = []
|
self.sectors = []
|
||||||
self.current_sector = self.sector_class(self.bytes_per_sector)
|
self.current_sector = self.get_dirent_sector()
|
||||||
self.encode_index = 0
|
self.encode_index = 0
|
||||||
|
|
||||||
d = self.dirents.items()
|
d = self.dirents.items()
|
||||||
|
@ -610,7 +610,10 @@ class Directory(BaseSectorList):
|
||||||
data = self.encode_dirent(dirent)
|
data = self.encode_dirent(dirent)
|
||||||
self.store_encoded(data)
|
self.store_encoded(data)
|
||||||
current = index + 1
|
current = index + 1
|
||||||
self.finish_encoding()
|
self.finish_encoding(image)
|
||||||
|
|
||||||
|
def get_dirent_sector(self):
|
||||||
|
return self.sector_class(self.bytes_per_sector)
|
||||||
|
|
||||||
def encode_empty(self):
|
def encode_empty(self):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
@ -624,16 +627,16 @@ class Directory(BaseSectorList):
|
||||||
data = self.current_sector.add_data(data)
|
data = self.current_sector.add_data(data)
|
||||||
if len(data) > 0:
|
if len(data) > 0:
|
||||||
self.sectors.append(self.current_sector)
|
self.sectors.append(self.current_sector)
|
||||||
self.current_sector = self.sector_class(self.bytes_per_sector)
|
self.current_sector = self.get_dirent_sector()
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
def finish_encoding(self):
|
def finish_encoding(self, image):
|
||||||
if not self.current_sector.is_empty:
|
if not self.current_sector.is_empty:
|
||||||
self.sectors.append(self.current_sector)
|
self.sectors.append(self.current_sector)
|
||||||
self.set_sector_numbers()
|
self.set_sector_numbers(image)
|
||||||
|
|
||||||
def set_sector_numbers(self):
|
def set_sector_numbers(self, image):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
|
101
atrcopy/dos33.py
101
atrcopy/dos33.py
|
@ -1,13 +1,58 @@
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from errors import *
|
from errors import *
|
||||||
from diskimages import AtrHeader, DiskImageBase
|
from diskimages import AtrHeader, DiskImageBase, Directory, VTOC, WriteableSector, BaseSectorList
|
||||||
from segments import DefaultSegment, EmptySegment, ObjSegment, RawSectorsSegment, SegmentSaver
|
from segments import DefaultSegment, EmptySegment, ObjSegment, RawSectorsSegment, SegmentSaver
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class Dos33VTOC(VTOC):
|
||||||
|
def parse_segments(self, segments):
|
||||||
|
self.vtoc1 = segments[0].data
|
||||||
|
bits = np.unpackbits(self.vtoc1[0x0a:0x64])
|
||||||
|
log.debug("vtoc before: %s" % bits)
|
||||||
|
self.sector_map[0:720] = bits
|
||||||
|
|
||||||
|
def calc_bitmap(self):
|
||||||
|
log.debug("vtoc after: %s" % self.sector_map[0:720])
|
||||||
|
packed = np.packbits(self.sector_map[0:720])
|
||||||
|
self.vtoc1[0x0a:0x64] = packed
|
||||||
|
s = WriteableSector(self.bytes_per_sector, self.vtoc1)
|
||||||
|
s.sector_num = 360
|
||||||
|
self.sectors.append(s)
|
||||||
|
|
||||||
|
|
||||||
|
class Dos33Directory(Directory):
|
||||||
|
@property
|
||||||
|
def dirent_class(self):
|
||||||
|
return Dos33Dirent
|
||||||
|
|
||||||
|
def get_dirent_sector(self):
|
||||||
|
s = self.sector_class(self.bytes_per_sector)
|
||||||
|
data = np.zeros([0x0b], dtype=np.uint8)
|
||||||
|
s.add_data(data)
|
||||||
|
return s
|
||||||
|
|
||||||
|
def encode_empty(self):
|
||||||
|
return np.zeros([Dos33Dirent.format.itemsize], dtype=np.uint8)
|
||||||
|
|
||||||
|
def encode_dirent(self, dirent):
|
||||||
|
data = dirent.encode_dirent()
|
||||||
|
log.debug("encoded dirent: %s" % data)
|
||||||
|
return data
|
||||||
|
|
||||||
|
def set_sector_numbers(self, image):
|
||||||
|
num = image.get_next_directory_sector(-1)
|
||||||
|
for sector in self.sectors:
|
||||||
|
sector.sector_num = num
|
||||||
|
num = image.get_next_directory_sector(num)
|
||||||
|
t, s = image.pair_from_sector(num)
|
||||||
|
sector.data[1] = t
|
||||||
|
sector.data[2] = s
|
||||||
|
|
||||||
|
|
||||||
class Dos33Dirent(object):
|
class Dos33Dirent(object):
|
||||||
format = np.dtype([
|
format = np.dtype([
|
||||||
('track', 'u1'),
|
('track', 'u1'),
|
||||||
|
@ -44,8 +89,8 @@ class Dos33Dirent(object):
|
||||||
0x4: "B",
|
0x4: "B",
|
||||||
0x8: "S",
|
0x8: "S",
|
||||||
0x10: "R",
|
0x10: "R",
|
||||||
0x20: "A",
|
0x20: "new A",
|
||||||
0x40: "B",
|
0x40: "new B",
|
||||||
}
|
}
|
||||||
|
|
||||||
def summary(self):
|
def summary(self):
|
||||||
|
@ -76,6 +121,25 @@ class Dos33Dirent(object):
|
||||||
self.filename = (bytes[3:0x20] - 0x80).tostring().rstrip()
|
self.filename = (bytes[3:0x20] - 0x80).tostring().rstrip()
|
||||||
self.num_sectors = int(values[4])
|
self.num_sectors = int(values[4])
|
||||||
self.is_sane = self.sanity_check(image)
|
self.is_sane = self.sanity_check(image)
|
||||||
|
|
||||||
|
def encode_dirent(self):
|
||||||
|
data = np.zeros([self.format.itemsize], dtype=np.uint8)
|
||||||
|
values = data.view(dtype=self.format)[0]
|
||||||
|
flag = (1 * int(self.opened_output)) | (2 * int(self.dos_2)) | (4 * int(self.mydos)) | (0x10 * int(self.is_dir)) | (0x20 * int(self.locked)) | (0x40 * int(self.in_use)) | (0x80 * int(self.locked))
|
||||||
|
values[0] = flag
|
||||||
|
values[1] = self.num_sectors
|
||||||
|
values[2] = self.starting_sector
|
||||||
|
values[3] = self.filename
|
||||||
|
values[4] = self.ext
|
||||||
|
return data
|
||||||
|
|
||||||
|
def mark_deleted(self):
|
||||||
|
self.deleted = True
|
||||||
|
self.in_use = False
|
||||||
|
|
||||||
|
def update_sector_info(self, sector_list):
|
||||||
|
self.num_sectors = sector_list.num_sectors
|
||||||
|
self.starting_sector = sector_list.first_sector
|
||||||
|
|
||||||
def sanity_check(self, image):
|
def sanity_check(self, image):
|
||||||
if self.deleted:
|
if self.deleted:
|
||||||
|
@ -107,6 +171,20 @@ class Dos33Dirent(object):
|
||||||
break
|
break
|
||||||
sector_list.append(image.header.sector_from_track(t, s))
|
sector_list.append(image.header.sector_from_track(t, s))
|
||||||
self.sector_map = sector_list
|
self.sector_map = sector_list
|
||||||
|
|
||||||
|
def get_sector_list(self, image):
|
||||||
|
sector_list = BaseSectorList(image.bytes_per_sector)
|
||||||
|
self.start_read(image)
|
||||||
|
sector_num = image.header.sector_from_track(self.track, self.sector)
|
||||||
|
while sector_num > 0:
|
||||||
|
sector = WriteableSector(image.bytes_per_sector, None, sector_num)
|
||||||
|
sector_list.append(sector)
|
||||||
|
values, style = image.get_sectors(sector_num)
|
||||||
|
sector = image.header.sector_from_track(values[1], values[2])
|
||||||
|
for sector_num in sector_list:
|
||||||
|
sector = WriteableSector(image.bytes_per_sector, None, sector_num)
|
||||||
|
sector_list.append(sector)
|
||||||
|
return sector_list
|
||||||
|
|
||||||
def start_read(self, image):
|
def start_read(self, image):
|
||||||
if not self.is_sane:
|
if not self.is_sane:
|
||||||
|
@ -135,6 +213,11 @@ class Dos33Dirent(object):
|
||||||
def get_filename(self):
|
def get_filename(self):
|
||||||
return self.filename
|
return self.filename
|
||||||
|
|
||||||
|
def set_values(self, filename, filetype, index):
|
||||||
|
self.filename = "%-30s" % filename[0:30]
|
||||||
|
self.flag = self.type_map.get(filetype, 0x04)
|
||||||
|
self.locked = False
|
||||||
|
|
||||||
|
|
||||||
class Dos33Header(AtrHeader):
|
class Dos33Header(AtrHeader):
|
||||||
file_format = "DOS 3.3"
|
file_format = "DOS 3.3"
|
||||||
|
@ -175,6 +258,10 @@ class Dos33Header(AtrHeader):
|
||||||
def sector_from_track(self, track, sector):
|
def sector_from_track(self, track, sector):
|
||||||
return track * 16 + sector
|
return track * 16 + sector
|
||||||
|
|
||||||
|
def pair_from_sector(self, sector):
|
||||||
|
track, sector = divmod(sector, 16)
|
||||||
|
return track, sector
|
||||||
|
|
||||||
|
|
||||||
class Dos33DiskImage(DiskImageBase):
|
class Dos33DiskImage(DiskImageBase):
|
||||||
def __init__(self, rawdata, filename=""):
|
def __init__(self, rawdata, filename=""):
|
||||||
|
@ -300,6 +387,14 @@ class Dos33DiskImage(DiskImageBase):
|
||||||
segment = DefaultSegment(raw, name="Catalog")
|
segment = DefaultSegment(raw, name="Catalog")
|
||||||
segments.append(segment)
|
segments.append(segment)
|
||||||
return segments
|
return segments
|
||||||
|
|
||||||
|
def get_next_directory_sector(self, sector):
|
||||||
|
self.assert_valid_sector(sector)
|
||||||
|
print "reading catalog sector", sector
|
||||||
|
raw, _, _ = self.get_raw_bytes(sector)
|
||||||
|
next_sector = self.header.sector_from_track(raw[1], raw[2])
|
||||||
|
if next_sector == 0:
|
||||||
|
# need to figure out where the next sector should be
|
||||||
|
|
||||||
def get_file_segment(self, dirent):
|
def get_file_segment(self, dirent):
|
||||||
byte_order = []
|
byte_order = []
|
||||||
|
|
Loading…
Reference in New Issue
Block a user