Building a Human68k Utility to Export X68000 Screenshots as PNG

The X68000 community has long relied on workarounds for capturing screen output, often pulling frames from emulators or photographing the CRT. Owning the original hardware and getting images off it is a different challenge, especially for those documenting a software collection or sharing discoveries with other enthusiasts. A native Human68k utility that converts the native screen format directly to PNG closes a long-standing gap.

Writing such a tool from scratch sounds intimidating, but the file format used by the system's graphics hardware is well documented in the official programmer's reference. With a small amount of C or even hand-written 68000 assembly, anyone comfortable with the command line can build something that boots from a floppy, reads a screen buffer, and produces a portable image file. The result is a self-contained archive that does not depend on a particular emulator version or capture card, which matters when you want screenshots that genuinely came from your own machine sitting on the desk in Sydney or Brisbane.

Understanding the X68000 Screen Memory Layout

The X68000 places its graphics data in a region of memory mapped by the CRT controller, with separate planes for the four bitplanes in 16-color mode and a dedicated area for 256-color and 65,536-color modes. For most homebrew software and a great deal of commercial games, the 512x512 16-color resolution is the sweet spot because it balances visual richness with a manageable buffer size. Each pixel is stored across four bytes in adjacent planes, and the bytes are arranged so that the low bit of each pixel index comes from plane zero.

Endianness is the first trap that catches people who try to interpret the buffer on a little-endian PC. The 68000 is big-endian, so a byte read from $C00000 is the high byte of a 16-bit word rather than the low byte. Reading screenshots correctly means either reversing pairs of bytes in software or using bitwise shifts to extract the high and low halves of each pixel index. Both approaches produce identical output once the encoder is debugged.

The same logic scales to higher resolutions, although the buffer size grows accordingly. A 768x512 16-color screen occupies 192 KB, while a 1024x1024 true-color screen occupies a full megabyte. For an archival utility, supporting 16-color and 256-color modes covers the vast majority of historical titles, including almost every game published before 1991. Once the basic decoder works, extending it to 65,000-color modes is mostly a matter of adding another code path that copies three bytes per pixel rather than indexing through a palette.

Tools and Compiler Choices for Human68k Development

Human68k is the operating system that shipped with the X68000, and it has a small but loyal toolchain ecosystem. The GNU Compiler Collection for m68k-coff targets the platform reliably when paired with a newlib-style C library, and there are also commercial compilers from the era that still produce tight code. For anyone working in Australia who imports Japanese development hardware, the higher shipping costs from Osaka make free cross-compilers running on a local PC much more attractive than a recurring parcel trail tracked through Australia Post.

A modern setup usually involves a cross-compiler on Windows, macOS, or Linux producing a .X file that can be transferred to the machine. The X68000 has its own executable format that is essentially a stripped-down COFF, and getting the section layout right is what allows the loader to place code in the right memory region. A few minutes spent reading the linker script pays off when the utility finally boots from a 2HD floppy without complaining about relocation errors.

Editor choice is a matter of taste, but most contributors on X68K.NET prefer something that handles Shift-JIS gracefully, since Human68k itself uses that encoding for filenames and console output. Vim and Emacs both cope, and VS Code with the right language extension works for those who do most of their work at a desk in Melbourne rather than in front of the actual machine. The point is to keep the iteration loop tight: edit, compile, copy, run, observe.

Reading the Frame Buffer on Real Hardware

Capturing the live screen on real hardware requires reading from the graphics memory region while the CRT controller is not in the middle of a refresh cycle. The simplest approach is to switch the screen to a known state, either by clearing it or by waiting for a vertical retrace, before copying bytes into a buffer in main memory. The IOCS call _GCTRL or direct access to the palette registers can freeze the visible output so that the read is stable.

A more polished utility exposes a hotkey that grabs whatever is on screen at the moment of the press. The 68000's auto-vectored interrupts make this easy: set up a level-six interrupt on a timer or watch the keyboard scan matrix, then call the conversion routine from the handler. The routine has to be quick, however, because Human68k expects to return to its own dispatch loop without much delay, and a slow encoder will leave the console feeling sluggish.

Storage of the captured buffer also matters. Writing directly to floppy in the middle of an interrupt risks buffer underruns, so a common pattern is to copy the frame into a large in-memory ring buffer first, then drain it to disk once the user releases the hotkey. For users with a CF card adapter, the draining step can target a fixed path, which makes the whole workflow as simple as pressing a single key to grab a screenshot mid-game.

Writing the PNG Encoder by Hand

PNG is a compressed image format, but its basic structure is approachable. Each file starts with an eight-byte signature, followed by a series of chunks, each with a length, type, data, and CRC. The IHDR chunk describes width, height, bit depth, color type, and other essentials, while the IDAT chunk carries the actual pixel data compressed with the deflate algorithm. Writing the file format without a library is tedious but feasible, since each chunk is independent and the entire image can be encoded in a single IDAT for a 16-color screen.

Deflate is the hard part. The reference zlib implementation is far too large to fit alongside a Human68k utility on a 1.2 MB floppy, but a stripped-down encoder that emits uncompressed deflate blocks is small enough to embed in a few hundred bytes. Uncompressed blocks are valid deflate and decoders everywhere accept them, so the resulting PNG opens correctly in every viewer from browsers to image editors on a modern PC.

For 16-color images, the encoder needs to convert the planar pixel data into a linear chunky format before passing it through the deflate stage. Each scanline is preceded by a filter byte, and the simplest filter, type zero, leaves the bytes unchanged. Choosing a smarter filter per scanline can shave a few percent off the file size, but for archival screenshots the difference rarely matters, and the simpler implementation is easier to audit. The CRC32 calculation is short enough to inline, and once it is right the file passes every PNG validator on the market.

Transferring Files and Validating the Output

Once the utility produces a PNG on the Human68k side, getting it onto a modern machine is the next hurdle. The classic route is a null-modem serial cable and a terminal emulator, but at 9600 baud a single screenshot takes a noticeable pause. Faster options include SCSI-to-USB bridges, network adapters that emulate the X68000's own NE2000-compatible card, and the CF card adapter that doubles as a shared drive. Each method has trade-offs in speed, cost, and the amount of fiddling required.

Australians working with vintage gear often find that local retailers do not stock X68000-specific cables, and ordering from Japanese hobbyist shops adds both shipping time and customs paperwork. Import duty and GST apply at the border, which is worth keeping in mind before placing a large order. The Australian Communications and Media Authority also regulates radio-emitting devices, so any active adapter should carry the RCM mark before it can be lawfully sold or used at scale; this rarely affects a single hobbyist device, but it matters when sharing designs with others.

The validation step on the PC side is straightforward. A quick file screenshot.png in a terminal reports the dimensions and color depth, and tools like ImageMagick or GIMP open the file without complaint if every chunk is well-formed. If a PNG refuses to open, the encoder almost certainly miscalculated a CRC, wrote the wrong length, or forgot the eight-byte signature at the start. Walking through the file with a hex editor against the PNG specification is the fastest way to find the bug, and there is something satisfying about watching a tool written in 68000 assembly produce a perfectly valid file that loads on a desktop running in Adelaide or Perth.

Comparing Approaches to Capturing X68000 Screenshots

Different workflows suit different goals, and choosing the right one depends on whether authenticity, speed, or convenience matters most. The table below summarizes the main options available to a hobbyist with both the original machine and a modern PC.

Method Authenticity Speed Hardware Needed Skill Level
Native Human68k utility Very high — pixel-perfect from real hardware Fast once written CF card or floppy drive Advanced C or assembly
Emulator screenshot High if matched to original Instant Modern PC only Beginner
Video capture card High for analogue output Real-time HDMI/USB capture device, CRT Intermediate
Camera photographing CRT Variable, suffers moiré Instant Any camera Beginner

For archival projects that aim to document what the machine actually showed, the native utility is hard to beat. Emulator captures are excellent for software distribution but cannot preserve the look of an unaccelerated CRT, while camera shots inherit scanlines, screen curvature, and ambient reflections. A capture card produces clean digital frames from the analogue video signal but requires fiddling with the monitor's geometry to avoid cropping the edges of the frame.

On real hardware, those geometry quirks are familiar to anyone who has ever opened the service menu. A walkthrough of CRT geometry adjustments covers the trim pots and on-screen alignment patterns, which becomes relevant when setting up a capture card to match the visible area exactly. The native Human68k utility sidesteps all of that by reading digital bytes directly from memory, leaving the CRT out of the equation entirely.

Try building the utility yourself, sharing your source on the X68K.NET project page, and joining the community of hobbyists who keep this remarkable machine alive well into the future.

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.

A two-ink risograph print in muted slate-blue and charcoal on off-white paper, showing a stylized desktop computer monitor beside a circuit board with soft geometric trace lines, conveying a calm retro-computing workshop atmosphere. A two-ink risograph print in deep purple and dark grey on cream stock, depicting a compact expansion card with connector ports and subtle Japanese technical annotations, evoking a hobbyist electronics bench. A two-ink risograph print in teal and charcoal on warm white paper, showing a server rack silhouette with soft network-line motifs and a small weather icon, suggesting a personal server room corner.

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.