; simple macro to create a Z80 pointer (relative to bank)
Z80PtrROM	function v,littleEndian(v)|$80

; simple macro to create little endian word values
littleEndian	function v,(((v)<<8)&$FF00)|(((v)>>8)&$FF)
; ---------------------------------------------------------------------------------------------
; Standard Octave Pitch Equates

smpsPitch10lo	equ $88
smpsPitch09lo	equ $94
smpsPitch08lo	equ $A0
smpsPitch07lo	equ $AC
smpsPitch06lo	equ $B8
smpsPitch05lo	equ $C4
smpsPitch04lo	equ $D0
smpsPitch03lo	equ $DC
smpsPitch02lo	equ $E8
smpsPitch01lo	equ $F4
smpsPitch00	equ $00
smpsPitch01hi	equ $0C
smpsPitch02hi	equ $18
smpsPitch03hi	equ $24
smpsPitch04hi	equ $30
smpsPitch05hi	equ $3C
smpsPitch06hi	equ $48
smpsPitch07hi	equ $54
smpsPitch08hi	equ $60
smpsPitch09hi	equ $6C
smpsPitch10hi	equ $78
; ---------------------------------------------------------------------------------------------
; Note Equates
	enum nRst=$80
	enum nC0=$81,  nCs0,nD0,nEb0,nE0,nF0,nFs0,nG0,nAb0,nA0,nBb0,nB0	; $01 - $0C
	enum nC1=nB0+1,nCs1,nD1,nEb1,nE1,nF1,nFs1,nG1,nAb1,nA1,nBb1,nB1 ; $0D - $18
	enum nC2=nB1+1,nCs2,nD2,nEb2,nE2,nF2,nFs2,nG2,nAb2,nA2,nBb2,nB2	; $19 - $24
	enum nC3=nB2+1,nCs3,nD3,nEb3,nE3,nF3,nFs3,nG3,nAb3,nA3,nBb3,nB3	; $25 - $30
	enum nC4=nB3+1,nCs4,nD4,nEb4,nE4,nF4,nFs4,nG4,nAb4,nA4,nBb4,nB4	; $31 - $3C
	enum nC5=nB4+1,nCs5,nD5,nEb5,nE5,nF5,nFs5,nG5,nAb5,nA5,nBb5,nB5 ; $3D - $48
	enum nC6=nB5+1,nCs6,nD6,nEb6,nE6,nF6,nFs6,nG6,nAb6,nA6,nBb6,nB6	; $49 - $54
	enum nC7=nB6+1,nCs7,nD7,nEb7,nE7,nF7,nFs7,nG7,nAb7,nA7,nBb7	; $55 - $5F
; ---------------------------------------------------------------------------------------------
; 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
; ---------------------------------------------------------------------------------------------
; Header Macros
sHeaderInit	macro
sPointZero set	*
    endm

; Header - Set up Patches Location
; Common to music and SFX
sHeaderPatch	macro loc
	if sPointZero<>*
		message "Missing smpsHeaderStartSong or smpsHeaderStartSongConvert"
	endif

	dc.w Z80PtrROM(loc)
    endm

; Header - Set up Patches Location as an Universal Voice Bank (S3/S&K)
; Common to music and SFX
sHeaderPatchUniv macro
	if sPointZero<>*
		message "Missing smpsHeaderStartSong or smpsHeaderStartSongConvert"
	endif

	dc.w littleEndian(smpsUniVoiceBank)
    endm

; Header macros
; Header - Set up Channel Usage
sHeaderCh	macro fm,psg
	dc.b fm

	if "psg"<>""
		dc.b psg
	endif
    endm

; Header - Set up Tempo and Tick Multiplier
sHeaderTempo	macro tmul,tempo
	dc.b tmul,tempo
    endm

; Header - Set up Tick Multiplier
sHeaderTick	macro tmul
	dc.b tmul
    endm

; Header - Set up DAC Channel
sHeaderDAC	macro loc,pitch,vol
	dc.w Z80PtrROM(loc), 0
    endm

; Header - Set up FM Channel
sHeaderFM	macro loc,pitch,vol
	dc.w Z80PtrROM(loc)
	dc.b pitch,vol
    endm

; Header - Set up PSG Channel
sHeaderPSG	macro loc,pitch,vol,null,volenv
	dc.w Z80PtrROM(loc)
	dc.b	pitch,vol,null,volenv
    endm

; Header - Set up SFX Channel
sHeaderSFX	macro play,patch,loc,pitch,vol
	dc.b play,patch
	dc.w Z80PtrROM(loc)
	dc.b pitch,vol
    endm
; ---------------------------------------------------------------------------------------------
; Command Flag Macros and Equates. Based on the original s1smps2asm, and Flamewing's smps2asm
spNone set $00
spRight set $40
spLeft set $80
spCentre set $C0
spCenter set $C0
; ---------------------------------------------------------------------------------------------
; Macros for FM instruments
; Patches - Feedback
spFeedback macro val
spFe set val
    endm

; Patches - Algorithm
spAlgorithm macro val
spAl set val
    endm

; Patches - Detune
spDetune macro op1,op2,op3,op4
spDe1 set op1
spDe2 set op2
spDe3 set op3
spDe4 set op4
    endm

; Patches - Multiple
spMultiple macro op1,op2,op3,op4
spMu1 set op1
spMu2 set op2
spMu3 set op3
spMu4 set op4
    endm

; Patches - Rate Scale
spRateScale macro op1,op2,op3,op4
spRS1 set op1
spRS2 set op2
spRS3 set op3
spRS4 set op4
    endm

; Patches - Attack Rate
spAttackRt macro op1,op2,op3,op4
spAR1 set op1
spAR2 set op2
spAR3 set op3
spAR4 set op4
    endm

; Patches - Amplitude Modulation
spAmpMod macro op1,op2,op3,op4
spAM1 set op1
spAM2 set op2
spAM3 set op3
spAM4 set op4
    endm

; Patches - Decay Rate
spDecayRt macro op1,op2,op3,op4
spDR1 set op1
spDR2 set op2
spDR3 set op3
spDR4 set op4
    endm

; Patches - Sustain Rate
spSustainRt macro op1,op2,op3,op4
spSR1 set op1
spSR2 set op2
spSR3 set op3
spSR4 set op4
    endm

; Patches - Sustain Level
spSustainLv macro op1,op2,op3,op4
spSL1 set op1
spSL2 set op2
spSL3 set op3
spSL4 set op4
    endm

; Patches - Release Rate
spReleaseRt macro op1,op2,op3,op4
spRR1 set op1
spRR2 set op2
spRR3 set op3
spRR4 set op4
    endm

; Patches - Total Level
spTotalLv macro op1,op2,op3,op4
spTL1 set op1
spTL2 set op2
spTL3 set op3
spTL4 set op4

	dc.b	(spFe<<3)+spAl
;   0     1     2     3     4     5     6     7
;%1000,%1000,%1000,%1000,%1010,%1110,%1110,%1111
spTLMask4 set $80
spTLMask2 set ((spAl>=5)<<7)
spTLMask3 set ((spAl>=4)<<7)
spTLMask1 set ((spAl=7)<<7)

	dc.b (spDe1<<4)+spMu1, (spDe3<<4)+spMu3, (spDe2<<4)+spMu2, (spDe4<<4)+spMu4
	dc.b (spRS1<<6)+spAR1, (spRS3<<6)+spAR3, (spRS2<<6)+spAR2, (spRS4<<6)+spAR4
	dc.b (spAM1<<7)+spDR1, (spAM3<<7)+spDR3, (spAM2<<7)+spDR2, (spAM4<<7)+spDR4
	dc.b spSR1,            spSR3,            spSR2,            spSR4
	dc.b (spSL1<<4)+spRR1, (spSL3<<4)+spRR3, (spSL2<<4)+spRR2, (spSL4<<4)+spRR4
	dc.b spTL1|spTLMask1,  spTL3|spTLMask3,  spTL2|spTLMask2,  spTL4|spTLMask4
    endm

smpsUniVoiceBank =	z80_UniVoiceBank
; E7 - Do not attack of next note (HOLD)
sHold =			$E7
nMaxPSG1 =		nBb6
nMaxPSG2 =		nB6
; ---------------------------------------------------------------------------------------------
; PSG volume envelope equates
	enum VolEnv_00=0,  VolEnv_01,VolEnv_02,VolEnv_03,VolEnv_04,VolEnv_05
	enum VolEnv_06=6,  VolEnv_07,VolEnv_08,VolEnv_09,VolEnv_0A,VolEnv_0B
	enum VolEnv_0C=$C, VolEnv_0D,VolEnv_0E,VolEnv_0F,VolEnv_10,VolEnv_11
	enum VolEnv_12=$12,VolEnv_13,VolEnv_14,VolEnv_15,VolEnv_16,VolEnv_17
	enum VolEnv_18=$18,VolEnv_19,VolEnv_1A,VolEnv_1B,VolEnv_1C,VolEnv_1D
	enum VolEnv_1E=$1E,VolEnv_1F,VolEnv_20,VolEnv_21,VolEnv_22,VolEnv_23
	enum VolEnv_24=$24,VolEnv_25,VolEnv_26
; ---------------------------------------------------------------------------------------------
; PSG modulation envelope equates
	enum ModEnv_00=0,ModEnv_01,ModEnv_02,ModEnv_03,ModEnv_04,ModEnv_05
	enum ModEnv_06=6,ModEnv_07
; ---------------------------------------------------------------------------------------------
; DAC Equates
	enum dSnare=$81,dHighTom,dMidTom,dLowTom,dFloorTom,dKick,dMuffledSnare
	enum dCrashCymbal=dMuffledSnare+1,dRideCymbal,dLowMetalHit,dMetalHit,dHighMetalHit
	enum dHigherMetalHit=dHighMetalHit+1,dMidMetalHit,dClap,dElectricHighTom
	enum dElectricMidTom=dElectricHighTom+1,dElectricLowTom,dElectricFloorTom
	enum dTightSnare=dElectricFloorTom+1,dMidpitchSnare,dLooseSnare,dLooserSnare
	enum dHiTimpani=dLooserSnare+1,dLowTimpani,dMidTimpani,dQuickLooseSnare
	enum dClick=dQuickLooseSnare+1,dPowerKick,dQuickGlassCrash

	enum dGlassCrashSnare=dQuickGlassCrash+1,dGlassCrash,dGlassCrashKick,dQuietGlassCrash
	enum dOddSnareKick=dQuietGlassCrash+1,dKickExtraBass,dComeOn,dDanceSnare,dLooseKick
	enum dModLooseKick=dLooseKick+1,dWoo,dGo,dSnareGo,dPowerTom,dHiWoodBlock,dLowWoodBlock
	enum dHiHitDrum=dLowWoodBlock+1,dLowHitDrum,dMetalCrashHit,dEchoedClapHit
	enum dLowerEchoedClapHit=dEchoedClapHit+1,dHipHopHitKick,dHipHopHitPowerKick
	enum dBassHey=dHipHopHitPowerKick+1,dDanceStyleKick,dHipHopHitKick2,dHipHopHitKick3
	enum dReverseFadingWind=dHipHopHitKick3+1,dScratch,dLooseSnareNoise,dPowerKick2
	enum dCrashingNoiseWoo=dPowerKick2+1,dQuickHit,dKickHey,dPowerKickHit
	enum dLowPowerKickHit=dPowerKickHit+1,dLowerPowerKickHit,dLowestPowerKickHit
	enum dEchoedClapHit3=dLowestPowerKickHit+1,dLowerEchoedClapHit3
; ---------------------------------------------------------------------------------------------
; SMPS commands

; E0xx - Panning, AMS, FMS (PANAFMS - PAFMS_PAN)
sPan		macro dir,amsfms
	if "amsfms"<>""
		dc.b $E0,dir+amsfms
	else
		dc.b $E0,dir
	endif
    endm

; E1xx - Set channel frequency displacement to xx (DETUNE)
saDetune	macro val
	dc.b $E1,val
    endm

; E2xx - Fade in previous song (FADE_IN_SONG)
sFade		macro val
	dc.b $E2, val
    endm

; E3 - Stop FM (TRK_END - TEND_MUTE)
sMuteStopFM	macro
	dc.b $E3
    endm

; E4 - S3K's special set volume absolute (VOLUME - VOL_ABS_S3K)
ssVol		macro val
	dc.b $E4,-(val)&$7F
    endm

; E5yyxx or E6xx - Add xx to volume. yy is broken/ignored (VOLUME - VOL_CC_FMP2 / VOL_CC_FM)
saVolFM		macro val1,val2
	if "val2"<>""
		dc.b $E5,val1,val2
	else
		dc.b $E6,val1
	endif
    endm

; E8xx - Stop note after xx ticks (NOTE_STOP - NSTOP_MULT)
sNoteTimeOut	macro val
	dc.b $E8,val
    endm

; E9 - Rev spindash once (SPINDASH_REV - SDREV_INC)
sSpDashRev	macro
	dc.b $E9
    endm

; EAxx - Play sample xx (bit7 clear) (PLAY_DAC)
sPlayDAC	macro sample
	dc.b $EA,(sample&$7F)
    endm

; EBxxyyyy - Jump to zzzz, if loop index xx is 1 (last iteration of loop) (LOOP_EXIT)
sLoopExit	macro index,loc
	dc.b $EB,index
	dc.w Z80PtrROM(loc)
    endm

; ECxx - Add xx to PSG channel volume (VOLUME - VOL_CC_PSG)
saVolPSG	macro vol
	dc.b $EC,vol
    endm

; E9xx - Set channel pitch to xx (TRANSPOSE - TRNSP_ADD)
ssTransposeS3K	macro val
	dc.b $ED,val
    endm

; EExxyy - Write yy to YM port 1 reg xx (FM_COMMAND - FMW_FM1)
sYM1cmd		macro reg,val
	dc.b $EE,reg,val
    endm

; EFxx[yy] - Set patch id of FM channel to xx. If xx bit7 set, read from another song instead
; (INSTRUMENT - INS_C_FMP)
sPatFM		macro pat, songID
	if "songID"<>""
		dc.b $EF,pat|$80,songID+$80
	else
		dc.b $EF,pat
	endif
    endm

; F0wwxxyyzz - Modulation
;  ww: wait time
;  xx: modulation speed
;  yy: change per step
;  zz: number of steps
; (MOD_SETUP)
ssModZ80	macro wait,speed,change,step
	dc.b $F0,wait,speed,change,step
    endm

; F1xxyy - ?? (MOD_ENV - MENV_FMP)
; F4xx - ?? (MOD_ENV - MENV_GEN)
sModEnv		macro val1, val2
	if "val2"==""
		dc.b $F4,val1
	else
		dc.b $F1,val1, val2
	endif
    endm

; F2 - End of channel (TRK_END - TEND_STD)
sStop		macro
	dc.b $F2
    endm

; F3xx - PSG waveform to xx (PSG_NOISE - PNOIS_SET)
sNoisePSG		macro val
	dc.b $F3,val
    endm

; F480 - Turn on Modulation (MOD_SET - MODS_ON)
sModOn		macro
	dc.b $F4,$80
    endm

; F5xx - PSG volume envelope to xx (INSTRUMENT - INS_C_PSG)
sVolEnvPSG	macro voice
	dc.b $F5,voice
    endm

; F6xxxx - Jump to xxxx (GOTO)
sJump		macro loc
	dc.b $F6
	dc.w Z80PtrROM(loc)
    endm

; F7xxyyzzzz - Loop back to zzzz yy times, xx being the loop index for loop recursion fixing (LOOP)
sLoop		macro index,loops,loc
	dc.b $F7,index,loops
	dc.w Z80PtrROM(loc)
    endm

; F8xxxx - Call pattern at xxxx, saving return point (GOSUB)
sCall		macro loc
	dc.b $F8
	dc.w Z80PtrROM(loc)
    endm

; F9 - Return (RETURN)
sRet		macro
	dc.b $F9
    endm

; FA - Turn off Modulation (MOD_SET - MODS_OFF)
sModOff		macro
	dc.b $FA
    endm

; FBxx - Add xx to channel pitch (TRANSPOSE - TRNSP_ADD)
saTranspose	macro val
	dc.b $FB,val
    endm

; FC - Keep SFX looping until stopped(?) (CONT_SFX)
sLoopSFX	macro loc
	dc.b $FC
	dc.w Z80PtrROM(loc)
    endm

; FDxx - Enable raw frequency mode (RAW_FREQ)
sRawFreq	macro val
	dc.b $FD,val
    endm

; FEwwxxyyzz - Enable special FM3 mode (broken?) (SPC_FM3)
sSpecFM3	macro ind1,ind2,ind3,ind4
	dc.b $FE,ind1,ind2,ind3,ind4
    endm

; FF00xx - Set music tempo to xx (TEMPO - TEMPO_SET)
ssTempo		macro tempo
	dc.b $FF,$00,tempo
    endm

; FF01xx - Play sound xx (SND_CMD)
sPlaySound	macro val
	dc.b $FF,$01,val
    endm

; FF02xx - Pause music (MUS_PAUSE - MUSP_Z80)
sMusPause	macro val
	dc.b $FF,$02,val
    endm

; FF03xxxxyy - Copy yy bytes from xxxx to here (only in Z80 RAM) (COPY_MEM)
sCopyMem	macro loc,len
	dc.b $FF,$03
	littleEndian loc
	dc.b len
    endm

; FF04xx - Set global tick multiplier to xx (TICK_MULT - TMULT_ALL)
ssTickMul	macro tmul
	dc.b $FF,$04,tmul
    endm

; FF05wwxxyyzz - Enable SSG-EG (SSG_EG - SEG_NORMAL)
sSSGEG		macro op1,op2,op3,op4
	dc.b $FF,$05,op1,op3,op2,op4
    endm

; FF06xxyy - ?? (FM_VOLENV)
sVolEnvFM	macro tone,mask
	dc.b $FF,$06,tone,mask
    endm

; FF07 - Reset spindash rev counter (SPINDASH_REV - SDREV_RESET)
sSpDashReset	macro
	dc.b $FF,$07
    endm

; FF08 - Freeze CPU
sFreeze	macro
	if extra_flags==1
		dc.b $FF,$08
	endif
    endm

; FF08 - Check for sync. Only use when all channel timers expire
sSync	macro chans
	if extra_flags==1
		dc.b $FF,$09, chans
	endif
    endm

; FF09 - Stop counting ticks
sTickStop	macro
	if extra_flags==1
		dc.b $FF,$0A
	endif
    endm
