Copy Link
Add to Bookmark
Report

Rob Hubbard's music: disassembled, commented and explained

RECOLLECTION issue 3

eZine's profile picture
Published in 
Recollection
 · 1 year ago

By Anthony McSweeney

Introduction

How do you introduce someone like Rob Hubbard?? He came, he saw and he conquered the C64 world. In my estimation, this one man was responsible for selling more C64 software than any other single person. Hell! I think that Rob Hubbard was responsible for selling more COMMODORE 64's than any other person! I certainly bought my C64 after being blown away by the Monty on the Run music in December 1985. In the next few years, Rob would totally dominate the C64 music scene, releasing one hit after another. I will even say that some really terrible games sold well only on the strength of their brilliant Rob Hubbard music (e.g. KnuckleBusters and W.A.R.).

So how did Rob achieve this success? Firstly (of course) he is a superb composer and musician, able to make the tunes that bring joy to our hearts every time we hear them! (Also consider the amazing diversity of styles of music that Rob composed). Secondly, he was able to make music which was suited to the strengths and limitations of the SID chip. Just recall the sound FX used at the beginning of Thrust, or in the Delta in-game music. Perhaps the biggest limitation of SID must be the meagre 3 channels that can be used, but most Hubbard songs appear to have four, five or even more instruments going (just listen to the beginning of Phantoms of the Asteroids for example... that's only one channel used!!). I could really go on for (p)ages identifying the outstanding things that Rob Hubbard did, so I will finally mention that Rob's coding skills and his music routines were a major factor in his success.

The First Rob Hubbard Routine

Rob Hubbard created a superb music routine from the very first tune which was released (Confuzion). Furthermore, Rob used this routine to make music for a very long time, only changing it _slightly_ over time. The source code that I present here was used (with slight modifications) in: Confuzion, Thing on a Spring, Monty on the Run, Action Biker, Crazy Comets, Commando, Hunter Patrol, Chrimera, The Last V8, Battle of Britain, Human Race, Zoids, Rasputin, Master of Magic, One Man & His Droid, Game Killer, Gerry the Germ, Geoff Capes Strongman Challenge, Phantoms of the Asteroids, Kentilla, Thrust, International Karate, Spellbound, Bump Set and Spike, Formula 1 Simulator, Video Poker, Warhawk or Proteus and many, many more! All you would need to do to play a different music is to change the music data at the bottom, and a few lines of the code.

This particular routine has been ripped off by many famous groups and people over the years, but I don't think that they were ever generous enough to share it around. Can you remember The Judges and Red Software?? They made the famous Red-Hubbard demo, and used it in Rhaa-Lovely and many of their other productions. I'm sure that the (Atari) ST freaks reading this will love Mad Max (aka Jochen Hippel), and remember the BIG demo which featured approximately 100 Rob Hubbard tunes converted to the ST. Although I hate to admit it, I decided to start sharing around my own source code after receiving the amazing Protracker source code (340K!) on the Amiga (thanks Lars Hamre). That made me shameful to be selfish, especially after I learned a lot of from it. Why don't YOU share around your old source codes too!

The particular routine that is included below was ripped from Monty on the Run, and it appeared in memory from $8000 to about $9554. The complete routine had code for sound fx in it, which I have taken out for the sake of clarity. Although the routine is really tiny - a mere 900 or 1000 bytes of code, there are some amazingly complex concepts in it which require a lot of explanation if you don't know much about computer music or SID. Fortunately for you, I have put in excellent label names for you, and also a lot of really helpful and amazing comments. In fact, I think this source code must have a much better structure and comments than Rob Hubbard's original!!! I think that the best way to understand the source code is to study it, and figure out what is going on using the comments.

Rob Hubbard's original 'Commando' music sheet.
Pin it
Rob Hubbard's original 'Commando' music sheet.

In addition to the comments in the source, there are *3* descriptions of the routine in this article. The first tells you how to use the music routine when it's viewed as an already assembled 'module'. The second goes through an overview of the music and instrument data format, and is great for getting an overall feel for what the code is doing. The third description looks at the various sections of the code, and how they come together.

How to use the source code

jsr music+0 to initialize the music number in the accumulator
jsr music+3 to play the music
jsr music+6 to stop the music and quieten SID


The music is supposed to run at 50Hz, or 50 times per second. Therefore PAL users can run the music routine off the IRQ like this:

lda #$00 ; init music number 0
jsr music+0
sei ; install the irq and a raster compare
lda # ldx #>irq
sta $314
stx $315
lda #$1b
sta $d011
lda #$01
sta $d01a
lda #$7f
sta $dc0d
cli
loop =*
jmp loop ; endless loop (music is now playing off interrupt :-)

irq =*
lda #$01
sta $d019
lda #$3c
sta $d012

inc $d020 ; play music, and show a raster for the time it takes
jsr music+3
dec $d020

lda #$14
sta $d018
jmp $ea31

If this method is used on NTSC machines, then the music will be running at 60Hz and will sound much to fast - possibly it might sound terrible. I'm afraid you'll have to put up with this unless YOU are good enough to make a CIA interrupt at 50Hz. As I haven't had to worry about NTSC users before, perhaps someone will send me the best way to do this...

[Ed. Note: You could also keep a counter for the IRQ and don't execute it every 6 interrupt. This will make it the right speed although the best solution is for modifying the CIA to 50Hz like he mentions above.]

How the music data is arranged

1. The music 'module' contains one or more songs

Each RH music is made up of a 'bunch' of songs in a single module. Thus the 'module' can have the title music, in-game music, and the game-over music all using the same play routine (and even the same instruments. :) The source that appears below only has the one song in it, and the music number is automatically set to 0 as a result (line 20). The label 'songs' is where you want to look for the pointers to the songs if you want to change this.


2. Each song is made up of three tracks

We all know that there are only 3 channels on the SID chip, so there are also 3 tracks - one for each channel. When I said 'pointers to the songs' above, I was therefore referring to 'pointers to the three tracks that make up the song'... hence we are looking at the label 'songs' again. Each track needs a high and low pointer, so there are 6 bytes needed to point to a song.


3. Each track is made up of a list of pattern numbers

Each track consists of a list of the pattern numbers in the order in which they are to be played. Here we are looking at the labels 'montymaintr1' and 'montymaintr2'and 'montymaintr3'. Therefore I can tell you that the initial patterns played in this song are $11, $12 and $13 on channels 1,2 and 3 respectively. The track is either ended with a $ff or $fe byte. A $ff means that the song needs to be looped when the end of the track is reached (like the Monty main tune), while a $fe means that the song is only to be played once. The current offset into the track is often called the current POSITION for that track.


4. A pattern consists of a sequence of notes

A pattern contains the data that says when the notes should be played, how long they should be played for, at what pitch, with what instrument, should there be ADSR, should there be bending (portamento) of the notes etc. Each pattern is ended with a $ff byte, and when this is encountered, the next pattern in the track will be played. Each note has up to a 4 byte specification.

- The first byte is always the length of the note from 0-31 or 0-$1f in hex. You will notice that the top three bits are not used for the length of the note, so they are used for other things.

- Bit#5 signals no release needed. - Bit#6 signals that this note is appended to the last one (no attack/etc). - Bit#7 signals that a new instrument or portamento is coming up.

- The second byte is an optional byte, and it holds the instrument number to use or the portamento value (i.e. a bended note). This byte will be needed according to whether bit#7 of the first byte is set or not...i.e. if the 1st byte was negative, then this byte is needed.

- If the second byte is positive, then this is the new instrument number.

- If the second byte is negative, then this is a bended note (portamento). And the value is the speed of the portamento (except for bits #7 and #0).

- Bit#0 of the portamento byte determines the direction of the bend.
- Bit#0 = 0 then portamento is up.
- Bit#0 = 1 then portamento is down.

- The third byte of the specification is the pitch of the note. A pitch of 0 is the lowest C possible. A pitch of 12 or $C(hex) is the next highest C above that. These pitches are denoted fairly universally as e.g. 'C-1' and for sharps e.g. 'D#3'. Notice that this routine uses pitches of higher than 72 ($48) which is c-6 :-)

- The fourth byte if it exists will denote the end of the pattern. i.e. If the next byte is a $ff, then this is the end of the pattern.

NOTE: I have labelled the various bytes with numbers for convenience. Bear in mind that some of these are optional, so if the second byte is not needed, then I will say that the pitch of the note coming up is the 'third byte', even though it isn't really.

Okay, here are some examples

e.g. $84,$04,$24 means that the length of the note is 4 (from the lower 5 bits of the first byte), that the instrument to use is instrument number 4 (the second byte, as indicated by bit #7 of the first byte), and that the pitch of the note is $24 or c-3.

e.g. $D6,$98,$25,$FF means that the length of the note is 22 ($16), that this note should be appended to the last, that the second byte is a portamento (as both 1st and 2nd bytes -ve!), that the portamento is going up (as bit#0 = 0) with a speed of 24 ($18), that the pitch of the note is $25 or c#3, and that this is the end of the pattern.

It doesn't get any harder than that!! Did you realise that this is exactly the way that Rob Hubbard made the music!! He worked out some musical ideas on his cheap (musical) keyboard, and typed the notes into his assembler in hex, just like this.


5. The instruments are an 8 byte data structure

You are looking at the label 'instr' at the bottom of the source code. The 8 bytes which come along first are instrument number 0, the next 8 define instrument number 1, etc. Here are the meanings of the bytes, but I suggest that you check out your programming manuals if you are unfamiliar with these:

- Byte 0 is the pulse width low byte, and
- Byte 1 is the pulse width high byte. (also see byte 7).

- Byte 2 is the control register byte. This specifies which type of sound should be used; sine, sawtooth etc.

- Byte 3 is the attack and decay values, and
- Byte 4 is the sustain and release values. The note's volume is altered according to these values. When the attack and decay are over, the volume of the note is held at the sustain level. When length of a note is over, a release is done through the 'gate' bit in SID.

- Byte 5 is the vibrato depth for the instrument.

- Byte 6 is the pulse speed. Timbre is created by changing the shape of the waveform each 50th of a second, and this is the most common way of achieving it. The shape of the pulse waveform changes from square to a very rectangular at a speed according to this byte. N.B. if you are interested in how the pulse value number works, then e-mail me sometime, as I found this out (exhaustively) a few days ago!

- Byte 7 is the instrument FX byte, and is the major thing which changes between different music routines. Each bit in this byte determines whether this instrument will have a certain effect in it.

- Bit#0 signals that this is a drum. Drums are made from a noise channel and also a fast frequency down, with fast decay. Bass drums use a square wave, and only the first 50th of a second is a noise channel. This is the tell-tale instrument that gives away a Rob Hubbard routine! Hihats and other drums use noise all the time.

- Bit#1 signals a 'skydive'. This is a slower frequency down, that I think sounds like somebody yelling as they fall out of a plane .. AHHHHhhhhgh.. ..hence I call it a skydive!!

- Bit#2 signals an octave arpeggio. It's a very limited arpeggio routine in this song. Listen for the arpeggio and the skydive when combined, which is used a lot in Hubbard songs.

- All the other bits have no meaning in this music, but were used a lot in later music for the FX.

A big reason that I presented this early routine, was because there was not too much in the way of special FX to confuse you. As a result, you can concentrate on the guts of the code instead of the special FX :-)

How the source code works

The routines at the top of the source code are concerned with turning the music on and off, and you will see that this is done through a variable called 'mstatus' (or music status). If mstatus is set to $C0, then the music is turned off and SID is quietened, thereafter mstatus is set to $80 which means that the music is still off, but SID doesn't need to be quietened again. When the music is initialized, then mstatus is given a value of $40 which kicks in the further initialization stuff. If mstatus is any other value, then the music is being played. For any of the initialization stuff to have any meaning to you, you of course have to understand the rest of the play routine. :-)

After we have got past the on/off/init stuff, we are at the label called 'contplay' at around line 100. The first thing you should notice is that this is the start of a huge loop that is done *3* times - once for each channel. The loop really *is* huge, as it ends right on the last few lines of the code. :-)

Now that we are talking about routines within the loop, we are talking about these routines being applied to the channels independently. There are 2 main routines within the loop, one is called NoteWork, and the other is called SoundWork. NoteWork checks to see whether a new note is needed on this channel, and if it is, then the note data is fetched and stuff is initialized. If no note is needed, then SoundWork is called which processes the instruments and does the portamento.

NoteWork first checks the speed at which the notes are fetched. If the delay is still occurring, then new notes are not needed and soundwork is called. N.B. that the speed for Monty on the Run is 1, which means that a note of length $1f will last for 64 calls to the routine (i.e. just over a second). If the speed of the song is reset, then NoteWork decrements the length of the current note. When the length of the current note hits $ff (-1) then a new note is needed, otherwise SoundWork is jumped to.

The data for a new note is collected at the label 'getnewnote'. In the simplest case, this involves getting the next bytes of data from the current pattern on this channel, but if the end of the pattern is reached, then the next pattern number is fetched by reference to the current position within this channel's track. In an even more complex situation, the end of a track is reached, and the current position needs to be reset to 0 before the next pattern number can be found.

You can see quite clearly in this part of the routine where the length of the note is collected, and it is determined whether a 2nd byte is needed, where the pitch is collected, and the end of the song checked. You can also see where some of the data is collected from the current instrument and jammed into the SID registers.

SoundWork is called if no new notes are needed, and it processes the instruments and does the portamento etc. This part of the routine is neatly expressed in sections which are really well commented and quite easy to understand.

- The first thing that occurs in SoundWork is that the 'gate bit' of SID is set when the length of the note is over - this causes a release of the note.

- The vibrato routine is quite inefficient, but it's pretty good for 1985! Of course vibrato is implemented by raising and lowering the pitch of the note ever-so-slightly causing the note to 'float'. The amount of the vibrato is determined in the current instrument.

- The pulsework routine changes the pulsewidth between square wave and very rectangular wave according to the pulsespeed in the current instrument. (i.e. it changes the sound of the instrument and thus alters the 'timbre') The routine goes backwards and forwards between the two; and switches when one extremity is reached. It's interesting to note that the current values of the pulse width are actually stored in the instrument. :-)

- Portamento is achieved by adding/subtracting an amount of frequency to the current frequency each time this part of the routine is called.

- The instrument FX routines are also really easy to figure out, as they are well commented. Both the drums and the skydive do a very fast frequency down, so it is the most significant byte of the frequency which is reduced... and not 16-bit maths (math?!). The arpeggio is only an octave arpeggio, so for the first 50th of a second, the current note is played, and for the next 50th of a second, current note+12 is played, followed by the current note again etc.

(If you don't know what an arpeggio is. it's generally when the notes of a chord are played individually in a rapid succession. It produces a 'full' sound depending on the speed of the arpeggio. In most cases the note is changed 50 times per second, which gives a very nice sound. If you have listened to some computer music, then you will have definitely listened to an arpeggios all the time, even if you don't realise it!

Final Thoughts

*Bounce* I'm finally near the end of this article! It has been a lot of work to try to explain this routine, but I'm glad that I've done it *grin*.

I would have given an arm or a leg for a commented Rob Hubbard source code in the past, so I hope you enjoy this valuable offering.

Rob Hubbard's music: disassembled, commented and explained
Pin it

;rob hubbard
;monty on the run music driver

;this player was used (with small mods)
;for his first approx 30 musix

.org $8000
.obj motr

jmp initmusic
jmp playmusic
jmp musicoff


;====================================
;init music

initmusic =*

lda #$00 ;music num
ldy #$00
asl
sta tempstore
asl
clc
adc tempstore ;now music num*6
tax

- lda songs,x ;copy ptrs to this
sta currtrkhi,y ;music's tracks to
inx ;current tracks
iny
cpy #$06
bne -

lda #$00 ;clear control regs
sta $d404
sta $d40b
sta $d412
sta $d417

lda #$0f ;full volume
sta $d418

lda #$40 ;flag init music
sta mstatus

rts


;====================================
;music off

musicoff =*

lda #$c0 ;flag music off
sta mstatus
rts


;====================================
;play music

playmusic =*

inc counter

bit mstatus ;test music status
bmi moff ;$80 and $c0 is off
bvc contplay ;$40 init, else play


;==========
;init the song (mstatus $40)

lda #$00 ;init counter
sta counter

ldx #3-1
- sta posoffset,x ;init pos offsets
sta patoffset,x ;init pat offsets
sta lengthleft,x ;get note right away
sta notenum,x
dex
bpl -

sta mstatus ;signal music play
jmp contplay


;==========
;music is off (mstatus $80 or $c0)

moff =*

bvc + ;if mstatus $c0 then
lda #$00
sta $d404 ;kill voice 1,2,3
sta $d40b ;control registers
sta $d412

lda #$0f ;full volume still
sta $d418

lda #$80 ;flag no need to kill
sta mstatus ;sound next time

+ jmp musicend ;end


;==========
;music is playing (mstatus otherwise)

contplay =*

ldx #3-1 ;number of chanels

dec speed ;check the speed
bpl mainloop

lda resetspd ;reset speed if needed
sta speed


mainloop =*

lda regoffsets,x ;save offset to regs
sta tmpregofst ;for this channel
tay


;check whether a new note is needed

lda speed ;if speed not reset
cmp resetspd ;then skip notework
beq checknewnote
jmp vibrato

checknewnote =*

lda currtrkhi,x ;put base addr.w of
sta $02 ;this track in $2
lda currtrklo,x
sta $03

dec lengthleft,x ;check whether a new
bmi getnewnote ;note is needed

jmp soundwork ;no new note needed


;==========
;notework
;a new note is needed. get the pattern
;number/cc from this position

getnewnote =*

ldy posoffset,x ;get the data from
lda ($02),y ;the current position

cmp #$ff ;pos $ff restarts
beq restart

cmp #$fe ;pos $fe stops music
bne getnotedata ;on all channels
jmp musicend

;cc of $ff restarts this track from the
;first position

restart =*

lda #$00 ;get note immediately
sta lengthleft,x ;and reset pat,pos
sta posoffset,x
sta patoffset,x
jmp getnewnote


;get the note data from this pattern

getnotedata =*

tay
lda patptl,y ;put base addr.w of
sta $04 ;the pattern in $4
lda patpth,y
sta $05

lda #$00 ;default no portamento
sta portaval,x

ldy patoffset,x ;get offset into ptn

lda #$ff ;default no append
sta appendfl

;1st byte is the length of the note 0-31
;bit5 signals no release (see sndwork)
;bit6 signals appended note
;bit7 signals a new instrument
; or portamento coming up

lda ($04),y ;get length of note
sta savelnthcc,x
sta templnthcc
and #$1f
sta lengthleft,x

bit templnthcc ;test for append
bvs appendnote

inc patoffset,x ;pt to next data

lda templnthcc ;2nd byte needed?
bpl getpitch

;2nd byte needed as 1st byte negative
;2nd byte is the instrument number(+ve)
;or portamento speed(-ve)

iny
lda ($04),y ;get instr/portamento
bpl +

sta portaval,x ;save portamento val
jmp ++

+ sta instrnr,x ;save instr nr

+ inc patoffset,x

;3rd byte is the pitch of the note
;get the 'base frequency' here

getpitch =*

iny
lda ($04),y ;get pitch of note
sta notenum,x
asl ;pitch*2
tay
lda frequenzlo,y ;save the appropriate
sta tempfreq ;base frequency
lda frequenzhi,y
ldy tmpregofst
sta $d401,y
sta savefreqhi,x
lda tempfreq
sta $d400,y
sta savefreqlo,x
jmp +

appendnote =*

dec appendfl ;clever eh?


;fetch all the initial values from the
;instrument data structure

+ ldy tmpregofst
lda instrnr,x ;instr num
stx tempstore
asl ;instr num*8
asl
asl
tax

lda instr+2,x ;get control reg val
sta tempctrl
lda instr+2,x
and appendfl ;implement append
sta $d404,y

lda instr+0,x ;get pulse width lo
sta $d402,y

lda instr+1,x ;get pulse width hi
sta $d403,y

lda instr+3,x ;get attack/decay
sta $d405,y

lda instr+4,x ;get sustain/release
sta $d406,y

ldx tempstore ;save control reg val
lda tempctrl
sta voicectrl,x


;4th byte checks for the end of pattern
;if eop found, inc the position and
;reset patoffset for new pattern

inc patoffset,x ;preview 4th byte
ldy patoffset,x
lda ($04),y

cmp #$ff ;check for eop
bne +

lda #$00 ;end of pat reached
sta patoffset,x ;inc position for
inc posoffset,x ;the next time

+ jmp loopcont


;==========
;soundwork
;the instrument and effects processing
;routine when no new note was needed

soundwork =*

;release routine
;set off a release when the length of
;the note is exceeded
;bit4 of the 1st note-byte can specify
;for no release

ldy tmpregofst

lda savelnthcc,x ;check for no release
and #$20 ;specified
bne vibrato

lda lengthleft,x ;check for length of
bne vibrato ;exceeded

lda voicectrl,x ;length exceeded so
and #$fe ;start the release
sta $d404,y ;and kill adsr
lda #$00
sta $d405,y
sta $d406,y


;vibrato routine
;(does a lot of work)

vibrato =*

lda instrnr,x ;instr num
asl
asl
asl ;instr num*8
tay
sty instnumby8 ;save instr num*8

lda instr+7,y ;get instr fx byte
sta instrfx

lda instr+6,y ;get pulse speed
sta pulsevalue

lda instr+5,y ;get vibrato depth
sta vibrdepth
beq pulsework ;check for no vibrato

lda counter ;this is clever!!
and #7 ;the counter's turned
cmp #4 ;into an oscillating
bcc + ;value (01233210)
eor #7
+ sta oscilatval

lda notenum,x ;get base note
asl ;note*2
tay ;get diff btw note
sec ;and note+1 frequency
lda frequenzlo+2,y
sbc frequenzlo,y
sta tmpvdiflo
lda frequenzhi+2,y
sbc frequenzhi,y

- lsr ;divide difference by
ror tmpvdiflo ;2 for each vibrdepth
dec vibrdepth
bpl -
sta tmpvdifhi

lda frequenzlo,y ;save note frequency
sta tmpvfrqlo
lda frequenzhi,y
sta tmpvfrqhi

lda savelnthcc,x ;no vibrato if note
and #$1f ;length less than 8
cmp #8
bcc +

ldy oscilatval

- dey ;depending on the osc
bmi + ;value, add the vibr
clc ;freq that many times
lda tmpvfrqlo ;to the base freq
adc tmpvdiflo
sta tmpvfrqlo
lda tmpvfrqhi
adc tmpvdifhi
sta tmpvfrqhi
jmp -

+ ldy tmpregofst ;save the final
lda tmpvfrqlo ;frequencies
sta $d400,y
lda tmpvfrqhi
sta $d401,y


;pulse-width timbre routine
;depending on the control/speed byte in
;the instrument datastructure, the pulse
;width is of course inc/decremented to
;produce timbre

;strangely the delay value is also the
;size of the inc/decrements

pulsework =*

lda pulsevalue ;check for pulsework
beq portamento ;needed this instr

ldy instnumby8
and #$1f
dec pulsedelay,x ;pulsedelay-1
bpl portamento

sta pulsedelay,x ;reset pulsedelay

lda pulsevalue ;restrict pulse speed
and #$e0 ;from $00-$1f
sta pulsespeed

lda pulsedir,x ;pulsedir 0 is up and
bne pulsedown ;1 is down

lda pulsespeed ;pulse width up
clc
adc instr+0,y ;add the pulsespeed
pha ;to the pulse width
lda instr+1,y
adc #$00
and #$0f
pha
cmp #$0e ;go pulsedown when
bne dumpulse ;the pulse value
inc pulsedir,x ;reaches max ($0exx)
jmp dumpulse

pulsedown =*

sec ;pulse width down
lda instr+0,y
sbc pulsespeed ;sub the pulsespeed
pha ;from the pulse width
lda instr+1,y
sbc #$00
and #$0f
pha
cmp #$08 ;go pulseup when
bne dumpulse ;the pulse value
dec pulsedir,x ;reaches min ($08xx)

dumpulse =*

stx tempstore ;dump pulse width to
ldx tmpregofst ;chip and back into
pla ;the instr data str
sta instr+1,y
sta $d403,x
pla
sta instr+0,y
sta $d402,x
ldx tempstore


;portamento routine
;portamento comes from the second byte
;if it's a negative value

portamento =*

ldy tmpregofst
lda portaval,x ;check for portamento
beq drums ;none

and #$7e ;toad unwanted bits
sta tempstore

lda portaval,x ;bit0 signals up/down
and #$01
beq portup

sec ;portamento down
lda savefreqlo,x ;sub portaval from
sbc tempstore ;current frequency
sta savefreqlo,x
sta $d400,y
lda savefreqhi,x
sbc #$00 ;(word arithmetic)
sta savefreqhi,x
sta $d401,y
jmp drums

portup =*

clc ;portamento up
lda savefreqlo,x ;add portval to
adc tempstore ;current frequency
sta savefreqlo,x
sta $d400,y
lda savefreqhi,x
adc #$00
sta savefreqhi,x
sta $d401,y


;bit0 instrfx are the drum routines
;the actual drum timbre depends on the
;crtl register value for the instrument:
;ctrlreg 0 is always noise
;ctrlreg x is noise for 1st vbl and x
;from then on

;see that the drum is made by rapid hi
;to low frequency slide with fast attack
;and decay

drums =*

lda instrfx ;check if drums
and #$01 ;needed this instr
beq skydive

lda savefreqhi,x ;don't bother if freq
beq skydive ;can't go any lower

lda lengthleft,x ;or if the note has
beq skydive ;finished

lda savelnthcc,x ;check if this is the
and #$1f ;first vbl for this
sec ;instrument-note
sbc #$01
cmp lengthleft,x
ldy tmpregofst
bcc firstime

lda savefreqhi,x ;not the first time
dec savefreqhi,x ;so dec freqhi for
sta $d401,y ;drum sound

lda voicectrl,x ;if ctrlreg is 0 then
and #$fe ;noise is used always
bne dumpctrl

firstime =*

lda savefreqhi,x ;noise is used for
sta $d401,y ;the first vbl also
lda #$80 ;(set noise)

dumpctrl =*

sta $d404,y


;bit1 instrfx is the skydive
;a long portamento-down from the note
;to zerofreq

skydive =*

lda instrfx ;check if skydive
and #$02 ;needed this instr
beq octarp

lda counter ;every 2nd vbl
and #$01
beq octarp

lda savefreqhi,x ;check if skydive
beq octarp ;already complete

dec savefreqhi,x ;decr and save the
ldy tmpregofst ;high byte freq
sta $d401,y


;bit2 instrfx is an octave arpeggio
;pretty tame huh?

octarp =*

lda instrfx ;check if arpt needed
and #$04
beq loopcont

lda counter ;only 2 arpt values
and #$01
beq +

lda notenum,x ;odd, note+12
clc
adc #$0c
jmp ++

+ lda notenum,x ;even, note

+ asl ;dump the corresponding
tay ;frequencies
lda frequenzlo,y
sta tempfreq
lda frequenzhi,y
ldy tmpregofst
sta $d401,y
lda tempfreq
sta $d400,y


;==========
;end of dbf loop

loopcont =*

dex ;dbf mainloop
bmi musicend
jmp mainloop

musicend =*

rts


;====================================
;frequenz data
;====================================

frequenzlo .byt $16
frequenzhi .byt $01
.byt $27,$01,$38,$01,$4b,$01
.byt $5f,$01,$73,$01,$8a,$01,$a1,$01
.byt $ba,$01,$d4,$01,$f0,$01,$0e,$02
.byt $2d,$02,$4e,$02,$71,$02,$96,$02
.byt $bd,$02,$e7,$02,$13,$03,$42,$03
.byt $74,$03,$a9,$03,$e0,$03,$1b,$04
.byt $5a,$04,$9b,$04,$e2,$04,$2c,$05
.byt $7b,$05,$ce,$05,$27,$06,$85,$06
.byt $e8,$06,$51,$07,$c1,$07,$37,$08
.byt $b4,$08,$37,$09,$c4,$09,$57,$0a
.byt $f5,$0a,$9c,$0b,$4e,$0c,$09,$0d
.byt $d0,$0d,$a3,$0e,$82,$0f,$6e,$10
.byt $68,$11,$6e,$12,$88,$13,$af,$14
.byt $eb,$15,$39,$17,$9c,$18,$13,$1a
.byt $a1,$1b,$46,$1d,$04,$1f,$dc,$20
.byt $d0,$22,$dc,$24,$10,$27,$5e,$29
.byt $d6,$2b,$72,$2e,$38,$31,$26,$34
.byt $42,$37,$8c,$3a,$08,$3e,$b8,$41
.byt $a0,$45,$b8,$49,$20,$4e,$bc,$52
.byt $ac,$57,$e4,$5c,$70,$62,$4c,$68
.byt $84,$6e,$18,$75,$10,$7c,$70,$83
.byt $40,$8b,$70,$93,$40,$9c,$78,$a5
.byt $58,$af,$c8,$b9,$e0,$c4,$98,$d0
.byt $08,$dd,$30,$ea,$20,$f8,$2e,$fd


regoffsets .byt $00,$07,$0e
tmpregofst .byt $00
posoffset .byt $00,$00,$00
patoffset .byt $00,$00,$00
lengthleft .byt $00,$00,$00
savelnthcc .byt $00,$00,$00
voicectrl .byt $00,$00,$00
notenum .byt $00,$00,$00
instrnr .byt $00,$00,$00
appendfl .byt $00
templnthcc .byt $00
tempfreq .byt $00
tempstore .byt $00
tempctrl .byt $00
vibrdepth .byt $00
pulsevalue .byt $00
tmpvdiflo .byt $00
tmpvdifhi .byt $00
tmpvfrqlo .byt $00
tmpvfrqhi .byt $00
oscilatval .byt $00
pulsedelay .byt $00,$00,$00
pulsedir .byt $00,$00,$00
speed .byt $00
resetspd .byt $01
instnumby8 .byt $00
mstatus .byt $c0
savefreqhi .byt $00,$00,$00
savefreqlo .byt $00,$00,$00
portaval .byt $00,$00,$00
instrfx .byt $00
pulsespeed .byt $00
counter .byt $00
currtrkhi .byt $00,$00,$00
currtrklo .byt $00,$00,$00


;====================================
;monty on the run main theme
;====================================

songs =*
.byt .byt .byt .byt >montymaintr1
.byt >montymaintr2
.byt >montymaintr3


;====================================
;pointers to the patterns

;low pointers
patptl =*
.byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt 0
.byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt .byt
;high pointers
patpth =*
.byt >ptn00
.byt >ptn01
.byt >ptn02
.byt >ptn03
.byt >ptn04
.byt >ptn05
.byt >ptn06
.byt >ptn07
.byt >ptn08
.byt >ptn09
.byt >ptn0a
.byt >ptn0b
.byt >ptn0c
.byt >ptn0d
.byt >ptn0e
.byt >ptn0f
.byt >ptn10
.byt >ptn11
.byt >ptn12
.byt >ptn13
.byt >ptn14
.byt >ptn15
.byt >ptn16
.byt >ptn17
.byt >ptn18
.byt >ptn19
.byt >ptn1a
.byt >ptn1b
.byt >ptn1c
.byt >ptn1d
.byt >ptn1e
.byt >ptn1f
.byt >ptn20
.byt >ptn21
.byt >ptn22
.byt >ptn23
.byt >ptn24
.byt >ptn25
.byt >ptn26
.byt >ptn27
.byt >ptn28
.byt >ptn29
.byt >ptn2a
.byt >ptn2b
.byt >ptn2c
.byt >ptn2d
.byt 0
.byt >ptn2f
.byt >ptn30
.byt >ptn31
.byt >ptn32
.byt >ptn33
.byt >ptn34
.byt >ptn35
.byt >ptn36
.byt >ptn37
.byt >ptn38
.byt >ptn39
.byt >ptn3a
.byt >ptn3b


;====================================
;tracks
;====================================

;track1
montymaintr1 =*
.byt $11,$14,$17,$1a,$00,$27,$00,$28
.byt $03,$05,$00,$27,$00,$28,$03,$05
.byt $07,$3a,$14,$17,$00,$27,$00,$28
.byt $2f,$30,$31,$31,$32,$33,$33,$34
.byt $34,$34,$34,$34,$34,$34,$34,$35
.byt $35,$35,$35,$35,$35,$36,$12,$37
.byt $38,$09,$2a,$09,$2b,$09,$0a,$09
.byt $2a,$09,$2b,$09,$0a,$0d,$0d,$0f
.byt $ff

;track2
montymaintr2 =*
.byt $12,$15,$18,$1b,$2d,$39,$39
.byt $39,$39,$39,$39,$2c,$39,$39,$39
.byt $39,$39,$39,$2c,$39,$39,$39,$01
.byt $01,$29,$29,$2c,$15,$18,$39,$39
.byt $39,$39,$39,$39,$39,$39,$39,$39
.byt $39,$39,$39,$39,$39,$39,$39,$39
.byt $39,$39,$39,$39,$39,$39,$39,$39
.byt $39,$39,$39,$39,$39,$01,$01,$01
.byt $29,$39,$39,$39,$01,$01,$01,$29
.byt $39,$39,$39,$39,$ff

;track3
montymaintr3 =*
.byt $13,$16,$19
.byt $1c,$02,$02,$1d,$1e,$02,$02,$1d
.byt $1f,$04,$04,$20,$20,$06,$02,$02
.byt $1d,$1e,$02,$02,$1d,$1f,$04,$04
.byt $20,$20,$06,$08,$08,$08,$08,$21
.byt $21,$21,$21,$22,$22,$22,$23,$22
.byt $24,$25,$3b,$26,$26,$26,$26,$26
.byt $26,$26,$26,$26,$26,$26,$26,$26
.byt $26,$26,$26,$02,$02,$1d,$1e,$02
.byt $02,$1d,$1f,$2f,$2f,$2f,$2f,$2f
.byt $2f,$2f,$2f,$2f,$2f,$2f,$2f,$2f
.byt $0b,$0b,$1d,$1d,$0b,$0b,$1d,$0b
.byt $0b,$0b,$0c,$0c,$1d,$1d,$1d,$10
.byt $0b,$0b,$1d,$1d,$0b,$0b,$1d,$0b
.byt $0b,$0b,$0c,$0c,$1d,$1d,$1d,$10
.byt $0b,$1d,$0b,$1d,$0b,$1d,$0b,$1d
.byt $0b,$0c,$1d,$0b,$0c,$23,$0b,$0b
.byt $ff


;====================================
;patterns
;====================================

ptn00 =*
.byt $83,$00,$37,$01,$3e,$01,$3e,$03
.byt $3d,$03,$3e,$03,$43,$03,$3e,$03
.byt $3d,$03,$3e,$03,$37,$01,$3e,$01
.byt $3e,$03,$3d,$03,$3e,$03,$43,$03
.byt $42,$03,$43,$03,$45,$03,$46,$01
.byt $48,$01,$46,$03,$45,$03,$43,$03
.byt $4b,$01,$4d,$01,$4b,$03,$4a,$03
.byt $48,$ff

ptn27 =*
.byt $1f,$4a,$ff

ptn28 =*
.byt $03,$46,$01,$48,$01,$46,$03,$45
.byt $03,$4a,$0f,$43,$ff

ptn03 =*
.byt $bf,$06
.byt $48,$07,$48,$01,$4b,$01,$4a,$01
.byt $4b,$01,$4a,$03,$4b,$03,$4d,$03
.byt $4b,$03,$4a,$3f,$48,$07,$48,$01
.byt $4b,$01,$4a,$01,$4b,$01,$4a,$03
.byt $4b,$03,$4d,$03,$4b,$03,$48,$3f
.byt $4c,$07,$4c,$01,$4f,$01,$4e,$01
.byt $4f,$01,$4e,$03,$4f,$03,$51,$03
.byt $4f,$03,$4e,$3f,$4c,$07,$4c,$01
.byt $4f,$01,$4e,$01,$4f,$01,$4e,$03
.byt $4f,$03,$51,$03,$4f,$03,$4c,$ff

ptn05 =*
.byt $83,$04,$26,$03,$29,$03,$28,$03
.byt $29,$03,$26,$03,$35,$03,$34,$03
.byt $32,$03,$2d,$03,$30,$03,$2f,$03
.byt $30,$03,$2d,$03,$3c,$03,$3b,$03
.byt $39,$03,$30,$03,$33,$03,$32,$03
.byt $33,$03,$30,$03,$3f,$03,$3e,$03
.byt $3c,$03,$46,$03,$45,$03,$43,$03
.byt $3a,$03,$39,$03,$37,$03,$2e,$03
.byt $2d,$03,$26,$03,$29,$03,$28,$03
.byt $29,$03,$26,$03,$35,$03,$34,$03
.byt $32,$03,$2d,$03,$30,$03,$2f,$03
.byt $30,$03,$2d,$03,$3c,$03,$3b,$03
.byt $39,$03,$30,$03,$33,$03,$32,$03
.byt $33,$03,$30,$03,$3f,$03,$3e,$03
.byt $3c,$03,$34,$03,$37,$03,$36,$03
.byt $37,$03,$34,$03,$37,$03,$3a,$03
.byt $3d

ptn3a =*
.byt $03,$3e,$07,$3e,$07,$3f,$07
.byt $3e,$03,$3c,$07,$3e,$57,$ff

ptn07 =*
.byt $8b
.byt $00,$3a,$01,$3a,$01,$3c,$03,$3d
.byt $03,$3f,$03,$3d,$03,$3c,$0b,$3a
.byt $03,$39,$07,$3a,$81,$06,$4b,$01
.byt $4d,$01,$4e,$01,$4d,$01,$4e,$01
.byt $4d,$05,$4b,$81,$00,$3a,$01,$3c
.byt $01,$3d,$03,$3f,$03,$3d,$03,$3c
.byt $03,$3a,$03,$39,$1b,$3a,$0b,$3b
.byt $01,$3b,$01,$3d,$03,$3e,$03,$40
.byt $03,$3e,$03,$3d,$0b,$3b,$03,$3a
.byt $07,$3b,$81,$06,$4c,$01,$4e,$01
.byt $4f,$01,$4e,$01,$4f,$01,$4e,$05
.byt $4c,$81,$00,$3b,$01,$3d,$01,$3e
.byt $03,$40,$03,$3e,$03,$3d,$03,$3b
.byt $03,$3a,$1b,$3b,$8b,$05,$35,$03
.byt $33,$07,$32,$03,$30,$03,$2f,$0b
.byt $30,$03,$32,$0f,$30,$0b,$35,$03
.byt $33,$07,$32,$03,$30,$03,$2f,$1f
.byt $30,$8b,$00,$3c,$01,$3c,$01,$3e
.byt $03,$3f,$03,$41,$03,$3f,$03,$3e
.byt $0b,$3d,$01,$3d,$01,$3f,$03,$40
.byt $03,$42,$03,$40,$03,$3f,$03,$3e
.byt $01,$3e,$01,$40,$03,$41,$03,$40
.byt $03,$3e,$03,$3d,$03,$3e,$03,$3c
.byt $03,$3a,$01,$3a,$01,$3c,$03,$3d
.byt $03,$3c,$03,$3a,$03,$39,$03,$3a
.byt $03,$3c,$ff

ptn09 =*
.byt $83,$00,$32,$01,$35,$01,$34,$03
.byt $32,$03,$35,$03,$34,$03,$32,$03
.byt $35,$01,$34,$01,$32,$03,$32,$03
.byt $3a,$03,$39,$03,$3a,$03,$32,$03
.byt $3a,$03,$39,$03,$3a,$ff

ptn2a =*
.byt $03,$34,$01,$37,$01,$35,$03,$34
.byt $03,$37,$03,$35,$03,$34,$03,$37
.byt $01,$35,$01,$34,$03,$34,$03,$3a
.byt $03,$39,$03,$3a,$03,$34,$03,$3a
.byt $03,$39,$03,$3a,$ff

ptn2b =*
.byt $03,$39,$03,$38,$03,$39,$03,$3a
.byt $03,$39,$03,$37,$03,$35,$03,$34
.byt $03,$35,$03,$34,$03,$35,$03,$37
.byt $03,$35,$03,$34,$03,$32,$03,$31
.byt $ff

ptn0a =*
.byt $03
.byt $37,$01,$3a,$01,$39,$03,$37,$03
.byt $3a,$03,$39,$03,$37,$03,$3a,$01
.byt $39,$01,$37,$03,$37,$03,$3e,$03
.byt $3d,$03,$3e,$03,$37,$03,$3e,$03
.byt $3d,$03,$3e,$03,$3d,$01,$40,$01
.byt $3e,$03,$3d,$03,$40,$01,$3e,$01
.byt $3d,$03,$40,$03,$3e,$03,$40,$03
.byt $40,$01,$43,$01,$41,$03,$40,$03
.byt $43,$01,$41,$01,$40,$03,$43,$03
.byt $41,$03,$43,$03,$43,$01,$46,$01
.byt $45,$03,$43,$03,$46,$01,$45,$01
.byt $43,$03,$46,$03,$45,$03,$43,$01
.byt $48,$01,$49,$01,$48,$01,$46,$01
.byt $45,$01,$46,$01,$45,$01,$43,$01
.byt $41,$01,$43,$01,$41,$01,$40,$01
.byt $3d,$01,$39,$01,$3b,$01,$3d,$ff

ptn0d =*
.byt $01,$3e,$01,$39,$01,$35,$01,$39
.byt $01,$3e,$01,$39,$01,$35,$01,$39
.byt $03,$3e,$01,$41,$01,$40,$03,$40
.byt $01,$3d,$01,$3e,$01,$40,$01,$3d
.byt $01,$39,$01,$3d,$01,$40,$01,$3d
.byt $01,$39,$01,$3d,$03,$40,$01,$43
.byt $01,$41,$03,$41,$01,$3e,$01,$40
.byt $01,$41,$01,$3e,$01,$39,$01,$3e
.byt $01,$41,$01,$3e,$01,$39,$01,$3e
.byt $03,$41,$01,$45,$01,$43,$03,$43
.byt $01,$40,$01,$41,$01,$43,$01,$40
.byt $01,$3d,$01,$40,$01,$43,$01,$40
.byt $01,$3d,$01,$40,$01,$46,$01,$43
.byt $01,$45,$01,$46,$01,$44,$01,$43
.byt $01,$40,$01,$3d,$ff

ptn0f =*
.byt $01,$3e,$01
.byt $39,$01,$35,$01,$39,$01,$3e,$01
.byt $39,$01,$35,$01,$39,$01,$3e,$01
.byt $39,$01,$35,$01,$39,$01,$3e,$01
.byt $39,$01,$35,$01,$39,$01,$3e,$01
.byt $3a,$01,$37,$01,$3a,$01,$3e,$01
.byt $3a,$01,$37,$01,$3a,$01,$3e,$01
.byt $3a,$01,$37,$01,$3a,$01,$3e,$01
.byt $3a,$01,$37,$01,$3a,$01,$40,$01
.byt $3d,$01,$39,$01,$3d,$01,$40,$01
.byt $3d,$01,$39,$01,$3d,$01,$40,$01
.byt $3d,$01,$39,$01,$3d,$01,$40,$01
.byt $3d,$01,$39,$01,$3d,$01,$41,$01
.byt $3e,$01,$39,$01,$3e,$01,$41,$01
.byt $3e,$01,$39,$01,$3e,$01,$41,$01
.byt $3e,$01,$39,$01,$3e,$01,$41,$01
.byt $3e,$01,$39,$01,$3e,$01,$43,$01
.byt $3e,$01,$3a,$01,$3e,$01,$43,$01
.byt $3e,$01,$3a,$01,$3e,$01,$43,$01
.byt $3e,$01,$3a,$01,$3e,$01,$43,$01
.byt $3e,$01,$3a,$01,$3e,$01,$43,$01
.byt $3f,$01,$3c,$01,$3f,$01,$43,$01
.byt $3f,$01,$3c,$01,$3f,$01,$43,$01
.byt $3f,$01,$3c,$01,$3f,$01,$43,$01
.byt $3f,$01,$3c,$01,$3f,$01,$45,$01
.byt $42,$01,$3c,$01,$42,$01,$45,$01
.byt $42,$01,$3c,$01,$42,$01,$48,$01
.byt $45,$01,$42,$01,$45,$01,$4b,$01
.byt $48,$01,$45,$01,$48,$01,$4b,$01
.byt $4a,$01,$48,$01,$4a,$01,$4b,$01
.byt $4a,$01,$48,$01,$4a,$01,$4b,$01
.byt $4a,$01,$48,$01,$4a,$01,$4c,$01
.byt $4e,$03,$4f,$ff

ptn11 =*
.byt $bf,$06,$56,$1f,$57,$1f,$56,$1f
.byt $5b,$1f,$56,$1f,$57,$1f,$56,$1f
.byt $4f,$ff

ptn12 =*
.byt $bf,$0c,$68,$7f,$7f,$7f,$7f,$7f
.byt $7f,$7f,$ff

ptn13 =*
.byt $bf,$08,$13,$3f,$13,$3f,$13,$3f
.byt $13,$3f,$13,$3f,$13,$3f,$13,$1f
.byt $13,$ff

ptn14 =*
.byt $97,$09,$2e,$03,$2e,$1b,$32,$03
.byt $32,$1b,$31,$03,$31,$1f,$34,$43
.byt $17,$32,$03,$32,$1b,$35,$03,$35
.byt $1b,$34,$03,$34,$0f,$37,$8f,$0a
.byt $37,$43,$ff

ptn15 =*
.byt $97,$09,$2b,$03,$2b,$1b,$2e,$03
.byt $2e,$1b,$2d,$03,$2d,$1f,$30,$43
.byt $17,$2e,$03,$2e,$1b,$32,$03,$32
.byt $1b,$31,$03,$31,$0f,$34,$8f,$0a
.byt $34,$43,$ff

ptn16 =*
.byt $0f,$1f,$0f,$1f,$0f,$1f,$0f,$1f
.byt $0f,$1f,$0f,$1f,$0f,$1f,$0f,$1f
.byt $0f,$1f,$0f,$1f,$0f,$1f,$0f,$1f
.byt $0f,$1f,$0f,$1f,$0f,$1f,$0f,$1f
.byt $ff

ptn17 =*
.byt $97,$09,$33,$03,$33,$1b,$37,$03
.byt $37,$1b,$36,$03,$36,$1f,$39,$43
.byt $17,$37,$03,$37,$1b,$3a,$03,$3a
.byt $1b,$39,$03,$39,$2f,$3c,$21,$3c
.byt $21,$3d,$21,$3e,$21,$3f,$21,$40
.byt $21,$41,$21,$42,$21,$43,$21,$44
.byt $01,$45,$ff

ptn18 =*
.byt $97,$09,$30,$03,$30,$1b,$33,$03
.byt $33,$1b,$32,$03,$32,$1f,$36,$43
.byt $17,$33,$03,$33,$1b,$37,$03,$37
.byt $1b,$36,$03,$36,$2f,$39,$21,$39
.byt $21,$3a,$21,$3b,$21,$3c,$21,$3d
.byt $21,$3e,$21,$3f,$21,$40,$21,$41
.byt $01,$42,$ff

ptn19 =*
.byt $0f,$1a,$0f,$1a,$0f,$1a,$0f,$1a
.byt $0f,$1a,$0f,$1a,$0f,$1a,$0f,$1a
.byt $0f,$1a,$0f,$1a,$0f,$1a,$0f,$1a
.byt $0f,$1a,$0f,$1a,$0f,$1a,$0f,$1a
.byt $ff

ptn1a =*
.byt $1f,$46,$bf,$0a,$46,$7f,$7f,$ff

ptn1b =*
.byt $1f,$43,$bf,$0a,$43,$7f,$ff

ptn1c =*
.byt $83,$02,$13,$03,$13,$03,$1e,$03
.byt $1f,$03,$13,$03,$13,$03,$1e,$03
.byt $1f,$03,$13,$03,$13,$03,$1e,$03
.byt $1f,$03,$13,$03,$13,$03,$1e,$03
.byt $1f,$03,$13,$03,$13,$03,$1e,$03
.byt $1f,$03,$13,$03,$13,$03,$1e,$03
.byt $1f,$03,$13,$03,$13,$03,$1e,$03
.byt $1f,$03,$13,$03,$13,$03,$1e,$03
.byt $1f,$ff

ptn29 =*
.byt $8f,$0b,$38,$4f,$ff

ptn2c =*
.byt $83,$0e,$32,$07,$32,$07,$2f,$07
.byt $2f,$03,$2b,$87,$0b,$46,$83,$0e
.byt $2c,$03,$2c,$8f,$0b,$32,$ff

ptn2d =*
.byt $43,$83,$0e,$32,$03,$32,$03,$2f
.byt $03,$2f,$03,$2c,$87,$0b,$38,$ff

ptn39 =*
.byt $83,$01
.byt $43,$01,$4f,$01,$5b,$87,$03,$2f
.byt $83,$01,$43,$01,$4f,$01,$5b,$87
.byt $03,$2f,$83,$01,$43,$01,$4f,$01
.byt $5b,$87,$03,$2f,$83,$01,$43,$01
.byt $4f,$01,$5b,$87,$03,$2f,$83,$01
.byt $43,$01,$4f,$01,$5b,$87,$03,$2f
.byt $83,$01,$43,$01,$4f,$01,$5b,$87
.byt $03,$2f

ptn01 =*
.byt $83,$01,$43,$01,$4f,$01,$5b,$87
.byt $03,$2f,$83,$01,$43,$01,$4f,$01
.byt $5b,$87,$03,$2f,$ff

ptn02 =*
.byt $83,$02,$13,$03,$13,$03,$1f,$03
.byt $1f,$03,$13,$03,$13,$03,$1f,$03
.byt $1f,$ff

ptn1d =*
.byt $03,$15,$03,$15,$03,$1f,$03,$21
.byt $03,$15,$03,$15,$03,$1f,$03,$21
.byt $ff

ptn1e =*
.byt $03,$1a,$03,$1a,$03,$1c,$03,$1c
.byt $03,$1d,$03,$1d,$03,$1e,$03,$1e
.byt $ff

ptn1f =*
.byt $03,$1a,$03,$1a,$03,$24,$03,$26
.byt $03,$13,$03,$13,$07,$1f,$ff

ptn04 =*
.byt $03,$18,$03,$18,$03,$24,$03,$24
.byt $03,$18,$03,$18,$03,$24,$03,$24
.byt $03,$20,$03,$20,$03,$2c,$03,$2c
.byt $03,$20,$03,$20,$03,$2c,$03,$2c
.byt $ff

ptn20 =*
.byt $03,$19,$03,$19,$03
.byt $25,$03,$25,$03,$19,$03,$19,$03
.byt $25,$03,$25,$03,$21,$03,$21,$03
.byt $2d,$03,$2d,$03,$21,$03,$21,$03
.byt $2d,$03,$2d,$ff

ptn06 =*
.byt $03,$1a,$03,$1a
.byt $03,$26,$03,$26,$03,$1a,$03,$1a
.byt $03,$26,$03,$26,$03,$15,$03,$15
.byt $03,$21,$03,$21,$03,$15,$03,$15
.byt $03,$21,$03,$21,$03,$18,$03,$18
.byt $03,$24,$03,$24,$03,$18,$03,$18
.byt $03,$24,$03,$24,$03,$1f,$03,$1f
.byt $03,$2b,$03,$2b,$03,$1f,$03,$1f
.byt $03,$2b,$03,$2b,$03,$1a,$03,$1a
.byt $03,$26,$03,$26,$03,$1a,$03,$1a
.byt $03,$26,$03,$26,$03,$15,$03,$15
.byt $03,$21,$03,$21,$03,$15,$03,$15
.byt $03,$21,$03,$21,$03,$18,$03,$18
.byt $03,$24,$03,$24,$03,$18,$03,$18
.byt $03,$24,$03,$24,$03,$1c,$03,$1c
.byt $03,$28,$03,$28,$03,$1c,$03,$1c
.byt $03,$28,$03,$28

ptn3b =*
.byt $83,$04,$36,$07
.byt $36,$07,$37,$07,$36,$03,$33,$07
.byt $32,$57,$ff

ptn08 =*
.byt $83,$02,$1b,$03,$1b,$03,$27,$03
.byt $27,$03,$1b,$03,$1b,$03,$27,$03
.byt $27,$ff

ptn21 =*
.byt $03,$1c,$03,$1c,$03,$28,$03,$28
.byt $03,$1c,$03,$1c,$03,$28,$03,$28
.byt $ff

ptn22 =*
.byt $03,$1d,$03,$1d,$03,$29,$03,$29
.byt $03,$1d,$03,$1d,$03,$29,$03,$29
.byt $ff

ptn23 =*
.byt $03,$18,$03,$18,$03,$24,$03,$24
.byt $03,$18,$03,$18,$03,$24,$03,$24
.byt $ff

ptn24 =*
.byt $03,$1e,$03,$1e,$03,$2a,$03,$2a
.byt $03,$1e,$03,$1e,$03,$2a,$03,$2a
.byt $ff

ptn25 =*
.byt $83,$05,$26,$01,$4a,$01,$34,$03
.byt $29,$03,$4c,$03,$4a,$03,$31,$03
.byt $4a,$03,$24,$03,$22,$01,$46,$01
.byt $30,$03,$25,$03,$48,$03,$46,$03
.byt $2d,$03,$46,$03,$24,$ff

ptn0b =*
.byt $83,$02,$1a,$03,$1a,$03,$26,$03
.byt $26,$03,$1a,$03,$1a,$03,$26,$03
.byt $26,$ff

ptn0c =*
.byt $03,$13,$03,$13,$03,$1d,$03,$1f
.byt $03,$13,$03,$13,$03,$1d,$03,$1f
.byt $ff

ptn26 =*
.byt $87,$02,$1a,$87,$03,$2f,$83,$02
.byt $26,$03,$26,$87,$03,$2f,$ff

ptn10 =*
.byt $07,$1a,$4f,$47,$ff

ptn0e =*
.byt $03,$1f,$03,$1f,$03,$24,$03,$26
.byt $07,$13,$47,$ff

ptn30 =*
.byt $bf,$0f,$32,$0f,$32,$8f,$90,$30
.byt $3f,$32,$13,$32,$03,$32,$03,$35
.byt $03,$37,$3f,$37,$0f,$37,$8f,$90
.byt $30,$3f,$32,$13,$32,$03,$2d,$03
.byt $30,$03,$32,$ff

ptn31 =*
.byt $0f,$32
.byt $af,$90,$35,$0f,$37,$a7,$99,$37
.byt $07,$35,$3f,$32,$13,$32,$03,$32
.byt $a3,$e8,$35,$03,$37,$0f,$35,$af
.byt $90,$37,$0f,$37,$a7,$99,$37,$07
.byt $35,$3f,$32,$13,$32,$03,$2d,$a3
.byt $e8,$30,$03,$32,$ff

ptn32 =*
.byt $07,$32,$03
.byt $39,$13,$3c,$a7,$9a,$37,$a7,$9b
.byt $38,$07,$37,$03,$35,$03,$32,$03
.byt $39,$1b,$3c,$a7,$9a,$37,$a7,$9b
.byt $38,$07,$37,$03,$35,$03,$32,$03
.byt $39,$03,$3c,$03,$3e,$03,$3c,$07
.byt $3e,$03,$3c,$03,$39,$a7,$9a,$37
.byt $a7,$9b,$38,$07,$37,$03,$35,$03
.byt $32,$af,$90,$3c,$1f,$3e,$43,$03
.byt $3e,$03,$3c,$03,$3e,$ff

ptn33 =*
.byt $03,$3e
.byt $03,$3e,$a3,$e8,$3c,$03,$3e,$03
.byt $3e,$03,$3e,$a3,$e8,$3c,$03,$3e
.byt $03,$3e,$03,$3e,$a3,$e8,$3c,$03
.byt $3e,$03,$3e,$03,$3e,$a3,$e8,$3c
.byt $03,$3e,$af,$91,$43,$1f,$41,$43
.byt $03,$3e,$03,$41,$03,$43,$03,$43
.byt $03,$43,$a3,$e8,$41,$03,$43,$03
.byt $43,$03,$43,$a3,$e8,$41,$03,$43
.byt $03,$45,$03,$48,$a3,$fd,$45,$03
.byt $44,$01,$43,$01,$41,$03,$3e,$03
.byt $3c,$03,$3e,$2f,$3e,$bf,$98,$3e
.byt $43,$03,$3e,$03,$3c,$03,$3e,$ff

ptn34 =*
.byt $03,$4a,$03,$4a,$a3,$f8,$48,$03
.byt $4a,$03,$4a,$03,$4a,$a3,$f8,$48
.byt $03,$4a,$ff

ptn35 =*
.byt $01,$51,$01,$54,$01
.byt $51,$01,$54,$01,$51,$01,$54,$01
.byt $51,$01,$54,$01,$51,$01,$54,$01
.byt $51,$01,$54,$01,$51,$01,$54,$01
.byt $51,$01,$54,$ff

ptn36 =*
.byt $01,$50,$01,$4f
.byt $01,$4d,$01,$4a,$01,$4f,$01,$4d
.byt $01,$4a,$01,$48,$01,$4a,$01,$48
.byt $01,$45,$01,$43,$01,$44,$01,$43
.byt $01,$41,$01,$3e,$01,$43,$01,$41
.byt $01,$3e,$01,$3c,$01,$3e,$01,$3c
.byt $01,$39,$01,$37,$01,$38,$01,$37
.byt $01,$35,$01,$32,$01,$37,$01,$35
.byt $01,$32,$01,$30,$ff

ptn37 =*
.byt $5f,$5f,$5f
.byt $47,$83,$0e,$32,$07,$32,$07,$2f
.byt $03,$2f,$07,$2f,$97,$0b,$3a,$5f
.byt $5f,$47,$8b,$0e,$32,$03,$32,$03
.byt $2f,$03,$2f,$47,$97,$0b,$3a,$5f
.byt $5f,$47,$83,$0e,$2f,$0b,$2f,$03
.byt $2f,$03,$2f,$87,$0b,$30,$17,$3a
.byt $5f,$8b,$0e,$32,$0b,$32,$0b,$2f
.byt $0b,$2f,$07,$2c,$07,$2c,$ff

ptn38 =*
.byt $87
.byt $0b,$34,$17,$3a,$5f,$5f,$84,$0e
.byt $32,$04,$32,$05,$32,$04,$2f,$04
.byt $2f,$05,$2f,$47,$97,$0b,$3a,$5f
.byt $5f,$84,$0e,$32,$04,$32,$05,$32
.byt $04,$2f,$04,$2f,$05,$2f,$ff

ptn2f =*
.byt $03,$1a,$03,$1a,$03
.byt $24,$03,$26,$03,$1a,$03,$1a,$03
.byt $18,$03,$19,$03,$1a,$03,$1a,$03
.byt $24,$03,$26,$03,$1a,$03,$1a,$03
.byt $18,$03,$19,$03,$18,$03,$18,$03
.byt $22,$03,$24,$03,$18,$03,$18,$03
.byt $16,$03,$17,$03,$18,$03,$18,$03
.byt $22,$03,$24,$03,$18,$03,$18,$03
.byt $16,$03,$17,$03,$13,$03,$13,$03
.byt $1d,$03,$1f,$03,$13,$03,$13,$03
.byt $1d,$03,$1e,$03,$13,$03,$13,$03
.byt $1d,$03,$1f,$03,$13,$03,$13,$03
.byt $1d,$03,$1e,$03,$1a,$03,$1a,$03
.byt $24,$03,$26,$03,$1a,$03,$1a,$03
.byt $18,$03,$19,$03,$1a,$03,$1a,$03
.byt $24,$03,$26,$03,$1a,$03,$1a,$03
.byt $18,$03,$19,$ff


;====================================
;instruments
;====================================

instr =*
.byt $80,$09,$41,$48,$60,$03,$81,$00
.byt $00,$08,$81,$02,$08,$00,$00,$01
.byt $a0,$02,$41,$09,$80,$00,$00,$00
.byt $00,$02,$81,$09,$09,$00,$00,$05
.byt $00,$08,$41,$08,$50,$02,$00,$04
.byt $00,$01,$41,$3f,$c0,$02,$00,$00
.byt $00,$08,$41,$04,$40,$02,$00,$00
.byt $00,$08,$41,$09,$00,$02,$00,$00
.byt $00,$09,$41,$09,$70,$02,$5f,$04
.byt $00,$09,$41,$4a,$69,$02,$81,$00
.byt $00,$09,$41,$40,$6f,$00,$81,$02
.byt $80,$07,$81,$0a,$0a,$00,$00,$01
.byt $00,$09,$41,$3f,$ff,$01,$e7,$02
.byt $00,$08,$41,$90,$f0,$01,$e8,$02
.byt $00,$08,$41,$06,$0a,$00,$00,$01
.byt $00,$09,$41,$19,$70,$02,$a8,$00
.byt $00,$02,$41,$09,$90,$02,$00,$00
.byt $00,$00,$11,$0a,$fa,$00,$00,$05
.byt $00,$08,$41,$37,$40,$02,$00,$00
.byt $00,$08,$11,$07,$70,$02,$00,$00

.end

← previous
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT