oaknut.discimage¶
The sector-level layer beneath every disc-backed filesystem. It has no notion of catalogues or files; it models the physical shape of a disc image and hands out byte-addressable views of its sectors.
The pieces fit together bottom-up: a DiscImage
wraps a byte buffer and one or more Surface
sides, each described by a SurfaceSpec
geometry. A range of sectors is returned as a
SectorsView that reads and writes straight
through to the buffer, and UnifiedDisc
flattens several surfaces into the single linear address space ADFS
expects. A DiscFormat, built from the
surface-spec helpers, names a complete geometry plus its catalogue
type; filesystem packages compose these into concrete format constants
of their own.
Every name documented here is importable directly from
oaknut.discimage.
The disc image¶
- class oaknut.discimage.DiscImage(buffer, surface_specs)¶
A disc image with one or more surfaces.
- Parameters:
buffer (memoryview)
surface_specs (Iterable[SurfaceSpec])
- property buffer: memoryview¶
The underlying buffer containing the disc image data.
- surface(surface_index)¶
Get the Surface object for the given surface index.
- sector_views(surface_index, sector_numbers)¶
Get memoryviews for sectors on a surface, optimized to merge contiguous sectors.
This method encapsulates all knowledge of physical sector layout. When multiple sectors are physically adjacent in the buffer, they are merged into a single memoryview for efficiency.
- Parameters:
- Returns:
List of memoryview slices (may be fewer than len(sector_numbers) if sectors are physically contiguous)
- Raises:
IndexError – If surface_index is out of range
ValueError – If any sector_number is out of range for that surface
- Return type:
- class oaknut.discimage.Surface(disc_image, spec, index)¶
A single disc surface.
A single-sided disc has one surface. A double-sided disc has two surfaces. Surface instances are created by DiscImage and reference their parent DiscImage.
- Parameters:
disc_image (DiscImage)
spec (SurfaceSpec)
index (int)
- sector_range(start_sector, num_sectors)¶
Create a Sectors view for a range of sectors.
- Parameters:
- Returns:
Sectors view wrapping the sector range
- Raises:
ValueError – If range is invalid or out of bounds
- Return type:
- class oaknut.discimage.SurfaceSpec(num_tracks, sectors_per_track, bytes_per_sector, track_zero_offset_bytes, track_stride_bytes)¶
Specification of how a surface maps to a disc image.
Sector access¶
- class oaknut.discimage.SectorsView(views)¶
Presents multiple disk sectors as a single logical buffer.
Supports reads via __getitem__ and writes via __setitem__. For reads, data is materialized from the underlying sector views on demand. For writes, changes are written back to the underlying sectors immediately.
This class does not distinguish between physically contiguous and non-contiguous sectors - it uses the same code path for both cases.
- Parameters:
views (list[memoryview])
- None¶
- Type:
implementation details are private
Example
# Single sector view = SectorsView([memoryview(buffer)[0:256]]) data = view[:100] # Read first 100 bytes
# Multiple sectors views = [memoryview(buffer)[0:256], memoryview(buffer)[256:512]] view = SectorsView(views) view[10:20] = b”new data” # Writes back to underlying buffers
- class oaknut.discimage.UnifiedDisc(disc_image)¶
Presents multiple surfaces as a single linear sector address space.
- Parameters:
disc_image (DiscImage)
- sector_range(start_sector, num_sectors)¶
Read/write sectors from the unified address space.
Handles ranges that span the boundary between surfaces by combining SectorsViews from each surface.
- Parameters:
- Returns:
SectorsView wrapping the requested sector range.
- Raises:
ValueError – If range is invalid or out of bounds.
- Return type:
Disc formats¶
A DiscFormat is a list of surface specs plus
the catalogue type that lives on them. The helpers build the
SurfaceSpec lists for the three common
physical layouts, so a filesystem package rarely constructs a
SurfaceSpec by hand.
- class oaknut.discimage.DiscFormat(surface_specs, catalogue_name)¶
Complete disk format specification including all surfaces and catalogue type.
- Parameters:
surface_specs (list[SurfaceSpec])
catalogue_name (str)
- oaknut.discimage.single_sided_spec(num_tracks, sectors_per_track, bytes_per_sector=256)¶
Create SurfaceSpec for a single-sided disc image.
- Parameters:
- Return type:
- oaknut.discimage.interleaved_double_sided_specs(num_tracks, sectors_per_track, bytes_per_sector=256)¶
Create SurfaceSpecs for an interleaved double-sided disc image.
The physical layout alternates sides per track (side 0 track 0, side 1 track 0, side 0 track 1, …).
- Parameters:
- Return type:
- oaknut.discimage.sequential_double_sided_specs(num_tracks, sectors_per_track, bytes_per_sector=256)¶
Create SurfaceSpecs for a sequential double-sided disc image.
The physical layout is all of side 0 first, then all of side 1.
- Parameters:
- Return type:
- oaknut.discimage.BYTES_PER_SECTOR = 256¶
int([x]) -> integer int(x, base=10) -> integer
Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.__int__(). For floating-point numbers, this truncates towards zero.
If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by ‘+’ or ‘-’ and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal. >>> int(‘0b100’, base=0) 4
Opening an image file¶
- oaknut.discimage.open_image_mmap(filepath)¶
Open
filepathas an mmap, writable when the host allows it.Tries
r+bfirst; onPermissionErrorfalls back torb. The yielded tuple is(mm, writable)so callers know whether tomm.flush()on clean exit.