Casio FZ-1 disk images
2025-07-23
I have started another project in the intersection of: samplers, obscure disk images and Casio. The work is not 100% done yet but I want to report some initial observations about Casio FZ-1 disk images. You can find the utilities I'm writing on GitHub.
The Casio FZ-1
Image source: mu:zines.
The FZ-1 was a sampler/synthesizer keyboard launched by Casio in 1987. It was a breakthrough at the time because it was the first product at its price level to offer 16-bit sampling. At that time 12-bit audio was still the norm for samplers.
Besides recording and playing back samples the FZ-1 can also generate rudimentary waveforms itself that you can then play as samples. This is why Casio called it a "digital sampling synthesizer".
The challenge
Like other instruments of its time, it stores audio data on floppy disks. I enjoy working with audio I recorded directly into the sampler but sometimes it is also useful to load audio files from the computer into the sampler digitally, rather than having to record them as analog audio.
The FZ-1 uses a custom disk format which thankfully is documented. But I did not find any non-Windows tools that can write to these floppies. Time to write my own!
My ultimate goals are to be able to:
- Load AdventureKid Waveforms into the FZ-1 so I can use it as a synthesizer with 4000 waveforms.
- Load drum samples into the FZ-1 so I can use it as a drum machine.
As a side goal it would be interesting to be able to load FZF files from the Internet into the machine but I find that less interesting for my own music making.
Formatting a disk image
I should point out I'm not actually working with floppy disks. I have replaced the disk drive in my FZ-1 with a floppy drive emulator that presents disk images from a USB stick to the host machine as if they are real floppies. So my task is to create these disk image files.
The Casio FZ disk format uses 1280 sectors of 1024 bytes each. This means that the disk images must be exactly 1280*1024=1310720
bytes big. There is a nice picture in the documentation:
The "head" sector contains the name (label) of the disk and a bitmap ("Cluster Allocation Table") which indicates which of the 1280 sectors are in use. The "dir" sector contains up to 64 directory entries. There are no subdirectories in this format; 64 is the maximum number of files on a disk.
Strictly speaking, in order to format a disk I think it is enough to write the "head" and "dir" sectors. But I noticed that in practice the FZ-1 writes "ZZZZZZ..." to all the data sectors so my formatting program does the same.
Directory entries
All numbers in the filesystem are little-Endian. This is because the FZ-1 uses a NEC V50 CPU which is 8086-compatible and thus little-Endian A directory entry is a 12-byte ASCII name, followed by a 16-bit integer file type (a number from 0-5) and a 16 bit integer denoting the file head sector of the directory entry.
File heads
Each file has a head sector which contains 64 "data block pointers". A data block pointer is a pair of 16-bit integers which denotes a range of disk sectors. The actual file contents are the concatenation of the ranges denoted by the data block pointers. Often there is only 1 range in the file but on a disk with fragmented empty space one may need multiple ranges.
Besides the data block pointers, each file head also contains 3 16-bit integers at the very end which determine the file structure. This turns out to be a pain in the neck because Casio FZ files on the internet omit the file head sector and hence these 3 layout numbers. The format documentation is also wrong about the meaning of the individual numbers but this is easier to fix than files not having these numbers.
This diagram from the FZ-1 Data Structures document, and all diagrams like it, states the order of the layout numbers is "vn bn wn". The actual order (as written by the machine) is "bn vn wn" which is also more logical because that is the order in which the data is laid out in the files themselves.
File types
There are 3 file types I am interested in.
- Voice (type 1). PCM audio data together with playback parameters such as amplitude envelope, key range, loop points etc. Computer file extension
.FZV
. - Bank (type 2). A collection of up to 64 voices spread across the MIDI keyboard and across MIDI channels. A bank file embeds up to 64 voices. Extension
.FZB
. - Full Dump Data (type 0). A file containing up to 8 banks, followed by up to 64 voices, followed by PCM audio data. Extension
.FZF
.
The layout numbers I mentioned earlier specify the number of banks (bn
), followed by the number of voices (vn
), followed by the number of sectors of audio data (wn
for "wave"). For a voice file bn=0
, vn=1
and wn
varies. For a bank file bn=1
and the other two vary. For a full dump data file all three numbers vary.
I need to work with Full Dump Data files
My first thought was to work with voice files and not worry about the rest but this is not user friendly. On the machine you can only load voice files one at a time. You select a file, press "load", press "yes", and wait for the floppy to load data. Repeat.
It's better to use the full dump data (FZF) files because then you load once and then you're done messing about with floppy disks.
In order to test my code for handling FZF files it makes sense to put "real" FZF files onto disk images with my utilities and check that the FZ-1 will load them. This meant that I had to solve the problem of the missing layout numbers because the FZF files I was able to find on the internet are all missing their layouts. I tried loading them anyway but the FZ-1 then loads nothing and says "LOAD OK".
Reconstructing the layout numbers
The goal is to figure out the layout numbers bn
, vn
and wn
. It is safe to assume that wn
is the file size minus bn
and vn
so the problem reduces to finding those two.
The format of these files is described in the Data Structures document. Each of them has a "name" field of 12 ASCII bytes followed by 2 zero bytes. Well that is what the documentation says, in reality the voice names are 12 ASCII bytes followed by garbage. Still, 12 ASCII bytes is something we can look for. It's not fool-proof (you could have a sequence of 12 ASCII bytes inside PCM audio data) but it will have to do.
And it works! My project is now at the point that I can put a pre-existing FZF file onto a virtual floppy image and load it on the FZ-1. The following commands create a disk image file helloworld.img
with label Hello World
and copy the FZF file Piano.fzf
of type 0 (full data dump) onto the image.
./fzformat 'Hello World' helloworld.img
./fzputfile helloworld.img 0 Piano.fzf
What's next
I have already figured out how to get an AKWF single cycle waveform into the FZ-1 as a "wave synth" voice (FZV file) using SoX. The problem is that loading voices one at a time is no fun. I need to write another utility that can pack multiple FZV files into one big FZF file. This is more work than just concatenating the FZV files because that would interleave voice parameters with PCM data and that is not how FZF files work.
I also need to make something that can take an arbitrary WAV file and convert it into a simple FZV voice file that will play back the audio data from start to finish. That would be enough to let me load drum samples.
I'll report back when I get that working. Thanks for reading!