Skip to content

Commit

Permalink
image: Replace most defs of from_file() with simpler from_bytes()
Browse files Browse the repository at this point in the history
  • Loading branch information
keirf committed Oct 4, 2023
1 parent 43f95c0 commit 27a3171
Show file tree
Hide file tree
Showing 14 changed files with 101 additions and 179 deletions.
14 changes: 2 additions & 12 deletions src/greaseweazle/image/a2r.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,29 +106,19 @@ def process_rwcp(self, dat: bytes) -> None:
t.add_cap(dat[start:i])


@classmethod
def from_file(cls, name: str, _fmt) -> Image:

splices = None

with open(name, "rb") as f:
dat = f.read()
def from_bytes(self, dat: bytes) -> None:

error.check(dat[:8] == b'A2R3\xff\x0a\x0d\x0a',
'A2R: Invalid signature')
dat = dat[8:]

a2r = cls(name, _fmt)

# Extract the RWCP chunk(s).
while len(dat) > 8:
id, sz = struct.unpack('<4sI', dat[:8])
dat = dat[8:]
if id == b'RWCP':
a2r.process_rwcp(dat)
self.process_rwcp(dat)
dat = dat[sz:]

return a2r


def get_track(self, cyl: int, side: int) -> Optional[Flux]:
Expand Down
15 changes: 6 additions & 9 deletions src/greaseweazle/image/d64.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,16 @@ def get_disk_id(self):
disk_id, = struct.unpack('<H', dat[162:164])
return disk_id

@classmethod
def from_file(cls, name: str, fmt: Optional[codec.DiskDef]) -> Image:
img = super().from_file(name, fmt)
assert isinstance(img, D64)
disk_id = img.get_disk_id()
for _, t in img.to_track.items():
def from_bytes(self, dat: bytes) -> None:
super().from_bytes(dat)
disk_id = self.get_disk_id()
for _, t in self.to_track.items():
error.check(isinstance(t, c64_gcr.C64GCR),
f'{cls.__name__}: Only {cls.default_format} format '
f'is supported')
f'{self.__class__.__name__}: '
f'Only {self.default_format} format is supported')
assert isinstance(t, c64_gcr.C64GCR) # mypy
if disk_id is not None:
t.set_disk_id(disk_id)
return img

class D71(D64):
default_format = 'commodore.1571'
Expand Down
30 changes: 13 additions & 17 deletions src/greaseweazle/image/dcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,33 +16,29 @@ class DCP(IMG):

read_only = True

@classmethod
def from_file(cls, name, fmt):
def from_bytes(self, dat: bytes) -> None:

with open(name, "rb") as f:
header = f.read(162)
format_str = 'pc98.2hd'
fmt = codec.get_diskdef(format_str)
dat = f.read()
header = dat[:162]
pos = 162
format_str = 'pc98.2hd'
fmt = codec.get_diskdef(format_str)
assert fmt is not None # mypy

img = cls(name, fmt)

pos = 0
for t in fmt.max_tracks:
for t in self.track_list():
cyl, head = t.cyl, t.head
if img.sides_swapped:
if self.sides_swapped:
head ^= 1
track = fmt.fmt(cyl, head)
track = fmt.mk_track(cyl, head)
if track is None:
continue
if cyl > 80:
break
if header[cyl * 2 + head] == 1:
pos += track.set_img_track(dat[pos:])
img.to_track[cyl,head] = track
self.to_track[cyl,head] = track
elif header[cyl * 2 + head] != 0:
raise error.Fatal("DCP: Corrupt header.")
img.format_str = format_str

return img
self.format_str = format_str

# Local variables:
# python-indent: 4
Expand Down
44 changes: 19 additions & 25 deletions src/greaseweazle/image/dim.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,37 +16,31 @@ class DIM(IMG):
default_format = None
read_only = True

@classmethod
def from_file(cls, name, fmt):

with open(name, "rb") as f:
header = f.read(256)
error.check(header[0xAB:0xB8] == b"DIFC HEADER ",
"DIM: Not a DIM file.")
(media_byte,) = struct.unpack('B255x', header)
if media_byte == 0:
format_str = 'pc98.2hd'
elif media_byte == 1:
format_str = 'pc98.2hs'
else:
raise error.Fatal("DIM: Unsupported format.")
fmt = codec.get_diskdef(format_str)
dat = f.read()

img = cls(name, fmt)

pos = 0
def from_bytes(self, dat: bytes) -> None:

header = dat[:256]
error.check(header[0xAB:0xB8] == b"DIFC HEADER ",
"DIM: Not a DIM file.")
media_byte, = struct.unpack('B255x', header)
if media_byte == 0:
format_str = 'pc98.2hd'
elif media_byte == 1:
format_str = 'pc98.2hs'
else:
raise error.Fatal("DIM: Unsupported format.")
fmt = codec.get_diskdef(format_str)
assert fmt is not None # mypy

pos = 256
for t in fmt.tracks:
cyl, head = t.cyl, t.head
if img.sides_swapped:
if self.sides_swapped:
head ^= 1
track = fmt.mk_track(cyl, head)
if track is not None:
pos += track.set_img_track(dat[pos:])
img.to_track[cyl,head] = track
img.format_str = format_str

return img
self.to_track[cyl,head] = track
self.format_str = format_str

# Local variables:
# python-indent: 4
Expand Down
2 changes: 1 addition & 1 deletion src/greaseweazle/image/dsk.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from greaseweazle.image.edsk import EDSK

class DSK(IMG):

@classmethod
def from_file(cls, name: str, fmt) -> Image:

Expand Down
14 changes: 3 additions & 11 deletions src/greaseweazle/image/edsk.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,13 +287,7 @@ def addcrc(t,n):
t += ibm.encode(bytes([track.gapbyte] * 80))
return track

@classmethod
def from_file(cls, name: str, _fmt) -> Image:

with open(name, "rb") as f:
dat = f.read()

edsk = cls(name, _fmt)
def from_bytes(self, dat: bytes) -> None:

sig, creator, ncyls, nsides, track_sz = struct.unpack(
'<34s14s2BH', dat[:52])
Expand All @@ -318,7 +312,7 @@ def from_file(cls, name: str, _fmt) -> Image:
'<12s4x2B2x4B', dat[o:o+24])
error.check(sig == b'Track-Info\r\n',
'EDSK: Missing track header')
error.check((cyl, head) not in edsk.to_track,
error.check((cyl, head) not in self.to_track,
'EDSK: Track specified twice')
bad_crc_clip_data = False
while True:
Expand Down Expand Up @@ -478,11 +472,9 @@ def from_file(cls, name: str, _fmt) -> Image:
track.bits.frombytes(ibm.mfm_encode(track.bytes))

# Register the track
edsk.to_track[cyl,head] = track
self.to_track[cyl,head] = track
o += track_size

return edsk


def get_track(self, cyl: int, side: int) -> Optional[MasterTrack]:
if (cyl,side) not in self.to_track:
Expand Down
41 changes: 16 additions & 25 deletions src/greaseweazle/image/fdi.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,35 +15,26 @@ class FDI(IMG):
default_format = 'pc98.2hd'
read_only = True

@classmethod
def from_file(cls, name, fmt):

with open(name, "rb") as f:
header = f.read(32)
(magic, fdd_type, headerSize, sectorSize, sectorsPerTrack, sides, tracks) = \
struct.unpack('<LLL4xLLLL', header)
error.check(magic == 0, "FDI: Not a FDI file.")
error.check(fdd_type == 0x90, "FDI: Unsupported format.")
error.check(sectorSize == 1024, "FDI: Unsupported sector size.")
error.check(sectorsPerTrack == 8, "FDI: Unsupported number of sectors per track.")
error.check(sides == 2, "FDI: Unsupported number of sides.")
error.check(tracks == 77, "FDI: Unsupported number of tracks.")
f.seek(headerSize)
dat = f.read()

img = cls(name, fmt)

pos = 0
for t in fmt.tracks:
def from_bytes(self, dat: bytes) -> None:

(magic, fdd_type, headerSize, sectorSize, sectorsPerTrack,
sides, tracks) = struct.unpack('<LLL4xLLLL', dat[:32])
error.check(magic == 0, "FDI: Not a FDI file.")
error.check(fdd_type == 0x90, "FDI: Unsupported format.")
error.check(sectorSize == 1024, "FDI: Unsupported sector size.")
error.check(sectorsPerTrack == 8, "FDI: Unsupported number of sectors per track.")
error.check(sides == 2, "FDI: Unsupported number of sides.")
error.check(tracks == 77, "FDI: Unsupported number of tracks.")

pos = headerSize
for t in self.track_list():
cyl, head = t.cyl, t.head
if img.sides_swapped:
if self.sides_swapped:
head ^= 1
track = fmt.mk_track(cyl, head)
track = self.fmt.mk_track(cyl, head)
if track is not None:
pos += track.set_img_track(dat[pos:])
img.to_track[cyl,head] = track

return img
self.to_track[cyl,head] = track

# Local variables:
# python-indent: 4
Expand Down
17 changes: 5 additions & 12 deletions src/greaseweazle/image/hfe.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,7 @@ def __init__(self, name: str, _fmt) -> None:
self.to_track: Dict[Tuple[int,int], HFETrack] = dict()


@classmethod
def from_file(cls, name: str, _fmt):

with open(name, "rb") as f:
dat = f.read()
def from_bytes(self, dat: bytes) -> None:

(sig, f_rev, n_cyl, n_side, t_enc, bitrate,
_, _, _, tlut_base) = struct.unpack("<8s4B2H2BH", dat[:20])
Expand All @@ -185,9 +181,8 @@ def from_file(cls, name: str, _fmt):
error.check(0 < n_cyl, "HFE: Invalid #cyls")
error.check(0 < n_side < 3, "HFE: Invalid #sides")

hfe = cls(name, _fmt)
hfe.opts.bitrate = bitrate
hfe.opts.version = version
self.opts.bitrate = bitrate
self.opts.version = version

tlut = dat[tlut_base*512:tlut_base*512+n_cyl*4]

Expand All @@ -204,13 +199,11 @@ def from_file(cls, name: str, _fmt):
offset += 1
track_v1 = HFETrack.from_hfe_bytes(tdat, bitrate)
if version == 1:
hfe.to_track[cyl,side] = track_v1
self.to_track[cyl,side] = track_v1
else:
hfe.to_track[cyl,side] = hfev3_mk_track(
self.to_track[cyl,side] = hfev3_mk_track(
cyl, side, track_v1)

return hfe


def get_track(self, cyl: int, side: int) -> Optional[MasterTrack]:
if (cyl,side) not in self.to_track:
Expand Down
24 changes: 18 additions & 6 deletions src/greaseweazle/image/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ class Image:
write_on_ctrl_c = False
opts = ImageOpts() # empty

def __init__(self, name: str, fmt) -> None:
raise NotImplementedError

## Context manager for image objects created using .to_file()

def __enter__(self) -> Image:
Expand All @@ -64,13 +67,27 @@ def __exit__(self, type, value, tb):

## Default .to_file() constructor
@classmethod
def to_file(cls, name, fmt, noclobber):
def to_file(cls, name: str, fmt: Optional[codec.DiskDef],
noclobber: bool) -> Image:
error.check(not cls.read_only,
"%s: Cannot create %s image files" % (name, cls.__name__))
obj = cls(name, fmt)
obj.noclobber = noclobber
return obj

## Default .from_file() constructor
@classmethod
def from_file(cls, name: str, fmt: Optional[codec.DiskDef]) -> Image:

obj = cls(name, fmt)
with open(name, "rb") as f:
obj.from_bytes(f.read())
return obj

## Used by default .from_file constructor
def from_bytes(self, dat: bytes) -> None:
raise NotImplementedError

# Maximum non-empty cylinder on each head, or -1 if no cylinders exist.
# Returns a list of integers, indexed by head.
def max_cylinder(self):
Expand All @@ -85,11 +102,6 @@ def max_cylinder(self):
## Above methods and class variables can be overridden by subclasses.
## Additionally, subclasses must provide following public interfaces:

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

def get_track(self, cyl: int, side: int) -> Optional[HasFlux]:
raise NotImplementedError

Expand Down
12 changes: 2 additions & 10 deletions src/greaseweazle/image/imd.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,7 @@ def __init__(self, name: str, _fmt):
self.filename = name


@classmethod
def from_file(cls, name: str, _fmt) -> Image:

with open(name, "rb") as f:
dat = f.read()

imd = cls(name, _fmt)
def from_bytes(self, dat: bytes) -> None:

# Check and strip the header
sig, = struct.unpack('4s', dat[:4])
Expand Down Expand Up @@ -108,9 +102,7 @@ def from_file(cls, name: str, _fmt) -> Image:
if rec&2:
s.dam.mark = ibm.Mark.DDAM

imd.to_track[cyl,head] = t

return imd
self.to_track[cyl,head] = t


def get_track(self, cyl: int, side: int) -> Optional[ibm.IBMTrack_Fixed]:
Expand Down
Loading

0 comments on commit 27a3171

Please sign in to comment.