Learn Multi platform 6502 Assembly Programming... For Monsters!

ChibiSound PRO / ChibiTracks / ChibiTracker PRO!

ChibiSound PRO, ChibiTracks, ChibiTracker PRO - The Unholy Trinity!

With the huge number of platforms and CPU's I cover, I had a bit of a problem! In the past I had done simple sounds with my multiplatform 'Chibisound' driver, and music with the AY based 'Arkostracker'... but while I had managed to write AY wrappers to allow it to play on some extra Z80 systems, it was too complex for me to realistically port to more platforms.

The solution I came up with was to develop my own music software from scratch!

ChibiSound PRO is the platform specific sound driver, it handles making consistent pitched tones and noise effects on the hardware.
ChibiTracks is the player, it works currently on Z80, GBZ80, 6502 and 68000, however it is simple enough to be ported to other systems, and such ports are likely!
ChibiTracker PRO is the windows based tracker, it's designed for composing songs to play on the retro systems

ChibiTracks is designed for simple music and provides a multiplatform solution to play a single compiled music binary file on multiple platforms.

ChibiTracks is NOT designed to provide advanced features comparable to solutions like ArkosTracker

To understand how ChibiTracks works, lets look at all the components:

ChibiSound PRO

ChibiSound is the sound driver that handles the particularities of a system, there is typically one driver per system, though the CPC and MSX drivers are essentially identical except for the AY register setting routines.

The original 'ChibiSound' gave us one channel, one Volume bit, six pitch bits, and the ability to turn noise on. Pitches were not matched across systems, so sound 32 won't sound the same on all systems.

The updated 'ChibiSound Pro' gives us all the channels provided by the hardware, 8 volume bits, 16 pitch bits, and the ability to turn noise on. Pitches were not matched across systems, however the 'ChibiOctave' lookup table provides values which ARE matched across all systems.

ChibiSound PRO is essentially a reduced subset of AY functionality, and was designed on the Z80 - it's 'PRO' suffix is a parody of the 'SoundBlaster PRO' - which could only do 8 bit sound so wasn't up to professional standards! (neither is ChibiSound PRO)

ChibiSound PRO provides a standard interface to the underlying hardware, it allows the following features to be set for each channel on the underlying hardware:

Channel Number (bit 0-6)
Noise On/Off (bit 7)
H Multiple channels can be supported, but on single channel systems only Channel 0 will be sure to play.
If possible Channel 0 will be a center channel, Channels 1+ may be left/right

Noise bit turns the noise effect on (1) or off (0) - this can be set on any channel, if the underlying hardware only supports one noise channel, this will be resolved by the driver.
Volume L Set volume of the channel (0-255). Higher numbers are louder. O is off
Pitch DE Set the pitch of the channel (0-65535). Higher numbers are higher pitch.
Using DE does not standardize the resulting pitch - however a 'Lookup table' of notes 'ChibiOctave' provides a standardized way of getting the correct DE value to get a pitch correct note on the platform.

Chibisound PRO does not offer features like Envelope, LFE etc, as providing consistent functionality across different platforms would not be realistic.

Lesson CT1 - ChibiTracks ASM Overview

Lets take a look at a ChibiTracks ASM source file - as saved by ChibiTracker PRO!

These are used to load and save work in progress songs - and can also be compiled by VASM into playable songs with ChibiTracks!



ChibiTracks is the player for music files.

A Song contains multiple Channels (Currently tested for 3)

A Channel takes it's commands from a Sequence of Patterns

Patterns contains a set of lines. Each of the lines contain a sequence of one or more commands, and a delay to wait until the next line.

Channels also play instruments (usually started by the pattern). These are also a sequence of commands and delays, and are used to set ChibiSound settings for the playing sound. A channel will stop making a sound when an instrument ends (unless it loops)

It is important to note that functionally Patterns and Instrument command lines are identical - they are literally processed by the same code in ChibiTracks, however it would not make sense to

ChibiTracker PRO can output two kinds of file - a binary file (.CBT) which can be used with any player, or an ASM file - the default format used to save and reload files (.ASM) - This is a VASM/MAXAM compatible Z80 ASM file which contains all the binary data in DB/DW lines, and all extra data for the player in rem statements (Starting with a semicolon).

There should be no difference between an compiled ASM and a binary CBT file.

There are two optional functions which can be enabled (but make the player larger)

ChibiTracks_AllowRelocation - This allows a song to be played from a different address than it was built, For example if a CBT binary was a save address of &4000, it can be loaded and played from address &8000 provided this function is enabled.

This function is mandatory on 68000, as only 16 bit addresses are specified in the binary files.

ChibiTracks_AllowSpeedChange - This allows the speed of songs to be changed via the 'SongSpeed' function - allowing songs to be sped up or slowed down on playback at the cost of a slightly slower and bigger player - Alternatively you can save with the 'PreMultiply Song Speed' option - in which case it's not needed.

ChibiTracks - A song file!

Lets take a look at the ASM file to see how ChibiTracks works.

At the start of the ASM file is the 'ChibiTracker' block

These lines all appear as comments in the ASM file, but are functional lines to ChibiTracker PRO.
These define settings and data that are used by the editor, but are not needed by the ChibiTracks player - because they are in REM statements, they will not be contained in any built file.
Next is the binary header - this is used by ChibiTracks player.... All 16 bit addresses are in Little Endian (even on 68000)

This contains the channel count (Should always be 3 at this stage as the player does not support more)

Repeatpoint is the entry number in the sequence which the song should restart when it reaches the end.

Songspeed is the multiplier for the line delay, A delay of 2 with a song speed of 5 would wait 10x interrupts before moving to the next line. NOTE: it is possible to assemble the player without songspeed support (ChibiTracks_AllowSpeedChange not defined). You can still get the same result by saving with 'Premultiplied songspeed' option enabled in ChibiTracker

PatternList is a pointer to the pattern list table. This list appears at the end of the ASM file

InstrumentList is a pointer to the Instrument list table. This list appears at the end of the ASM file

There then follows one 16 bit address for each channel, which points to the sequence of patterns for that channel.
The Sequences define the pattern numbers that make up the song.  These are looked up in the PatternList table.

Patten 255 represents the end of the song, at which play will resume at the repeatpoint.
Here are two sample patterns.

Each line in the ASM file is a line of the pattern. Lets take a look at one!

  db 2,&0D,&3A,&0B,&01,&00        ;2

first is the length of the delay after this line before the next line is processed. 2 means 2*Songspeed ticks until the next line.

There then follows a sequence of commands to be processed by ChibiTracks.
&0D means set pitch to note &3A
&0B means play instrument &01

&00 is the 'End of commands' command, the player will wait until the delay finishes before processing the next line

  db 1,&10,&00        ;33

Line 33 of the first pattern just has the 'End of pattern' command &10 - This tells the player to move to the next pattern in sequence - The delay has no effect in this case
Instruments are in the exact same format, and use the exact same decoding routine of the player.

However!... a instrument should end with a delay of 0, at which point the instrument will stop sounding.

it is also possible to loop an instrument with a loop (Byte &0C, followed by a negative byte), the byte value will be added (subtracted) from the current position in the command sequence, effectively looping part of the sequence.

To stop such a loop, a silent instrument, or other instrument should be played on the channel to stop the looping one.
At the end of the song data is the PatternList and InstrumentList,

These are a table of little endian 16 bit addresses of the pattern and instrument command sequences.

ChibiTracks - Byte commands

There are two types of command in ChibiTracks.

One Byte commands have the command number in the high nibble, and the 4 bit parameter in the bottom nibble, For Example &F1:     &F_ = Shift volume    &_1= Volume up 1

Two Byte commands have a second byte parameter, their top nibble is always Zero, For Example &0E,&FF:    &0E = Set Volume    &FF= New Volume

Command Type
Byte Data
One Byte &Fx
Vol shift -8 to +7
Pitch shift down 0 to -15
Pitch shift up 0 to +15
&Cx Noise state x (1=on 0=off)
End of Pattern
Two Byte &0F,x Pitch to x
&0E,x Vol to x
&0D,x Note to x (Even=true pitch Odd = Flat/Sharp)
&0C,x Loop to Offset -0 to -255 bytes (eg &FF = back 1 byte)
&0B,x Play Instrument x
&01,x &02,x &03,x &04,x Reserved for you to add custom functionality to the player!
(Named in ChibiTracker IXH IXL IYH IYL)

Top Nibble commands: &B0 A0 90 80 70 60 50 40 30 20 spare!
Two Byte Commands: &0A 09 08 07 06 05 04 03 02 01 spare!

ChibiTracker PRO

ChibiTracker PRO is a DotNet 3.5 application.

It requires SlimDX (SlimDX Runtime .NET 2.0 (January 2012).msi or SlimDX SDK (January 2012).msi), which is used for the sound buffer.

ChibiTracker supports a variety of MIDI controllers where available.

This is the instrument list.

It's used to select an instrument to enter into the pattern when editing.

It's also used to select the edited instrument in the instrument editor.
This is the sequence list, it defines the patterns played in the song.

Each column is a different channel, each row is a pattern to play at that point.

You can change the selected pattern at a point by double clicking, and selecting a new pattern from the list.
This is the Play controls and Status.

The play controls allow for start, stop, looping and edit of the pattern.

The Status line shows the byte data produced by the player, and MIDI data received from the controller when connected.
This is the Pattern editor.  each column is a different channel.
When in 'Edit Mode' (purple background) the pattern can be edited.

Space - Toggle edit mode

letter / num keys - note keys.
Num0 - Num9 - Drum (when editing) / Select instrument 0-9

Backspace - clear line
Insert - Add line
Delete - Remove line

F1 - Restart Play
F2 - Resume Play
F3 - Pattern Loop
F4 - Stop
F8 - Octave down
F9 - Octave up
F9 - Set Volume
F10 - Set Pitch

This is the instrument editor... it's rather basic at the moment!

A line of the instrument can be selected in the top list.

The Command / events for that line can be altered in the bottom panel.

The data in the top list is in the format:

Delay   (byte count)   Commands........
This is the settings page. It allows various changes.

Song Settings define options of the edited song.

Editor settings change how the editor works, if you're getting 'clicking' or poor performance, you can try changing these.

Midi Controller Allows you to connect a Midi Controller such as a piano type keyboard.
This is the pattern list.

You can double click on a pattern to rename it - This is optional, and is just to allow you to organize your song more easilly
This is the Info Panel.

It shows some help info by default, and may show debug information in some special cases.
This is the Midi Editor.

This only appears if you connect a midi device.

This allows you to map buttons and dials to ChibiTracker events.

Of course A keyboard can also be used to set notes in the pattern!

Lesson CT2 - ChibiTracks Header Load and Init

Lets start to look at the 68000 ChibiTracks music player code!


State Memory, symbols, and the silent instrument

ChibiTracks uses a 32 byte block to keep track of each of the channels (32*3=96 bytes total)
These contain the values to be passed to the ChibiSound PRO driver,

There are address pointers for the playing Instrument Line and Pattern Line, as well as 'Timeouts' after which the next line must be processed.
There is also an address for the sequence position - this has no timeout, as the next sequence is loaded when the playing pattern ends.

ChibiTracks will zero and initialize the memory it is provided for its channel data. Instrument/Pattern/Sequence data are loaded from the playing song.

There are EQU definitions which are used as offsets to the corresponding data for a channel

NOTE: This block was half the size on 8 bit systems, but is a different format on the 68000 due to the larger address bus.
Some Extra EQU definitions point to the start of the channels, and the end of the data block
When a channel ends it must be switched to a 'silent instrument' - this is an instrument script which only sets the channel volume to zero

ChibiTracks is designed to work from ROM, so the variables for channels and other core purposes can be loaded in a small block of RAM.

NOTE: the Binary song file uses 16 bit LITTLE ENDIAN addresses.
Relocation is optional on 8 bit systems. but Relocation support is MANDATORY on systems with a >16 bit address bus, as the addresses in the binary song file are incomplete

Common functions

The tracker updates patterns after a certain 'time' has passed. This time may need to speed up and slow down depending on how fast the end system is.

enabling 'ChibiTracks_AllowSpeedChange' will calculate this speed change at play time.

Alternately, enable 'PreMultiply SongSpeed' during export - and this calculation will be done in advance and 'ChibiTracks_AllowSpeedChange' is not needed - saving memory and CPU power, but losing the ability to change song speed later.

We run StartSong to init the music.

RAM variable SongBase should point to the music data.

Before we start playing anything, we need to clear the contents of the ChibiTracks RAM

We can zero pretty much everything - but we need to program each channel with its number.
The first time we play as song, we start from sequence entry 0 (we may loop back to an alternate position)

We first load in the song channel count and the repeat point

If we use speed changes, we load that too.

Addresses in the song are in LITTLE ENDIAN (L byte, then H byte)

We load them in separately and shift them into our register.

We calculate the 'SongOffset) (the difference between the address the song is in memory, and the address it was saved for). The song offset is used to calculate the actual address of things like the InstrumentList and PatternList.

If we are allowing relocation we calculate the difference between the address we're playing from, and the address the song was exported to play from - the result is out offset.
The next three addresses are the song sequences.

we use these to Initialize each of the channel patterns
We use any offset in D0 (for looping back) as an offset, and load in the first pattern in the channels sequence.

We start the channel playing the silent instrument to silence it.

We use GetNextSequence to read in a pattern number and get the channel to play it.

Pattern=255 is the end of the song - in which case we force a restart.

Otherwise we calculate the address of the pattern, and load it in to the channel pattern address.
To restart the song we clear down the stack, load in the repeat pos (sequence offset) and reload the song.

Lesson CT3 - The main play routine

Lets look at the main player code of ChibiTracks


The Update routine
We run ChibiTracks_Play during our interrupt routine.
This uses D0-D6 and A2-A4

We update all the channels separately. First we decrease the delay time for the current pattern line... if it reached zero we need to process a new line of the pattern.

Next we update the channel itself (for any current playing instrument. If the delay time for the current instrument IS zero - there is no instrument playing any more... if it REACHED zero, the we need to process a new line of the instrument.
We repeat for all the other channels, and run the ChibiSoundPro_Update routine. this is only used on systems like the ZX Spectrum Beeper, which needs positive action by the cpu to generate the sound
To update the pattern we read in the address of the next line, we load in the Delay (the time the next line should play) and multiply it by the playing speed.

We process the commands for this pattern line, and store the new pattern address.
To update the channel we read in the address of the next line, we load in the Delay (the time the next line should play) - if it's zero the instrument has stopped and we need to silence the channel

We process the commands for this instrument line, and store the new instrument address.
We need to update the sound the channel is playing.

We use TweenTone to calculate the DE pair for the note frequency from the ChibiOctave lookup table

We load H and L from the channels settings and use ChibiSoundPro_Set to update the sound the channel is playing

The Script processor
There are two types of commands.

One byte commands use the top nibble as the command number, and the bottom nibble as the parameter (D1)

Two byte commands use the first byte as the command number (The top nibble is always zero) , and the following byte as the parameter

A Zero byte &00 is a special case - and represents the end of the script.
We can use a one nibble pitch bend for small adjustments (slight wavy notes).

There is a 1 byte version as well for larger shifts.
A -8 to +7 volume shift can also be used.
The noise command is a bit of an odd case!

The only valid options are &C0 or &C1, as only the bottom bit of the parameter is used.

It either turns noise on (&C1) or off (&C0)
Pattern End is defined by command &10 - This tells the player to load the next pattern in the sequence
The two byte command routine loads the second byte into the D4 register
We have commands to set the playing note (in the octave) volume and pitch bend

These are just loaded into the channel data for processing by the channel code.
The loop command uses the parameter as a negative byte offset within the script - to work correctly it should point to a command byte within the script

It's used for repeating instruments - for example a wavy sound with a looping pitch bend.
If an instrument is to be triggered, the instrument's address is loaded from the Instrument List.

The Delay is set to 1, so it will reach 0 next tick and force the first line of the instrument to play.

Lesson CT4 - Tone Calculation

The Note number and pitch shift need to be used to calculate a 16 bit 'D2' tone value for ChibiSound Pro... Lets learn how!


Tone Lookup
ChibiSound PRO is the platform specific driver for the sound on each system.
There is a matching ChibiOctave table which allows the lookup of the correct frequency for notes.

It only contains the pure tones, not sharps or flats, however these can be calculated by adding two notes and dividing by two to calculate the in-between value.
GetChibiTone will lookup the note D2 from the lookup table.

The format is %NNNNNNNS - where N is a Note, and S 'sharpens' the note.

TweenTone takes a note in D2,  and a shift in D0

The top nibble in D0 is a direct shift to the note number in D2,

The bottom nibble in D0 is a 0-15 'fractional shift' to the note number in D2, allowing a smooth transition between note D2 and D2+1

0-15 fractional Tweener
Tween16HLDE calculates a fractional position between D3 and D2. it returns a result in D3

D0 should be a value of 0-15, any value over 16 is treated as 16

If D0=0 then the result is D3=100% of the value in D3
If D0=16 then the result is D3=100% of the value in D2
If D0=8 then the result is D3 is halfway between D3 and D2
and so on
Fraction16 performs the calculation D3=D3 * (D0 / 16)

We move our value into D2, and repeatedly divide it by two, testing the matching bit in D0 to see if we need to add it to HL to create the correct resulting fraction.

This gives a quick calculated 1/16 - 15/16 fraction of D3


View Options
Default Dark
Simple (Hide this menu)
Print Mode (white background)

Top Menu
***Main Menu***
Youtube channel
Introduction to Assembly (Basics for absolute beginners)
Email Newsletter
Amazon Affiliate Link
AkuSprite Editor
Dec/Bin/Hex/Oct/Ascii Table

Alt Tech
Please note: I wlll upload more content to these alt platforms based on the views they bring in

Z80 Content
***Z80 Tutorial List***
Learn Z80 Assembly (2021)
Learn Z80 Assembly (old)
Hello World
Advanced Series
Multiplatform Series
Platform Specific Series
ChibiAkumas Series
Grime Z80
Z80 Downloads
Z80 Cheatsheet
DevTools kit
Z80 Platforms
Amstrad CPC
Elan Enterprise
Gameboy & Gameboy Color
Master System & GameGear
Sam Coupe
ZX Spectrum
Spectrum NEXT
Camputers Lynx

6502 Content
***6502 Tutorial List***
Learn 6502 Assembly
Advanced Series
Platform Specific Series
Hello World Series
Grime 6502
6502 Cheatsheet
DevTools kit
6502 Platforms
Apple IIe
Atari 800 and 5200
Atari Lynx
BBC Micro
Commodore 64
Commodore PET
Commander x16
Super Nintendo (SNES)
Nintendo NES / Famicom
PC Engine (Turbografx-16)
Vic 20

68000 Content
***68000 Tutorial List***
Learn 68000 Assembly
Hello World Series
Platform Specific Series
Grime 68000
68000 Cheatsheet
DevTools kit
68000 Platforms
Amiga 500
Atari ST
Neo Geo
Sega Genesis / Mega Drive
Sinclair QL
X68000 (Sharp x68k)

8086 Content
Learn 8086 Assembly
Platform Specific Series
Hello World Series
8086 Cheatsheet
DevTools kit
8086 Platforms

ARM Content
Learn ARM Assembly
Learn ARM Thumb Assembly
Platform Specific Series
ARM Downloads
ARM Cheatsheet
DevTools kit
ARM Platforms
Gameboy Advance
Nintendo DS
Risc Os

Risc-V Content
Learn Risc-V Assembly
Risc-V Downloads
Risc-V Cheatsheet
DevTools kit

MIPS Content
Learn Risc-V Assembly
MIPS Downloads
MIPS Cheatsheet
DevTools kit
N64 Platforms

PDP-11 Content
Learn PDP-11 Assembly
PDP-11 Downloads
PDP-11 Cheatsheet
DevTools kit

TMS9900 Content
Learn TMS9900 Assembly
TMS9900 Downloads
TMS9900 Cheatsheet
DevTools kit
TMS9900 Platforms
Ti 99

6809 Content
Learn 6809 Assembly
Learn 6309 Assembly
6809/6309 Cheatsheet
DevTools kit
6809 Platforms
Dragon 32/Tandy Coco
Fujitsu FM7
TRS-80 Coco 3

65816 Content
Learn 65816 Assembly
65816 Cheatsheet
DevTools kit
65816 Platforms

eZ80 Content
Learn eZ80 Assembly
eZ80 Downloads
eZ80 Cheatsheet
DevTools kit
eZ80 Platforms
Ti84 PCE

IBM370 Content
Learn IBM370 Assembly
IBM370 Downloads
IBM370 Cheatsheet
DevTools kit

Super-H Content
Learn SH2 Assembly
SH2 Downloads
SH2 Cheatsheet
DevTools kit
SH2 Platforms

PowerPC Content
Learn PowerPC Assembly
PowerPC Downloads
PowerPC Cheatsheet
DevTools kit
PowerPC Platforms

Work in Progress

Misc bits
Ruby programming

Buy my Assembly programming book
on Amazon in Print or Kindle!

Buy my Assembly programming book

Available worldwide!
Search 'ChibiAkumas' on
your local Amazon website!
Click here for more info!

Buy my Assembly programming book
on Amazon in Print or Kindle!

Buy my Assembly programming book

Available worldwide!
Search 'ChibiAkumas' on
your local Amazon website!
Click here for more info!

Buy my Assembly programming book
on Amazon in Print or Kindle!

Buy my Assembly programming book

Available worldwide!
Search 'ChibiAkumas' on
your local Amazon website!
Click here for more info!

Buy my Assembly programming book
on Amazon in Print or Kindle!

Buy my Assembly programming book

Available worldwide!
Search 'ChibiAkumas' on
your local Amazon website!
Click here for more info!

Buy my Assembly programming book
on Amazon in Print or Kindle!

Buy my Assembly programming book

Available worldwide!
Search 'ChibiAkumas' on
your local Amazon website!
Click here for more info!

Buy my Assembly programming book
on Amazon in Print or Kindle!

Buy my Assembly programming book

Available worldwide!
Search 'ChibiAkumas' on
your local Amazon website!
Click here for more info!

Buy my Assembly programming book
on Amazon in Print or Kindle!

Buy my Assembly programming book

Available worldwide!
Search 'ChibiAkumas' on
your local Amazon website!
Click here for more info!

Buy my Assembly programming book
on Amazon in Print or Kindle!

Buy my Assembly programming book

Available worldwide!
Search 'ChibiAkumas' on
your local Amazon website!
Click here for more info!

Buy my Assembly programming book
on Amazon in Print or Kindle!

Buy my Assembly programming book

Available worldwide!
Search 'ChibiAkumas' on
your local Amazon website!
Click here for more info!

Buy my Assembly programming book
on Amazon in Print or Kindle!

Buy my Assembly programming book

Available worldwide!
Search 'ChibiAkumas' on
your local Amazon website!
Click here for more info!