{{ ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ SIDcog - SID/MOS8580 emulator V0.80 (C) 2010-02 Johannes Ahlebrand │ ├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │ TERMS OF USE: Parallax Object Exchange License │ ├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │ │files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │ │modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│ │is furnished to do so, subject to the following conditions: │ │ │ │The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│ │ │ │THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │ │WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │ │COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │ │ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ }} { 11-07-2010-dr235 - änderung in setWaveform } CON PAL = 985248.0 NTSC = 1022727.0 MAXF = 1031000.0 TRIANGLE = 16 SAW = 32 SQUARE = 64 NOISE = 128 C64_CLOCK_FREQ = PAL ' ___ CUTOFF_LIMIT = 1300' │ LP_MAX_CUTOFF = 10' │ BP_MAX_CUTOFF = 11' │ Don't alter these unless you know what you are doing. ;) FILTER_OFFSET = 27' │ DECAY_DIVIDE_REF = $6C6C6C6C' │ NOISE_ADD = $979D21B5' │ NOISE_ROTATE = 28' ___│ PUB start(right,left) arg1 := $18000000 | left arg2 := $18000000 | right r1 := ((1<>3 PUB setFilterMask(ch1,ch2,ch3) byte[@Filter3] := (byte[@Filter3]&$F0) | (ch1&1) | (ch2&2) | (ch3&4) PUB setFilterType(lp,bp,hp) byte[@volume] := (byte[@volume]&$0F) | (lp&16) | (bp&32) | (hp&64) PUB enableRingmod(ch1,ch2,ch3) byte[@ch1_controlRegister] := (byte[@ch1_controlRegister]&$FB) | (ch1&4) byte[@ch2_controlRegister] := (byte[@ch2_controlRegister]&$FB) | (ch2&4) byte[@ch3_controlRegister] := (byte[@ch3_controlRegister]&$FB) | (ch3&4) PUB enableSynchronization(ch1,ch2,ch3) byte[@ch1_controlRegister] := (byte[@ch1_controlRegister]&$FD) | (ch1&2) byte[@ch2_controlRegister] := (byte[@ch2_controlRegister]&$FD) | (ch2&2) byte[@ch3_controlRegister] := (byte[@ch3_controlRegister]&$FD) | (ch3&2) dat org 0 ' ' Assembly SID emulator ' SIDEMU mov dira, r1 mov ctra, arg1 mov ctrb, arg2 mov waitCounter, cnt add waitCounter, sampleRate '----------------------------------------------------------- mainLoop call #getRegisters call #SID call #filter call #mixer jmp #mainLoop '----------------------------------------------------------- ' ' Read all SID-registers from hub memory and convert ' them to more convenient representations. ' getRegisters mov tempValue, par ' Read in first long ( 16bit frequency / 16bit pulse-width ) rdlong frequency1, tempValue mov pulseWidth1, frequency1 shl pulseWidth1, #4 ' Shift in "12 bit" pulse width value( make it 32 bits ) andn pulseWidth1, mask20bit and frequency1, mask16bit ' Mask out 16 bit frequency value shl frequency1, #13 '----------------------------------------------------------- add tempValue, #4 ' Read in next long ( Control register / ADSR ) rdlong selectedWaveform1, tempValue mov controlRegister1, selectedWaveform1 '----------------------------------------------------------- mov arg1, selectedWaveform1 '| shr arg1, #8 '| call #getDecay '| mov decay1, r1 '| shr arg1, #4 '| call #getAttack '| mov attack1, r1 '| Convert 4bit ADSR "presets" to their corresponding shr arg1, #4 '| 32bit values using attack/decay tables. call #getDecay '| mov release1, r1 '| mov sustain1, selectedWaveform1 '| shl sustain1, #8 '| andn sustain1, mask28bit '| '----------------------------------------------------------- shr selectedWaveform1, #4 ' Mask out waveform selection and selectedWaveform1, #15 wz, wc '----------------------------------------------------------- test controlRegister1, #1 wc cmp envelopeState1, #2 wz if_z_and_c mov envelopeState1, #0 if_nz_and_nc mov envelopeState1, #2 '─────────────────────────────────────────────────────────── ' Channel 2 '─────────────────────────────────────────────────────────── add tempValue, #4 ' Read in first long ( 16bit frequency / 16bit pulse-width ) rdlong frequency2, tempValue mov pulseWidth2, frequency2 shl pulseWidth2, #4 ' Shift in "12 bit" pulse width value( make it 32 bits ) andn pulseWidth2, mask20bit and frequency2, mask16bit ' Mask out 16 bit frequency value shl frequency2, #13 '----------------------------------------------------------- add tempValue, #4 ' Read in next long ( Control register / ADSR ) rdlong selectedWaveform2, tempValue mov controlRegister2, selectedWaveform2 '----------------------------------------------------------- mov arg1, selectedWaveform2 '| shr arg1, #8 '| call #getDecay '| mov decay2, r1 '| shr arg1, #4 '| call #getAttack '| mov attack2, r1 '| Convert 4bit ADSR "presets" to their corresponding shr arg1, #4 '| 32bit values using attack/decay tables. call #getDecay '| mov release2, r1 '| mov sustain2, selectedWaveform2 '| shl sustain2, #8 '| andn sustain2, mask28bit '| '----------------------------------------------------------- shr selectedWaveform2, #4 ' Mask out waveform selection and selectedWaveform2, #15 wz, wc '----------------------------------------------------------- test controlRegister2, #1 wc cmp envelopeState2, #2 wz if_z_and_c mov envelopeState2, #0 if_nz_and_nc mov envelopeState2, #2 '─────────────────────────────────────────────────────────── ' Channel 3 '─────────────────────────────────────────────────────────── add tempValue, #4 ' Read in first long ( 16bit frequency / 16bit pulse-width ) rdlong frequency3, tempValue ' mov pulseWidth3, frequency3 shl pulseWidth3, #4 ' Shift in "12 bit" pulse width value( make it 32 bits ) andn pulseWidth3, mask20bit and frequency3, mask16bit ' Mask out 16 bit frequency value shl frequency3, #13 '----------------------------------------------------------- add tempValue, #4 ' Read in next long ( Control register / ADSR ) rdlong selectedWaveform3, tempValue mov controlRegister3, selectedWaveform3 '----------------------------------------------------------- mov arg1, selectedWaveform3 '| shr arg1, #8 '| call #getDecay '| mov decay3, r1 '| shr arg1, #4 '| call #getAttack '| mov attack3, r1 '| Convert 4bit ADSR "presets" to their corresponding shr arg1, #4 '| 32bit values using attack/decay tables. call #getDecay '| mov release3, r1 '| mov sustain3, selectedWaveform3 '| shl sustain3, #8 '| andn sustain3, mask28bit '| '----------------------------------------------------------- shr selectedWaveform3, #4 ' Mask out waveform selection and selectedWaveform3, #15 wz, wc '----------------------------------------------------------- test controlRegister3, #1 wc cmp envelopeState3, #2 wz if_z_and_c mov envelopeState3, #0 if_nz_and_nc mov envelopeState3, #2 '─────────────────────────────────────────────────────────── ' Filter / Volume '─────────────────────────────────────────────────────────── add tempValue, #4 '| rdlong filterControl, tempValue '| mov filterCutoff, filterControl '| '----------------------------------------------------------- shr filterControl, #16 '| Filter control '----------------------------------------------------------- shr filterCutoff, #5 '| andn filterCutoff, #7 '| mov tempValue, filterControl '| and tempValue, #7 '| Filter cutoff frequency or filterCutoff, tempValue '| and filterCutoff, mask11bit '| add filterCutoff, filterOffset '| '----------------------------------------------------------- mov filterMode_Volume, filterControl '| Main volume and filter mode shr filterMode_Volume, #8 '| '----------------------------------------------------------- mov filterResonance,filterControl '| and filterResonance,#$F0 '| shr filterResonance,#5 '| add filterResonance,#resTable '| Filter Resonance level (Ariba) movs rdRes,filterResonance '| nop '| rdRes mov filterResonance,0-0 '| getRegisters_ret ret ' ' Calculate sid samples channel 1-3 and store in out1-out3 ' '─────────────────────────────────────────────────────────── ' Increment phase accumulator 1-3 and handle syncing '─────────────────────────────────────────────────────────── SID add phaseAccumulator1, frequency1 wc ' Add frequency value to phase accumulator 1 if_nc andn controlRegister2, #2 test controlRegister2, #10 wz ' Sync oscilator 2 to oscilator 1 if sync = on if_nz mov phaseAccumulator2, #0 ' Or reset counter 2 when bit 4 of control register is 1 '----------------------------------------------------------- add phaseAccumulator2, frequency2 wc if_nc andn controlRegister3, #2 test controlRegister3, #10 wz ' Sync oscilator 3 to oscilator 2 if sync = on if_nz mov phaseAccumulator3, #0 ' Or reset oscilator 3 when bit 4 of control register is 1 '----------------------------------------------------------- add phaseAccumulator3, frequency3 wc if_nc andn controlRegister1, #2 test controlRegister1, #10 wz ' Sync oscilator 1 to oscilator 3 if sync = on if_nz mov phaseAccumulator1, #0 ' Or reset oscilator 1 when bit 4 of control register is 1 '─────────────────────────────────────────────────────────── ' Waveform shaping channel 1 -> arg1 '─────────────────────────────────────────────────────────── Triangle1 tjz selectedWaveform1, #Triangle2 cmp selectedWaveform1, #1 wz if_nz jmp #Saw1 abs arg1, phaseAccumulator1 max arg1, mask31bit test controlRegister1, #4 wc '| if_c test phaseAccumulator3, val31bit wc '| These 3 lines handles ring modulation if_c xor arg1, mask32bit '| shl arg1, #1 jmp #Env_Attack1 '----------------------------------------------------------- Saw1 cmp selectedWaveform1, #2 wz if_z mov arg1, phaseAccumulator1 if_z jmp #Env_Attack1 '----------------------------------------------------------- Square1 cmp selectedWaveform1, #4 wz if_z sub pulseWidth1, phaseAccumulator1 wc ' C holds the pulse width modulated square wave if_z muxc arg1, mask32bit if_z jmp #Env_Attack1 '----------------------------------------------------------- Noise1 cmp selectedWaveform1, #8 wz if_nz jmp #Combined1 mov tempValue, phaseAccumulator1 and tempValue, mask28bit sub tempValue, frequency1 wc if_z_and_c ror noiseValue1, NOISE_ROTATE if_z_and_c add noiseValue1, noiseAdd if_z mov arg1, noiseValue1 jmp #Env_Attack1 '----------------------------------------------------------- Combined1 sub selectedWaveform1, #4 mins selectedWaveform1, #0 shl selectedWaveform1, #8 mov tempValue, phaseAccumulator1 shr tempValue, #24 add selectedWaveform1, tempValue add selectedWaveform1, combTableAddr rdbyte arg1, selectedWaveform1 shl arg1, #24 '─────────────────────────────────────────────────────────── ' Envelope shaping channel 1 -> arg2 '─────────────────────────────────────────────────────────── Env_Attack1 cmp envelopeState1, #0 wz if_nz jmp #InitDecay1 add envelopeLevel1, attack1 wc if_c mov envelopeLevel1, mask32bit if_c mov envelopeState1, #1 mov decayDivide1, #0 jmp #Amplitude1 '----------------------------------------------------------- InitDecay1 mov tempValue, decayDivideRef shr tempValue, decayDivide1 cmp envelopeLevel1, tempValue wc if_c add decayDivide1, #1 '----------------------------------------------------------- Env_Decay1 cmp envelopeState1, #1 wz if_nz jmp #Env_Release1 shr decay1, decayDivide1 sub envelopeLevel1, decay1 min envelopeLevel1, sustain1 wc jmp #Amplitude1 '----------------------------------------------------------- Env_Release1 cmp envelopeState1, #2 wz if_nz jmp #Amplitude1 shr release1, decayDivide1 cmpsub envelopeLevel1, release1 '─────────────────────────────────────────────────────────── 'Calculate sample out1 = arg1 * arg2 (waveform * amplitude) '─────────────────────────────────────────────────────────── Amplitude1 shr arg1, #16 sub arg1, val15bit mov arg2, envelopeLevel1 shr arg2, #22 call #multiply mov out1, r1 '─────────────────────────────────────────────────────────── ' Waveform shaping channel 2 -> arg1 '─────────────────────────────────────────────────────────── Triangle2 tjz selectedWaveform2, #Triangle3 cmp selectedWaveform2, #1 wz if_nz jmp #Saw2 abs arg1, phaseAccumulator2 max arg1, mask31bit test controlRegister2, #4 wc '| if_c test phaseAccumulator1, val31bit wc '| These 3 lines handles ring modulation if_c xor arg1, mask32bit '| shl arg1, #1 jmp #Env_Attack2 '----------------------------------------------------------- Saw2 cmp selectedWaveform2, #2 wz if_z mov arg1, phaseAccumulator2 if_z jmp #Env_Attack2 '----------------------------------------------------------- Square2 cmp selectedWaveform2, #4 wz if_z sub pulseWidth2, phaseAccumulator2 wc ' C holds the pulse width modulated square wave if_z muxc arg1, mask32bit if_z jmp #Env_Attack2 '----------------------------------------------------------- Noise2 cmp selectedWaveform2, #8 wz if_nz jmp #Combined2 mov tempValue, phaseAccumulator2 and tempValue, mask28bit sub tempValue, frequency2 wc if_z_and_c ror noiseValue2, NOISE_ROTATE if_z_and_c add noiseValue2, noiseAdd if_z mov arg1, noiseValue2 jmp #Env_Attack2 '----------------------------------------------------------- Combined2 sub selectedWaveform2, #4 mins selectedWaveform2, #0 shl selectedWaveform2, #8 mov tempValue, phaseAccumulator2 shr tempValue, #24 add selectedWaveform2, tempValue add selectedWaveform2, combTableAddr rdbyte arg1, selectedWaveform2 shl arg1, #24 '─────────────────────────────────────────────────────────── ' Envelope shaping channel 2 -> arg2 '─────────────────────────────────────────────────────────── Env_Attack2 cmp envelopeState2, #0 wz if_nz jmp #InitDecay2 add envelopeLevel2, attack2 wc if_c mov envelopeLevel2, mask32bit if_c mov envelopeState2, #1 mov decayDivide2, #0 jmp #Amplitude2 '----------------------------------------------------------- InitDecay2 mov tempValue, decayDivideRef shr tempValue, decayDivide2 cmp envelopeLevel2, tempValue wc if_c add decayDivide2, #1 '----------------------------------------------------------- Env_Decay2 cmp envelopeState2, #1 wz if_nz jmp #Env_Release2 shr decay2, decayDivide2 sub envelopeLevel2, decay2 min envelopeLevel2, sustain2 wc jmp #Amplitude2 '----------------------------------------------------------- Env_Release2 cmp envelopeState2, #2 wz if_nz jmp #Amplitude2 shr release2, decayDivide2 cmpsub envelopeLevel2, release2 '─────────────────────────────────────────────────────────── 'Calculate sample out2 = arg1 * arg2 (waveform * amplitude) '─────────────────────────────────────────────────────────── Amplitude2 shr arg1, #16 sub arg1, val15bit mov arg2, envelopeLevel2 shr arg2, #22 call #multiply mov out2, r1 '─────────────────────────────────────────────────────────── ' Waveform shaping channel 3 -> arg1 '─────────────────────────────────────────────────────────── Triangle3 tjz selectedWaveform3, #SID_ret cmp selectedWaveform3, #1 wz if_nz jmp #Saw3 abs arg1, phaseAccumulator3 max arg1, mask31bit test controlRegister3, #4 wc '| if_c test phaseAccumulator2, val31bit wc '| These 3 lines handles ring modulation if_c xor arg1, mask32bit '| shl arg1, #1 jmp #Env_Attack3 '----------------------------------------------------------- Saw3 cmp selectedWaveform3, #2 wz if_z mov arg1, phaseAccumulator3 if_z jmp #Env_Attack3 '----------------------------------------------------------- Square3 cmp selectedWaveform3, #4 wz if_z sub pulseWidth3, phaseAccumulator3 wc ' C holds the pulse width modulated square wave if_z muxc arg1, mask32bit if_z jmp #Env_Attack3 '----------------------------------------------------------- Noise3 cmp selectedWaveform3, #8 wz if_nz jmp #Combined3 mov tempValue, phaseAccumulator3 and tempValue, mask28bit sub tempValue, frequency3 wc if_z_and_c ror noiseValue3, NOISE_ROTATE if_z_and_c add noiseValue3, noiseAdd if_z mov arg1, noiseValue3 jmp #Env_Attack3 '----------------------------------------------------------- Combined3 sub selectedWaveform3, #4 mins selectedWaveform3, #0 shl selectedWaveform3, #8 mov tempValue, phaseAccumulator3 shr tempValue, #24 add selectedWaveform3, tempValue add selectedWaveform3, combTableAddr rdbyte arg1, selectedWaveform3 shl arg1, #24 '─────────────────────────────────────────────────────────── ' Envelope shaping channel 3 -> arg2 '─────────────────────────────────────────────────────────── Env_Attack3 cmp envelopeState3, #0 wz if_nz jmp #InitDecay3 add envelopeLevel3, attack3 wc if_c mov envelopeLevel3, mask32bit if_c mov envelopeState3, #1 mov decayDivide3, #0 jmp #Amplitude3 '----------------------------------------------------------- InitDecay3 mov tempValue, decayDivideRef shr tempValue, decayDivide3 cmp envelopeLevel3, tempValue wc if_c add decayDivide3, #1 '----------------------------------------------------------- Env_Decay3 cmp envelopeState3, #1 wz if_nz jmp #Env_Release3 shr decay3, decayDivide3 sub envelopeLevel3, decay3 min envelopeLevel3, sustain3 wc jmp #Amplitude3 '----------------------------------------------------------- Env_Release3 cmp envelopeState3, #2 wz if_nz jmp #Amplitude3 shr release3, decayDivide3 cmpsub envelopeLevel3, release3 '─────────────────────────────────────────────────────────── 'Calculate sample out3 = arg1 * arg2 (waveform * amplitude) '─────────────────────────────────────────────────────────── Amplitude3 shr arg1, #16 sub arg1, val15bit mov arg2, envelopeLevel3 shr arg2, #22 call #multiply mov out3, r1 SID_ret ret ' ' Handle multi-mode filtering ' filter mov ordinaryOutput, #0 '| mov highPassFilter, #0 '| test filterControl, #1 wc '| if_c add highPassFilter, out1 '| if_nc add ordinaryOutput, out1 '| test filterControl, #2 wc '| Route channels trough the filter if_c add highPassFilter, out2 '| or bypass them if_nc add ordinaryOutput, out2 '| test filterControl, #4 wc '| if_c add highPassFilter, out3 '| if_nc add ordinaryOutput, out3 '| '----------------------------------------------------------- mov tempValue, bandPassFilter '| sar tempValue, filterResonance '| High pass filter sub highPassFilter, tempValue '| sub highPassFilter, lowPassFilter '| '----------------------------------------------------------- mov arg1, highPassFilter '| sar arg1, #BP_MAX_CUTOFF '| mov arg2, filterCutoff '| Band pass filter max arg2, maxCutoff call #multiplyNS '| add bandPassFilter, r1 '| '----------------------------------------------------------- mov arg1, bandPassFilter '| sar arg1, #LP_MAX_CUTOFF '| mov arg2, filterCutoff '| Low pass filter call #multiplyNS '| add lowPassFilter, r1 '| '----------------------------------------------------------- mov filterOutput, #0 '| test filterMode_Volume, #16 wc '| if_c add filterOutput, lowPassFilter '| test filterMode_Volume, #32 wc '| Enable/Disable if_c add filterOutput, bandPassFilter '| Low/Band/High pass filtering test filterMode_Volume, #64 wc '| if_c add filterOutput, highPassFilter '| filter_ret ret ' ' Mix channels and update FRQA/FRQB PWM-values ' mixer mov arg1, filterOutput add arg1, ordinaryOutput '----------------------------------------------------------- maxs arg1, clipLevelHigh '| mins arg1, clipLevelLow '| mov arg2, filterMode_Volume '| Main volume adjustment and arg2, #15 '| call #multiplyNS '| '----------------------------------------------------------- add r1, val31bit ' DC offset waitcnt waitCounter, sampleRate ' Wait until the right time to update mov FRQA, r1 '| Update PWM values in FRQA/FRQB mov FRQB, r1 '| mov tempValue, par add tempValue, #28 wrlong r1, tempValue '| Write the sample to hub ram mixer_ret ret ' ' Get attack value r1 = attackTable[arg1] ' getAttack mov arg2, arg1 and arg1, #15 add arg1, #ADSRTable movs :indexed1, arg1 mov arg1, arg2 :indexed1 mov r1, 0 getAttack_ret ret ' ' Get decay value r1 = decayTable[arg1] ' getDecay mov arg2, arg1 and arg1, #15 add arg1, #ADSRTable movs :indexed2, arg1 mov arg1, arg2 :indexed2 mov r1, 0 getDecay_ret ret ' ' Multiplication r1(I32) = arg1(I32) * arg2(I32) ' multiply cmp arg1, arg2 wc 'If arg1 is less than arg2 C is set if_c xor arg1, arg2 'Swap arguments if_c xor arg2, arg1 if_c xor arg1, arg2 multiplyNS mov r1, #0 'Clear 32-bit product :multiLoop shr arg2, #1 wc, wz 'Half multiplyer and get LSB of it if_c add r1, arg1 'Add multiplicand to product on C shl arg1, #1 'Double multiplicand if_nz jmp #:multiLoop 'Check nonzero multiplier to continue multiplication multiplyNS_ret multiply_ret ret ' ' Variables, tables, masks and reference values ' ADSRTable long 68719476 '2 ms long 17179870 '8 ms long 8589934 '16 ms long 5726622 '24 ms long 3616814 '38 ms long 2454268 '56 ms long 2021160 '68 ms long 1717986 '80 ms long 1374390 '100 ms long 549754 '250 ms long 274876 '500 ms long 171798 '800 ms long 137438 '1 s long 45812 '3 s long 27486 '5 s long 17180 '8 s resTable long 0,1,1,1,1,1,2,2 '(Ariba) 'Masks and reference values mask32bit long $ffffffff mask31bit long $7fffffff mask28bit long $fffffff mask24bit long $ffffff mask20bit long $fffff mask16bit long $ffff mask11bit long $7ff val31bit long $80000000 val28bit long $10000000 val27bit long $8000000 val16bit long $10000 val15bit long $8000 clipLevelHigh long $8000000 clipLevelLow long-$8000000 noiseAdd long NOISE_ADD 'Value to add to the noise generator every noise update filterOffset long FILTER_OFFSET decayDivideRef long DECAY_DIVIDE_REF maxCutoff long CUTOFF_LIMIT sampleRate long 0 'clocks between samples ( ~31.250 khz ) combTableAddr long 0 'Setup and subroutine parameters arg1 long 1 arg2 long 1 r1 long 1 'Sid variables envelopeLevel1 long 1 envelopeLevel2 long 1 envelopeLevel3 long 1 controlRegister1 res 1 controlRegister2 res 1 controlRegister3 res 1 frequency1 res 1 frequency2 res 1 frequency3 res 1 phaseAccumulator1 res 1 phaseAccumulator2 res 1 phaseAccumulator3 res 1 pulseWidth1 res 1 pulseWidth2 res 1 pulseWidth3 res 1 selectedWaveform1 res 1 selectedWaveform2 res 1 selectedWaveform3 res 1 envelopeState1 res 1 envelopeState2 res 1 envelopeState3 res 1 noiseValue1 res 1 noiseValue2 res 1 noiseValue3 res 1 attack1 res 1 attack2 res 1 attack3 res 1 decay1 res 1 decay2 res 1 decay3 res 1 sustain1 res 1 sustain2 res 1 sustain3 res 1 release1 res 1 release2 res 1 release3 res 1 decayDivide1 res 1 decayDivide2 res 1 decayDivide3 res 1 out1 res 1 out2 res 1 out3 res 1 filterResonance res 1 filterCutoff res 1 highPassFilter res 1 bandPassFilter res 1 lowPassFilter res 1 filterMode_Volume res 1 filterControl res 1 filterOutput res 1 ordinaryOutput res 1 'Working variables waitCounter res 1 tempValue res 1 fit dat combinedWaveforms file "adm-sid-combined-waveforms.bin" VAR byte ch1_frequencyLo byte ch1_frequencyHi byte ch1_pulseWidthLo byte ch1_pulseWidthHi byte ch1_controlRegister byte ch1_attackDecay byte ch1_sustainRelease byte ch1_dummy byte ch2_frequencyLo byte ch2_frequencyHi byte ch2_pulseWidthLo byte ch2_pulseWidthHi byte ch2_controlRegister byte ch2_attackDecay byte ch2_sustainRelease byte ch2_dummy byte ch3_frequencyLo byte ch3_frequencyHi byte ch3_pulseWidthLo byte ch3_pulseWidthHi byte ch3_controlRegister byte ch3_attackDecay byte ch3_sustainRelease byte ch3_dummy byte Filter1 byte Filter2 byte Filter3 byte Volume long SIDSample byte cog