Building A Human68k CPU Usage Graph Utility
The Sharp X68000 invites a particular kind of software archaeology. A program that draws a live CPU usage graph is small enough to understand from first principles, yet deep enough to involve Human68k, 68000 assembly, timer interrupts, video memory, DOS conventions, and the limits of an old single-user operating environment. The finished utility can turn an otherwise invisible performance problem into a moving line across the screen.
This project is useful for more than decoration. It can show whether a game loop is missing its timing target, whether a disk tool is spending too long waiting on I/O, or whether a TSR is consuming processor time in the background. For Australian owners working with imported machines, repaired power supplies, and scarce original documentation, it also provides a practical way to verify that restored hardware and modern expansions are behaving sensibly.
Define The Measurement Before Drawing
A modern operating system usually exposes idle time, scheduler counters, and per-process statistics. Human68k does not automatically provide that convenience. A DOS application normally owns the machine while it runs, so “CPU usage” needs a clear definition before any code is written. The most useful definition for a small utility is the percentage of timer intervals in which the system is doing work rather than entering a known idle path.
There are two practical designs. A resident utility can hook a periodic timer and count ticks while the machine is active, then count idle ticks when Human68k reaches its idle routine. This gives a genuine system-load estimate, provided the idle hook is reliable. A simpler foreground program can measure how much time its own loop spends processing, waiting for keyboard input, reading a disk, or yielding to DOS. That figure is better described as application activity, not total CPU utilisation.
The distinction matters when comparing results. A graph that sits at 100 percent while a program waits in a tight loop is accurate for processor occupancy, even if the user sees no useful progress. A graph that drops during disk access may indicate that the CPU is free, or it may simply reflect a blocking routine whose internal behaviour has not been instrumented. Document the metric in the utility’s help screen so nobody mistakes an estimate for a kernel-level statistic.
On an Australian workbench, this clarity is especially valuable when testing an X68000 fitted with a SCSI2SD device, CompactFlash adapter, or accelerator. A machine purchased through eBay Australia or shipped from Japan may have several variables at once. A graph cannot diagnose every fault, but it can reveal whether a delay is computational, I/O-related, or caused by a badly behaved background tool.
Select A Timer And Sampling Strategy
A graph needs a regular sampling clock. The X68000’s Motorola 68000 system includes the MFP, whose timer facilities can generate periodic interrupts. The exact timer configuration depends on the model, Human68k version, and the development libraries being used, so the safest approach is to inspect existing system headers, resident utilities, and hardware documentation before selecting a vector. Avoid copying a vector number from an unrelated 68000 machine.
For a first version, a sample rate between 10 and 20 updates per second is sensible. At 10 Hz, each sample represents 100 milliseconds and the graph is easy to read. At 20 Hz, short bursts become more visible, although the interrupt overhead and screen updates increase. The interrupt handler should do almost nothing: increment a tick counter, record whether the idle state was observed, set a flag, and return. It should never draw pixels, allocate memory, access the disk, or call a non-reentrant DOS routine.
Timer ownership is the difficult part. Save the original handler, install yours during startup, chain or restore it correctly, and ensure that the program removes the hook before exiting. If the program crashes, a resident handler pointing into freed memory can lock the machine or corrupt later sessions. A resident version should remain deliberately small and provide a clean disable path. During development, a foreground test program that installs the handler for a short period is safer than immediately building a TSR.
Use a fixed-point accumulator rather than floating-point arithmetic. If the interval contains 100 timer ticks and 73 are classified as busy, calculate 73 * 100 / 100, or retain a scaled integer such as 7300 for 73.00 percent. Fixed-point maths is quicker on a 68000 and avoids pulling in a large floating-point library. A rolling average over four or eight samples makes the display calmer without hiding sustained load.
Build The Usage Counter
The central problem is deciding how an interrupt can tell whether the processor is busy. The strongest approach is to observe a known Human68k idle path. When the idle routine is entered, set an idle marker or increment an idle counter; when the timer fires, the utility can compare idle and active ticks. The implementation must be matched to the specific Human68k environment because a hard-coded address or undocumented routine may change between versions.
A less invasive option is to measure time around a cooperative yield or wait call. The main program records a timestamp, performs a known operation, and records the next timestamp. This is useful for a benchmark or a game diagnostic, but it is not a universal system monitor. Another option is to count timer interrupts received while the application is running and call all of them busy. That produces a straightforward “foreground occupancy” graph and is often adequate for demonstrating timing spikes.
The interrupt routine should preserve every register it uses, acknowledge the timer source as required by the MFP, update counters in a predictable order, and chain to the previous handler when necessary. Shared counters should be read atomically from the foreground code. On a 68000, a multi-byte counter can be interrupted halfway through a read, so briefly masking the relevant interrupt or using a double-read consistency check prevents occasional impossible values.
Keep sampling and rendering separate. The handler writes a small record such as {tick_count, busy_count} into a volatile structure. The main loop notices the sample-ready flag, copies the values while interrupts are protected, calculates the percentage, and draws the newest column. This division keeps interrupt latency low and makes the program easier to debug using an emulator before moving to physical hardware.
Useful background material can be found in technical references covering older Japanese computers and low-level repair work. Cross-check any register-level information against X68000 documentation, because a similar-looking 68000 peripheral may use different interrupt acknowledgement rules.
Render A Readable Scrolling Graph
The display can begin as plain text. Print a percentage, a bar made from repeated characters, and a small history line using console output. This version is quick to compile and helps verify the timer, counter arithmetic, and cleanup code. It also works over a simple terminal or capture setup, which is handy when the X68000’s original monitor is unavailable.
A graphical version is more convincing. Reserve a rectangular area of the screen, map zero percent to its bottom edge and 100 percent to its top edge, then draw one vertical column for each sample. When the right edge is reached, either shift the history left or wrap around and overwrite old columns. Shifting an entire bitmap every sample is wasteful, so a circular column index is preferable. Clear only the column being replaced, draw the new height, and advance the index.
The X68000 offers several graphics modes and VRAM planes, and the best choice depends on the target display mode. Direct VRAM writes offer speed and a distinctive retrocomputer feel, but the address layout, bit planes, page selection, and colour handling need careful study. IOCS drawing calls are easier to maintain but may add enough overhead to distort a high-frequency measurement. For an initial release, a monochrome or single-plane graph with a labelled scale is a sound compromise.
Add a baseline, a 25/50/75 percent guide, and a numeric current value. A peak marker can record the highest recent sample, while a separate average line shows sustained pressure. Keep the graph’s own cost visible during testing: if enabling a full-colour display causes the usage line to rise sharply, reduce the refresh rate or draw only changed regions.
A practical layout might reserve the top 32 scanlines for status, the middle 160 scanlines for history, and the bottom area for tick rate, sample interval, and the measurement mode. Use a compact palette that remains legible on a period RGB monitor. If the machine is connected to a modern scaler, test both the original 15 kHz output and the scaler’s interpretation; uneven pixels can make a one-column graph look misleading.
Test The Utility On Real Workloads
Testing should begin with predictable synthetic loads. A tight integer loop should push the graph close to full activity. A loop that waits for keyboard input should produce a low or intermittent reading, depending on the chosen measurement model. Disk reads, sprite animation, decompression, and serial transfers then provide more realistic cases. Record the expected behaviour in a small test log rather than relying on memory.
Run the program with and without common TSRs. MIDI tools, disk caches, mouse drivers, and accelerator support software may install their own handlers or alter timing assumptions. If the graph becomes unstable after another resident program loads, inspect interrupt chaining before blaming the display code. A correct utility must coexist politely: preserve old vectors, avoid long critical sections, and restore the system on every exit path.
Hardware conditions matter too. Australian enthusiasts often run imported Japanese machines from the 1980s on local 240-volt, 50-hertz mains through a suitable transformer or a correctly repaired internal supply. A failing power supply can create resets, visual glitches, or disk errors that look like software timing problems. Test with a stable supply, allow for summer heat in places such as Brisbane or Perth, and check whether an expansion board is seated properly before interpreting a strange graph.
For repeatable results, capture screenshots or serial logs at fixed workloads. Compare the same program from floppy, SCSI, CompactFlash, and network storage. A graph that rises during a modern storage adapter’s initialisation may be normal, while a repeating spike every few seconds could indicate polling or an interrupt conflict. Local buying patterns also affect testing: replacement boards and cables may arrive through Japanese sellers, Gumtree, or small Australian retrocomputing groups with different revisions and documentation.
Package The Tool For Preservation
A useful release should include the executable, source code, build instructions, a short technical note, and a warning about the measurement model. Name the binaries clearly, keep the program small enough for common storage media, and include a command-line option for text mode, sample rate, graph height, and resident operation. A no-frills default is important because many X68000 users want to copy a utility to a disk image and run it immediately.
The source should separate platform-specific code from general logic. Put MFP setup, interrupt entry and VRAM access in assembly or a narrow hardware module. Keep percentage calculation, ring-buffer management, peak tracking, and command parsing in C or portable 68000 code where possible. This structure allows the graph algorithm to be tested on a modern machine while the hardware layer is checked on an emulator and then on an actual X68000.
The following design choices suit different goals:
| Design | Measurement quality | Development effort | Best use |
|---|---|---|---|
| Text bar in the foreground loop | Application activity only | Low | Early timer and arithmetic testing |
| Timer counter with busy ticks | Approximate system activity | Medium | Compact diagnostic utility |
| Idle-path hook with timer sampling | Closest to total CPU usage | High | Serious system monitoring |
| Direct VRAM scrolling graph | Good visual feedback, display overhead must be measured | Medium to high | Demonstrations and profiling |
| IOCS-rendered graph | Easier to maintain, potentially slower | Medium | Portable graphical prototype |
| Resident sampler with separate viewer | Continuous background history | High | Long-running diagnostics |
Keep a development diary with hardware revision, Human68k version, compiler, sample frequency, and observed results. The X68K.NET diary is a useful model for documenting the small decisions that otherwise disappear once a repair or experiment is finished. That record can save another enthusiast hours when a timer behaves differently on a second machine.
Release the utility with honest limitations. Say whether idle time is detected directly, whether the graph measures the foreground process, and how much overhead the sampler adds. Include a recovery note explaining how to reboot or remove a resident copy if a test build misbehaves. Clear documentation is part of preservation: future users may run the program decades after the original development environment has become difficult to reproduce.
Build the first version around a text display, one reliable timer source, fixed-point counters, and a clean shutdown path. Once those foundations behave consistently, add direct VRAM rendering, peak and average lines, and optional resident monitoring. Share the source, binaries, screenshots, and test notes with the X68000 community so the utility becomes a reusable instrument for repairs, software profiling, and continued hands-on work with Human68k.
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.