CopperDisk 2.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package CopperDisk --version 2.0.0
                    
NuGet\Install-Package CopperDisk -Version 2.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="CopperDisk" Version="2.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="CopperDisk" Version="2.0.0" />
                    
Directory.Packages.props
<PackageReference Include="CopperDisk" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add CopperDisk --version 2.0.0
                    
#r "nuget: CopperDisk, 2.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package CopperDisk@2.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=CopperDisk&version=2.0.0
                    
Install as a Cake Addin
#tool nuget:?package=CopperDisk&version=2.0.0
                    
Install as a Cake Tool

CopperDisk

CopperDisk is a managed Amiga floppy disk-image library for emulator hosts and disk tools. It loads standard 880 KiB ADF sector images, decodes SPS/CAPS IPF images into raw Amiga track streams, and exposes both decoded AmigaDOS sectors and encoded track data through one small API.

The package targets .NET 10 and has no external runtime dependencies.

Supported Images

  • .adf: standard 880 KiB AmigaDOS sector images.
  • .ipf: SPS/CAPS IPF images decoded to raw track streams.
  • .zip: an archive containing exactly one .adf or .ipf entry.

ADF media is writable at the sector-image level. IPF and encoded-track media are read-only, but still expose a best-effort decoded sector view when sectors can be recognized.

Loading Disk Images

using CopperDisk;

var loaded = AmigaDiskLoader.Load("Workbench.adf");

Console.WriteLine(loaded.DisplayName);

var media = loaded.Media;
var track = media.ReadTrack(cylinder: 0, head: 0);

Console.WriteLine(track.BitLength);
Console.WriteLine(track.Features);

AmigaDiskLoader.Load accepts direct ADF/IPF paths and ZIP files containing exactly one ADF or IPF image. Direct and ZIP-wrapped IPF files use the same optional decode options:

var loaded = AmigaDiskLoader.Load(
    "protected-disk.zip",
    new IpfDecodeOptions
    {
        StartAtIndex = false,
        AlignTracksToWord = true
    });

Use FromIpfBytes when IPF bytes are already in memory. The input is read during decoding and is not retained by the returned media:

ReadOnlySpan<byte> ipfBytes = File.ReadAllBytes("protected-disk.ipf");
IAmigaSectorDiskMedia ipf = AmigaDiskLoader.FromIpfBytes(ipfBytes);

Sector Media

Use IAmigaSectorDiskMedia when you need the decoded AmigaDOS sector view:

if (loaded.Media is IAmigaSectorDiskMedia sectors)
{
    ReadOnlyMemory<byte> bootBlock = sectors.BootBlock;
    ReadOnlyMemory<byte> sector0 = sectors.ReadSector(0);
    ReadOnlyMemory<byte> diskBytes = sectors.SectorData;

    Console.WriteLine(sectors.HasCompleteDecodedSectorData);
}

SectorData is always the standard 880 KiB AmigaDOS sector image layout. Missing or unreadable sectors are zero-filled and HasCompleteDecodedSectorData reports whether every sector was decoded.

Writable ADF Media

ADF loaders return IWritableAmigaSectorDiskMedia, so callers that need write support do not need casts through unrelated interfaces:

byte[] adfBytes = File.ReadAllBytes("blank.adf");
IWritableAmigaSectorDiskMedia adf = AmigaDiskLoader.FromAdfBytes(adfBytes);

IAmigaTrack encodedTrack = adf.ReadTrack(0, 0);
bool wroteAnySector = adf.TryWriteTrack(0, 0, encodedTrack);
if (adf.IsDirty)
{
    File.WriteAllBytes("blank.adf", adf.SectorData.ToArray());
}

Encoded Tracks

All media exposes encoded floppy-controller data through IAmigaDiskMedia and IAmigaTrack.

IAmigaTrack track = media.ReadTrack(cylinder: 40, head: 1);

ReadOnlyMemory<byte> encodedBytes = track.EncodedData;
int encodedBits = track.BitLength;
int indexBit = track.StartBit;
AmigaTrackFeatures features = track.Features;

Use AmigaEncodedTrack when a tool needs byte-backed track helpers:

var encoded = new AmigaEncodedTrack(track.EncodedData, track.BitLength, track.StartBit, track.Features);

ushort sync = encoded.ReadUInt16AtBit(0);
int wrappedOffset = AmigaEncodedTrack.WrapBitOffset(-1, encoded.BitLength);

FromEncodedTracks accepts exactly AmigaDiskGeometry.TrackCount tracks. FromEncodedTrackBytes accepts exactly the same number of byte arrays and treats null entries as unformatted tracks:

byte[]?[] tracks = new byte[AmigaDiskGeometry.TrackCount][];
tracks[0] = File.ReadAllBytes("track-00.0.raw");

IAmigaSectorDiskMedia disk = AmigaDiskLoader.FromEncodedTrackBytes(tracks);

Ownership And Mutability

ADF and encoded-track byte-array entry points take ownership of the supplied arrays and do not make defensive copies. After passing an owned array to CopperDisk, do not mutate it while the returned media or track object is still in use.

This applies to:

  • AmigaDiskLoader.FromAdfBytes
  • AmigaDiskLoader.FromEncodedTrackBytes
  • AmigaEncodedTrack.FromBytes

Public output uses ReadOnlyMemory<byte> where possible. Treat these values as read-only views over CopperDisk-owned media. Writable ADF media updates its sector view after successful writes.

IPF Decoder Notes

IpfDecoder is an expert API for hosts that need decoded IPF track streams directly:

byte[] ipfBytes = File.ReadAllBytes("disk.ipf");
IpfDiskImage image = IpfDecoder.Decode(ipfBytes);

foreach (IpfTrack track in image.Tracks)
{
    Console.WriteLine($"{track.Cylinder}/{track.Head}: {track.BitLength} bits");
}

The managed IPF decoder currently supports the SPS/CAPS stream forms needed by CopperScreen's floppy path, with these limitations:

  • Weak data is materialized deterministically and marked with AmigaTrackFeatures.WeakData and AmigaTrackFeatures.ApproximateWeakData.
  • Stored IPF gap streams are not implemented.
  • Unknown IPF block encoders are rejected with IpfDecodeException.

Use AmigaDiskLoader.FromIpfBytes or AmigaDiskLoader.Load for normal disk loading. Use IpfDecoder only when a tool needs the IPF model types directly.

AmigaDOS Track Helpers

AmigaDosTrackEncoder and AmigaDosTrackDecoder are expert APIs for standard AmigaDOS MFM track data. They are useful for emulator tests, disk-inspection tools, and import/export paths that need raw floppy-controller streams rather than a filesystem-level API.

They do not validate Amiga filesystems. The decoder scans for standard sector headers and checksums, returns a best-effort 880 KiB sector image, and leaves unreadable sectors zero-filled.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on CopperDisk:

Package Downloads
CopperMod.Cust

Native Amiga CUST Hunk loader with an A500 PAL MC68000/Paula playback sandbox.

CopperMod.Amiga.Emulator

Full Amiga emulator host services, boot helpers, and disk media adapters layered on CopperMod.Amiga.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.1.0 126 6/21/2026
2.0.0 120 6/17/2026
1.0.0 144 6/6/2026

ADF, IPF, and ZIP-wrapped disk loading; decoded AmigaDOS sector and encoded track APIs; writable ADF media; ReadOnlySpan IPF input; package icon, README, and XML API documentation.