Building a Human68k disk surface scan utility with block verification
The Sharp X68000 remains one of the most architecturally distinctive home computers ever produced, and keeping a fleet of these machines running in the present day requires a steady supply of practical diagnostic tools. Floppy disks from the early 1990s are now well past their expected service life, and even SCSI hard drives sourced from estate sales show signs of media decay. A purpose-built surface scanner that runs natively under Human68k gives owners the ability to identify marginal sectors before they corrupt important save files or game data.
Australian collectors in Melbourne and Sydney have long relied on community-developed diagnostics for their vintage gear, often trading utilities at monthly retro meets held in suburban RSL halls. The local scene is small but technically sharp, with several enthusiasts maintaining multiple X68000 CZ-600 series machines alongside their Amiga and MSX collections. Writing a Human68k utility that performs a real surface scan with block verification slots neatly into that tradition of self-reliance.
This article walks through the design and implementation of such a tool, covering disk geometry handling, read algorithms, checksum verification, and a clean text-mode interface. The approach assumes you are comfortable with C and have access to the X68000 development environment, either through a cross-compiler or a native Human68k setup. By the end, you should have a working utility that you can compile, customise, and distribute to other users on the Australian X68k mailing list.
Understanding disk geometry on Human68k
Human68k presents storage devices through a combination of BIOS calls and IOCS (I/O Control System) routines, and a surface scanner needs to understand both layers to do its job properly. A 2HD floppy formatted under Human68k uses 1,024-byte sectors arranged in a standard 77-track, 2-side geometry, while a 2DD disk uses 512-byte sectors across 80 tracks. Hard drives connected through the SASI or SCSI interface follow variable geometries reported by the controller at boot.
The IOCS provides functions such as B_SEEK, B_READ, and B_WRITE that operate on physical or logical sector addresses, but they do not automatically retry on bad reads. That is by design, as Human68k expects the underlying hardware and driver to handle error recovery. A surface scanner deliberately bypasses this layer to expose every marginal block, forcing the application to interpret the raw error codes returned by the floppy disk controller (FDC) or SCSI host adapter.
| Media type | Logical sectors | Bytes per sector | Common capacity |
|---|---|---|---|
| 2DD floppy | 1,440 | 512 | 720 KB |
| 2HD floppy | 1,232 | 1,024 | 1.2 MB |
| MO disk (128 MB) | 248,820 | 512 | 128 MB |
| SCSI hard disk | variable | 512 | 20–540 MB |
For floppy work, the relevant IOCS calls live in the disk-related portions of the system, while SCSI commands require direct interaction with the host bus adapter through I/O port access. Your utility should detect the device type at startup and select the appropriate code path, because the error handling philosophy differs significantly between the two. Building a CompactFlash IDE adapter provides useful context for modern media that emulates IDE behaviour on the X68000, even though the focus there is replacement rather than verification.
Choosing the right language
Most Human68k utilities are written in C using the GCC cross-compiler targeting m68k-coff, or in assembly using the HAS060 assembler. For a disk surface scanner, C is the pragmatic choice because the bulk of the work is sector address arithmetic, buffer management, and error reporting, all of which map cleanly to C structs and pointers. Assembly becomes valuable only when you need to squeeze maximum throughput out of the FDC, but for verification work that favours reliability, the trade-off favours readability.
The X68000 uses the Motorola 68000 CPU at 10 MHz in the original CZ-601 model, with later variants climbing to 16 MHz. A scanner written in C will easily saturate the floppy controller because the bottleneck is the rotation latency of the disk itself, not the CPU. Code that performs unnecessary work inside the read loop can still affect performance on 68000-class silicon, so keep inner loops tight and avoid allocating memory on every iteration.
Australian developers often compile on Linux or BSD hosts using m68k-x68k-elf-gcc or similar toolchains, then transfer the resulting .X or .R executables to a working X68000 via null-modem serial or by burning them onto a floppy using a Gotek-style floppy emulator. Local postal deliveries through Australia Post remain the most common way to ship physical media between enthusiasts in different states, so plan to produce something that fits comfortably on a single 1.2 MB floppy.
Designing the verification algorithm
A genuine surface scan reads every block on the device and checks it against some form of expected content. For a blank floppy, the test reduces to a read-without-error check, but for disks containing actual files you want stronger validation. The standard approach is to compute a 16-bit or 32-bit checksum over each sector and compare it against a value stored alongside the original data, similar to how Unix dd with conv=noerror behaves on a damaged volume.
Your utility needs to maintain a block map in memory that tracks the status of every sector: good, suspect, or bad. The map size depends on the device — a 2HD floppy fits comfortably in 8 KB using two bits per sector, while a 120 MB SCSI drive would require nearly 30 KB. Either way, the map must persist to a log file on completion so the user can identify clusters of damage that suggest a physical problem rather than random bit rot.
One subtlety of Human68k block devices is that logical block numbering does not always match physical geometry, particularly when using the XDF or other extended formats that cram more data onto a floppy. A well-behaved scanner should honour the IOCS-reported logical layout rather than assuming the standard 1,024-byte-per-sector geometry. If you find unexpected sector counts, double-check that the disk was formatted with the standard Human68k tool rather than a third-party formatter that may use non-standard sector IDs.
Implementing the sector read loop
The core of the utility is a loop that issues a read, captures any error code, and updates the block map. The IOCS B_READ function returns a status word where bit 7 indicates a CRC error and bit 6 indicates a missing address mark. Bits 0-4 carry the FDC error code from the NEC µPD72065 controller used in the X68000, which distinguishes problems such as sector not found, data overrun, and write protect violations.
A reasonable structure in pseudocode goes like this: open the device, allocate a buffer equal to the maximum sector size, then iterate from sector 0 to the last logical sector. For each sector, call B_READ, capture the status, and based on the bits either mark the block good, increment a retry counter, or mark it bad after a configurable number of retries (typically three). Flaky media often succeeds on the second or third attempt, which is why a single-shot read gives an unfairly pessimistic picture.
Retries slow the scan considerably, so expose the value as a command-line option. A quick scan with zero retries works well for routine checks before a critical save operation, while a thorough scan with five retries is the right choice when assessing a floppy you have just pulled out of a garage sale box at a Brisbane market stall. The local term "boot sale" for these gatherings captures the cultural texture of Australian retro hunting.
Adding checksum verification
Pure read-without-error is a weak test because silent corruption is possible without triggering any FDC error flag. A stronger scanner computes a checksum over the sector data and compares it against a stored reference. The simplest scheme is a Fletcher-16 or Adler-32 hash, both of which are fast enough to run inside the inner loop without measurably slowing the scan. Avoid CRC-32 unless you genuinely need error-detection strength, because the per-sector cost adds up across hundreds of thousands of sectors on a SCSI drive.
If you are scanning a disk containing a known file system, the logical layer is to walk the directory and verify that the cluster chain matches the FAT-style allocation table used by Human68k. Human68k uses a variant of FAT16 that is documented in the system manuals, and you can parse the boot sector to recover the cluster size, FAT location, and root directory entry count. A scanner that detects allocation inconsistencies gives the user actionable information beyond a simple sector-level map.
For users who want to validate newly burned floppy images, the scanner should accept an MD5 or SHA-1 reference file alongside the target disk. This lets you confirm that the freshly written media matches the master image bit-for-bit, which is a useful sanity check before archiving important software. The hashing cost is borne once per sector during the verification pass, so it slots into the existing loop without restructuring the code.
Building a text-mode interface
The X68000 shipped with a beautiful 768×512 16-colour display, but most serious Human68k utilities still target the 768×512 text mode or even the 512×512 mode used by the original CZ-601. A clean text-mode interface is more than adequate for a diagnostic tool and runs happily on the lower-cost CRT monitors still common in Australian collector setups. The interface should display progress as a percentage, current sector address, and a rolling error count that updates in place.
Use IOCS console calls like B_PUTC and B_PRINT for output, and consider reserving a status line at the top of the screen that shows the device name, total sectors, and elapsed time. A bottom status line can show the count of good, suspect, and bad blocks as the scan progresses. Avoid the temptation to render fancy graphics — focus on legibility from across the room, because Australian garage workshops often have the scanner output going to a distant CRT while the operator sits at a workbench.
Once the scan completes, write a human-readable report file to the current directory listing every bad sector with its logical block number and error code. A simple text format is fine; XML or JSON would be overkill for a Human68k utility. Include a summary line at the top of the report with the device, scan date, and pass/fail count, then list detailed results below.
Testing on real hardware
Before distributing your utility, run it against media with known conditions. A scratch disk with intentional damage is invaluable for calibration — use a magnet to corrupt a known range of sectors on a test floppy, then verify that the scanner reports the expected block addresses. Repeat the exercise with a clean disk to confirm that no false positives appear, which would suggest a bug in the error handling code rather than a media problem.
Field testing at a retro computing meet, such as the monthly gathering at the Australian Centre for the Moving Image in Melbourne, gives you access to a wider range of disks and drives than any single collection could provide. Bring a null-modem cable so attendees can upload the latest build of your scanner to their machines and provide feedback on performance and usability. The local slang "arvo" for afternoon is sometimes applied to these meetups, as in "see you at the retro arvo on Saturday".
Pay particular attention to behaviour on real SCSI drives, because emulator environments such as XM6 or EX68 rarely reproduce the timing-sensitive failure modes that surface on vintage hardware. If you do not have a working SCSI setup, a CF-IDE adapter running in true IDE mode is the next best thing. Document any quirks you discover and include them in the README so future users can interpret their scans with confidence.
If you have built a surface scanner for Human68k and would like to share it with the community, drop a copy on an FTP site or a file mirror that the X68K mailing list archives can reference. Australian contributors are encouraged to add a short note about local testing conditions, drive models, and any sector counts that differ from the standard Human68k geometry. Sharing the tool helps preserve the platform and gives other collectors a reliable way to assess the media they acquire through estate sales, swap meets, and the steady stream of late-night eBay Australia auctions that keep the local community well-stocked.
Nereid-X Expansion Board
A personally-produced LAN+USB+Memory expansion board for Sharp X68000 series computers. Multiple production runs were offered, including a final batch and a later revival reproduction run.
Power Supply Repair
X68 power supply repair and modification services were offered by the site owner, with documentation shared through diary entries spanning 2001–2006.
Server & Networking
Notes on FreeBSD administration, ISP changes, server migration, and networking topics. The site itself ran on FreeBSD with the hns diary system and Namazu search integration.
Get in touch
X68K.NET connects Sharp X68000 enthusiasts through community links and shared projects. Reach out with questions about the Nereid project or X68 resources.