Skip to content

An abstraction layer over the C64 SID, providing basic operaitons to define instruments. These can then be used to compose tunes in a classic sequencer style.

License

Notifications You must be signed in to change notification settings

nicolacimmino/C64-Music-Routine

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

C64 Music Routine

A long running hobby project of mine, much longer than the git history shows. I started with this back in 1987, and a big part of it has actually been written on paper (!) as my parents allowed me only one hour of screen time a day. At some point I moved from paper and C64 to cross compilation on my PC and, from time to time, still work on this.

The idea is to abstract the SID (though I didn't call it that fancy at that time), and develop basic operaitons to define instruments to then be used to compose tunes.

V-Sid

V-SID offers the music composer an abstract view of the SID hardware and a set of micro instructions that allow the creation of rich, evolving sounds. At the very core is a set of registers that closely map to those offered by the SID but are voice independent. This allows to write generic instrument code that can be run on any voice. On top of the virutualised registers is a set of registers manipulation and flow control instructions. We will refer to them as the Instrument MicroCode as IMC throughout this text and, where needed, in the source code.

Instruments are defined by a sequence of IMC instructions that allow to create sounds that are more complex than it would be possible by just defyning a waveform and an ADSR envelope. Microcoded instruments can evolve all the sound parameters over time, giving access to a more rich sound palette. We will refer to the Instrument MicroCode as IMC throughout this text and, where needed, in the source code.

Addittionally tracks can be composed sequencing phrases that can be combined and repeated. Each phrase is a sequence of notes played on a given instrument.

vsid block diagram

The block diagram above shows the V-SID architecture. While not strictly necessary, a rough understanding of the architecture can help make the most out of the V-SID. Details about the internals are at the bottom of this read-me.

TICK

The TICK is the time base of the V-SID, one tick elapses every time the music player routine is called. Usually this would happen once per frame so, on a PAL machines, every 20mS. This will affect the timings of IMC execution so you will need to estabilish how many times per frame the music routine will be called as a first step.

The virtualised SID Registers

IMC operates on a virtualised SID that exposes the SID 29 registers in just 16 registers: 7 voice registers and 8 global registers (there's an unused register between the two blocks to align things nicely). The 7 voice registers, as opposed to the 7 registers per voice of the SID, allow to write instruments in IMC that can be played on any voice. The global 8 registers are the voice independent registers as found in the SID. Below is the registers map as seen by IMC intructions.

REG Direction Purpose
0 W Voice Frequency Low
1 W Voice Frequency Hi
2 W Voice Pulse Width Low
3 W Voice Pulse Width Hi
4 W Voice Control Register
5 W Voice Attack/Decay
6 W Voice Sustain/Release
7 W Not in use
8 W Filter Cutoff Low
9 W Filter Cutoff Hi
10 W Filter Resonance and Voice Selectors
11 W Mode and Volume
12 R Potentiometer X
13 R Potentiometer Y
14 R Oscillator 3 Sample
15 R Envelope 3 Sample

IMC Instructions

The following instructions are available in IMC. Most intructions, once executed, cause the execution of the following instruction to take place immediately, except for those intructions that return a status register with the Yield (Y) flags set. Instructions returning with the Y bit set will cause the player to give up execution for that voice until the next frame triggers a call to the routine.

Each instruction is encoded in the high nibble of the command value. The lower nibble of the same byte is the first, 4 bits, parameter of the instructions, this is referred as P0. Some commands require an other byte to encode an other parameter, this is referred to as P1.

0          8         16
| CMD Byte | Operator |
| CMD | P0 |    P1    |

WIN - Wait Init

Initialises the wait counter to the desired amount of ticks a following wait instruction will have to wait. The amount of ticks to wait is encoded in P0. This allows waits ranging from 20mS to to 320mS in steps of 20mS. Note that while MUWAIT is an 8 bit register, and can be set for a delay up to 256 ticks (roughly 4 seconds), the WIN instruction allows to set it only up to 32 because of the limited size of P0. This is considered enough for intra-instruction durations as the purpose of WIN/LWW is not to sustain the note but to allow delays between waveform evolutions.

LENGTH:1        STATUS Y---
                       0---
AFFECTS:       
P0         => MUWAIT
INSTRP + 1 => INSTRP

LWW - Loop While Waiting

Waits the amount of ticks in MUWAIT. This is not an idle wait, the command will set the Y flag so it will cause the virtualised SID to yield and the other voices will be executed as well. Additionally INSTRP will be decremented by P0 unless MUWAIT has reached zero in which case the command will let the flow progress to the next instruction.

LENGTH:1        STATUS Y---
                       1---
AFFECTS:       
MUWAIT - 1  => MUWAIT
INSTRP - P0 => INSTRP IF MUWAIT>0
INSTRP + 1  => INSTRP IF MUWAIT=0

WRI - Write Register

Writes a value into the specified register. This command takes the virtualised SID register in P0 and the value to write in P1. See "Virtualised SID registers" section above for the actual registers map.

LENGTH:2        STATUS Y---
                       0---
AFFECTS:       
P1         => REG[P0] 
INSTRP + 2 => INSTRP
<