mirror of
https://github.com/robmcmullen/atrcopy.git
synced 2024-06-12 20:29:43 +00:00
Added tests for DOS 33 disk images; code still failing all tests, but making progress
This commit is contained in:
parent
4928a35700
commit
3157b13727
|
@ -57,14 +57,14 @@ class Dos33Dirent(object):
|
||||||
format = np.dtype([
|
format = np.dtype([
|
||||||
('track', 'u1'),
|
('track', 'u1'),
|
||||||
('sector', 'u1'),
|
('sector', 'u1'),
|
||||||
('flags', 'u1'),
|
('flag', 'u1'),
|
||||||
('name','S30'),
|
('name','S30'),
|
||||||
('num_sectors','<u2'),
|
('num_sectors','<u2'),
|
||||||
])
|
])
|
||||||
|
|
||||||
def __init__(self, image, file_num=0, bytes=None):
|
def __init__(self, image, file_num=0, bytes=None):
|
||||||
self.file_num = file_num
|
self.file_num = file_num
|
||||||
self.flags = 0
|
self.file_type = 0
|
||||||
self.locked = False
|
self.locked = False
|
||||||
self.deleted = False
|
self.deleted = False
|
||||||
self.track = 0
|
self.track = 0
|
||||||
|
@ -79,8 +79,8 @@ class Dos33Dirent(object):
|
||||||
self.parse_raw_dirent(image, bytes)
|
self.parse_raw_dirent(image, bytes)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
flags = self.summary()
|
flag = self.summary()
|
||||||
return "File #%-2d (%s) %03d %-30s %03d %03d" % (self.file_num, flags, self.num_sectors, self.filename, self.track, self.sector)
|
return "File #%-2d (%s) %03d %-30s %03d %03d" % (self.file_num, flag, self.num_sectors, self.filename, self.track, self.sector)
|
||||||
|
|
||||||
type_map = {
|
type_map = {
|
||||||
0x0: "T",
|
0x0: "T",
|
||||||
|
@ -94,18 +94,25 @@ class Dos33Dirent(object):
|
||||||
}
|
}
|
||||||
|
|
||||||
def summary(self):
|
def summary(self):
|
||||||
locked = "*" if self.flags else " "
|
locked = "*" if self.locked else " "
|
||||||
f = self.flags & 0x7f
|
|
||||||
try:
|
try:
|
||||||
file_type = self.type_map[f]
|
file_type = self.type_map[self.file_type]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
file_type = "?"
|
file_type = "?"
|
||||||
flags = "%s%s" % (locked, file_type)
|
flag = "%s%s" % (locked, file_type)
|
||||||
return flags
|
return flag
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def verbose_info(self):
|
def verbose_info(self):
|
||||||
return self.summary
|
return self.summary
|
||||||
|
|
||||||
|
@property
|
||||||
|
def in_use(self):
|
||||||
|
return not self.deleted
|
||||||
|
|
||||||
|
@property
|
||||||
|
def flag(self):
|
||||||
|
return 0xff if self.deleted else self.file_type | (0x80 * int(self.locked))
|
||||||
|
|
||||||
def parse_raw_dirent(self, image, bytes):
|
def parse_raw_dirent(self, image, bytes):
|
||||||
if bytes is None:
|
if bytes is None:
|
||||||
|
@ -114,10 +121,12 @@ class Dos33Dirent(object):
|
||||||
self.track = values[0]
|
self.track = values[0]
|
||||||
if self.track == 0xff:
|
if self.track == 0xff:
|
||||||
self.deleted = True
|
self.deleted = True
|
||||||
|
self.track = bytes[0x20]
|
||||||
else:
|
else:
|
||||||
self.deleted = False
|
self.deleted = False
|
||||||
self.sector = values[1]
|
self.sector = values[1]
|
||||||
self.flags = values[2]
|
self.file_type = values[2] & 0x7f
|
||||||
|
self.locked = values[2] & 0x80
|
||||||
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)
|
||||||
|
@ -125,12 +134,11 @@ class Dos33Dirent(object):
|
||||||
def encode_dirent(self):
|
def encode_dirent(self):
|
||||||
data = np.zeros([self.format.itemsize], 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.locked))
|
values[0] = self.track
|
||||||
values[0] = flag
|
values[1] = self.sector
|
||||||
values[1] = self.num_sectors
|
values[2] = self.flag
|
||||||
values[2] = self.starting_sector
|
|
||||||
values[3] = self.filename
|
values[3] = self.filename
|
||||||
values[4] = self.ext
|
values[4] = self.num_sectors
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def mark_deleted(self):
|
def mark_deleted(self):
|
||||||
|
@ -215,8 +223,9 @@ class Dos33Dirent(object):
|
||||||
|
|
||||||
def set_values(self, filename, filetype, index):
|
def set_values(self, filename, filetype, index):
|
||||||
self.filename = "%-30s" % filename[0:30]
|
self.filename = "%-30s" % filename[0:30]
|
||||||
self.flag = self.type_map.get(filetype, 0x04)
|
self.file_type = self.type_map.get(filetype, 0x04)
|
||||||
self.locked = False
|
self.locked = False
|
||||||
|
self.deleted = False
|
||||||
|
|
||||||
|
|
||||||
class Dos33Header(AtrHeader):
|
class Dos33Header(AtrHeader):
|
||||||
|
@ -281,6 +290,14 @@ class Dos33DiskImage(DiskImageBase):
|
||||||
@property
|
@property
|
||||||
def payload_bytes_per_sector(self):
|
def payload_bytes_per_sector(self):
|
||||||
return 256
|
return 256
|
||||||
|
|
||||||
|
@property
|
||||||
|
def vtoc_class(self):
|
||||||
|
return Dos33VTOC
|
||||||
|
|
||||||
|
@property
|
||||||
|
def directory_class(self):
|
||||||
|
return Dos33Directory
|
||||||
|
|
||||||
def get_boot_sector_info(self):
|
def get_boot_sector_info(self):
|
||||||
# based on logic from a2server
|
# based on logic from a2server
|
||||||
|
@ -326,7 +343,7 @@ class Dos33DiskImage(DiskImageBase):
|
||||||
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']
|
||||||
|
|
||||||
def get_directory(self):
|
def get_directory(self, directory=None):
|
||||||
sector = self.first_catalog
|
sector = self.first_catalog
|
||||||
num = 0
|
num = 0
|
||||||
files = []
|
files = []
|
||||||
|
@ -338,10 +355,14 @@ class Dos33DiskImage(DiskImageBase):
|
||||||
i = 0xb
|
i = 0xb
|
||||||
while i < 256:
|
while i < 256:
|
||||||
dirent = Dos33Dirent(self, num, values[i:i+0x23])
|
dirent = Dos33Dirent(self, num, values[i:i+0x23])
|
||||||
if not dirent.is_sane:
|
if dirent.flag == 0:
|
||||||
sector = 0
|
|
||||||
break
|
break
|
||||||
files.append(dirent)
|
if not dirent.is_sane:
|
||||||
|
self.all_sane = False
|
||||||
|
else:
|
||||||
|
files.append(dirent)
|
||||||
|
if directory is not None:
|
||||||
|
directory.set(num, dirent)
|
||||||
print dirent
|
print dirent
|
||||||
i += 0x23
|
i += 0x23
|
||||||
num += 1
|
num += 1
|
||||||
|
@ -389,12 +410,14 @@ class Dos33DiskImage(DiskImageBase):
|
||||||
return segments
|
return segments
|
||||||
|
|
||||||
def get_next_directory_sector(self, sector):
|
def get_next_directory_sector(self, sector):
|
||||||
|
if sector == -1:
|
||||||
|
sector = self.first_catalog
|
||||||
self.assert_valid_sector(sector)
|
self.assert_valid_sector(sector)
|
||||||
print "reading catalog sector", sector
|
print "reading catalog sector", sector
|
||||||
raw, _, _ = self.get_raw_bytes(sector)
|
raw, _, _ = self.get_raw_bytes(sector)
|
||||||
next_sector = self.header.sector_from_track(raw[1], raw[2])
|
next_sector = self.header.sector_from_track(raw[1], raw[2])
|
||||||
if next_sector == 0:
|
if next_sector == 0:
|
||||||
# need to figure out where the next sector should be
|
raise NoSpaceInDirectory("No space left in catalog")
|
||||||
|
|
||||||
def get_file_segment(self, dirent):
|
def get_file_segment(self, dirent):
|
||||||
byte_order = []
|
byte_order = []
|
||||||
|
|
|
@ -2,15 +2,19 @@ import numpy as np
|
||||||
|
|
||||||
from mock import *
|
from mock import *
|
||||||
|
|
||||||
from atrcopy import SegmentData, AtariDosDiskImage, InvalidBinaryFile
|
from atrcopy import SegmentData, AtariDosDiskImage, Dos33DiskImage,InvalidBinaryFile
|
||||||
from atrcopy.errors import *
|
from atrcopy.errors import *
|
||||||
|
|
||||||
|
|
||||||
class TestAtariDosSDImage(object):
|
class BaseFilesystemModifyTest(object):
|
||||||
|
diskimage_type = None
|
||||||
|
sample_file = None
|
||||||
|
num_files_in_sample = 0
|
||||||
|
|
||||||
def setup(self):
|
def setup(self):
|
||||||
data = np.fromfile("../test_data/dos_sd_test1.atr", dtype=np.uint8)
|
data = np.fromfile(self.sample_file, dtype=np.uint8)
|
||||||
rawdata = SegmentData(data)
|
rawdata = SegmentData(data)
|
||||||
self.image = AtariDosDiskImage(rawdata)
|
self.image = self.diskimage_type(rawdata)
|
||||||
|
|
||||||
def check_entries(self, entries, prefix="TEST", save=None):
|
def check_entries(self, entries, prefix="TEST", save=None):
|
||||||
orig_num_files = len(self.image.files)
|
orig_num_files = len(self.image.files)
|
||||||
|
@ -39,21 +43,21 @@ class TestAtariDosSDImage(object):
|
||||||
return filenames
|
return filenames
|
||||||
|
|
||||||
def test_small(self):
|
def test_small(self):
|
||||||
assert len(self.image.files) == 5
|
assert len(self.image.files) == self.num_files_in_sample
|
||||||
|
|
||||||
data = np.asarray([0xff, 0xff, 0x00, 0x60, 0x01, 0x60, 1, 2], dtype=np.uint8)
|
data = np.asarray([0xff, 0xff, 0x00, 0x60, 0x01, 0x60, 1, 2], dtype=np.uint8)
|
||||||
self.image.write_file("TEST.XEX", None, data)
|
self.image.write_file("TEST.XEX", None, data)
|
||||||
assert len(self.image.files) == 6
|
assert len(self.image.files) == self.num_files_in_sample + 1
|
||||||
|
|
||||||
data2 = self.image.find_file("TEST.XEX")
|
data2 = self.image.find_file("TEST.XEX")
|
||||||
assert data.tostring() == data2
|
assert data.tostring() == data2
|
||||||
|
|
||||||
def test_50k(self):
|
def test_50k(self):
|
||||||
assert len(self.image.files) == 5
|
assert len(self.image.files) == self.num_files_in_sample
|
||||||
|
|
||||||
data = np.arange(50*1024, dtype=np.uint8)
|
data = np.arange(50*1024, dtype=np.uint8)
|
||||||
self.image.write_file("RAMP50K.BIN", None, data)
|
self.image.write_file("RAMP50K.BIN", None, data)
|
||||||
assert len(self.image.files) == 6
|
assert len(self.image.files) == self.num_files_in_sample + 1
|
||||||
|
|
||||||
data2 = self.image.find_file("RAMP50K.BIN")
|
data2 = self.image.find_file("RAMP50K.BIN")
|
||||||
assert data.tostring() == data2
|
assert data.tostring() == data2
|
||||||
|
@ -75,14 +79,14 @@ class TestAtariDosSDImage(object):
|
||||||
self.check_entries(entries, save="many_small.atr")
|
self.check_entries(entries, save="many_small.atr")
|
||||||
|
|
||||||
def test_big_failure(self):
|
def test_big_failure(self):
|
||||||
assert len(self.image.files) == 5
|
assert len(self.image.files) == self.num_files_in_sample
|
||||||
|
|
||||||
data = np.arange(50*1024, dtype=np.uint8)
|
data = np.arange(50*1024, dtype=np.uint8)
|
||||||
self.image.write_file("RAMP50K.BIN", None, data)
|
self.image.write_file("RAMP50K.BIN", None, data)
|
||||||
assert len(self.image.files) == 6
|
assert len(self.image.files) == self.num_files_in_sample + 1
|
||||||
with pytest.raises(NotEnoughSpaceOnDisk):
|
with pytest.raises(NotEnoughSpaceOnDisk):
|
||||||
self.image.write_file("RAMP50K2.BIN", None, data)
|
self.image.write_file("RAMP50K2.BIN", None, data)
|
||||||
assert len(self.image.files) == 6
|
assert len(self.image.files) == self.num_files_in_sample + 1
|
||||||
|
|
||||||
def test_delete(self):
|
def test_delete(self):
|
||||||
entries1 = [
|
entries1 = [
|
||||||
|
@ -104,15 +108,25 @@ class TestAtariDosSDImage(object):
|
||||||
]
|
]
|
||||||
|
|
||||||
filenames = self.check_entries(entries1, "FIRST")
|
filenames = self.check_entries(entries1, "FIRST")
|
||||||
assert len(self.image.files) == 16
|
assert len(self.image.files) == self.num_files_in_sample + 11
|
||||||
self.image.delete_file(filenames[2])
|
self.image.delete_file(filenames[2])
|
||||||
self.image.delete_file(filenames[5])
|
self.image.delete_file(filenames[5])
|
||||||
self.image.delete_file(filenames[0])
|
self.image.delete_file(filenames[0])
|
||||||
self.image.delete_file(filenames[8])
|
self.image.delete_file(filenames[8])
|
||||||
assert len(self.image.files) == 12
|
assert len(self.image.files) == self.num_files_in_sample + 7
|
||||||
|
|
||||||
filename = self.check_entries(entries2, "SECOND", save="test_delete.atr")
|
filename = self.check_entries(entries2, "SECOND", save="test_delete.atr")
|
||||||
assert len(self.image.files) == 14
|
assert len(self.image.files) == self.num_files_in_sample + 9
|
||||||
|
|
||||||
|
# class TestAtariDosSDImage(BaseFilesystemModifyTest):
|
||||||
|
# diskimage_type = AtariDosDiskImage
|
||||||
|
# sample_file = "../test_data/dos_sd_test1.atr"
|
||||||
|
# num_files_in_sample
|
||||||
|
|
||||||
|
class TestDos33Image(BaseFilesystemModifyTest):
|
||||||
|
diskimage_type = Dos33DiskImage
|
||||||
|
sample_file = "../test_data/dos33_master.dsk"
|
||||||
|
num_files_in_sample = 19
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
Loading…
Reference in New Issue
Block a user