Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Catalog · How the catalog works
Anything · Lazarus or Delphi
Random projectRandom project

NG-atariATR

Tools for Atari 8-bit disk images: 16 MB MyDOS and SpartaDOS support, plus a Total Commander packer plugin

View on GitHub

Member rating

No ratings yet.

Sign in to rate this project.

README

atariATR

Tools for Atari 8-bit disk images — including 16 MB images (65535 × 256 B) in MyDOS and SpartaDOS format, with full subdirectory support.

Polish version / wersja polska

Downloads

Ready-made binaries are attached to every release:

File What it is
atrtool-X.Y-windows-x64.exe command line tool, 64-bit Windows
atrtool-X.Y-macos-arm64 command line tool, Apple Silicon
AtrWcx-X.Y.zip Total Commander packer plugin — drag onto TC to install
AtrWfx-X.Y.zip Total Commander file system plugin — same, separate package
AtrWcx-X.Y-macos-arm64.wcx Double Commander packer plugin, Apple Silicon
AtrWfx-X.Y-macos-arm64.wfx Double Commander file system plugin, Apple Silicon
AtrWcx-X.Y-linux-x86_64.wcx, AtrWfx-X.Y-linux-x86_64.wfx the same two for Linux

Releases are built per platform by GitHub Actions, so the Intel Mac and Linux artifacts come from native builds. A 32-bit .wcx is not among them — see Building.

macOS refuses to run unsigned downloads; clear the quarantine flag once:

bash
xattr -d com.apple.quarantine atrtool-*-macos-arm64
chmod +x atrtool-*-macos-arm64

What's inside

Two things share one engine:

  • atrtool — a command line tool to create, inspect and modify ATR/XFD images: format them, add and remove files, make subdirectories, and turn an image into a bootable disk by transplanting a DOS from a template image.
  • Two plugins for Total Commander and Double Commander (Windows, macOS, Linux):
    • a packer plugin (WCX) — open an .atr like an archive: browse the directory tree, copy files in and out, create directories, delete;
    • a file system plugin (WFX) — everything above plus what the archive interface has no functions for: renaming, moving inside the image, attributes, file dates and extra panel columns.

The engine is plain Object Pascal with no GUI dependencies, so the same code compiles under Free Pascal (macOS, Linux, Windows) and Delphi.

Why

Large Atari disk images are where most tools stop. Existing ones read a MyDOS image but don't walk its subdirectories, or write only in the root directory of a SpartaDOS disk, or create images without being able to modify them afterwards. This project handles the full matrix: read and write, subdirectories included, up to the 16 MB ceiling of the 8-bit world, and it is checked against real disks rather than against its own assumptions — see How it is verified.

Supported formats

Container Notes
ATR 128, 256 and 512 byte sectors; up to 65535 sectors (~16 MB)
XFD headerless, geometry inferred from file size
File system Read Write Notes
Atari DOS 2.0S yes yes 720 sectors, 10-bit sector links
Atari DOS 2.5 yes yes enhanced density, second VTOC at sector 1024
MyDOS yes yes subdirectories, 16-bit links, multi-sector VTOC, up to 16 MB
SpartaDOS / SDFS yes yes sector maps, nested subdirectories, timestamps, up to 16 MB
BW-DOS, SpartaDOS X, RealDOS yes yes all use SDFS, so they are covered by the above

Above 1023 sectors only MyDOS and the SDFS family exist — Atari DOS 2.0S stops at 720 sectors and DOS 2.5 at 1040. That is a limit of the platform, not of these tools.

Standard geometries: sd (90K), ed (130K), dd (180K), qd (360K), 512k, 1m, 2m, 4m, 8m, 16m, plus free-form sizes such as 65535x256, 1040s or 180K.

atrtool

bash
atrtool info image.atr                    # geometry, header, warnings
atrtool list image.atr -r                 # contents, recursively

atrtool create new.atr 16m                # empty 16 MB image
atrtool format new.atr mydos              # mydos | dos2 | dos25
atrtool format new.atr sparta MYDISK      # SpartaDOS with a volume name

atrtool add image.atr game.xex GAME.XEX   # add a file (name is optional)
atrtool extract image.atr GAME.XEX out.xex
atrtool del image.atr GAME.XEX
atrtool mkdir image.atr GAMES             # subdirectory (MyDOS / SpartaDOS)
atrtool rmdir image.atr GAMES

atrtool installdos new.atr template.atr   # make the image bootable
atrtool dump image.atr 360                # hex dump of a sector
atrtool roundtrip image.atr               # verify write fidelity

Making a bootable 16 MB MyDOS disk from scratch:

bash
atrtool create hd.atr 16m
atrtool format hd.atr mydos
atrtool installdos hd.atr "Mydos 4.50.atr"    # copies boot code + DOS.SYS/DUP.SYS
atrtool add hd.atr mygame.xex

No DOS binaries are shipped with this project. installdos takes the boot sectors and system files from an image you already have, and patches the fields that depend on the target disk: the DOS.SYS start sector, the density flag, the link field offset, and — crucially for large disks — the sector link mask, which MyDOS switches from AND #$03 to AND #$FF when a disk uses 16-bit links. Without that patch a boot loader copied from a floppy stops at the first sector above 1023.

Host file names are converted to 8.3 using the rules of the target file system, with Polish letters transliterated:

On disk MyDOS SpartaDOS
my-file v2.txt MYFILEV2.TXT MYFILEV2.TXT
2ndfile.dat X2NDFILE.DAT 2NDFILE.DAT
moj_plik-2.dat MOJPLIK2.DAT MOJ_PLI2.DAT
ŻÓŁW.TXT ZOLW.TXT ZOLW.TXT
zmienne_01.wav ZMIENN01.WAV ZMIENN01.WAV
file_1234567890.wav FILE7890.WAV FILE7890.WAV
bardzo dluga nazwa pliku.dokument BARDZOD8.DOK BARDZOD8.DOK

DOS 2 requires a letter in the first position and allows no underscore, which is why the MyDOS column differs.

Shortening never throws away the digits at the end of a name, because those are what tell a series apart: zmienne_01, zmienne_02, zmienne_03 would all collapse to ZMIENNE0 if the name were simply cut at eight characters. Letters give way instead, so the numbering survives and copying a whole series asks nothing.

When there are no digits to keep, the last character becomes a hexadecimal index derived from the source name — BARDZOD8 above. It looks arbitrary, and it is: bardzo dluga nazwa pliku.dokument and bardzo dluga nazwa pliku bo czemu nie.dokument are identical for their first eight characters, so no algorithm can squeeze the difference into an 8.3 name. What the index buys is that the 8.3 name is a pure function of the name on disk: the same file always lands in the same place, so copying it again overwrites its own file instead of a neighbour with a similar name. Directory names follow the same rule, which keeps two long directories from silently merging into one.

Both plugins report every conversion, so you can see which file became what: the file system plugin writes it to the file manager's log window, the packer plugin to its own log, and atrtool add prints it.

File manager plugins

Two plugins share the engine, and they answer different needs:

Packer (WCX) File system (WFX)
Enter an .atr clicked in the panel yes no — images come from a list
Browse, copy in and out, delete yes yes
Create directory yes yes
Rename (F2) no yes
Move within the image no yes
Attributes (Atari lock ↔ read-only) no yes
File dates (SpartaDOS) no yes
Extra panel columns no yes

If you only want to look inside an .atr you clicked, install the packer plugin. If you want to manage image contents like a drive, add the file system plugin too — they coexist without conflict.

Packer plugin

Grab AtrWcx-X.Y.zip from the Releases page (or build it yourself — see Building) and drag it onto a Total Commander window: the bundled pluginst.inf makes TC offer to install it. Then Ctrl+PgDn on an .atr file enters the image, F5/F6 copy files in and out, F7 creates a directory and F8 deletes — a directory is removed with everything inside it.

Copying a whole directory into an image preserves its structure: every path component is converted to a valid 8.3 name for the target file system (Moje Gry/Level 1/dane.dat becomes MOJEGRY/LEVEL1/DANE.DAT), and missing directories are created along the way — empty ones included.

The plugin browses the full subdirectory tree of MyDOS and SpartaDOS images, extracts and adds files (including into subdirectories), deletes them, and recognises images by content, not by extension — so an .atr file that is really a raw-sector disk is not shown as an empty archive.

It does not create images: a new image needs decisions about geometry, file system and DOS that belong in atrtool, not in a packer dialog. Total Commander does list .atr in its pack dialog, because withholding PK_CAPS_NEW also stops it from adding files to an existing image — so creation is refused with a clear error instead.

If something does not work as expected, create an empty file named AtrWcx.log in the same directory as the .atr. The plugin then appends a line for every operation it is asked to perform, which answers the first question worth asking: whether the file manager called the plugin at all.

Requires 64-bit Total Commander. The 32-bit version does not load .wcx64 files at all, so the package is not recognised as a plugin — TC just opens the ZIP. Build AtrWcx.wcx on Windows (see below), add it to the same package and point file= at it; a 64-bit TC then picks the .wcx64 from the same archive by itself.

File system plugin

Install AtrWfx-X.Y.zip the same way as the packer package (it carries its own pluginst.inf; for Double Commander take the native AtrWfx-*.wfx). It then appears as Atari ATR among network connections, not tied to any single file.

The extra panel columns show what a fixed archive listing has no room for: starting sector, sector count, the image's file system, the 16-bit link flag and Atari attributes — sortable, like any other column.

File dates work only where the format has them: SpartaDOS stores a date and time per file, so copying into such an image preserves the date from disk. MyDOS has no date field at all and the plugin reports that instead of pretending it worked.

Because a file system plugin is not tied to a clicked file, it needs to know which images to show. Enter it and you will find one file, _LISTA-OBRAZOW.TXT: press F3 to read it (its first line tells you where it lives on disk) or F4 to edit it, then refresh the panel. One entry per line — either an image file or a directory, in which case every .atr/.xfd inside is listed:

pascal
C:\Atari\images
C:\Atari\games\labyrinth.atr

ATRWFX_CONFIG overrides the location of that list if you prefer to keep it elsewhere.

You do not have to type paths by hand. Copy an .atr onto the plugin root with F5 and its path is appended to the list — the file stays where it is, only a reference is recorded, so nothing is duplicated. Repeating it changes nothing, and anything that is not a disk image is refused. F6 (move) is refused too: nothing was copied, so "moving" could only mean deleting your image.

F8 on an image in the root removes it from the list and leaves both the file and its contents alone. This needs care, because a file manager has no recursive delete in the API: before removing something that looks like a directory, it deletes the contents itself, file by file. Left unguarded, that gesture empties the disk image, DOS included — measured in Double Commander. The plugin therefore watches FsStatusInfo, which reports the directory an operation started in:

  • delete started in the image list, target inside an image → skipped without touching anything, and the closing FsRemoveDir removes the list entry instead. The skip is reported as success on purpose: the image disappears from the panel a moment later, so nothing can show a state that contradicts it, and reporting failure meant one error dialog per file — on an image with a dozen files the gesture turned into clicking "skip all";
  • delete started inside an image → passed through, so deleting files and non-empty directories from a disk works as before.

If a file manager does not report that context, nothing switches on: deletion behaves as it always did and removing an entry is refused with a message pointing at F4. The convenience only appears where the guard actually protects you.

An image shown by a directory entry has no line of its own, so F8 refuses it rather than removing the directory entry — that entry serves other images too.

Set AtrWfx.log next to the list file and the plugin appends the call sequence it receives; useful for checking what a particular file manager does.

Directories are moved by the file manager itself (create, move contents, remove), so moving a whole directory in one call reports "not supported" — the end result is the same.

Double Commander (macOS, Linux)

The same plugin works in Double Commander, which implements the same plugin interface and — verified in its source — calls the Unicode entry points on every platform, converting its UTF-8 strings to UTF-16. So no separate code is needed, only a native build:

bash
build/build-wcx-native.sh          # -> bin/AtrWcx.wcx (native shared library)

Then in Double Commander: Configuration → Options → Plugins → Packer plugins → Add, pick AtrWcx.wcx and associate the extension atr (and xfd if you want). Double Commander keeps native plugins under plugins/wcx/<name>/<name>.wcx, so copying it there fits its layout.

One catch worth knowing if you write plugins yourself. On macOS the loader resolves symbols with dlsym, which prepends an underscore to the name per the C convention, while Free Pascal exports OpenArchiveW rather than _OpenArchiveW. The failure is quiet: the library loads fine and not a single function is found. This project exports underscore-prefixed names under {$IFDEF DARWIN} and tests/wcx-loadcheck guards it by loading the built plugin exactly the way a file manager does.

Building

Engine and atrtool (macOS, Linux, Windows)

bash
brew install fpc          # or your distribution's fpc package
./build/build.sh          # -> bin/atrtool

The plugins

On Windows, Free Pascal or Lazarus is enough:

bash
build/build-wcx.sh win64      # packer plugin      -> AtrWcx.wcx64
build/build-wfx.sh win64      # file system plugin -> AtrWfx.wfx64

On macOS and Linux the native builds for Double Commander are:

bash
build/build-wcx-native.sh     # -> bin/AtrWcx.wcx
build/build-wfx-native.sh     # -> bin/AtrWfx.wfx

On macOS or Linux you need an FPC cross-compiler for Windows. Build it once:

bash
curl -LO https://sourceforge.net/projects/freepascal/files/Source/3.2.2/fpc-3.2.2.source.tar.gz/download
tar xzf fpc-3.2.2.source.tar.gz && cd fpc-3.2.2
SDK=$(xcrun --show-sdk-path)          # macOS only
make -j8 crossall CPU_TARGET=x86_64 OS_TARGET=win64 \
     OPT="-XR$SDK -Fl$SDK/usr/lib" CROSSOPT="-O2"
make crossinstall CPU_TARGET=x86_64 OS_TARGET=win64 INSTALL_PREFIX=~/fpc-cross

FPC_CROSS_ROOT=~/fpc-cross build/build-wcx.sh win64
FPC_CROSS_ROOT=~/fpc-cross build/build-wfx.sh win64

The -XR/-Fl flags are required on macOS because make invokes the compiler with -n, which skips fpc.cfg and with it the SDK paths.

A 32-bit .wcx/.wfx cannot be cross-compiled on an ARM Mac: FPC refuses to target i386 from a host without an 80-bit extended floating point type. It is also not built by CI — the Windows runner's Free Pascal only targets x86_64. If you need it, build it on Windows with a 32-bit FPC or Lazarus installation: build/build-wcx.sh win32.

Tests

bash
tools/fetch-dos-images.sh     # reference DOS images from AtariWiki (once)
tests/make-boot-images.sh     # bootable images for emulator testing
tests/run-tests.sh [image-dir]

run-tests.sh scans a directory of real .atr files (~/Downloads by default) and reports round-trip fidelity, then exercises both file systems and the plugin.

Whether an Atari actually boots from a generated image is the one thing no test can answer — docs/EMULATOR-TESTING.md lists what to check in an emulator and how to tell the failure modes apart.

make-boot-images.sh needs a MyDOS image with DOS.SYS on it as a template for the MyDOS set; AtariWiki publishes MyDOS sources but no ready boot disk, so point it at your own: MYDOS_TEMPLATE=/path/to/mydos.atr tests/make-boot-images.sh. Without it only the SpartaDOS set is generated.

How it is verified

Correctness here is not self-reported: every claim below is produced by tests/run-tests.sh or by an independent implementation.

  • Round-trip on 1705 real images: 1689 are written back byte-for-byte identically. 14 have headers inconsistent with their file size (reported as such — we pad to the full geometry, which repairs the header), 2 are corrupt or not ATR files at all.
  • Reading the same corpus: 943 images are read as file systems, with their complete subdirectory trees and no exceptions. The other 760 have no file system at all — see non-filesystem images.
  • Cross-validation both ways: 16 MB images created and filled by this code — MyDOS and SpartaDOS alike — are read, listed and byte-exactly extracted by an independent implementation, lsatr from mkatr (C), with free sector counts matching exactly. In the other direction we read images written by real MyDOS and real SpartaDOS, subdirectories included.
  • Writing into a real SpartaDOS X 4.48 image: after adding a 300 KB file and a subdirectory, exactly 5 bytes of the boot sectors changed — the free sector count, the allocation hint and the sequence number. The boot code is untouched, so the disk still boots, and both independent readers accept the result.
  • Agreement with original documentation: MyDOS formatting parameters match TECH.DOC from the MyDOS 4.51 sources, down to details like 708 free sectors on an empty single density disk — MyDOS includes sector 720 in its file system, plain DOS 2 leaves 707.
  • A 16-bit-link image actually boots: an 8 MB MyDOS image created by this code (17 VTOC sectors, patched link mask) boots on real MyDOS in an emulator, with its subdirectory visible in the DOS menu.
  • Both plugins are tested without Windows: tests/wcx-harness (67 checks) and tests/wfx-harness (57 checks) call the plugin functions in exactly the order a file manager uses, on MyDOS and SpartaDOS 16 MB images — including the operations only the file system plugin can do: renaming, moving inside the image, attributes, dates and custom columns. tests/wcx-loadcheck and tests/wfx-loadcheck verify every entry point resolves through dlopen/dlsym, the check that caught the macOS symbol-underscore trap.
  • File system writes are checked on SD, DD, 8 MB and 16 MB geometries in both file systems: extracted data is byte-identical, and the free sector count returns exactly to its post-format value after everything is deleted. For SDFS this also covers files spanning 10 chained sector maps, directories growing across sector boundaries, and reuse of deleted directory entries.

Non-filesystem images

Roughly 45% of the test corpus (760 of 1705 images) contains no file system: the boot sectors hold a custom loader that reads data straight off sectors. This is normal for demos, games and cartridge-oriented images, and such images cannot be browsed as files by any tool.

The engine reports this as a distinct condition (EAtariFsNoFileSystem) rather than as a read error, and both front ends make use of that instead of turning the user away:

  • atrtool list prints what is known about the image — geometry, whether the header agrees with the file size, and a decoded Atari boot record (how many sectors the loader reads, its load and init addresses).
  • the plugin opens the image anyway and shows a single read-only virtual file, INFO-DYSK.TXT, containing that same description. So entering such an .atr in Total Commander or Double Commander explains what the image is instead of failing. Writing to these images is refused — there is no directory and no free sector map, so any write would overwrite the loader.

Project layout

pascal
src/core/                 engine ??? plain Pascal, no GUI dependencies
  Atari.Atr.pas             ATR/XFD container, sector access
  Atari.Geometry.pas        standard geometries, size parsing
  Atari.FileSystem.pas      file system interface, 8.3 names, ATASCII, paths
  Atari.Fs.Dos2.pas         Atari DOS 2.0S / 2.5 / MyDOS
  Atari.Fs.Sparta.pas       SpartaDOS / SDFS
  Atari.Fs.Detect.pas       file system detection, boot sector disambiguation
  Atari.RawInfo.pas         description of images that have no file system
  Atari.DosInstall.pas      transplanting a DOS from a template image
src/cli/atrtool.dpr       command line tool
src/plugin/               plugins for Total Commander / Double Commander
  WcxHead.pas, AtrWcxImpl.pas, AtrWcx.lpr      packer plugin
  WfxHead.pas, AtrWfxImpl.pas, AtrWfx.lpr      file system plugin
docs/FORMATS.md           format notes gathered from specs and measurements (Polish)
build/                    build scripts, including make-release.sh
.github/workflows/        CI and per-platform release builds
tests/                    test suite, WCX harness and dynamic load check
tools/fetch-dos-images.sh downloads reference DOS images from AtariWiki

docs/FORMATS.md is worth a look if you work with these formats yourself: it documents the ATR boot-sector ambiguity with measurements from a 1705-image corpus, the MyDOS VTOC layout and link rules, the DOS 2 boot record fields, and the SDFS structures — with the reasoning behind each.

Current limitations

  • SDFS writing supports 128 and 256 byte sectors; 512 byte sectors (which would allow 32 MB images under SpartaDOS X) are read but not written, because the meaning of one superblock field for that case is undocumented and could not be verified here.
  • The 32-bit .wcx has to be built on Windows or x86 (see above).
  • No GUI yet — a Lazarus front end is the next step.

Credits and references

Specifications used, with the implementations consulted, are listed in docs/FORMATS.md. The main ones:

The reference tools are GPL-2 licensed. This implementation was written from the specifications and from observations of real disk images; no code was copied.

License

MIT