mirror of
https://github.com/robmcmullen/atrcopy.git
synced 2024-11-29 11:51:14 +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)
|
||||
return data
|
||||
|
||||
def set_sector_numbers(self):
|
||||
def set_sector_numbers(self, image):
|
||||
num = 361
|
||||
for sector in self.sectors:
|
||||
sector.sector_num = num
|
||||
@ -137,7 +137,7 @@ class AtariDosDirent(object):
|
||||
self.is_sane = self.sanity_check(image)
|
||||
|
||||
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]
|
||||
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
|
||||
|
@ -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)
|
||||
vtoc_segments = self.get_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(vtoc)
|
||||
self.write_sector_list(directory)
|
||||
@ -427,7 +427,7 @@ class DiskImageBase(object):
|
||||
sector_list = dirent.get_sector_list(self)
|
||||
vtoc_segments = self.get_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(vtoc)
|
||||
self.write_sector_list(directory)
|
||||
@ -554,10 +554,10 @@ class Directory(BaseSectorList):
|
||||
return dirent
|
||||
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)
|
||||
dirent.update_sector_info(sector_list)
|
||||
self.calc_sectors()
|
||||
self.calc_sectors(image)
|
||||
|
||||
def place_sector_list(self, dirent, vtoc, sector_list):
|
||||
""" Map out the sectors and link the sectors together
|
||||
@ -583,18 +583,18 @@ class Directory(BaseSectorList):
|
||||
last_sector.next_sector_num = 0
|
||||
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)
|
||||
dirent.mark_deleted()
|
||||
self.calc_sectors()
|
||||
self.calc_sectors(image)
|
||||
|
||||
@property
|
||||
def dirent_class(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def calc_sectors(self):
|
||||
def calc_sectors(self, image):
|
||||
self.sectors = []
|
||||
self.current_sector = self.sector_class(self.bytes_per_sector)
|
||||
self.current_sector = self.get_dirent_sector()
|
||||
self.encode_index = 0
|
||||
|
||||
d = self.dirents.items()
|
||||
@ -610,7 +610,10 @@ class Directory(BaseSectorList):
|
||||
data = self.encode_dirent(dirent)
|
||||
self.store_encoded(data)
|
||||
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):
|
||||
raise NotImplementedError
|
||||
@ -624,16 +627,16 @@ class Directory(BaseSectorList):
|
||||
data = self.current_sector.add_data(data)
|
||||
if len(data) > 0:
|
||||
self.sectors.append(self.current_sector)
|
||||
self.current_sector = self.sector_class(self.bytes_per_sector)
|
||||
self.current_sector = self.get_dirent_sector()
|
||||
else:
|
||||
break
|
||||
|
||||
def finish_encoding(self):
|
||||
def finish_encoding(self, image):
|
||||
if not self.current_sector.is_empty:
|
||||
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
|
||||
|
||||
|
||||
|
101
atrcopy/dos33.py
101
atrcopy/dos33.py
@ -1,13 +1,58 @@
|
||||
import numpy as np
|
||||
|
||||
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
|
||||
|
||||
import logging
|
||||
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):
|
||||
format = np.dtype([
|
||||
('track', 'u1'),
|
||||
@ -44,8 +89,8 @@ class Dos33Dirent(object):
|
||||
0x4: "B",
|
||||
0x8: "S",
|
||||
0x10: "R",
|
||||
0x20: "A",
|
||||
0x40: "B",
|
||||
0x20: "new A",
|
||||
0x40: "new B",
|
||||
}
|
||||
|
||||
def summary(self):
|
||||
@ -76,6 +121,25 @@ class Dos33Dirent(object):
|
||||
self.filename = (bytes[3:0x20] - 0x80).tostring().rstrip()
|
||||
self.num_sectors = int(values[4])
|
||||
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):
|
||||
if self.deleted:
|
||||
@ -107,6 +171,20 @@ class Dos33Dirent(object):
|
||||
break
|
||||
sector_list.append(image.header.sector_from_track(t, s))
|
||||
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):
|
||||
if not self.is_sane:
|
||||
@ -135,6 +213,11 @@ class Dos33Dirent(object):
|
||||
def get_filename(self):
|
||||
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):
|
||||
file_format = "DOS 3.3"
|
||||
@ -175,6 +258,10 @@ class Dos33Header(AtrHeader):
|
||||
def sector_from_track(self, track, sector):
|
||||
return track * 16 + sector
|
||||
|
||||
def pair_from_sector(self, sector):
|
||||
track, sector = divmod(sector, 16)
|
||||
return track, sector
|
||||
|
||||
|
||||
class Dos33DiskImage(DiskImageBase):
|
||||
def __init__(self, rawdata, filename=""):
|
||||
@ -300,6 +387,14 @@ class Dos33DiskImage(DiskImageBase):
|
||||
segment = DefaultSegment(raw, name="Catalog")
|
||||
segments.append(segment)
|
||||
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):
|
||||
byte_order = []
|
||||
|
Loading…
Reference in New Issue
Block a user