MSX-Music programming
This page was last modified 22:18, 14 August 2017 by MichelM. Based on work by NYYRIKKI and Tvalenca.

MSX-Music is YM2413 aka OPLL implementation standard for MSX. This implementation can be found inside most MSX2+ computers and all MSX tR computers. It is also very popular as external cartridge among MSX2 users. There exists only few software that supports MSX-Music on MSX1.

Contents

Usage in ML

You may also want to check out music replayer routines

Detecting

In #4018 there is text "APRLOPLL" (see notes about FM-PAC)

Direct usage

PORT R/W Usage Wait (in μsec)
#7C W Register Index 3.36
#7D W Register data 23.52


YM2413 Application Manual

FM-BIOS

Address Name Meaning Usage
#4110 WRTOPL Write to OPLL registers IN: A=Register, E=Data
#4113 INIOPL Initialize OPLL IN: HL=Work area (needs to be even address)
#4116 MSTART Start music IN: A=Repeat count 0-254 (0=infinite repeat) HL=Music address
#4119 MSTOP Stop music
#411C RDDATA Read instrument data IN: A=Instrument number (0-63), HL=8 byte buffer to output.
#411F OPLDRV Handle music data. Put in H.TIMI hook
#4122 TESTBGM LD A,(Workarea + #3A) Output: A=Playing status 0=Not playing
#5000 Statement handler CALL-command handler
#5003 Interrupt handler
#5006 Stop background music
#5009 Enable & reset OPLL


For BIOS music format, please look MSX Datapack chapter 3.3.4

FM-PAC

FM-PAC is popular cardridge from Panasoft that includes both PAC (Pana Amusement Cartridge) and MSX-Music functionality. How ever this cartridge needs some extra attention in order to activate MSX-Music compatibility mode.

The identification string (#4018) on this cartrige is changed to "PAC2OPLL" to indicate that it is external MSX-Music. If you want to activate the I/O ports, you need to set bit 0 of address #7FF6 in FM-PAC slot else OPLL chip will be available for use only trough memory I/O. To prevent two devices on same I/O ports it is not recommended to activate FM-PAC when there is internal MSX-MUSIC present.

PLEASE NOTE: Do not set the bit0 of #7FF6 if there is no "PAC2OPLL" string. This will break compatibility with Panasonic MSX2+ computers! In Panasonic A1WX and A1WSX seting bit 0 in any address between #7FF0 and #7FFF will disable the MSX-MUSIC ROM completely.

If you use MSX-BASIC or FM-BIOS then no extra attention is needed because CALL MUSIC command and OPLINI routine will both automatically activate OPLL when needed. These routines will always search first for internal MSX-MUSIC (APRLOPLL) and then external (PAC2OPLL) and activate the external only if internal is not found.

Usage in MSX-BASIC

Looking from BASIC MSX-Music usage is pretty much same as using MSX-Audio but some commands are more limited.

Commands

Command Effect Usage
MUSIC Starts up MSX-MUSIC and determines how the
channels are to be divided and used.
This command must be used first.
CALL MUSIC [(<MODE>[,0[,<n1>
[,<n2>[,......[,<n9>]]]]]]]]]])]
BGM Specifies to allow other commands to be
executed while music is playing
CALL BGM(n)
STOPM Stop play of BGM CALL STOPM
TRANSPOSE Will tranpose in units of half tones 1/100 units CALL TRANSPOSE
TEMPER This sets the rhythm for the FM sound CALL TEMPER(n)
VOICE Sets what instrument voice is to be played by
the FM sound channels. However, values
without * mark and array values are limited
to 2 when used together.
CALL VOICE ([@n1], [@n2], .... [@n9]
VOICE COPY This command copies the voice data to number 63
or an array variable.
CALL VOICE COPY (@n1, -n2)
PITCH This sets the pitch of the sounds to be played
with the FM sounds. All sounds will be adjusted
to this pitch.
CALL PITCH(n)
PLAY (function) Checks if music is being played and returns
the result as a value.
CALL PLAY (n,x)
PLAY (command) Play MML. Up to 9-channels can be used PLAY #2,<string>[,<string>...][,<string>]

Music MML Table

This is a table of the MML (music macro language) that can be used with the PLAY command.

Statement Meaning Range Default Value *1
Mn Envelope cycle setting *2 1>=n<=65535 m255
Sn Envelope shape *2 0<=n<=15 S0
Vn Volume 0<=n<=15 V8
Ln Length 1<=n<=64 L4
Qn Division of sound length 1<=n<=8 Q8
On Octave 1<=n<=8 O4
> Raise 1 Octave - -
< Lower 1 Octave - -
Tn Tempo setting 32<=n<=255 T120
Nn Plays Note raised to n 0<=n<=96 -
Rn Rest setting 1<=n<=64 R4
A-G Note - -
+, # Sharp (raise half tone) - -
- Flat (Lower half tone) - -
(period). Lengthen note or rest by 1.5 - -
XA$ Plays MML stored in string variable A$ *3 - -
=x; sets parameter to x *4 -
& Tie - -
{}n will generate even notes of n for the number within the {} 1<=n<=64 value set with Ln
@n changes the voice set to n 0<=n<=63 -
Yn,v direct register access 0<=v<=255 -
@Vn sets detail change in volume 0<=n<=127 -
@Nn maintain length set by n 1<=n<=64 value set with Ln


*1 Initial value set when CALL MUSIC is used
*2 For PSG only
*3 Adding MML after [XA$;] will result in error
*4 The value range is determined by the preceding MML but it cannot exceed the value 32767

Rhythm MML Table

There are 5 different voices that are available for the rhythm (percussion) MML and up to 3 voices may be played simultaneously. For this reason the rhythm MML first lines up the instruments that are to be played simultaneously.

Statement Meaning Range Default
B Bass drum - -
S Snare drum - -
M Tom tom - -
C Cymbals - -
H Hi Hat - -
n (number) previous notes are played and n th note are rested 1<=n<=64 -
Vn Volume 0<=n<=15 8
! Accents preceding note - -
@An Sets volume for voices that are accented. 0<=n<=15 -


[Tn], [@Vn], [Rn], [Yn,v], [XA$;], [=x;], [.(period)] is the same as music MML

example:
PLAY#2,"","","","BSH8H8H8S!H!8H8"

Plays: Bass, snare, hi-hat and wait an 8th note,
hi-hat and wait an 8th note,
snare, hi-hat plays accented and waits an 8th note,
hi-hat and wait an 8th note.

Voice Data Table

This is a list of the voices available for use with Voice command or the MML @ statement.

Voice No. Name Voice no. Name
0 * Piano 1 32 Piano 3
1 Piano 2 33 * Wood Bass
2 * Violin 34 Santule 2
3 * Flute 1 35 Brass
4 * Clarinet 36 Flute 2
5 * Oboe 37 Clavicord 2
6 * Trumpet 38 Clavicord 3
7 Pipe Organ 39 Koto 2
8 Xylophone 40 Pipe Organ 2
9 * Organ 41 P0hdsPLA
10 * Guitar 42 P0hdsPRA
11 Santule 1 43 Church Organ L
12 * Electric bass 44 Church Organ R
13 Clavicord 1 45 Synth Violin
14 * Hapsicord 46 Synth Organ
15 Hapsicord 47 Synth Brass
16 * Vibraphone 48 * Horn
17 Koto 1 49 Shamisen
18 Taiko 50 Magical
19 Engine 1 51 Fuwawa
20 UFO 52 Wonderflat
21 Synth Bell 53 Hard Rock
22 Chime 54 Machine
23 * Synth Bass 55 Machine V
24 * Synthesizer 56 Comic
25 Synth drum 57 SE comic
26 Synth rhythm 58 SE laser
27 Harmo drum 59 SE noise
28 Cow Bell 60 SE star 1
29 Hi Hat 61 SE star 2
30 Snare drum 62 Engine 2
31 Bass drum 63 no sound


*The names of the voices are given for reference only and they may not sound the same as the real instruments.
*Are sounds that are built in the FM sound chip and sounds without an * indicates sounds generated by software.

Rhythm Table

Table of Rhythm usable with the TEMPER statement

No. Rhythm
0 Pythograph
1 Mintone
2 Welkmeyster
3 Welkmeyster (adjusted)
4 Welkmeyster (seperate)
5 Kilanbuger
6 Kilanbuger (adjusted)
7 Velotte Young
8 Lamour
9 Perfect Rhythm (default)
10 Pure Rhythm c major (a minor)
11 Pure Rhythm cis major (b minor)
12 Pure Rhythm d major (h minor)
13 Pure Rhythm es major (c minor)
14 Pure Rhythm e major (cis minor)
15 Pure Rhythm f major (d minor)
16 Pure Rhythm fis major (es minor)
17 Pure Rhythm g major (e minor)
18 Pure Rhythm gis major (f minor)
19 Pure Rhythm a major (fis minor)
20 Pure Rhythm b minor (g minor)
21 Pure Rhythm h minor (gis minor)

Example

1 '----->IDENTIFICATION DIVISION
2 'BIZET:Carmen(Habanera)
3 'by JL2TBB for MSX-MUSIC on HB-F1XD
100 '----->ENVIRONMENT DIVISION
110 CALLMUSIC(1,0,1,1,1,1,1,1):CALLPITCH(440):CALLTRANSPOSE(0):POKE-1460,20:SOUND6,0:SOUND7,49
120 CLEAR3000:DEFSTRA-K:DEFINTL-Z:DIMA(12),B(12),C(12),D(12),E(12),F(12),G(12),H(12),I(12)
130 '----->RHYTHM PATTERN
140 J="M500C12M200C24":K="M4000C8"
150 H(0)="T100SL24"+J+J+K+J+J+J+K+"V10CV9CVDS"+J+J+K+J+J+J+K+J:I(0)="T100R2.R8L24O8VEV7EV6E"
160 G(0)="T100V15@A2Y40,5Y24,153BM!24M!24M!24M!12M!24S8R12B8B24B8S4B4S8R12B8B24B8S8Y24,15C8"
170 H(1)=LEFT$(H(0),151)+"M5000R12C8R24C4":I(1)=I(0)
180 G(1)=LEFT$(G(0),66)+"SCB8R24SCB4"
190 G(11)="BCS24BCS4"
200 H(10)="RS0M500R4L32CCCCM1000CCCCM1500CCCCM2000CCCC":H(11)="M3000C24C4"
210 '----->BASS PATTERN
220 A(0)="T100@13V13O3D1.":B(0)="T100@13V14O2D1."
230 B(1)="D2.>>@31L24C12DF12DF12GC12DFGA>C<A>CR12V15DR8D<V14"
240 B(2)="Q4D8RR12FG8G8A8>QD8Q4<D8RR12FG8G8A8>QE8Q4<":B(3)="D8RR12FG8A8>E8<QA8E8R12GAGA>C+12<AR12>DR8D<"
250 B(4)="Q4D8RR12F+G8G8A8>QD8Q4<D8RR12F+G8G8A8>QE8Q4<":B(5)="E8RR12F+G8A8>E8<QA8E8R12GAGA>C+12<AR12>DR8D<"
260 B(6)="Y19,0V5L2T150OD.<A.>DE-4E."
270 B(7)="<B.>D.C+.<A>C+4":B(8)="E.T130D.T120C+<A":B(10)="T150>V4D"
280 '----->MELODY
290 A(1)="R1R8OL24@6DCDFGA>C<A>CR@0V13O6Q4L8DD-"
300 J="Q6C12C12C12Q4<BB-AR12A24":A(2)=J+"A-GF24G24F24E12F24GF12QG48F48Q4E4>DD-"
310 A(3)=J+"GFQL24EFED12EQ4L8FED&D>DD-"
320 A(4)="R48"+J+"A-GF+24G24F+24E12F+24GF+12QG48F+48Q4E4>DD-16"
330 A(5)="R48"+J+"GF+E24F+24E24D12E24F+E12<A24>D12..R12@21VY0,40Y1,36Y2,26Y4,244<A24>DE"
340 C(4)="@0O5VQ4L8A12A12A12A-GF+R12F+24FED24E24D24C+12D24ED12E48D48C+4BB-"
350 C(5)="A12A12A12A-GF+R12F+24EDC+24D24C+24<B12>C+24D<A12G24F+12Y50,5R8A24>DE"
360 A(6)="V5T150L8F+4.AF+ED4.EF+GAAAABAG4.<B>EF+":A(7)="G4.BGF+E4.F+GABBBB>C+<BA4.<A>DE"
370 A(8)="T140G4.BGF+T130E4.F+GAT120>C+<BG+AL32>EF+L28EF+L24EF+L20EF+L16EF+L12EF+L8EF+L7EF+L6EF+L5EF+L4EF+L3EF+E"
380 A(10)="T150R8.D"
390 '----->OTHERS
400 J="@10D8R12A24>@16F8<@6A8":C(0)="T100Q2O4"+J+J+J+J:C(1)=J+J
410 D(0)="@14V13T100R1.RR12O5C24R12D24"
420 E(0)="@14V13T100R1.RR12OG24R12A24"
430 F(0)="@6V14T100L24O3"
440 J="R1RL24@6>FGA>C<A>CR12":D(1)=J+"V15DR8D8V10L64V9C<BVAGV7FEV6DC"
450 E(1)=J+"V15AR8A8V10L64V9GFVEDV7C<BV6AG":F(1)=J+">GR8G8V10L64V9FEVDC<V7BAGF"
460 F(1)=J+">GR8G8V10L64V9FEVDC<V7BAGF"
470 D(2)="@2L24V10O5D&Y19,120&Y19,130&Y19,140&D&Y19,150&D&Y19,160&D&Y19,170&D&Y19,178&D1&D4F2"
480 E(2)="@2L24V9OG&G&Y20,5&G&Y20,10&G&Y20,15&GY20,50&G&Y20,225Y20,30&G1&G4B-2"
490 F(2)="@2L24V9OE&Y21,160&E&Y21,170&E&Y21,180&E&Y21,190&E&Y21,200&E&E1&E4G2"
500 D(3)=LEFT$(D(2),77)+"2.R24C+2@6R12V13>DR8D"
510 E(3)="A&Y20,0&A&Y20,10&A&Y20,20&A&Y20,30&A&Y20,40&A&Y20,50&A2.A2V13@6>>>R12DR8D"
520 F(3)="E&E&Y21,215&E&Y21,225&E&Y21,235&E&Y21,245&E&Y21,255&E2.G2@6>>R12AR8A"
530 D(4)="@16LRVO5F+A2R>D<B2":E(4)="@16LRVO5DF+2RAG2":F(4)="@16LRVOA>D2RF+E2"
540 D(5)="RE>E2R<A>DY51,90":E(5)="R<B>B2RGF+":F(5)="R<G>G2RED"
550 D(6)="T150L8Q4OR64D4A>F+<A4DA>F+4<A4D4A>F+D+4E<EF+GAB16."
560 D(7)="E4B>G<B4EB>G4<B4A4>C+AG4F+<<AB>C+DE":D(8)="T140E4B>G<B4T130EB>G4D4E"
570 IJ="SM100T100O8L64CCCL48CCCL32CCCL24CCCR":I(9)=IJ+IJ+IJ
580 D(10)="Y51,5R16O5F+":E(10)="Y52,5R8O5A"
590 J="T100Q8L24V15A>D":A(11)="@6O5"+J:B(11)="@31O4"+J:C(11)="@6O6"+J:D(11)="@2O5"+J:E(11)="@2O3"+J:F(11)="@6O3"+J
600 E(6)="T150@3O6V5Q4L8RDEF+GL24QABABABABABABABABABA4"
610 '----->PROCEDURE DIVISION
620 FORX=0TO5:IFX=4ANDY=0THENX=2:Y=1
630 Z=XMOD2:PLAY#2,A(X),B(X),C(X),D(X),E(X),F(X),G(Z),H(Z),I(Z):NEXT
640 FORX=6TO11:IFX=8ANDY=1THENX=6:Y=0
650 X=X+(X=7)*(Y=0):PLAY#2,A(X),B(X),C(X),D(X),E(X),F(X),G(X),H(X),I(X):NEXT
660 END