479 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			479 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
_runtimePath_ "../runtime"
 | 
						|
_runtimeStart_ &h7FFF
 | 
						|
_arraysStart_ &h7FFF
 | 
						|
 | 
						|
const X_POS = 34
 | 
						|
const Y_POS = 46
 | 
						|
const VU_LEVELS = 64
 | 
						|
 | 
						|
'frequency sweep
 | 
						|
const F_LUT=&h0500
 | 
						|
def word(F_LUT, y, 0.0, 360.0, 256) = sin(y)*2000.0 + 5000.0
 | 
						|
 | 
						|
'volume sweep
 | 
						|
const V_LUT=&h08A0
 | 
						|
const V_SIZ=64
 | 
						|
def byte(V_LUT, y, 0.0, 360.0, V_SIZ) = 63.0 - (cos(y)*0.5 + 0.5)*55.0
 | 
						|
 | 
						|
'extinction function, (modelled in Desmos), used to control attack and decay for crash sound
 | 
						|
'don't use variable names that clash with functions, i.e. 'x' and 'exp'
 | 
						|
const D_LUT=&h09A0
 | 
						|
const D_SIZ=64
 | 
						|
def byte(D_LUT, y, 0.0, 0.5, D_SIZ) = 63.0 - exp(-y)*(1.0-exp(-2.0*y))*2.5*58.0
 | 
						|
 | 
						|
const T_LUT=&h09E0
 | 
						|
const T_SIZ=8
 | 
						|
def byte(T_LUT, y, 0.0, 3.0, T_SIZ) = 63.0 - 1.398*exp(-y)*(1.0-exp(-10.0*y))*63.0
 | 
						|
 | 
						|
_spriteStripeChunks_ 32, &h0400, ascending
 | 
						|
load sprite, ../../res/image/VUerase.tga, 0
 | 
						|
load sprite, ../../res/image/VUdraw.tga, 1, FlipY
 | 
						|
 | 
						|
t = 0 : f = t : v = 0
 | 
						|
 | 
						|
'audio fix for ROMv5a
 | 
						|
poke &h21, peek(&h21) OR 3
 | 
						|
sound off
 | 
						|
set FGBG_COLOUR, &h3C00
 | 
						|
cls
 | 
						|
mode 2
 | 
						|
 | 
						|
at 33,2 : print "Keys: <1> to <0>"
 | 
						|
at 33 :   print "      <q> to <r>"
 | 
						|
 | 
						|
dim volume%(4) = 127
 | 
						|
dim ypos%(4) = 1
 | 
						|
 | 
						|
kk = 255
 | 
						|
state = 0
 | 
						|
 | 
						|
init midiv
 | 
						|
 | 
						|
loop:
 | 
						|
    'wait
 | 
						|
    set SOUND_TIMER, 2
 | 
						|
 | 
						|
    gosub vuMeter
 | 
						|
    
 | 
						|
    k = get("SERIAL_RAW")
 | 
						|
    if kk &&= 255 then gosub k
 | 
						|
    gosub state
 | 
						|
    kk = k
 | 
						|
goto &loop
 | 
						|
 | 
						|
midiOff:
 | 
						|
    set MIDI_STREAM, &h0000
 | 
						|
    sound off
 | 
						|
return
 | 
						|
 | 
						|
1:  gosub siren
 | 
						|
    return
 | 
						|
    
 | 
						|
2:  gosub crash
 | 
						|
    return
 | 
						|
 | 
						|
3:  gosub beep
 | 
						|
    return
 | 
						|
 | 
						|
4:  gosub tictoc
 | 
						|
    return
 | 
						|
 | 
						|
5:  gosub pucDeath
 | 
						|
    return
 | 
						|
 | 
						|
6:  gosub ghostMove
 | 
						|
    return
 | 
						|
 | 
						|
7:  gosub invaderMove
 | 
						|
    return
 | 
						|
 | 
						|
8:  gosub invaderShoot
 | 
						|
    return
 | 
						|
 
 | 
						|
9:  gosub saucerMove
 | 
						|
    return
 | 
						|
    
 | 
						|
10: gosub invaderExplode
 | 
						|
    return    
 | 
						|
 | 
						|
11: gosub testSfx
 | 
						|
    return
 | 
						|
 | 
						|
12: gosub saucerExplode
 | 
						|
    return
 | 
						|
    
 | 
						|
13: gosub playerExplode
 | 
						|
    return
 | 
						|
    
 | 
						|
14: if get("MIDI_STREAM") &= &h0000
 | 
						|
        play midiv, &h0AA0, 2
 | 
						|
    else
 | 
						|
        tick midiv
 | 
						|
    endif
 | 
						|
    return
 | 
						|
 | 
						|
 | 
						|
48: state = 14
 | 
						|
    return    
 | 
						|
    
 | 
						|
49: t = 0
 | 
						|
    state = 1
 | 
						|
    gosub midiOff
 | 
						|
    return
 | 
						|
 | 
						|
50: t = 0
 | 
						|
    state = 2
 | 
						|
    gosub midiOff
 | 
						|
    return
 | 
						|
    
 | 
						|
51: t = 0
 | 
						|
    state = 3
 | 
						|
    gosub midiOff
 | 
						|
    return
 | 
						|
 | 
						|
52: t = 0
 | 
						|
    state = 4
 | 
						|
    gosub midiOff
 | 
						|
    return
 | 
						|
 | 
						|
53: t = 0
 | 
						|
    state = 5 
 | 
						|
    gosub midiOff
 | 
						|
    return
 | 
						|
    
 | 
						|
54: t = 0
 | 
						|
    state = 6
 | 
						|
    gosub midiOff
 | 
						|
    return
 | 
						|
 | 
						|
55: t = 0
 | 
						|
    f = 0
 | 
						|
    vv = 63
 | 
						|
    state = 7
 | 
						|
    gosub midiOff
 | 
						|
    return
 | 
						|
 | 
						|
56: t = 0
 | 
						|
    state = 8
 | 
						|
    gosub midiOff
 | 
						|
    return
 | 
						|
 | 
						|
57: t = 0
 | 
						|
    f = 0
 | 
						|
    vv = 63
 | 
						|
    state = 9
 | 
						|
    gosub midiOff
 | 
						|
    return
 | 
						|
 | 
						|
113:t = 0
 | 
						|
    f = 0
 | 
						|
    vv = 63
 | 
						|
    state = 10
 | 
						|
    gosub midiOff
 | 
						|
    return
 | 
						|
 | 
						|
119:t = 0
 | 
						|
    f = 0
 | 
						|
    vv = 63
 | 
						|
    state = 11
 | 
						|
    gosub midiOff
 | 
						|
    return
 | 
						|
  
 | 
						|
101:t = 0
 | 
						|
    f = 0
 | 
						|
    vv = 60
 | 
						|
    state = 12
 | 
						|
    gosub midiOff
 | 
						|
    return
 | 
						|
 | 
						|
114:t = 0
 | 
						|
    f = 0
 | 
						|
    vv = 63
 | 
						|
    state = 13
 | 
						|
    gosub midiOff
 | 
						|
    return
 | 
						|
    
 | 
						|
    
 | 
						|
vuMeter:
 | 
						|
    for i=1 to 4
 | 
						|
        i8 = i LSL 8
 | 
						|
        v = peek(i8 + &h00FA)
 | 
						|
        vol = volume(i)
 | 
						|
        y = ypos(i)
 | 
						|
        
 | 
						|
        if v &>= VU_LEVELS
 | 
						|
            i4 = (i LSL 4) + X_POS
 | 
						|
            if deek(i8 + &h00FC) &= 0 then goto decay 'if frequency is 0, (i.e. note off), then decay
 | 
						|
            if v &< vol
 | 
						|
                y = ((VU_LEVELS-1) - (v - VU_LEVELS)) LSR 1 'transform 127->64 to 0->63
 | 
						|
                vol = v
 | 
						|
            else
 | 
						|
decay:
 | 
						|
                dec y
 | 
						|
                inc vol
 | 
						|
                if y &< 1
 | 
						|
                    inc y
 | 
						|
                    dec vol
 | 
						|
                endif
 | 
						|
            endif
 | 
						|
            
 | 
						|
            'erase led
 | 
						|
            sprite noFlip, 0, i4, (Y_POS + 32) - (y + 1)
 | 
						|
            
 | 
						|
            'adjust height of led bar
 | 
						|
            lut = (y LSL 2) + y + y + get("SPRITE_LUT", 1)
 | 
						|
            save = peek(lut)
 | 
						|
            poke lut, -1
 | 
						|
            sprite flipY, 1, i4, Y_POS
 | 
						|
            sprite flipY, 1, i4 + 6, Y_POS
 | 
						|
            poke lut, save
 | 
						|
        endif
 | 
						|
        
 | 
						|
        volume(i) = vol
 | 
						|
        ypos(i) = y
 | 
						|
    next i
 | 
						|
return
 | 
						|
 | 
						|
siren:
 | 
						|
    v_lut = peek(V_LUT + (t AND (V_SIZ - 1)))
 | 
						|
    f_lut = deek(F_LUT + (t LSL 1))
 | 
						|
    sound on, 1, f_lut    , v_lut, 2 
 | 
						|
    sound on, 2, f_lut+100, v_lut, 2
 | 
						|
    sound on, 3, f_lut+200, v_lut, 2
 | 
						|
    sound on, 4, f_lut+300, v_lut, 2
 | 
						|
    inc t
 | 
						|
    if t &= 64
 | 
						|
        t = 0
 | 
						|
        state = 0
 | 
						|
        sound off
 | 
						|
    endif
 | 
						|
return
 | 
						|
 | 
						|
crash:
 | 
						|
    d_lut = peek(D_LUT + (t AND (D_SIZ - 1)))
 | 
						|
    f_lut = deek(F_LUT + ((t AND 1) LSL 1))
 | 
						|
    sound on, 1, f_lut    , d_lut, 0
 | 
						|
    sound on, 2, f_lut+100, d_lut, 0
 | 
						|
    sound on, 3, f_lut+200, d_lut, 0
 | 
						|
    sound on, 4, f_lut+300, d_lut, 0
 | 
						|
    inc t
 | 
						|
    if t &= 64
 | 
						|
        t = 0
 | 
						|
        state = 0
 | 
						|
        sound off
 | 
						|
    endif
 | 
						|
return
 | 
						|
 | 
						|
beep:
 | 
						|
    sound on, 1, 8000, 63, 1
 | 
						|
    inc t
 | 
						|
    if t &= 3
 | 
						|
        t = 0
 | 
						|
        state = 0
 | 
						|
        sound off
 | 
						|
    endif
 | 
						|
return
 | 
						|
 | 
						|
tictoc:
 | 
						|
    t_lut = peek(T_LUT + (t AND (T_SIZ - 1)))
 | 
						|
    sound on, 1, t_lut LSL 4, t_lut, 0
 | 
						|
 | 
						|
    inc t
 | 
						|
    if t &= T_SIZ-2
 | 
						|
        t = 0
 | 
						|
        state = 0
 | 
						|
        sound off
 | 
						|
    endif
 | 
						|
return
 | 
						|
 | 
						|
 | 
						|
dim pnotes%(15) = 74, 72, 71, 69, 67, 65, 64, 62, 60, 62, 64, 65, 67, 69, 71, 72
 | 
						|
def byte(&h0701, x, 0.0, 1.0, 64, 4) = sin(pow(x + 1.8, 3.13)*57.2957795)*31.0 + 32.0
 | 
						|
'def byte(&h0701, y, 0.0, 1.0, 64, 4) = (sin(pow(y + 1.8, 3.13)*57.2957795)*exp(-1.5*y)*1.2)*31.0 + 32.0
 | 
						|
'def byte(&h0701, y, 0.0, 1.0, 64, 4) = sin(pow(y + 1.8, 3.13)*57.2957795)*(1-y)*31.0 + 32.0
 | 
						|
pucDeath:
 | 
						|
    n = get("MIDI_NOTE", peek(@pnotes + (t AND 15)))
 | 
						|
    sound on, 1, n - f, 63 - (t LSR 2), 1
 | 
						|
    inc t
 | 
						|
    if (t AND 7) &= 0
 | 
						|
        f = f + 200
 | 
						|
    endif
 | 
						|
    if t &= 128
 | 
						|
        t = 0
 | 
						|
        f = 0
 | 
						|
        state = 0
 | 
						|
        sound off
 | 
						|
    endif
 | 
						|
return
 | 
						|
 | 
						|
dim gnotes%(15) = 60, 62, 64, 65, 67, 69, 71, 72, 74, 72, 71, 69, 67, 65, 64, 62
 | 
						|
ghostMove:
 | 
						|
    n = get("MIDI_NOTE", peek(@gnotes + (t AND 15)) + 10)
 | 
						|
    sound on, 1, n, 63, 2
 | 
						|
    inc t
 | 
						|
    if t &= 128
 | 
						|
        t = 0
 | 
						|
        state = 0
 | 
						|
        sound off
 | 
						|
    endif
 | 
						|
return
 | 
						|
 | 
						|
'overwrite waveform 0 in audio memory, (invader move)
 | 
						|
'load wave, ../../res/audio/Invader/IMove.gtwav, &h0702, 4
 | 
						|
dim inotes%(3) = 40, 38, 36, 34
 | 
						|
vv = 0
 | 
						|
invaderMove:
 | 
						|
    n = get("MIDI_NOTE", peek(@inotes + (f AND 3)))    
 | 
						|
    sound on, 1, n, vv, 3
 | 
						|
    inc t
 | 
						|
    if t &= 25
 | 
						|
        t = 0
 | 
						|
        vv = 63
 | 
						|
        inc f
 | 
						|
        if f &= 4
 | 
						|
            f = 0
 | 
						|
            state = 0
 | 
						|
            sound off
 | 
						|
        endif
 | 
						|
    elseif t &= 4
 | 
						|
        vv = 0
 | 
						|
    endif
 | 
						|
return
 | 
						|
 | 
						|
const I_LUT=&h6EA0
 | 
						|
const IF_LUT=&h6DA0
 | 
						|
const I_SIZ=32
 | 
						|
'def word(I_LUT, y, 0.0, 1.0, I_SIZ) = (10.0*exp(-15.0*y)*(1.0-exp(-9.75*(y-0.015)))*0.343 + 0.25)*25000.0
 | 
						|
def byte(I_LUT, y, 0.0, 1.0, I_SIZ) = exp(-5.0*pow(y, 3.0))*32.0
 | 
						|
'def byte(I_LUT, y, 0.0, 10.0, I_SIZ) = exp(-0.2*y)*(sin(15.0*y/6.28*360.0)*0.25 + 0.75)*32.0
 | 
						|
def word(IF_LUT, y, 0.0, 1.0, I_SIZ) = exp(-3.0*y)*6000.0 + 14000.0
 | 
						|
invaderShootOld:
 | 
						|
    ff = max(25000 - f, 13000)
 | 
						|
    sound on, 1, ff, vv, 2
 | 
						|
    'sound on, 1, deek(I_LUT + (t AND 31)), vv, 2
 | 
						|
    inc t
 | 
						|
    vv = vv - 2
 | 
						|
    if vv &<= 0
 | 
						|
        t = 0
 | 
						|
        vv = 63
 | 
						|
        state = 0
 | 
						|
        sound off
 | 
						|
    endif
 | 
						|
return
 | 
						|
 | 
						|
invaderShoot:
 | 
						|
    ff = deek(IF_LUT + ((t AND 31) LSL 1))
 | 
						|
    vvv = peek(I_LUT + (t AND 31))
 | 
						|
    sound on, 1, ff, vvv, 3
 | 
						|
    sound on, 2, ff, vvv, 0
 | 
						|
    inc t
 | 
						|
    if t &= 32
 | 
						|
        t = 0
 | 
						|
        state = 0
 | 
						|
        sound off
 | 
						|
    endif
 | 
						|
return
 | 
						|
 | 
						|
const SF_LUT=&h6CA0
 | 
						|
const SF_SIZ=12
 | 
						|
'def word(SF_LUT, y, 0.0, 360.0, SF_SIZ) = (sin(y)*0.5 + 0.5) * 5000.0
 | 
						|
'def word(SF_LUT, y, 0.5, 1.5, SF_SIZ) = sin(exp(-pow(4.0*y - 4.0, 2.0))/6.28*360) * 5000.0
 | 
						|
'def word(SF_LUT, y, 0.0, 180.0, SF_SIZ) = sin(y) * sin(y) * 2121.0 + 2121.0
 | 
						|
def word(SF_LUT, y, 0.0, SF_SIZ, SF_SIZ) = (y % (SF_SIZ/2)) * 300.0 + 3000.0
 | 
						|
'def word(SF_LUT, y, 0.0, 360, SF_SIZ) = (asin(cos(y))/90.0*0.5 + 0.5) * 300.0 + 3000.0
 | 
						|
'def byte(&h0702, x, 0.0, 360.0, 64, 4) = sin(x)*31.0 + 32.0
 | 
						|
saucerMove:
 | 
						|
    ff = deek(SF_LUT + (t LSL 1))
 | 
						|
    sound on, 1, ff, 32, 2
 | 
						|
    inc t
 | 
						|
    if t &= SF_SIZ
 | 
						|
        t = 0
 | 
						|
    endif
 | 
						|
return
 | 
						|
 | 
						|
const IE_LUT=&h6BA0
 | 
						|
const IE_SIZ=3
 | 
						|
'def word(IE_LUT, y, 0.0, 1.0, IE_SIZ) = exp(-3.0*y)*5000.0
 | 
						|
'def word(IE_LUT, y, 0.0, 720.0, IE_SIZ) = sin(y) * sin(y) * 1000.0 + 500
 | 
						|
'def word(IE_LUT, y, 0.0, 360, IE_SIZ) = (asin(cos(y))/90.0*0.5 + 0.5) * 3000.0 + 3000.0
 | 
						|
def word(IE_LUT, y, 0.0, IE_SIZ, IE_SIZ) = 6000.0*(1 - exp(-0.5*y))
 | 
						|
'def byte(&h0702, x, 0.0, 720.0, 64, 4) = sin(x)*31.0 + 32.0
 | 
						|
invaderExplode:
 | 
						|
    sound on, 1, deek(IE_LUT + (t LSL 1)), vv, 2
 | 
						|
    inc t
 | 
						|
    if t &= IE_SIZ then t = 0
 | 
						|
    vv = vv - 2
 | 
						|
    if vv &<= 0
 | 
						|
        t = 0
 | 
						|
        vv = 60
 | 
						|
        state = 0
 | 
						|
        sound off
 | 
						|
    endif
 | 
						|
return
 | 
						|
 | 
						|
testSfx:
 | 
						|
    ff = 16384 - (vv LSL 8) + f
 | 
						|
    sound on, 1, ff, vv, 2
 | 
						|
    inc t
 | 
						|
    vv = vv - 8
 | 
						|
    if vv &<= 0
 | 
						|
        t = 0
 | 
						|
        vv = 63
 | 
						|
        f = f + 1000
 | 
						|
        if f &= 4000
 | 
						|
            f = 0
 | 
						|
            state = 0
 | 
						|
            sound off
 | 
						|
        endif
 | 
						|
    endif
 | 
						|
return
 | 
						|
 | 
						|
const SEF_LUT=&h69A0
 | 
						|
const SEF_SIZ=12
 | 
						|
'def word(SEF_LUT, y, 0.0, 180.0, SEF_SIZ) = sin(y) * sin(y) * 2121.0 + 2121.0
 | 
						|
def word(SEF_LUT, y, 0.0, SEF_SIZ, SEF_SIZ) = (y % (SEF_SIZ/2)) * 300.0 + 3000.0
 | 
						|
saucerExplode:
 | 
						|
    m = min(vv + 10, 63)
 | 
						|
    ff = deek(SEF_LUT + (t LSL 1)) - f
 | 
						|
    sound on, 1, ff, vv, 2
 | 
						|
    sound on, 2, ff LSR 4, vv, 0
 | 
						|
    inc t
 | 
						|
    if t &= SEF_SIZ
 | 
						|
        t = 0
 | 
						|
        f = f + 600
 | 
						|
        vv = vv - 15
 | 
						|
        if vv &<= 0
 | 
						|
            f = 0
 | 
						|
            vv = 60
 | 
						|
            state = 0
 | 
						|
            sound off
 | 
						|
        endif
 | 
						|
    endif
 | 
						|
return
 | 
						|
 | 
						|
const PEF_LUT=&h6AA0
 | 
						|
const PEF_SIZ=32
 | 
						|
'def word(PEF_LUT, y, 0.0, 180.0, PEF_SIZ) = sin(y) * sin(y) * 2121.0 + 2121.0
 | 
						|
'def word(PEF_LUT, y, 0.0, PEF_SIZ, PEF_SIZ) = (y % (PEF_SIZ/2)) * 300.0 + 3000.0
 | 
						|
'def word(PEF_LUT, y, 0.0, 360, PEF_SIZ) = (asin(cos(y))/90.0*0.5 + 0.5) * 300.0 + 300.0
 | 
						|
'def word(PEF_LUT, y, 0.0, PEF_SIZ, PEF_SIZ) = 900.0*(exp(-1.125*y)) + 300.0
 | 
						|
def word(PEF_LUT, 0.0, PEF_SIZ, PEF_SIZ) = rand(PEF_SIZ) / PEF_SIZ * 300.0
 | 
						|
playerExplode:
 | 
						|
    f = deek(PEF_LUT + (t LSL 1))
 | 
						|
    sound on, 1, f, vv, 0
 | 
						|
    sound on, 2, f, vv, 0
 | 
						|
    sound on, 3, f, vv, 0
 | 
						|
    sound on, 4, f, vv, 0
 | 
						|
    inc t
 | 
						|
    if t &= PEF_SIZ then t = 0
 | 
						|
    vv = vv - 1
 | 
						|
    if vv &<= 0
 | 
						|
        t = 0
 | 
						|
        vv = 60
 | 
						|
        state = 0
 | 
						|
        sound off
 | 
						|
    endif
 | 
						|
return
 | 
						|
 | 
						|
module "MidiFx.i"
 |