XPMCK - Cross Platform Music Compiler Kit
Mic, 2009
Website: http://jiggawatt.org/muzak/xpmck/
Contact: micol972@gmail.com
What you will need
Some basic knowledge of MML. For syntax information in english, see these guides:
http://www.nullsleep.com/treasure/mck_guide/
http://www.geocities.co.jp/Playtown-Denei/9628/mck/mckc-e.txt (mirror)
You may also want some information about the audio capabilities of some of the systems
supported by XPMCK:
Gameboy
YM2151 (CPS-1)
SN79489 (SMS/GG/CLV)
YM2413 (SMS)
YM2612 (Genesis)
AY-3-8910 (KSS)
Konami SCC (KSS)
To build the SEGA Master System / Game Gear / ColecoVision version of the player you need WLA-DX:
http://www.villehelin.com/wla.html (or here, or here)
To build the SEGA Genesis version of the player you need the GNU binutils for M68000.
You can find prebuilt binaries for Windows here.
The Genesis Z80 driver source builds with WLA-DX, although it isn't necessary to rebuild
it unless you want to make changes to it.
To build the Gameboy / Gameboy Color version of the player you need WLA-DX:
http://www.villehelin.com/wla.html (or here, or here)
To build the Commodore 64 version of the player you need WLA-DX:
http://www.villehelin.com/wla.html (or here, or here)
To build the KSS version of the player you need WLA-DX:
http://www.villehelin.com/wla.html (or here, or here)
P(P)MCK commands supported in XPMCK
&, ^, <, >, [], {}, D, l, o, q, t, v, v-, v+, @, @@, @EN, @EP, @MP, @q, @v
New commands added in XPMCK
@ADSR, @CS, @es, @FBM, @FT, @MOD, @WT, @XPCM, @pw, @te, @ve, $, !, \, (, AM, FB, k, M, MF, n, OP, pw, RING, RS, s, SSG, SYNC, w
New commands by target
ColecoVision
$, !, k
Commodore 64
@ADSR, @FT, @pw, $, !, k, pw, RING, SYNC
CPS-1
@ADSR, @FBM, @MOD, $, !, AM, FB, k, M, MF, OP, RS
Gameboy / Gameboy Color
@CS, @WT, @te, @ve, $, !, k
KSS
@CS, @es, @WT, @te, $, !, k, n
SEGA Genesis / Megadrive
@ADSR, @FBM, @MOD, @XPCM, $, !, AM, FB, k, M, MF, OP, RS, SSG
SEGA Game Gear
@CS, $, !, k
SEGA Master System
@ADSR, $, !, AM, FB, k, M, MF, RS
Specifications and limitations by target
ColecoVision
Commodore 64
CPS-1
Gameboy / Gameboy Color
KSS
SEGA Genesis / Megadrive
SEGA Game Gear
SEGA Master System
Commandline options
-h Show help
-v Verbose mode
-w Treat warnings as errors
-c64 Output data suitable for the Commodore 64
-clv Output data suitable for the ColecoVision
-cps Output data suitable for the CPS-1 (YM2151)
-gbc Output data suitable for the Gameboy / Gameboy Color
-gen Output data suitable for the SEGA Genesis
-kss Output data suitable for KSS files
-sgg Output data suitable for the SEGA Game Gear
-sms Output data suitable for the SEGA Master System
If no output filename is specified it will be given the name .asm by
default (or .s when the target is -gen).
If the output filename has a .vgm extension and the target is cps, gen, sms or sgg the
compiler will generate a .vgm file (uncompressed) instead of an .asm file.
If the output filename has a .vgz extension and the target is cps, gen, sms or sgg the
compiler will generate a .vgz file (compressed) instead of an .asm file.
Examples:
xpmc.exe -cps foo ; Compile the file foo.mml into foo.vgm (only vgm output is supported for CPS-1).
xpmc.exe -sgg foo.mml bar.vgz ; Compile the file foo.mml into bar.vgz.
xpmc.exe -gbc -v foo.mml ; Compile the file foo.mml into foo.asm, verbose mode.
Compiler directives
These are the XPMCK-specific preprocessor commands available:
#ELSE Used together with IFDEF/IFNDEF.
#ELSIFDEF Used together with IFDEF/IFNDEF.
#ENDIF Used together with IFDEF/IFNDEF.
#EN-REV num If num==0 EN macros work similar to other
MML implementations.
If num==1 EN is not cumulative, meaning that
instead of {| 3 4 -7} you write {| 3 7 0}.
#ERROR "message" Output an error message and abort compilation.
#GB-NOISE num Use an alternative frequency table for the GBC noise
channel if num==1. The alternative table tries to assign
unique frequencies for each note, but is limited to 5 octaves,
compared to 11 for the standard table.
#IFDEF, #IFNDEF Conditional compilation depending on if a
symbol is defined or not.
Currently the only symbol defined is the selected
target, so this check would be valid:
#IFDEF SMS
; blah
#ELSIFDEF SGG
; blah
#ENDIF
The boolean operators & (AND) and | (OR) can be
used:
#IFDEF SMS | SGG
; blah
#ENDIF
Note that the boolean operators take opposite
meanings when IFNDEF is used, i.e.:
#IFNDEF SMS | SGG ; Means "If not defined SMS or not defined SGG"
#INCLUDE "filename" Include the contents of another MML file.
#NTSC Inform the compiler that you are going to play the
song with an update frequency of ~60 Hz. Along with
the tempo and the note lengths this is used to
calculate how long each note should be played.
#PAL Specify a 50 Hz update frequency. Mutually exclusive
to #NTSC. Some targets only support 60 Hz playback -
for these targets this command is ignored.
#SONG num Start a new song. This directive is used to put multiple songs
in the same mml file. num has a valid range of 2-100.
All songs share the same effect macros.
#TUNE Use an alternative frequency table on the SEGA Master
System to lower the error percentage on higher octaves.
#WARNING "message" Output a warning. Aborts compilation if the -w switch has been used.
#UNIFORM-VOLUME num Specify a custom maximum volume for all channels.
The volumes will be scaled to the valid range of
the target machine.
Syntax
Comment
Single line comments start with a ; (semi-colon).
Multiline comments start with /* and end with */
Instrument / algorithm selection (All)
@num
Apart from selecting the duty cycle for channels that support it,
@ also has another purpose in XPMCK. For FM channels it is used to
select the instrument or algorithm for the channel.
On the SEGA Master System (YM2413) the valid range depends on the
channel's current output mode:
M0 (melody):
@0 = Custom
@1 = Violin
@2 = Guitar
@3 = Piano
@4 = Flute
@5 = Clarinet
@6 = Oboe
@7 = Trumpet
@8 = Organ
@9 = Horn
@10 = Synthesizer
@11 = Harpsichord
@12 = Vibraphone
@13 = Synthesizer bass
@14 = Acoustic bass
@15 = Electric guitar
M1 (rhythm):
@0 = Bass drum
@1 = Snare drum
@2 = Hi-hat
@3 = Top cymbal
@4 = Tom-tom
When in rhythm mode, each instrument has a global volume that is shared by
all channels. This means that a channel modifying the volume for one of the
rhythm instruments will affect all other channels that are using the same
instrument.
On the SEGA Genesis (YM2612) the valid range is 0-7 and selects a range
of instrument sounds according to the following table:
@0 = Distortion guitar, high hat chopper bass
@1 = Harp, PSG-like sound
@2 = Bass, electric guitar, brass, piano, woods
@3 = Strings, folk guitar, chimes
@4 = Flute, bells, chorus, bass drum, snare drum, tom-tom
@5 = Brass, organ
@6 = Xylophone, tom-tom, organ, vibraphone, snare drum, bass drum
@7 = Pipe organ
On the CPS-1 (YM2151) the valid range is 0-7 and selects a range
of instrument sounds similar to the SEGA Genesis.
The type of sound generated on the SEGA Genesis and CPS-1 also depends on
the current feedback setting (see the FB command).
On the Commodore 64 this command selects the waveform to use:
@0 = Triangle
@1 = Saw
@2 = Square
@3 = Noise
For KSS AY channels (E,F,G) the valid range is 0-7 and toggles tone, noise and envelope
on/off depending on which bits are set in the value:
Bit 0: note
Bit 1: noise
Bit 2: envelope
For example, @1 would enable tone, while @6 enables noise and envelope.
One the Gameboy, SEGA Master System and SEGA Game Gear this command switches between
white noise and periodic noise generation for channel D (0 = white, 1 = periodic).
ADSR envelope (C64, CPS-1, Genesis, Master System)
@ADSRnum = { attack decay sustain release } or
{ attack decay1 decay2 sustain release }
Specify attack rate, decay rate, sustain level and release rate.
On the SEGA Master System (YM2413) the four-parameter version
is used and all values have a range of 0-15 (15 being the fastest
rate / maximum level). Only the custom instrument (@0) uses the
ADSR parameters, all other instruments have fixed ADSR envelopes.
On the SEGA Genesis (YM2612) the five-parameter version is used
and all values have a range of 0-31 (the LSB of sustain and release
is ignored since they are stored as 4-bit values in the YM2612
registers). decay1 is the initial fast decay rate, while decay2 is
the secondary slower decay rate. This command is operator-specific.
The CPS-1 (YM2151) uses the same type of ADSR envelopes as the SEGA
Genesis.
On the Commodore 64 the four-parameter version is used and all values
have a range of 0-15 (15 being the fastest rate / maximum level).
Example:
#IFDEF GEN|CPS
@ADSR1 = {28 29 4 25 10}
#ELSIFDEF SMS
@ADSR1 = {12 13 11 9}
#ENDIF
F v10 OP0 ADSR1 c4
Channel separation (pan) macro (GBC, Game Gear)
@CSnum = { ... | ...}
Pans the sound on targets that support it. Valid range is -63-63.
-63 means full left, 0 means center and 63 means full right.
The macro is applied to a channel with CSnum and disabled with CSOF.
Envelope speed (KSS)
@esnum
Set the speed of the AY envelope generator.
Valid range of num is 0-65535, where 65535 is the maximum speed.
Example:
G @es2500 @te15 @5 c1
FM feedback macro (CPS-1, Genesis)
@FBMnum = { ... | ...}
Specifies the amount of self-feedback for operator 1. This command
is used in combination with the @ command on the SEGA Genesis and
CPS-1 FM channels to select the type of sound generated.
This is the macro version of FB, and allows for rapid changes of
the feedback value.
Valid range is 0-7.
Example:
@FBM0 = { | 0 0 3 3 7 7}
E v9 @2 FBM0 c1
Filter macro (C64)
@FTnum = { type cutoff resonance }
Specifies a filter macro for use on Commodore 64 channels.
type selects the type of filter to use, and has a valid range of 0-3 (0 = low pass,
1 = high pass, 2 = band pass, 3 = notch reject).
cutoff specifies the cutoff frequency, and has a valid range of 0-2047 (which
corresponds to a frequency range of about 30-12000 Hz).
resonance specifies the filter resonance, and has a valid range of 0-15.
Note that the filter parameters are shared between all channels, while filtering
can be enabled/disabled individually per channel. Thus, applying a new filter on one
channel will affect all other channels that have filtering enabled, while disabling
filtering will not affect other channels.
The macro is applied to a channel with FTnum and disabled with FTOF.
Example:
@FT0 = {0 400 2} ; Set a low pass filter.
A @0 v10 FT0
Modulator (CPS-1, Genesis)
@MODnum = { lfo ams fms } or
{ lfo amd fmd ams fms waveform }
Specifies a modulator to be used for modulating the amplitude and/or
frequency of a channel.
SEGA genesis:
The 3-parameter form is used.
lfo selects the frequency of the modulator LFO. Valid range is 0-7
(7 beging the maximum frequency). Note that the LFO is shared for all channels,
so issuing a MOD command on one channel will affect all other channels that
are using a modulator.
ams selects the amplitude modulation sensitivity. Valid range is 0-7
(7 being the maximum sensitivity). Amplitude modulation also has to be separately
enabled with the AM command. This can be done per operator.
fms selects the frequency modulation sensitivity. Valid range is 0-3
(3 being the maximum sensitivity).
CPS-1:
The 6-parameter form is used.
lfo selects the frequency of the modulator LFO. Valid range is 0-255
(255 beging the maximum frequency). Note that the LFO is shared for all channels,
so issuing a MOD command on one channel will affect all other channels that
are using a modulator.
amd selects the amplitude modulation depth. Valid range is 0-127.
fmd selects the frequency modulation depth. Valid range is 0-127.
ams selects the amplitude modulation sensitivity. Valid range is 0-3
(3 being the maximum sensitivity). Amplitude modulation also has to be separately
enabled with the AM command. This can be done per operator.
fms selects the frequency modulation sensitivity. Valid range is 0-7
(7 being the maximum sensitivity).
waveform selects the waveform of the modulator LFO. Valid range is 0-3
(0 = saw, 1 = square, 2 = triangle, 3 = noise).
This command is currently only supported for the FM channels on the SEGA Genesis,
and on the CPS-1.
The macro is applied to a channel with MODnum and disabled with MODOF.
Example:
@MOD0 = {4 2 2}
E v100 MOD0 OP0 AM1 c1
Waveform definition (GBC, KSS)
@WTnum = { sample sample sample ... } or
{ "filename.wav" resample volume }
Defines a waveform for playback on channels that supports it.
In the first case the sequence should contain 32 unsigned samples in the
range 0..15 for the GBC, and -128..127 for KSS.
In the second case the first value should be a string specifying a
.wav file to convert. The resample parameter is the frequency to
resample the .wav file to, and volume specifies the upper limit
of the volume range the sample data will be scaled to.
Example:
@WT0 = {"kickdrum.wav" 8000 15}
@WT1 = {0 0 0 15 0 0 0 15 0 0 0 15 0 0 0 15 0 0 0 15 0 0 0 15 0 0 0 15 0 0 0 15}
C v3 WT1 c4
PCM definition (Genesis)
@XPCMnum = { "filename.wav" resample }
Defines a PCM sample for playback on channels that supports it.
The resample parameter is the frequency to resample the .wav file to (or 0 if you
don't want any resampling). The resampling done by XPMC is of quite poor quality, so
you should consider resampling in a wave editor instead. The native playback rates
in XPMCK are as follows:
SEGA Genesis: 8820 Hz
XPMC will automatically convert the samples to 8-bit mono if needed.
Each sample is tied to a specific note, specified by num, starting from C in
octave 0. So num=0 means a C in octave 0 is used to play the sample, 3 means
D+ in octave 0, 12 means C in octave 1, etc. Usually one will skip all the numbers
that correspond to sharps, simply because it's easier to type dddd than c+c+c+c+.
Example:
@XPCM0 = {"kickdrum.wav" 8000}
J o0 M2 c4
Pulse width macro (C64)
@pwnum = { ... | ... }
Macro version of pw.
Example:
@pw0 = {1 2 3}
@pw1 = {2 2 | 0 0 1 1}
A @pw0 c1 pw9 d1 ; pw and @pw override eachother
Alternative rest (All)
s
This works the same as r, except that it doesn't mute the channel.
Useful when using the w command.
Example:
A l8 s s4. s&s32
Tone envelope (GBC, KSS)
@tenum
On the GBC this command specifies the current tone envelope (frequency sweep).
Valid range of num is -7-7. Positive numbers make the frequency
gradually increase, negative numbers make the frequency gradually
decrease, and zero disables the effect.
Only supported for channel A.
For KSS this command specifies the envelope shape to use on the PSG (AY), and
is shared between all three channels.
Valid range of num is 0-15.
Only supported for channels E..G.
Use @ to toggle the envelope on/off for any of the
PSG channels.
Example:
A @te2 c1
Volume envelope (GBC)
@venum
Specifies the current volume envelope.
Valid range of num is -7-7. Positive numbers make the volume
gradually increase, negative numbers make the volume gradually
decrease, and zero disables the effect.
This command is currently only supported when the target is Gameboy /
Gameboy Color and the channel is A, B or D.
Example:
A @ve-5 c1
Volume set (All)
vnum
v+
v-
v+num
v-num
@vnum
For the SEGA Genesis FM channels (channels E..J) and for the CPS-1, this
command is operator specific, meaning that you can set the volume
individually per operator. To set the volume for all operators at once,
put an OP0 command before the volume command(s).
On the Commodore 64 there is only one global volume that affects all
channels. To get different loudness levels for different channels
you can use ADSR envelopes and/or filters.
v+ and v- increases/decreases the volume by one. It is also possible to specify an
amount for these commands, e.g. v+3 would increase the volume by three units.
Example:
E OP0 v100
F OP1 v105 OP2 v95 OP3 v80 OP4 v100
Direct write (All)
waddress,data
w(port),data
Write one byte of data to a given memory address or port.
This is similar to the @n command in ppmck, but you're not limited to just
the frequency registers - you can write to any address/port.
All parameters must be entered in decimal form. The address/port must
be in the range 0-65535. The data must be in the range 0-255.
Example:
#IFDEF SMS
A w(127),208 w(127),0 ; Set maximum volume on channel 2
#ENDIF
General macro (All)
$id { ... }
$id(default1,default2,...) { ... }
$id(param1,param2,...)
Define/use a general macro. These can be used to save typing if a
lot of smilar patterns are used in a song. Parameters are dereferenced
with %num% (%1% being the first parameter).
It is possible to define default parameters for a macro. For example
if you had:
$1(8,,a) { c%1% d%2% %3% }
then
A $1()
would expand to:
A c8 d a
Example:
$1 { [%1%]4 %2%.. }
A $1(c, a)
The macro invokation on channel A will expand to [c]4 a..
Callback (All)
!id(frequency)
Call a function on the host CPU. E.g. if playing a song on the
SEGA Master System this command would call a function in your
Z80 code. This can be used to synchronize the visual output
of your program with the music.
The frequency parameter specifies how often the function should be
called. The available values are:
0 Never (disable the callback).
1 Once (called during the next update).
EVERY-NOTE Called for every new note that is
played on the channel(s).
Example:
AD !foo(EVERY-NOTE)
A l16 cdef
D l32 [g]8
Here the function foo will be called each time a new note is
played on channel A or D.
Repeat loop (All)
[ ... ]n
[ ... | ... ]n
Repeat everything between the brackets n times.
When the second form is used the part after the | will be skipped on the last
iteration.
n must be >=1, or >=2 when the second form is used.
Loops can be nested up to two levels:
[[cde]2 fg]4 ; This is ok
[[cde]2 fg]4 a]2 ; This is not ok
Loops are not expanded by the compiler, they are handled by the playback library
at runtime.
Example:
[cde]2 ; Play the sequence cde twice.
[cde | fg]3 ; Play the sequence cdefg twice, then play cde once.
Pattern (All)
\id { ... }
\id()
Define/use a pattern. If you want to use the exact same pattern of commands
several times throughout a song, but inconsecutively such that they can't just
be put in a loop, then the pattern construct can be used. The difference compared
to macros is that macros simply result in a text replacement
at compile time, which saves typing for the programmer but doesn't save any
space in the compiled song. Patterns on the other hand are more like subroutines,
where only a single copy of the data exists in the compiled song which be can be used
from multiple places.
If you're outputting to a logged format such as VGM, then using patterns is useless
since they won't save you any space in the compiled song in that case, and macros
are more flexible. But if you are creating a ROM or an executable music format (such as
SID or GBS) and the size of the file matters, then patterns should be used whenever possible.
Example:
\1 { t150 l16 q6 b4g8c8 }
AB \1() r1 e \1()
Note that patterns don't take any arguments, but are still required to have the parentheses
as a delimiter. Also, you can't invoke another pattern from within a pattern.
Since a pattern can be invoked by zero or more channels, which all can have different settings
for tempo, note lengths and so on, you have to specify such settings inside each pattern.
The fact that a pattern can be used on any channel also means that some of the regular sanity
checks done by the compiler will be disabled. You will for example not get a warning if you use
a pattern that contains FM commands on a PSG channel.
Multiline channel activation (All)
( ... )
Activates one or more channels until a ) is found, as a means to save typing.
Example:
AB (
cde
efg
b
)
this is equal to writing
AB cde
AB efg
AB b
Note that the starting ( must be on the same line as the channel enumerators.
Amplitude modulation enable (CPS-1, Genesis, Master System)
AMnum
Used for the FM channels on the SEGA Genesis (channels E..J), and on the CPS-1.
Enable/disable amplitude modulation for the currenly selected operator(s).
Valid range of num is 0-1 (0=OFF, 1=ON).
This command is used in conjunction with MOD.
Detune (All)
Dnum
For most targets this command works as usual.
For the FM channels on the SEGA Genesis (channels E..J) the detune
command has a more limited range of -3-3. The reason for this is that
the value is written to the DT1 bits of the selected operator(s).
Detuning for these channels is also controlled by the MF command.
On the CPS-1 this command works as on the SEGA Genesis.
FM feedback (CPS-1, Genesis, Master System)
FBnum
Specifies the amount of self-feedback for operator 1. This command
is used in combination with the @ command on the SEGA Genesis FM
channels and on the CPS-1 to select the type of sound generated.
Valid range is 0-7.
Example:
E v9 @2 FB6 c1
Set note length (alternative version) (All)
knum
Specifies the length of subsequent notes as num 32nd notes.
Valid range is 1-256.
Example:
A k7 cdef ; This is the same as A c8..d8..e8..f8..
Set note length (All)
lnum
Specifies the length of subsequent notes as 1/num (e.g with num=1 you get whole notes, with num=2 you get half notes, etc.)
Valid range of num is 1, 2, 3, 4, 6, 8, 12, 16, 24, 32.
Example:
A l8 cd l12 ef
B c8d8 e12f12
Output mode (CPS-1, Genesis, Master System)
Mnum
Specifies the output mode for channels that support more than one
output mode.
For the SEGA Master System this command is used for FM channels G..J
to select melody or rhythm mode (M0 = melody (default), M1 = rhythm).
Note that switching mode on any of these three channels affects all of
them.
For channel J on the SEGA Genesis this command is used to switch
between FM and XPCM mode (M0 = FM, M2 = XPCM).
For channel H on the CPS-1 this command is used to switch between melody
and noise mode (M0 = melody, M1 = noise).
Example:
E v8 M0 @7 c1
F v9 M1 @0 [d32r32]16
FM detuning multiplier (CPS-1, Genesis, Master System)
MFnum
Specifies the amount of detuning together with the D command for the FM
channels on the SEGA Genesis and on the CPS-1.
Valid range is 0-15.
This command is operator specific.
Example:
E OP1 D1 MF7 ; Set detune and multiplier for operator 1 on channel E
Noise speed (KSS)
nnum
Set the speed of the AY noise generator.
Valid range of num is 0-31, where 31 is the maximum speed.
Example:
E n25 @2 v13 c
FM Operator select (CPS-1, Genesis)
OPnum
Used for the FM channels on the SEGA Genesis (channels E..J), and on the CPS-1.
Each channel has four operators, which are set up in various configurations
depending on the selected algorithm. Some commands are applied on the channel
while others can be applied per operator. OP selects the operator to apply
subsequent operator-specific commands to.
Valid range of num is 0-4. If num==0 all operators are selected.
Example:
E OP0 ADSR1 ; Set ADSR envelope for all operators on channel E
Pulse width (C64)
pwnum = { ... | ... }
Set the current waveform pulse width when the selected waveform is square (@2).
num has a valid range of 0-15 (which corresponds to a pulse width range of
about 0-93.8%).
Example:
A pw0 c1 pw12 d1
Ring modulation enable (C64)
RINGnum
When num == 1, the triangle waveform (@0) of channel X (where X == A, B or C) is
replaced by a ring modulated combination of the osciallators of channel X and another
channel according to the following list:
A: A + C
B: B + A
C: C + B
Ring modulation is disabled when num == 0.
FM rate scaling (CPS-1, Genesis, Master System)
RSnum
Used for the FM channels on the SEGA Genesis (channels E..J), and on the CPS-1.
Specifies the amount with which envelopes scale to the note's pitch,
creating narrower envelopes as the pitch rises.
Valid range of num is 0-3 (3 being the maximum amount of scaling).
The command is operator specific.
Example:
E OP1 RS2 ; Set rate scaling for operator 1 on channel E
SSG envelope generator (Genesis)
SSGnum
Used for the FM channels on the SEGA Genesis (channels E..J).
When the SSG is active, the ADSR envelope will repeat according to various patterns.
The pattern to use is selected by num and has a valid range of 0-7. SSG is
deactivated with SSGOF.
When SSG is used you should set the attack rate to max (31) in the ADSR envelope
used by the affected operator(s), or you might get distorted output.
This command is operator specific.
Example:
@ADSR0 = {31 10 10 8}
E @2 OP0 v100 SSG0 ADSR0 c1 SSGOF d1
Hard sync enable (C64)
SYNCnum
When num == 1, the oscillator of channel X (where X == A, B or C) is
synchronized with the oscillator of another channel according to the following list:
A: A + C
B: B + A
C: C + B
Hard sync is disabled when num == 0.
Implementation specific notes
SEGA Game Gear
Volume range is 0..15. The lowest playable note is A in octave 2.
Channels A, B, C are tone channels that output square waves.
Channel D is used for noise. @0 selects white noise and @1 selects periodic
noise.
Limited panning is supported (negative values means full left, zero means center,
positive values means full right).
EP and MP can be used together, but they will interfere with eachother.
For the noise channel the octave setting is irrelevant. The noise generator has
four different clock settings that is determined by the current note MOD 4. Below
is a list of what each note corresponds to:
c, e, g+: High pitch
c+, f, a: Medium pitch
d, f+, a+: Low pitch
d+, g, b: Pitch determined by channel C.
By selecting periodic noise generation with pitch determined by channel C it is
possible to use the noise channel as a kind of extra tone channel.
SEGA Master System
Volume range is 0..15.
The lowest playable note is A in octave 2 for channels A..D, and C in octave 1 for
channels E..J.
Channels A, B, C are tone channels that output square waves.
Channel D is used for noise. @0 selects white noise and @1 selects periodic
noise. The noise's pitch is determined in the same way as for the SEGA Game Gear.
Channels E, F, G, H, I, J are FM channels that can output a variety and sounds. Note
that if you want to play a song using these channels on an actual console
you will need a modified SMS / Mark-III with an added YM2413 (or a japanese SMS).
EP and MP can be used together, but they will interfere with eachother.
SEGA Genesis
Volume range is 0..15 for channels A..D, and 0..127 for channels E..J. Note that it's
possible to set the volume separately per operator for channels E..J.
The lowest playable note is A in octave 2 for channels A..D, and C in octave 1 for
channels E..J.
Channels A, B, C are tone channels that output square waves.
Channel D is used for noise. @0 selects white noise and @1 selects periodic
noise. The noise's pitch is determined in the same way as for the SEGA Game Gear.
Channels E, F, G, H, I, J are FM channels that can output a variety and sounds.
Channel J can also be used for PCM playback, see the @XPCM and M commands for more
info (Note that PCM playback only works when outputting to VGM).
Due to the fact that effect tables are copied to the limited audio RAM, you've got
harder restrictions on the number of effect macros you can declare. These limits are
as follows:
@: 20
@v: 32
@EN: 32
@EP: 16
@MP: 16
@ADSR: 16
@MOD: 8
@FBM: 7
The number of patterns you can declare are limited to 10 in this case.
The playback library doesn't handle bank switching, so the compiled size of your music data must
be <= 32 kB and should start as close as possible to the beginning of a 32 kB page. (Note that
this isn't relevant when outputting to VGM).
Callbacks are currently not supported.
EP and MP can be used together, but they will interfere with eachother.
MP is ignored for channels E..J since MOD can achieve pretty much the same thing.
Gameboy / Gameboy Color
Volume range is 0..15 for channels A, B, D and 0..3 for channel C.
The lowest playable note is C in octave 2, except for channels C and D which can go down
to C in octave 1. Channel D can go up to octave 11 (octave 5 when #GB-NOISE 1 is used), while
the maximum octave for the other channels is 7.
Channels A, B are tones channels that output square waves with
controllable duty cycle (0..3, representing 12.5..75%).
Channel C is used for Wave playback. You must execute at least one
WT command on channel C to load a waveform, or the channel will not
be activated.
Channel D is used for noise. @0 selects white noise and @1 selects periodic
noise. You should avoid using EP and MP on the noise channel.
Limited panning is supported (negative values means full left, zero means center,
positive values means full right).
It is preferred to use @ve rather than @v on channels A, B and D.
The reason for that being that the envelope effect specified by the @ve command is handled
by the Gameboy hardware, while an @v command causes the player to update the volume bits for
the selected channel(s) and reset the waveform, which causes distortion.
CPS-1 (Capcom Play System)
Only VGM output is supported for this target. Also, only the YM2151 is supported - no ADPCM.
Volume range is 0..127 for channels A..H. Note that it's possble to set the volume separately
per operator.
The lowest playable note is C in octave 1.
Channels A..H are FM channels that can output a variety and sounds.
Channel H can also output noise, see the M command for more info.
EP and MP can be used together, but they will interfere with eachother.
MP is ignored since MOD can achieve pretty much the same thing.
Commodore 64
Volume range is 0..15 for channels A..C. See the notes about volume on the C64.
The lowest playable note is C in octave 0.
Channels A..C are tone channels that can output the waveform of one of four different
oscillators, with adjustable ADSR envelopes and filtering.
Ring modulation can be used to combine the waveforms of two channels.
ColecoVision
Volume range is 0..15.
The lowest playable note is A in octave 2 for channels A..D.
Channels A, B, C are tone channels that output square waves.
Channel D is used for noise. @0 selects white noise and @1 selects periodic
noise. The noise's pitch is determined in the same way as for the SEGA Game Gear.
EP and MP can be used together, but they will interfere with eachother.
KSS
Volume range is 0..15.
The lowest playable note is A in octave 2 for channels A..D, and C in octave 1 for
channels E..L
Channels A, B, C, D are for the SN79489 (see the SMS/GG/ColecoVision section for more
info).
Channels E, F, G are for the PSG (AY-3-8910). Each of these channels can output tones and/or
noise (see @, n), using either an adjustable volume or one of 16 predefined envelopes (see @te, @es).
Channels H, I, J, K, L are for the Konami SCC. These channels are used for waveform playback.
Channels H..J have their own 32-byte signed 8-bit waveforms that needs to be loaded with the WT command.
Channels K and L share the same waveform, so issuing a WT command on either of those channels will also affect the other.
Note that using the SN79489 will effectively disable the PSG and SCC.
General
Effects are stepped through once per frame.
TODO
Things that would be nice to do, time permitting:
- Fix bugs.
- Write playback libraries for other platforms.
- Implement more effects.
- Create a player for Windows.
- Optimize the playback libraries.