Build Akai MPC60 hard-disk images from folders of WAVs — and take apart the ones you already have.
Tested on hardwareA small Python toolchain for the Akai MPC60 / MPC60-II running from a ZuluSCSI or similar SCSI emulator. Point it at folders of samples and it produces a bootable multi-partition drive image with drum programs already built.
A 26-partition, 753 MB image built by these tools loads on an MPC60 and plays.
The formats were reverse engineered from a working CompactFlash card and a real
PROGRAM_.pgm, then verified against the machine.
Requires Python 3 and numpy. Nothing else.
Folders of WAVs to a finished drive image. Converts to 40 kHz / 12-bit, builds and splits programs automatically, lays out FAT12 partitions, and budgets everything against the machine's sound memory rather than disk space.
Inspect and edit a drive. List what is on every partition, pull one out as a mountable image, drag files around in Finder, and write it back. Refuses a wrong-sized image rather than corrupting the partition next door.
Take programs and samples apart field by field, with every undecoded field
labelled UNKNOWN. Includes a diff that compares two
programs — the fastest way to work out what is still not understood.
Samples on their own. WAV to SND and back, header inspection, and a
verify that proves the codec round-trips a file byte-for-byte.
One folder per partition. Subfolders inside a kit are just grouping — every WAV underneath gets used.
STAGING/
Roland R-70/ -> becomes drive A
AcidLab Miami/ -> drive B
LSDJ/ -> drive C
python3 tools/mpc60build.py STAGING -o HD0_512.hda \
--boot reference/boot.bin \
--pgm-donor reference/donor.PGM \
--snd-header reference/header.SND \
--memory-kb 1400
python3 tools/mpc60drive.py list HD0_512.hda
Then copy HD0_512.hda to the root of the SD card. The filename
matters — ZuluSCSI parses the SCSI ID and block size out of it.
HD0_512.hda through HD6_512.hda; never HD7,
that is the MPC's own controller.
Budget against memory, not disk. This is the thing that wastes people's time on this machine — a 29 MB partition holds far more than the MPC can load at once.
| Limit | Value | Why |
|---|---|---|
| Sound memory | 750 KB / 1500 KB | 12.8 or 25.6 seconds of audio. Stock or expanded. |
| Partition load | whole partition | The MPC appears to load every sound on a partition, not just a program's. |
| Partition size | ~29 MB | FAT12 caps at 4084 clusters, at 8 KB each. |
| Root directory | 224 entries | Every .SND and .PGM costs one. |
| Partitions | 26 (A–Z) | Partitions, not SCSI IDs — SCSI only has 8. |
| Sounds per program | 16 | Slots the program format exposes. |
| Filenames | DOS 8.3 | The disk is FAT12. |
.SND is a 39-byte header followed by 12-bit linear audio at
40 kHz mono, packed two samples per three bytes. There is no
sample-rate field — the machine is fixed at 40 kHz.
A = (b0 << 4) | (b1 & 0x0F)
B = (b1 >> 4) | (b2 << 4)
.PGM is 4608 bytes. Three things are easy to get wrong:
0xFF,
or a pad references a nameless, zero-length sample.Full field tables, including everything still undecoded, are in the README.
u24 and two u8 fields in the SND header.u16 at PGM offset 0, and the block at 0x0A82.To work on any of these: save a program from your MPC and diff it
against a generated one. A small program of four to six sounds tells you
most, because a full 16-slot donor never shows what the machine does with fewer.
Python 3 and numpy. Each script is standalone — save it and run it.
| File | What it does |
|---|---|
| mpc60build.py | folders of WAVs → a bootable drive image |
| mpc60conv.py | WAV ↔ SND, 12-bit packed |
| mpc60drive.py | list, extract, replace and format partitions |
| mpc60decompile.py | take an existing image apart and label the fields |
| boot.bin | boot sector from a working card |
| donor.PGM | real program file, used as the template |
| header.SND | SND header layout |
| README.md | full field tables and the traps |