Skip to content

Commit

Permalink
D88: Add read support for multiple disks in one file.
Browse files Browse the repository at this point in the history
  • Loading branch information
tdaede committed Oct 3, 2023
1 parent 56af717 commit 210b0a7
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 10 deletions.
33 changes: 26 additions & 7 deletions src/greaseweazle/image/d88.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,32 @@ def remove_duplicate_sectors(secs) -> List[Tuple[int,int,int,int,bytes]]:
return new_secs

@classmethod
def from_file(cls, name: str, _fmt) -> Image:
def from_file(cls, name: str, _fmt, index: int = -1) -> Image:

with open(name, "rb") as f:
f.seek(0, os.SEEK_END)
file_size = f.tell()
f.seek(0)
disk_offsets: List[int] = []
current_disk_index = 0
while 1:
disk_offsets.append(f.tell())
header = struct.unpack('<16sB9xBBL', f.read(32))
_, _, _, _, disk_size = header
if f.tell() + disk_size >= file_size:
break
f.seek(disk_offsets[current_disk_index] + disk_size)
current_disk_index += 1

if index < 0 and len(disk_offsets) > 1:
print('D88: Warning: Multiple disks found in image, '
'only using first.')
index = 0
if index >= len(disk_offsets):
raise error.Fatal("D88: No disk with index %d in image file."
% index)

f.seek(disk_offsets[index])
header = struct.unpack('<16sB9xBBL', f.read(32))
disk_name, terminator, write_prot, media_flag, disk_size = header
track_table = [x[0] for x in struct.iter_unpack('<L', f.read(640))]
Expand All @@ -47,18 +70,14 @@ def from_file(cls, name: str, _fmt) -> Image:
struct.iter_unpack('<L', f.read(16))])
elif track_table[0] != 672:
raise error.Fatal("D88: Unsupported track table length.")
f.seek(0, os.SEEK_END)
if f.tell() != disk_size:
print('D88: Warning: Multiple disks found in image, '
'only using first.')

d88 = cls(name)

for track_index, track_offset in enumerate(track_table):
if track_offset == 0:
continue
f.seek(track_offset)
if f.tell() >= disk_size:
f.seek(disk_offsets[index] + track_offset)
if f.tell() >= disk_offsets[index] + disk_size:
continue
cyl = track_index // 2
head = track_index % 2
Expand Down
3 changes: 2 additions & 1 deletion src/greaseweazle/image/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ def max_cylinder(self):

## Read support:
@classmethod
def from_file(cls, name: str, fmt: Optional[codec.DiskDef]) -> Image:
def from_file(cls, name: str, fmt: Optional[codec.DiskDef],
index: Optional[int]) -> Image:
raise NotImplementedError

def get_track(self, cyl: int, side: int) -> Optional[HasFlux]:
Expand Down
4 changes: 3 additions & 1 deletion src/greaseweazle/tools/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
plls = track.plls

def open_input_image(args, image_class: Type[Image]) -> Image:
return image_class.from_file(args.in_file, args.fmt_cls)
return image_class.from_file(args.in_file, args.fmt_cls, int(args.disk_index))


def open_output_image(args, image_class: Type[Image]) -> Image:
Expand Down Expand Up @@ -117,6 +117,8 @@ def main(argv) -> None:
epilog=epilog)
parser.add_argument("--diskdefs", help="disk definitions file")
parser.add_argument("--format", help="disk format")
parser.add_argument("--disk-index", help="disk index within input "
"image file", default=-1)
parser.add_argument("--tracks", type=util.TrackSet,
help="which tracks to read & convert from input",
metavar="TSPEC")
Expand Down
4 changes: 3 additions & 1 deletion src/greaseweazle/tools/write.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

# Read and parse the image file.
def open_image(args, image_class: Type[image.Image]) -> image.Image:
return image_class.from_file(args.file, args.fmt_cls)
return image_class.from_file(args.file, args.fmt_cls, int(args.disk_index))

# write_from_image:
# Writes the specified image file to floppy disk.
Expand Down Expand Up @@ -188,6 +188,8 @@ def main(argv) -> None:
help="drive to read")
parser.add_argument("--diskdefs", help="disk definitions file")
parser.add_argument("--format", help="disk format")
parser.add_argument("--disk-index", help="disk index within image file",
default=-1)
parser.add_argument("--tracks", type=util.TrackSet, metavar="TSPEC",
help="which tracks to write")
parser.add_argument("--pre-erase", action="store_true",
Expand Down

0 comments on commit 210b0a7

Please sign in to comment.