Skip to content

Instantly share code, notes, and snippets.

@Brainulator9
Created October 14, 2022 02:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Brainulator9/e7a641fdad91e337339b338fd81c88d5 to your computer and use it in GitHub Desktop.
Save Brainulator9/e7a641fdad91e337339b338fd81c88d5 to your computer and use it in GitHub Desktop.
SMPS2ASM - Flamewing's version, ported to ASM68K, for Sonic the Hedgehog 1 on Sega Mega Drive/Genesis
; ===========================================================================
; Created by Flamewing, based on S1SMPS2ASM version 1.1 by Marc Gordon (AKA Cinossu)
; ===========================================================================
; Permission to use, copy, modify, and/or distribute this software for any
; purpose with or without fee is hereby granted.
;
; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
; WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
; MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
; ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
; WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
; ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
; OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
; ===========================================================================
SonicDriverVer = 1
SMPS2ASMVer = 1
; Set the following to non-zero to use all S2 DAC samples, or to zero otherwise.
; The S1 samples are a subset of this.
use_s2_samples = 1
; Set the following to non-zero to use all S3D DAC samples, or to zero
; otherwise. Most of the S3D samples are also present in S3/S&K, but
; there are two samples specific to S3D.
use_s3d_samples = 1
; Set the following to non-zero to use all S3 DAC samples,
; or to zero otherwise.
use_s3_samples = 1
; Set the following to non-zero to use all S&K DAC samples,
; or to zero otherwise.
use_sk_samples = 1
; PSG conversion to S3/S&K/S3D drivers require a tone shift of 12 semi-tones.
psgdelta EQU 12
; ---------------------------------------------------------------------------
; Standard Octave Pitch Equates
rsset $88
smpsPitch10lo rs.b $C
smpsPitch09lo rs.b $C
smpsPitch08lo rs.b $C
smpsPitch07lo rs.b $C
smpsPitch06lo rs.b $C
smpsPitch05lo rs.b $C
smpsPitch04lo rs.b $C
smpsPitch03lo rs.b $C
smpsPitch02lo rs.b $C
smpsPitch01lo rs.b $C
rsreset
smpsPitch00 rs.b $C
smpsPitch01hi rs.b $C
smpsPitch02hi rs.b $C
smpsPitch03hi rs.b $C
smpsPitch04hi rs.b $C
smpsPitch05hi rs.b $C
smpsPitch06hi rs.b $C
smpsPitch07hi rs.b $C
smpsPitch08hi rs.b $C
smpsPitch09hi rs.b $C
smpsPitch10hi rs.b $C
; ---------------------------------------------------------------------------
; Note Equates
rsset $80
nRst rs.b 1
nC0 rs.b 1
nCs0 rs.b 1
nD0 rs.b 1
nEb0 rs.b 1
nE0 rs.b 1
nF0 rs.b 1
nFs0 rs.b 1
nG0 rs.b 1
nAb0 rs.b 1
nA0 rs.b 1
nBb0 rs.b 1
nB0 rs.b 1
nC1 rs.b 1
nCs1 rs.b 1
nD1 rs.b 1
nEb1 rs.b 1
nE1 rs.b 1
nF1 rs.b 1
nFs1 rs.b 1
nG1 rs.b 1
nAb1 rs.b 1
nA1 rs.b 1
nBb1 rs.b 1
nB1 rs.b 1
nC2 rs.b 1
nCs2 rs.b 1
nD2 rs.b 1
nEb2 rs.b 1
nE2 rs.b 1
nF2 rs.b 1
nFs2 rs.b 1
nG2 rs.b 1
nAb2 rs.b 1
nA2 rs.b 1
nBb2 rs.b 1
nB2 rs.b 1
nC3 rs.b 1
nCs3 rs.b 1
nD3 rs.b 1
nEb3 rs.b 1
nE3 rs.b 1
nF3 rs.b 1
nFs3 rs.b 1
nG3 rs.b 1
nAb3 rs.b 1
nA3 rs.b 1
nBb3 rs.b 1
nB3 rs.b 1
nC4 rs.b 1
nCs4 rs.b 1
nD4 rs.b 1
nEb4 rs.b 1
nE4 rs.b 1
nF4 rs.b 1
nFs4 rs.b 1
nG4 rs.b 1
nAb4 rs.b 1
nA4 rs.b 1
nBb4 rs.b 1
nB4 rs.b 1
nC5 rs.b 1
nCs5 rs.b 1
nD5 rs.b 1
nEb5 rs.b 1
nE5 rs.b 1
nF5 rs.b 1
nFs5 rs.b 1
nG5 rs.b 1
nAb5 rs.b 1
nA5 rs.b 1
nBb5 rs.b 1
nB5 rs.b 1
nC6 rs.b 1
nCs6 rs.b 1
nD6 rs.b 1
nEb6 rs.b 1
nE6 rs.b 1
nF6 rs.b 1
nFs6 rs.b 1
nG6 rs.b 1
nAb6 rs.b 1
nA6 rs.b 1
nBb6 rs.b 1
nB6 rs.b 1
nC7 rs.b 1
nCs7 rs.b 1
nD7 rs.b 1
nEb7 rs.b 1
nE7 rs.b 1
nF7 rs.b 1
nFs7 rs.b 1
nG7 rs.b 1
nAb7 rs.b 1
nA7 rs.b 1
nBb7 rs.b 1
; SMPS2ASM uses nMaxPSG for songs from S1/S2 drivers.
; nMaxPSG1 and nMaxPSG2 are used only for songs from S3/S&K/S3D drivers.
; The use of psgdelta is intended to undo the effects of PSGPitchConvert
; and ensure that the ending note is indeed the maximum PSG frequency.
if SonicDriverVer<=2
nMaxPSG EQU nA5
nMaxPSG1 EQU nA5+psgdelta
nMaxPSG2 EQU nA5+psgdelta
else
nMaxPSG EQU nBb6-psgdelta
nMaxPSG1 EQU nBb6
nMaxPSG2 EQU nB6
endif
; ---------------------------------------------------------------------------
; PSG volume envelope equates
if SonicDriverVer=1
rsset 1
fTone_01 rs.b 1
fTone_02 rs.b 1
fTone_03 rs.b 1
fTone_04 rs.b 1
fTone_05 rs.b 1
fTone_06 rs.b 1
fTone_07 rs.b 1
fTone_08 rs.b 1
fTone_09 rs.b 1
elseif SonicDriverVer=2
rsset 1
fTone_01 rs.b 1
fTone_02 rs.b 1
fTone_03 rs.b 1
fTone_04 rs.b 1
fTone_05 rs.b 1
fTone_06 rs.b 1
fTone_07 rs.b 1
fTone_08 rs.b 1
fTone_09 rs.b 1
fTone_0A rs.b 1
fTone_0B rs.b 1
fTone_0C rs.b 1
fTone_0D rs.b 1
else;if SonicDriverVer>=3
rsset 1
sTone_01 rs.b 1
sTone_02 rs.b 1
sTone_03 rs.b 1
sTone_04 rs.b 1
sTone_05 rs.b 1
sTone_06 rs.b 1
sTone_07 rs.b 1
sTone_08 rs.b 1
sTone_09 rs.b 1
sTone_0A rs.b 1
sTone_0B rs.b 1
sTone_0C rs.b 1
sTone_0D rs.b 1
sTone_0E rs.b 1
sTone_0F rs.b 1
sTone_10 rs.b 1
sTone_11 rs.b 1
sTone_12 rs.b 1
sTone_13 rs.b 1
sTone_14 rs.b 1
sTone_15 rs.b 1
sTone_16 rs.b 1
sTone_17 rs.b 1
sTone_18 rs.b 1
sTone_19 rs.b 1
sTone_1A rs.b 1
sTone_1B rs.b 1
sTone_1C rs.b 1
sTone_1D rs.b 1
sTone_1E rs.b 1
sTone_1F rs.b 1
sTone_20 rs.b 1
sTone_21 rs.b 1
sTone_22 rs.b 1
sTone_23 rs.b 1
sTone_24 rs.b 1
sTone_25 rs.b 1
sTone_26 rs.b 1
sTone_27 rs.b 1
; For conversions:
if SonicDriverVer>=5
fTone_01 rs.b 1
fTone_02 rs.b 1
fTone_03 rs.b 1
fTone_04 rs.b 1
fTone_05 rs.b 1
fTone_06 rs.b 1
fTone_07 rs.b 1
fTone_08 rs.b 1
fTone_09 rs.b 1
fTone_0A rs.b 1
fTone_0B rs.b 1
fTone_0C rs.b 1
fTone_0D rs.b 1
endif
endif
; ---------------------------------------------------------------------------
; DAC Equates
if SonicDriverVer=1
rsset $81
dKick rs.b 1
dSnare rs.b 1
dTimpani rs.b 1
rsset $88
dHiTimpani rs.b 1
dMidTimpani rs.b 1
dLowTimpani rs.b 1
dVLowTimpani rs.b 1
elseif SonicDriverVer=2
rsset $81
dKick rs.b 1
dSnare rs.b 1
dClap rs.b 1
dScratch rs.b 1
dTimpani rs.b 1
dHiTom rs.b 1
dVLowClap rs.b 1
dHiTimpani rs.b 1
dMidTimpani rs.b 1
dLowTimpani rs.b 1
dVLowTimpani rs.b 1
dMidTom rs.b 1
dLowTom rs.b 1
dFloorTom rs.b 1
dHiClap rs.b 1
dMidClap rs.b 1
dLowClap rs.b 1
else;if SonicDriverVer>=3
if (use_s3_samples<>0)|(use_sk_samples<>0)|(use_s3d_samples<>0)
rsset $81
dSnareS3 rs.b 1
dHighTom rs.b 1
dMidTomS3 rs.b 1
dLowTomS3 rs.b 1
dFloorTomS3 rs.b 1
dKickS3 rs.b 1
dMuffledSnare rs.b 1
dCrashCymbal rs.b 1
dRideCymbal rs.b 1
dLowMetalHit rs.b 1
dMetalHit rs.b 1
dHighMetalHit rs.b 1
dHigherMetalHit rs.b 1
dMidMetalHit rs.b 1
dClapS3 rs.b 1
dElectricHighTom rs.b 1
dElectricMidTom rs.b 1
dElectricLowTom rs.b 1
dElectricFloorTom rs.b 1
dTightSnare rs.b 1
dMidpitchSnare rs.b 1
dLooseSnare rs.b 1
dLooserSnare rs.b 1
dHiTimpaniS3 rs.b 1
dLowTimpaniS3 rs.b 1
dMidTimpaniS3 rs.b 1
dQuickLooseSnare rs.b 1
dClick rs.b 1
dPowerKick rs.b 1
dQuickGlassCrash rs.b 1
endif
if (use_s3_samples<>0)|(use_sk_samples<>0)
dGlassCrashSnare rs.b 1
dGlassCrash rs.b 1
dGlassCrashKick rs.b 1
dQuietGlassCrash rs.b 1
dOddSnareKick rs.b 1
dKickExtraBass rs.b 1
dComeOn rs.b 1
dDanceSnare rs.b 1
dLooseKick rs.b 1
dModLooseKick rs.b 1
dWoo rs.b 1
dGo rs.b 1
dSnareGo rs.b 1
dPowerTom rs.b 1
dHiWoodBlock rs.b 1
dLowWoodBlock rs.b 1
dHiHitDrum rs.b 1
dLowHitDrum rs.b 1
dMetalCrashHit rs.b 1
dEchoedClapHit rs.b 1
dLowerEchoedClapHit rs.b 1
dHipHopHitKick rs.b 1
dHipHopHitPowerKick rs.b 1
dBassHey rs.b 1
dDanceStyleKick rs.b 1
dHipHopHitKick2 rs.b 1
dHipHopHitKick3 rs.b 1
dReverseFadingWind rs.b 1
dScratchS3 rs.b 1
dLooseSnareNoise rs.b 1
dPowerKick2 rs.b 1
dCrashingNoiseWoo rs.b 1
dQuickHit rs.b 1
dKickHey rs.b 1
dPowerKickHit rs.b 1
dLowPowerKickHit rs.b 1
dLowerPowerKickHit rs.b 1
dLowestPowerKickHit rs.b 1
endif
; For conversions:
if (use_s2_samples<>0)
if (use_s3_samples<>0)|(use_sk_samples<>0)|(use_s3d_samples<>0)
dKick rs.b 1
else
rsset $81
dKick rs.b 1
endif
dSnare rs.b 1
dClap rs.b 1
dScratch rs.b 1
dTimpani rs.b 1
dHiTom rs.b 1
dVLowClap rs.b 1
dHiTimpani rs.b 1
dMidTimpani rs.b 1
dLowTimpani rs.b 1
dVLowTimpani rs.b 1
dMidTom rs.b 1
dLowTom rs.b 1
dFloorTom rs.b 1
dHiClap rs.b 1
dMidClap rs.b 1
dLowClap rs.b 1
endif
if (use_s3d_samples<>0)
dFinalFightMetalCrash rs.b 1
dIntroKick rs.b 1
endif
if (use_s3_samples<>0)
dEchoedClapHit_S3 rs.b 1
dLowerEchoedClapHit_S3 rs.b 1
endif
endif
; ---------------------------------------------------------------------------
; Channel IDs for SFX
cPSG1 EQU $80
cPSG2 EQU $A0
cPSG3 EQU $C0
cNoise EQU $E0 ; Not for use in S3/S&K/S3D
cFM3 EQU $02
cFM4 EQU $04
cFM5 EQU $05
cFM6 EQU $06 ; Only in S3/S&K/S3D, overrides DAC
; ---------------------------------------------------------------------------
; Conversion macros and functions
if ~def(little_endian)
little_endian macros
dc.w ((\1<<8)&$FF00)|((\1>>8)&$FF)
endif
if ~def(z80_ptr)
z80_ptr macros
dc.w ((\1<<8)&$FF00)|((\1>>8)&$7F)|$80
endif
;conv0To256 function n,((n==0)<<8)|n
;s2TempotoS1 function n,(((768-n)>>1)/(256-n))&$FF
;s2TempotoS3 function n,($100-((n==0)|n))&$FF
;s1TempotoS2 function n,((((conv0To256(n)-1)<<8)+(conv0To256(n)>>1))/conv0To256(n))&$FF
;s1TempotoS3 function n,s2TempotoS3(s1TempotoS2(n))
;s3TempotoS1 function n,s2TempotoS1(s2TempotoS3(n))
;s3TempotoS2 function n,s2TempotoS3(n)
s2TempotoS1 macro n
s21convval: = (((768-n)>>1)/(256-n))&$FF
endm
s2TempotoS3 macro n
s23convval: = ($100-((n=0)|n))&$FF
s32convval: = s23convval
endm
s1TempotoS2 macro n
if n=0
s12convval: = ((((256-1)<<8)+(256>>1))/256)&$FF
else
s12convval: = ((((n-1)<<8)+(n>>1))/n)&$FF
endif
endm
s1TempotoS3 macro n
s1TempotoS2 n
s2TempotoS3 s12convval
endm
s3TempotoS1 macro n
s2TempotoS3 n
s2TempotoS1 s23convval
endm
s3TempotoS2 macros
s2TempotoS3 \_
convertMainTempoMod macro val
if ((SourceDriver>=3)&(SonicDriverVer>=3))|(SonicDriverVer=SourceDriver)
dc.b \val
elseif SourceDriver=1
if \val\=1
inform 3,"Invalid main tempo of 1 in song from Sonic 1"
endif
if SonicDriverVer=2
s1TempotoS2 \val
dc.b s12convval
else;if SonicDriverVer>=3
s1TempotoS3 \val
dc.b s13convval
endif
elseif SourceDriver=2
if \val\=0
inform 3,"Invalid main tempo of 0 in song from Sonic 2"
endif
if SonicDriverVer=1
s2TempotoS1 \val
dc.b s21convval
else;if SonicDriverVer>=3
s2TempotoS3 \val
dc.b s23convval
endif
else;if SourceDriver>=3
if \val\=0
inform 2,"Performing approximate conversion of Sonic 3 main tempo modifier of 0"
endif
if SonicDriverVer=1
s3TempotoS1 \val
dc.b s31convval
else;if SonicDriverVer=2
s3TempotoS2 \val
dc.b s32convval
endif
endif
endm
; PSG conversion to S3/S&K/S3D drivers require a tone shift of 12 semi-tones.
PSGPitchConvert macro val
if (SonicDriverVer>=3)&(SourceDriver<3)
dc.b (\val\+psgdelta)&$FF
elseif (SonicDriverVer<3)&(SourceDriver>=3)
dc.b (\val\-psgdelta)&$FF
else
dc.b \val
endif
endm
CheckedChannelPointer macro location
if SonicDriverVer<>1
z80_ptr \location\
else
if def(\location)
inform 3,"Tracks for Sonic 1 songs must come after the start of the song"
else
dc.w \location\-songStart
endif
endif
endm
; ---------------------------------------------------------------------------
; Header Macros
smpsHeaderStartSong macro ver,sourcesmps2asmver
SourceDriver set ver
if (narg=2)
SourceSMPS2ASM set sourcesmps2asmver
else
SourceSMPS2ASM set 0
endif
songStart set *
if SMPS2ASMVer<SourceSMPS2ASM
inform 1,"Song at 0x%h was made for a newer version of SMPS2ASM (this is version %d, but song wants at least version %d).",songStart,SMPS2ASMVer,SourceSMPS2ASM
endif
endm
smpsHeaderVoiceNull macro
if songStart<>*
inform 3,"Missing smpsHeaderStartSong"
endif
dc.w $0000
endm
; Header - Set up Voice Location
; Common to music and SFX
smpsHeaderVoice macro location
if songStart<>*
inform 3,"Missing smpsHeaderStartSong"
endif
if SonicDriverVer<>1
z80_ptr \location\
else
if def(\location)
inform 3,"Voice banks for Sonic 1 songs must come after the song"
else
dc.w \location\-songStart
endif
endif
endm
; Header - Set up Voice Location as S3's Universal Voice Bank
; Common to music and SFX
smpsHeaderVoiceUVB macro
if songStart<>*
inform 3,"Missing smpsHeaderStartSong"
endif
if SonicDriverVer>=5
z80_ptr z80_UniVoiceBank
elseif SonicDriverVer>=3
little_endian z80_UniVoiceBank
else
inform 3,"Universal Voice Bank does not exist in Sonic 1 or Sonic 2 drivers"
endif
endm
; Header macros for music (not for SFX)
; Header - Set up Channel Usage
smpsHeaderChan macro fm,psg
dc.b fm,psg
endm
; Header - Set up Tempo
smpsHeaderTempo macro div,mod
dc.b div
convertMainTempoMod \mod
endm
; Header - Set up DAC Channel
smpsHeaderDAC macro location,pitch,vol
CheckedChannelPointer \location
if strlen("\pitch")>0
dc.b pitch
if strlen("\vol")>0
dc.b vol
else
dc.b $00
endif
else
dc.w $00
endif
endm
; Header - Set up FM Channel
smpsHeaderFM macro location,pitch,vol
CheckedChannelPointer \location
dc.b pitch,vol
endm
; Header - Set up PSG Channel
smpsHeaderPSG macro location,pitch,vol,mod,voice
CheckedChannelPointer \location
PSGPitchConvert \pitch
dc.b vol
; Frequency envelope
if (SonicDriverVer>=3)&(SourceDriver<3)
; In SMPS 68k Type 1, this byte is skipped and can contain garbage.
; Sonic 2's Oil Ocean Zone and Ending themes set this byte to a non-zero value which
; other drivers may try to process as valid data, so manually force it to 0 here.
dc.b 0
else
if (SonicDriverVer<3)&(SourceDriver>=3)&(\mod<>0)
inform 1,"This track header specifies a frequency envelope, but this driver does not support them."
endif
dc.b \mod
endif
; Volume envelope
dc.b voice
endm
; Header macros for SFX (not for music)
; Header - Set up Tempo
smpsHeaderTempoSFX macro div
dc.b div
endm
; Header - Set up Channel Usage
smpsHeaderChanSFX macro chan
dc.b chan
endm
; Header - Set up FM Channel
smpsHeaderSFXChannel macro chanid,location,pitch,vol
if (SonicDriverVer>=3)&(chanid=cNoise)
inform 3,"Using channel ID of cNoise ($E0) in Sonic 3 driver is dangerous. Fix the song so that it turns into a noise channel instead."
elseif (SonicDriverVer<3)&(chanid=cFM6)
inform 3,"Using channel ID of FM6 ($06) in Sonic 1 or Sonic 2 drivers is unsupported. Change it to another channel."
endif
dc.b $80,chanid
CheckedChannelPointer \location\
if (chanid&$80)<>0
PSGPitchConvert \pitch
else
dc.b pitch
endif
dc.b vol
endm
; ---------------------------------------------------------------------------
; Co-ord Flag Macros and Equates
; E0xx - Panning, AMS, FMS
smpsPan macro direction,amsfms
dc.b $E0,direction+amsfms
endm
panNone equ $00
panRight equ $40
panLeft equ $80
panCentre equ $C0
panCenter equ $C0 ; silly Americans :U
; E1xx - Set channel detune to val
smpsDetune macro val
dc.b $E1,val
endm
; E2xx - Useless
smpsNop macro val
if SonicDriverVer<3
dc.b $E2,val
endif
endm
; Return (used after smpsCall)
smpsReturn macro val
if SonicDriverVer>=3
dc.b $F9
else
dc.b $E3
endif
endm
; Fade in previous song (ie. 1-Up)
smpsFade macro val
if SonicDriverVer>=3
dc.b $E2
if strlen("\val")>0
dc.b val
else
dc.b $FF
endif
if SourceDriver<3
smpsStop
endif
elseif (SourceDriver>=3)&(strlen("\val"))&(strcmp("\val","$FF"))
; This is one of those weird S3+ "fades" that we don't need
else
dc.b $E4
endif
endm
; E5xx - Set channel tempo divider to xx
smpsChanTempoDiv macro val
if SonicDriverVer>=5
; New flag unique to Flamewing's modified S&K driver
dc.b $FF,$08,val
elseif SonicDriverVer=3
inform 3,"Coord. Flag to set tempo divider of a single channel does not exist in S3 driver. Use Flamewing's modified S&K sound driver instead."
else
dc.b $E5,val
endif
endm
; E6xx - Alter Volume by xx
smpsAlterVol macro val
dc.b $E6,val
endm
; E7 - Prevent attack of next note
smpsNoAttack EQU $E7
; E8xx - Set note fill to xx
smpsNoteFill macro val
if (SonicDriverVer>=5)&(SourceDriver<3)
; Unique to Flamewing's modified driver
dc.b $FF,$0A,val
else
if (SonicDriverVer>=3)&(SourceDriver<3)
inform 1,"Note fill will not work as intended unless you divide the fill value by the tempo divider or complain to Flamewing to add an appropriate coordination flag for it."
elseif (SonicDriverVer<3)&(SourceDriver>=3)
inform 1,"Note fill will not work as intended unless you multiply the fill value by the tempo divider or complain to Flamewing to add an appropriate coordination flag for it."
endif
dc.b $E8,val
endif
endm
; Add xx to channel pitch
smpsChangeTransposition macro val
if SonicDriverVer>=3
dc.b $FB,val
else
dc.b $E9,val
endif
endm
; Set music tempo modifier to xx
smpsSetTempoMod macro val
if SonicDriverVer>=3
dc.b $FF,$00
else
dc.b $EA
endif
convertMainTempoMod \val
endm
; Set music tempo divider to xx
smpsSetTempoDiv macro val
if SonicDriverVer>=3
dc.b $FF,$04,val
else
dc.b $EB,val
endif
endm
; ECxx - Set Volume to xx
smpsSetVol macro val
if SonicDriverVer>=3
dc.b $E4,val
else
inform 3,"Coord. Flag to set volume (instead of volume attenuation) does not exist in S1 or S2 drivers. Complain to Flamewing to add it."
endif
endm
; Works on all drivers
smpsPSGAlterVol macro vol
dc.b $EC,vol
endm
; Clears pushing sound flag in S1
smpsClearPush macro
if SonicDriverVer=1
dc.b $ED
else
inform 3,"Coord. Flag to clear S1 push block flag does not exist in S2 or S3 drivers. Complain to Flamewing to add it."
endif
endm
; Stops special SFX (S1 only) and restarts overridden music track
smpsStopSpecial macro
if SonicDriverVer=1
dc.b $EE
else
inform 2,"Coord. Flag to stop special SFX does not exist in S2 or S3 drivers. Complain to Flamewing to add it. With adequate caution, smpsStop can do this job."
smpsStop
endif
endm
; EFxx[yy] - Set Voice of FM channel to xx; xx < 0 means yy present
smpsFMvoice macro voice,songID
if (SonicDriverVer>=3)&(strlen("\songID")>0)
dc.b $EF,voice|$80,songID+$81
else
dc.b $EF,voice
endif
endm
; F0wwxxyyzz - Modulation - ww: wait time - xx: modulation speed - yy: change per step - zz: number of steps
smpsModSet macro wait,speed,change,step
dc.b $F0
if (SonicDriverVer>=3)&(SourceDriver<3)
dc.b wait+1,speed,change,((step+1)*speed)&$FF
elseif (SonicDriverVer<3)&(SourceDriver>=3)
dc.b wait-1,speed,change
conv_step: = ((step=0)<<8)|step
conv_speed: = ((speed=0)<<8)|speed
dc.b (conv_step/conv_speed)-1
else
dc.b wait,speed,change,step
endif
;dc.b speed,change,step
endm
; Turn on Modulation
smpsModOn macro type
if SonicDriverVer>=3
if strlen("\type")>0
dc.b $F4,type
else
dc.b $F4,$80
endif
else
dc.b $F1
endif
endm
; F2 - End of channel
smpsStop macro
dc.b $F2
endm
; F3xx - PSG waveform to xx
smpsPSGform macro form
dc.b $F3,form
endm
; Turn off Modulation
smpsModOff macro
if SonicDriverVer>=3
dc.b $FA
else
dc.b $F4
endif
endm
; F5xx - PSG voice to xx
smpsPSGvoice macro voice
dc.b $F5,voice
endm
; F6xxxx - Jump to xxxx
smpsJump macro loc
dc.b $F6
if SonicDriverVer<>1
z80_ptr loc
else
dc.w loc-*-1
endif
endm
; F7xxyyzzzz - Loop back to zzzz yy times, xx being the loop index for loop recursion fixing
smpsLoop macro index,loops,loc
dc.b $F7
dc.b index,loops
if SonicDriverVer<>1
z80_ptr loc
else
dc.w loc-*-1
endif
endm
; F8xxxx - Call pattern at xxxx, saving return point
smpsCall macro loc
dc.b $F8
if SonicDriverVer<>1
z80_ptr loc
else
dc.w loc-*-1
endif
endm
; ---------------------------------------------------------------------------
; Alter Volume
smpsFMAlterVol macro val1,val2
if (SonicDriverVer>=3)&(strlen("\val2")>0)
dc.b $E5,val1,val2
else
dc.b $E6,val1
endif
endm
; S3/S&K/S3D-only coordination flags
if SonicDriverVer>=3
; Silences FM channel then stops as per smpsStop
smpsStopFM macro
dc.b $E3
endm
; Spindash Rev
smpsSpindashRev macro
dc.b $E9
endm
smpsPlayDACSample macro sample
dc.b $EA,(sample&$7F)
endm
smpsConditionalJump macro index,loc
dc.b $EB
dc.b index
z80_ptr loc
endm
; Set note values to xx-$40
smpsSetNote macro val
dc.b $ED,val
endm
smpsFMICommand macro reg,val
dc.b $EE,reg,val
endm
; Set Modulation
smpsModChange2 macro fmmod,psgmod
dc.b $F1,fmmod,psgmod
endm
; Set Modulation
smpsModChange macro val
dc.b $F4,val
endm
; FCxxxx - Jump to xxxx
smpsContinuousLoop macro loc
dc.b $FC
z80_ptr loc
endm
smpsAlternateSMPS macro flag
dc.b $FD,flag
endm
smpsFM3SpecialMode macro ind1,ind2,ind3,ind4
dc.b $FE,ind1,ind2,ind3,ind4
endm
smpsPlaySound macro index
if SonicDriverVer>=5
inform 1,"smpsPlaySound only plays SFX in Flamedriver; use smpsPlayMusic to play music or fade effects."
endif
dc.b $FF,$01,index
endm
smpsHaltMusic macro flag
dc.b $FF,$02,flag
endm
smpsCopyData macro data,len
inform 3,"Coord. Flag to copy data should not be used. Complain to Flamewing if any music uses it."
dc.b $FF,$03
little_endian data
dc.b len
endm
smpsSSGEG macro op1,op2,op3,op4
dc.b $FF,$05,op1,op3,op2,op4
endm
smpsFMVolEnv macro tone,mask
dc.b $FF,$06,tone,mask
endm
smpsResetSpindashRev macro val
dc.b $FF,$07
endm
; Flags ported from other drivers.
if SonicDriverVer>=5
smpsChanFMCommand macro reg,val
dc.b $FF,$09,reg,val
endm
smpsPitchSlide macro enable
dc.b $FF,$0B,enable
endm
smpsSetLFO macro enable,amsfms
dc.b $FF,$0C,enable,amsfms
endm
smpsPlayMusic macro index
dc.b $FF,$0D,index
endm
endif
endif
; ---------------------------------------------------------------------------
; S1/S2 only coordination flag
; Sets D1L to maximum volume (minimum attenuation) and RR to maximum for operators 3 and 4 of FM1
smpsMaxRelRate macro
if SonicDriverVer>=3
; Emulate it in S3/S&K/S3D driver
smpsFMICommand $88,$0F
smpsFMICommand $8C,$0F
else
dc.b $F9
endif
endm
; ---------------------------------------------------------------------------
; Backwards compatibility
smpsAlterNote macro
smpsDetune \_
endm
smpsAlterPitch macro
smpsChangeTransposition \_
endm
smpsFMFlutter macro
smpsFMVolEnv \_
endm
smpsWeirdD1LRR macro
smpsMaxRelRate \_
endm
smpsSetvoice macro
smpsFMvoice \_
endm
; ---------------------------------------------------------------------------
; Macros for FM instruments
; Voices - Feedback
smpsVcFeedback macro val
vcFeedback set val
endm
; Voices - Algorithm
smpsVcAlgorithm macro val
vcAlgorithm set val
endm
smpsVcUnusedBits macro val,d1r1,d1r2,d1r3,d1r4
vcUnusedBits set val
if (strlen("\d1r1")>0)&(strlen("\d1r2")>0)&(strlen("\d1r3")>0)&(strlen("\d1r4")>0)
vcD1R1Unk set d1r1<<5
vcD1R2Unk set d1r2<<5
vcD1R3Unk set d1r3<<5
vcD1R4Unk set d1r4<<5
else
vcD1R1Unk set 0
vcD1R2Unk set 0
vcD1R3Unk set 0
vcD1R4Unk set 0
endif
endm
; Voices - Detune
smpsVcDetune macro op1,op2,op3,op4
vcDT1 set op1
vcDT2 set op2
vcDT3 set op3
vcDT4 set op4
endm
; Voices - Coarse-Frequency
smpsVcCoarseFreq macro op1,op2,op3,op4
vcCF1 set op1
vcCF2 set op2
vcCF3 set op3
vcCF4 set op4
endm
; Voices - Rate Scale
smpsVcRateScale macro op1,op2,op3,op4
vcRS1 set op1
vcRS2 set op2
vcRS3 set op3
vcRS4 set op4
endm
; Voices - Attack Rate
smpsVcAttackRate macro op1,op2,op3,op4
vcAR1 set op1
vcAR2 set op2
vcAR3 set op3
vcAR4 set op4
endm
; Voices - Amplitude Modulation
; The original SMPS2ASM erroneously assumed the 6th and 7th bits
; were the Amplitude Modulation.
; According to several docs, however, it's actually the high bit.
smpsVcAmpMod macro op1,op2,op3,op4
if SourceSMPS2ASM=0
vcAM1 set op1<<5
vcAM2 set op2<<5
vcAM3 set op3<<5
vcAM4 set op4<<5
else
vcAM1 set op1<<7
vcAM2 set op2<<7
vcAM3 set op3<<7
vcAM4 set op4<<7
endif
endm
; Voices - First Decay Rate
smpsVcDecayRate1 macro op1,op2,op3,op4
vcD1R1 set op1
vcD1R2 set op2
vcD1R3 set op3
vcD1R4 set op4
endm
; Voices - Second Decay Rate
smpsVcDecayRate2 macro op1,op2,op3,op4
vcD2R1 set op1
vcD2R2 set op2
vcD2R3 set op3
vcD2R4 set op4
endm
; Voices - Decay Level
smpsVcDecayLevel macro op1,op2,op3,op4
vcDL1 set op1
vcDL2 set op2
vcDL3 set op3
vcDL4 set op4
endm
; Voices - Release Rate
smpsVcReleaseRate macro op1,op2,op3,op4
vcRR1 set op1
vcRR2 set op2
vcRR3 set op3
vcRR4 set op4
endm
; Voices - Total Level
; The original SMPS2ASM decides TL high bits automatically,
; but later versions leave it up to the user.
; Alternatively, if we're converting an SMPS 68k song to SMPS Z80,
; then we *want* the TL bits to match the algorithm, because SMPS 68k
; prefers the algorithm over the TL bits, ignoring the latter, while
; SMPS Z80 does the opposite.
; Unfortunately, there's nothing we can do if we're trying to convert
; an SMPS Z80 song to SMPS 68k. It will ignore the bits no matter
; what we do, so we just print a warning.
smpsVcTotalLevel macro op1,op2,op3,op4
vcTL1 set op1
vcTL2 set op2
vcTL3 set op3
vcTL4 set op4
dc.b (vcUnusedBits<<6)+(vcFeedback<<3)+vcAlgorithm
; 0 1 2 3 4 5 6 7
;%1000,%1000,%1000,%1000,%1010,%1110,%1110,%1111
if SourceSMPS2ASM=0
vcTLMask4 set ((vcAlgorithm=7)<<7)
vcTLMask3 set ((vcAlgorithm>=4)<<7)
vcTLMask2 set ((vcAlgorithm>=5)<<7)
vcTLMask1 set $80
else
vcTLMask4 set 0
vcTLMask3 set 0
vcTLMask2 set 0
vcTLMask1 set 0
endif
if (SonicDriverVer>=3)&(SourceDriver<3)
vcTLMask4 set ((vcAlgorithm=7)<<7)
vcTLMask3 set ((vcAlgorithm>=4)<<7)
vcTLMask2 set ((vcAlgorithm>=5)<<7)
vcTLMask1 set $80
vcTL1 set vcTL1&$7F
vcTL2 set vcTL2&$7F
vcTL3 set vcTL3&$7F
vcTL4 set vcTL4&$7F
elseif (SonicDriverVer<3)&(SourceDriver>=3)&((((vcTL1|vcTLMask1)&$80)<>$80)|(((vcTL2|vcTLMask2)&$80)<>((vcAlgorithm>=5)<<7))|(((vcTL3|vcTLMask3)&$80)<>((vcAlgorithm>=4)<<7))|(((vcTL4|vcTLMask4)&$80)<>((vcAlgorithm=7)<<7)))
inform 1,"Voice at 0x%h has TL bits that do not match its algorithm setting. This voice will not work in S1/S2 drivers.",*
endif
if SonicDriverVer=2
dc.b (vcDT4<<4)+vcCF4, (vcDT2<<4)+vcCF2, (vcDT3<<4)+vcCF3, (vcDT1<<4)+vcCF1
dc.b (vcRS4<<6)+vcAR4, (vcRS2<<6)+vcAR2, (vcRS3<<6)+vcAR3, (vcRS1<<6)+vcAR1
dc.b vcAM4|vcD1R4|vcD1R4Unk, vcAM2|vcD1R2|vcD1R2Unk, vcAM3|vcD1R3|vcD1R3Unk, vcAM1|vcD1R1|vcD1R1Unk
dc.b vcD2R4, vcD2R2, vcD2R3, vcD2R1
dc.b (vcDL4<<4)+vcRR4, (vcDL2<<4)+vcRR2, (vcDL3<<4)+vcRR3, (vcDL1<<4)+vcRR1
dc.b vcTL4|vcTLMask4, vcTL2|vcTLMask2, vcTL3|vcTLMask3, vcTL1|vcTLMask1
else
dc.b (vcDT4<<4)+vcCF4, (vcDT3<<4)+vcCF3, (vcDT2<<4)+vcCF2, (vcDT1<<4)+vcCF1
dc.b (vcRS4<<6)+vcAR4, (vcRS3<<6)+vcAR3, (vcRS2<<6)+vcAR2, (vcRS1<<6)+vcAR1
dc.b vcAM4|vcD1R4|vcD1R4Unk, vcAM3|vcD1R3|vcD1R3Unk, vcAM2|vcD1R2|vcD1R2Unk, vcAM1|vcD1R1|vcD1R1Unk
dc.b vcD2R4, vcD2R3, vcD2R2, vcD2R1
dc.b (vcDL4<<4)+vcRR4, (vcDL3<<4)+vcRR3, (vcDL2<<4)+vcRR2, (vcDL1<<4)+vcRR1
dc.b vcTL4|vcTLMask4, vcTL3|vcTLMask3, vcTL2|vcTLMask2, vcTL1|vcTLMask1
endif
endm
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment