Human68k MOD playback through the custom SP

MOD music gives the Sharp X68000 access to a large library of compact tracker pieces. A file holds sampled instruments, note patterns and effect commands rather than a finished stereo waveform. A Human68k program can read it, resample the instruments and send PCM to the custom SP sound processor. That differs from driving the original Yamaha YM2151 FM synthesiser or Ricoh RF5C01 ADPCM chip, neither of which accepts raw tracker samples directly.

An Australian build adds some practical constraints. A Japanese-market machine may arrive through international freight, with Australian GST and any applicable customs charges included in the budget. The original supply expects 100 V, while household power is 230 V at 50 Hz, so use a suitably rated isolation transformer and have the mains work checked by a qualified electrician. Australia Post or StarTrack can handle insured, padded shipments, while local collectors in Sydney, Melbourne and Brisbane are useful contacts for donor parts and spare boards.

The approach here covers classic four-channel MOD files with 31 instruments. It keeps DOS file access, tracker interpretation and SP hardware control in separate layers. Exact SP commands, sample formats and status bits must come from the documentation for the particular board; there is no safe substitute for guessing register values from a similarly named device. The result is a player designed for real X68000 hardware, where original 68000 timing and limited memory matter.

What the custom SP changes

Treat the SP as a PCM destination with an explicit contract: supported rates, sample width, channel packing and the meaning of its status bits. The example uses signed 16-bit mono at a rate the board accepts; 22,050 Hz is a reasonable starting target for tracker material, not a universal SP setting. If the custom hardware expects another format, change the adapter and mixer output, not the MOD parser.

A practical program has five parts: a Human68k file reader, a MOD header and pattern decoder, an instrument cache, a channel mixer and an SP output driver. The original X68000 usually has too little memory for every converted instrument and waveform, so read samples in blocks and keep only active data close at hand. The SCSI2SD storage notes provide a useful example of using modern storage with an original machine while leaving the audio hardware untouched.

Before writing the player, make a tiny SP test program that configures the stream, writes a known waveform and reports underruns. Some SP revisions expose a writable FIFO, others a ring buffer or DMA-style interface. The program-facing operations remain similar: configure the format, ask how much space is available, write PCM and commit it. Keep those operations in a board-specific header so later changes do not spread through the tracker code.

Reading a classic MOD file

A standard 31-instrument MOD header occupies 1,084 bytes: 20 bytes of title, thirty 30-byte instrument records, two length bytes, 128 order entries and a four-byte signature. Instrument lengths and loop positions are stored in big-endian words; loop lengths count words, not bytes. The signature identifies formats such as M.K. or FLT4. Fifteen-instrument files, extended channel counts and trackers with automatic sample saving need separate handling.

The following C fragment assumes a Human68k toolchain with the familiar FILE functions. Replace those calls with the library equivalents if your compiler exposes only DOS primitives.

#include <stdint.h>
#include <stdio.h>
#include <string.h>

typedef struct {
    uint8_t name[22];
    uint16_t length, loop_start, loop_length;
    uint8_t finetune, volume;
} ModSample;

typedef struct {
    ModSample sample[31];
    uint8_t song_length, restart;
    uint8_t order[128];
    uint8_t pattern[64][64][4];
} Mod;

static uint16_t be16(const uint8_t *p)
{
    return (uint16_t)(((uint16_t)p[0] << 8) | p[1]);
}

static int read_mod_header(FILE *f, Mod *m)
{
    char title[20];
    uint8_t word[2], tag[4];

    if (fread(title, 1, 20, f) != 20)
        return 0;

    for (unsigned i = 0; i < 31; ++i) {
        ModSample *s = &m->sample[i];

        if (fread(s->name, 1, 22, f) != 22 ||
            fread(word, 1, 2, f) != 2)
            return 0;

        s->length = be16(word) * 2;

        if (fread(&s->finetune, 1, 1, f) != 1 ||
            fread(word, 1, 2, f) != 2)
            return 0;

        s->loop_start = be16(word) * 2;

        if (fread(word, 1, 2, f) != 2 ||
            fread(&s->volume, 1, 1, f) != 1)
            return 0;

        s->loop_length = be16(word) * 2;
    }

    if (fread(&m->song_length, 1, 1, f) != 1 ||
        fread(&m->restart, 1, 1, f) != 1 ||
        fread(m->order, 1, 128, f) != 128 ||
        fread(tag, 1, 4, f) != 4)
        return 0;

    if (memcmp(tag, "M.K.", 4) != 0 &&
        memcmp(tag, "M!K!", 4) != 0 &&
        memcmp(tag, "FLT4", 4) != 0 &&
        memcmp(tag, "4CHN", 4) != 0)
        return 0;

    return fread(m->pattern, 1, sizeof m->pattern, f) ==
           sizeof m->pattern;
}

After the pattern area, read sample data in instrument order. MOD samples are signed eight-bit PCM; their loop start and length select a repeating region, and a zero loop length disables looping. Convert on demand to the SP’s format rather than altering the original file. When a note retriggers, reset the voice phase and apply the tracker’s restart behaviour. Keep the source sample pointer and phase per channel, otherwise a short sample or loop can desynchronise the remaining instruments.

Resampling and mixing tracker channels

A period in a MOD pattern is not a sample rate. Use the period-to-frequency mapping of the tracker that made the file to derive the source frequency, then convert that to the SP output rate. The file itself has no reliable sample-rate field. Amiga, PC and later tracker conventions can differ, so preserve the chosen clock constant in the source and compare a reference note with the original tracker before accepting the tuning.

Use a fixed-point phase accumulator so notes do not drift during long samples. This excerpt advances one voice; the integer division happens once when a note starts, not for every output sample:

uint32_t step =
    (uint32_t)(((uint64_t)source_hz << 16) / output_hz);

phase += step;
uint32_t index = phase >> 16;
phase &= 0xffffu;

Mix all four voices into one accumulator, apply the instrument volume and tracker effects, then clamp once to the SP’s range. Implement at least tone portamento, volume slides, vibrato, sample offset and note cut before expecting a convincing MOD performance. The original 16 MHz 68000 has limited time for work between buffer refills, so avoid floating-point maths in the inner loop and favour fixed-point arithmetic. Linear interpolation can improve resampling quality, but it also costs time.

Keeping playback timing stable

Keep two clocks separate. The SP consumes PCM at a fixed sample rate, while the tracker advances through rows and ticks using its own tempo rules. Old MOD tempo values are tracker-specific and should not be replaced blindly by a modern BPM formula. Select the timing behaviour of the tracker family you are targeting, then schedule row events at sample boundaries so a note change cannot occur in the middle of a mixed block.

File input is the main threat to smooth playback. Human68k DOS calls may block, and a read that misses a refill deadline causes an audible gap. Cache instrument blocks before they are needed and avoid disk activity inside an interrupt handler. If a timer interrupt drives the player, have it set a volatile flag or queue a short PCM block, then do mixing work in the main loop. Use the timer and interrupt conventions supplied by your Human68k development environment rather than guessing timer-controller registers.

Polling the SP for FIFO space is often simpler on the original hardware, provided interrupts remain enabled and the loop has another task to perform. Maintain a small queue of prepared frames, and let the SP’s sample counter or underrun status drive playback time. Reprefill the FIFO well before it empties, detect an underrun explicitly, and preserve channel phase when recovering. A stable stream matters more than a perfectly timed row change after a missed deadline.

Building and testing on real hardware

Build in small stages: a tone test, one sample, a single voice, then four channels and effects. Use a C compiler targeting Human68k, and put all board access behind a compact driver interface. Test with a short known MOD file before trying a demanding tracker tune. A debugger or emulator is useful for parsing and memory faults, but it cannot certify SP timing; verify the final path on the original machine and the installed custom board.

Keep a written record of the SP revision, clock, format and measured buffer settings. The project diary on X68K.NET provides a suitable home for that kind of practical record, and publishing a tested source archive helps another owner avoid repeating the same work. For local testing, bring the machine to a Sydney or Melbourne retro-computing meeting and compare notes with owners using similar hardware. Preserve original files separately from converted test material.

Watch memory use, CPU load and underruns rather than relying on a successful first note. Keep the module on storage, cache only active samples, and avoid allocating during playback. Licensing also deserves attention: a MOD file may circulate with the tracker author’s permission, so do not redistribute it merely because it was easy to download.

The main playback paths have different strengths:

Playback path Sample handling CPU and timing Best fit
Custom SP PCM stream Direct resampled samples in the board’s chosen format Moderate mixer cost with FIFO or ring-buffer pacing Authentic MOD playback through the installed SP
Buffered SP block writes Same PCM, prepared in larger blocks Fewer driver calls but greater memory use Stable output with limited bus overhead
Original RF5C01 PCM MOD samples must become 4-bit ADPCM Compact output with extra conversion and tonal loss Playing through the stock Ricoh path
Yamaha YM2151 FM Samples must be analysed and mapped to synthesis Complex mapping and no raw waveform playback Familiar X68000 music rather than sample-faithful MOD

Start with the SP tone test today. Preserve the working driver, sample-format notes and timing measurements, then expand the player one tracker feature at a time until a short MOD tune plays cleanly through the custom sound hardware.

Share the results with fellow X68000 owners, add compatible test material where you have permission to do so, and keep the project’s development record current. That chain of evidence—hardware revision, source code and repeatable tests—helps preserve both the software and the custom SP knowledge for the next enthusiast.

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.