Programming a Human68k TSR to Display System Information
A terminate-and-stay-resident utility, or TSR, is a small program that remains in memory after its original command has finished. On a Sharp X68000 running Human68k, this makes it possible to add a keyboard shortcut, a background monitor, or a compact system-information display without replacing the operating system. The program can report memory usage, CPU state, drive activity, and hardware details whenever the user needs them.
The useful part of this project is the close relationship between software and the X68000’s hardware. Human68k provides DOS and IOCS services, while the 68000 processor, interrupt vectors, video memory, and peripheral registers expose information that ordinary command-line tools may not show. A carefully designed TSR can bridge those layers in a practical way.
The main difficulty is not drawing text. It is becoming resident safely, avoiding conflicts with DOS, preserving registers and interrupt state, and collecting information without making assumptions about every X68000 model. A reliable utility should degrade gracefully when a device or expansion board is absent, and it should remain unobtrusive during normal software use.
What a Human68k TSR must accomplish
A Human68k TSR generally performs three jobs before it becomes resident. It parses command-line options, allocates or reserves the memory needed by its resident portion, and installs a hook that can detect the chosen activation event. That event might be a keyboard combination, a timer tick, or an existing system service that the program can intercept.
The initialization code should then release everything it no longer needs. Temporary buffers, command-line parsing routines, and diagnostic messages can be discarded or placed outside the resident block. The smaller the permanent footprint, the lower the chance of reducing the memory available to games, compilers, and disk utilities.
A display request must be treated as a short transaction. The TSR saves the processor context, determines whether DOS or another interrupt handler is already busy, gathers a limited set of values, writes the display, restores the original context, and returns. If it performs a long disk operation or waits for input while running inside an interrupt path, it can corrupt the active application or lock the machine.
For that reason, many robust designs divide the utility into a small interrupt-side trigger and a larger foreground routine. The interrupt side records that the hotkey was pressed, while a polling loop or cooperative entry point performs the actual formatting and rendering when it is safe.
Choosing safe system information sources
Memory statistics are an excellent starting point because Human68k already manages the relevant allocation data. The resident program can call the appropriate DOS service from a safe execution context, calculate free and total memory, and format the result as kilobytes or hexadecimal paragraphs. It should distinguish between free memory reported by DOS and physical RAM detected through hardware probing; those figures answer different questions.
Drive and file-system information requires greater care. A mounted device may be a floppy disk, hard disk, SCSI unit, RAM disk, or a device supplied by a third-party driver. Querying a drive letter through normal DOS services is safer than reading controller registers directly, especially when the drive is active. A status display can show the current drive, available space, and an error state without attempting to inspect a device that is unavailable.
CPU and video information can be read from known system variables or hardware registers, but the program must identify which values are stable across models. The X68000 family includes several CPU configurations and display arrangements. A monitor that labels every machine as a 68000 or assumes one fixed video mode will eventually provide misleading output.
Expansion hardware deserves the same caution. If a system contains a network or memory board such as the Nereid-X expansion, the utility may offer additional status information, but it should first verify that the board responds at its expected address or through its documented interface. Unsupported probing can generate bus errors, so optional hardware detection should be isolated and guarded.
Useful fields for a first version include:
- CPU family or configured clock information
- Current video mode or screen dimensions
- Free DOS memory and largest available block
- Current drive and selected device status
- Resident utility version and activation state
Designing resident memory and interrupt hooks
A TSR has a transient section and a resident section. The transient portion runs during startup, installs the necessary hooks, and calculates the exact amount of memory to keep. The resident portion contains the activation routine, saved original vectors, buffers, fonts or text data, and any code called after installation.
On the 68000, interrupt vectors occupy the beginning of the address space, and changing a vector is a privileged operation that must be done with interrupts controlled appropriately. The installer should save the old vector, write the new address through the supported mechanism when available, and restore the original vector when the TSR is removed. A removal command is harder than installation because it must prove that the current vector still belongs to the utility and that no later TSR has chained after it.
Chaining is usually safer than replacing. The new handler can inspect the event, respond when its hotkey is detected, and pass control to the previous handler for all other cases. It must preserve every register and condition code expected by the old handler, use a dedicated resident stack if the entry path requires one, and avoid recursive activation.
Keyboard handling has several traps. A key event may be delivered repeatedly while the key is held, and the interrupt may occur while the foreground program is changing video state. The handler should debounce the activation key, set a busy flag while the screen is visible, and provide a clear exit key. If a second activation arrives during rendering, it should be ignored rather than starting a nested display routine.
Memory allocation must also respect Human68k conventions. A program should use the documented DOS mechanisms or compiler runtime facilities for its target environment, then keep only the resident block. Hard-coded assumptions about memory segment layout are tempting on an old platform, but they make the utility fragile when run under a different DOS version, memory manager, emulator, or expansion configuration.
Comparing implementation paths
The best implementation language depends on how deeply the utility needs to interact with the machine. C makes string formatting, command parsing, and DOS calls convenient, while assembly gives precise control over vectors, register preservation, and screen output. A hybrid design is often the most maintainable: C handles policy and formatting, and a small assembly module handles the interrupt boundary.
The display method also affects reliability. Direct writes to text VRAM are fast and predictable when the screen mode is known, but they can interfere with an application’s own display. IOCS or a documented console service is friendlier to the operating environment, though it may be slower or unsuitable inside an interrupt handler. A full-screen overlay should save the affected area and restore it exactly, including attributes and cursor state.
| Implementation path | Strengths | Risks | Suitable first use |
|---|---|---|---|
| C with DOS and IOCS calls | Easy formatting and maintenance | Compiler conventions vary; unsafe calls in interrupt context | Memory and drive summary |
| Assembly resident core | Precise context and vector control | More difficult debugging and portability | Hotkey hook and minimal overlay |
| Direct text VRAM output | Fast and compact | Can damage an application’s display state | Dedicated diagnostic screen |
| Foreground polling helper | Safer DOS interaction | Requires a running helper or cooperation from the shell | Detailed system report |
| Hardware-specific probe | Rich board and device data | Bus errors and model dependence | Optional expansion diagnostics |
A useful development strategy is to begin with a command-line diagnostic that prints the desired values and exits normally. Once the information is correct, move the formatting code into a foreground display routine. Only after that should the hotkey hook and resident memory management be added. This sequence separates information errors from TSR errors and greatly reduces debugging time.
Rendering an unobtrusive status display
A system-information overlay should make its temporary nature obvious. A narrow panel with a contrasting border, a title such as the utility name and version, and a consistent set of labels is easier to read than a screen filled with raw hexadecimal values. Aligning numbers in columns also helps reveal changes in memory or device state.
The program can preserve the screen region beneath the overlay, but the amount of memory required depends on the display mode and color depth. A simpler alternative is to switch to a known text screen, display the report, and restore the previous mode only if the operating environment supports that transition safely. A TSR should never assume that the foreground application is using the same screen organization as the utility.
Avoid DOS console output from an interrupt handler. DOS may already be processing a disk request, allocating memory, or updating internal structures when the hotkey arrives. Calling back into DOS at that moment can cause re-entry problems. The interrupt routine should set a flag, and a safe foreground path should perform DOS calls after checking that the system is available.
Formatting should use fixed-size resident buffers. Dynamic allocation from the interrupt path is inappropriate, and unbounded string operations can overwrite the saved context or neighboring resident code. Numeric conversion routines should define maximum field widths and handle unavailable values with clear markers such as “unknown” or “offline.”
Testing on hardware and emulators
Testing should begin with installation and removal. Run the utility repeatedly from a clean boot, inspect the reported free memory before and after installation, and confirm that the expected resident size is stable. Test invalid options, missing devices, duplicate installation, and removal after other utilities have been loaded.
The hotkey must be tested during several kinds of activity: an idle DOS prompt, directory access, floppy or SCSI transfers, a running text editor, and a graphics program. If the screen becomes corrupted only during disk access, the problem is probably an unsafe DOS call or an interrupt timing issue. If the machine hangs immediately, check vector installation, stack handling, and register restoration before investigating the display code.
An emulator is valuable for rapid development, especially when it provides memory inspection, breakpoint support, and configurable hardware. Real X68000 hardware remains essential for validating bus timing, video behavior, keyboard differences, and expansion-board detection. A report that works in an emulator with every device enabled may encounter absent registers or different wait states on an actual compact or tower model.
Keep a crash log during development. Record the model, CPU, memory configuration, Human68k version, emulator settings, loaded TSRs, and the exact action that preceded the failure. Old systems often expose bugs only after a particular sequence of resident utilities has changed the interrupt chain.
A practical build checklist
A small, focused first release is easier to trust than a feature-heavy monitor. Build the resident mechanism around conservative assumptions, document the tested Human68k and compiler versions, and make optional hardware features independently switchable. The following checks cover the areas most likely to cause trouble:
- Verify installation, duplicate detection, and removal without changing the resident memory size unexpectedly.
- Save and chain the original interrupt or service vector, preserving all required registers and status flags.
- Defer DOS calls and disk access until a safe foreground context is available.
- Bound every resident buffer and handle unknown hardware with a visible, non-fatal status.
- Test the overlay during keyboard input, disk activity, graphics programs, and multiple X68000 configurations.
Version information should be visible in the display and available from the command line. When users report a failure, the utility version, machine model, memory size, and active expansions become immediately useful. A plain text diagnostic mode is also worthwhile because it can be redirected to a file without invoking the resident overlay.
Documentation belongs with the binary. Explain which interrupt or system service is used, how much memory remains resident, what hardware is detected, and how to remove the utility safely. Include source code where possible, especially for the vector and assembly portions, so future X68000 enthusiasts can audit the behavior and adapt it to newer preservation projects.
Put the monitor to work
A Human68k TSR that displays system information is a compact exercise in operating-system integration. It brings together 68000 assembly, DOS conventions, IOCS services, video memory, interrupt chaining, memory management, and hardware detection. The finished program can be modest in size while still teaching lessons that apply to much larger retrocomputing projects.
Start with a normal diagnostic command, make its output accurate, and then introduce residency one layer at a time. Keep the interrupt handler short, treat DOS as non-reentrant, preserve the user’s display state, and make every optional hardware probe fail safely. With those principles in place, the utility becomes a dependable instrument for exploring an X68000 rather than another source of unexplained crashes.
Build the first version around memory, video, and drive status, test it on both an emulator and real hardware, and publish the source alongside the executable. That gives the wider X68000 community a practical monitor they can use, inspect, and extend as their own machines and expansion boards evolve.
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.