mirror of
https://github.com/vsariola/sointu.git
synced 2025-05-28 03:10:24 -04:00
The preprocessing is done sointu-cli and (almost) nothing is done by the NASM preprocessor anymore (some .strucs are still there. Now, sointu-cli loads the .yml song, defines bunch of macros (go functions / variables) and passes the struct to text/template parses. This a lot more powerful way to generate .asm code than trying to fight with the nasm preprocessor. At the moment, tests pass but the repository is a bit of monster, as the library is still compiled using the old approach. Go should generate the library also from the templates.
127 lines
5.2 KiB
NASM
127 lines
5.2 KiB
NASM
{{- if .Opcode "out"}}
|
|
;-------------------------------------------------------------------------------
|
|
; OUT opcode: outputs and pops the signal
|
|
;-------------------------------------------------------------------------------
|
|
{{- if .Mono "out"}}
|
|
; Mono: add ST0 to main left port, then pop
|
|
{{- end}}
|
|
{{- if .Stereo "out"}}
|
|
; Stereo: add ST0 to left out and ST1 to right out, then pop
|
|
{{- end}}
|
|
;-------------------------------------------------------------------------------
|
|
{{.Func "su_op_out" "Opcode"}} ; l r
|
|
mov {{.AX}}, [{{.Stack "Synth"}}] ; AX points to the synth object
|
|
{{- if .StereoAndMono "out" }}
|
|
jnc su_op_out_mono
|
|
{{- end }}
|
|
{{- if .Stereo "out" }}
|
|
call su_op_out_mono
|
|
add {{.AX}}, 4 ; shift from left to right channel
|
|
su_op_out_mono:
|
|
{{- end}}
|
|
fmul dword [{{.Input "out" "gain"}}] ; multiply by gain
|
|
fadd dword [{{.AX}} + su_synthworkspace.left] ; add current value of the output
|
|
fstp dword [{{.AX}} + su_synthworkspace.left] ; store the new value of the output
|
|
ret
|
|
{{end}}
|
|
|
|
|
|
{{- if .Opcode "outaux"}}
|
|
;-------------------------------------------------------------------------------
|
|
; OUTAUX opcode: outputs to main and aux1 outputs and pops the signal
|
|
;-------------------------------------------------------------------------------
|
|
; Mono: add outgain*ST0 to main left port and auxgain*ST0 to aux1 left
|
|
; Stereo: also add outgain*ST1 to main right port and auxgain*ST1 to aux1 right
|
|
;-------------------------------------------------------------------------------
|
|
{{.Func "su_op_outaux" "Opcode"}} ; l r
|
|
mov {{.AX}}, [{{.Stack "Synth"}}]
|
|
{{- if .StereoAndMono "outaux" }}
|
|
jnc su_op_outaux_mono
|
|
{{- end}}
|
|
{{- if .Stereo "outaux" }}
|
|
call su_op_outaux_mono
|
|
add {{.AX}}, 4
|
|
su_op_outaux_mono:
|
|
{{- end}}
|
|
fld st0 ; l l
|
|
fmul dword [{{.Input "outaux" "outgain"}}] ; g*l
|
|
fadd dword [{{.AX}} + su_synthworkspace.left] ; g*l+o
|
|
fstp dword [{{.AX}} + su_synthworkspace.left] ; o'=g*l+o
|
|
fmul dword [{{.Input "outaux" "auxgain"}}] ; h*l
|
|
fadd dword [{{.AX}} + su_synthworkspace.aux] ; h*l+a
|
|
fstp dword [{{.AX}} + su_synthworkspace.aux] ; a'=h*l+a
|
|
ret
|
|
{{end}}
|
|
|
|
|
|
{{- if .Opcode "aux"}}
|
|
;-------------------------------------------------------------------------------
|
|
; AUX opcode: outputs the signal to aux (or main) port and pops the signal
|
|
;-------------------------------------------------------------------------------
|
|
; Mono: add gain*ST0 to left port
|
|
; Stereo: also add gain*ST1 to right port
|
|
;-------------------------------------------------------------------------------
|
|
{{.Func "su_op_aux" "Opcode"}} ; l r
|
|
lodsb
|
|
mov {{.DI}}, [{{.Stack "Synth"}}]
|
|
{{- if .StereoAndMono "aux" }}
|
|
jnc su_op_aux_mono
|
|
{{- end}}
|
|
{{- if .Stereo "aux" }}
|
|
call su_op_aux_mono
|
|
add {{.DI}}, 4
|
|
su_op_aux_mono:
|
|
{{- end}}
|
|
fmul dword [{{.Input "aux" "gain"}}] ; g*l
|
|
fadd dword [{{.DI}} + su_synthworkspace.left + {{.AX}}*4] ; g*l+o
|
|
fstp dword [{{.DI}} + su_synthworkspace.left + {{.AX}}*4] ; o'=g*l+o
|
|
ret
|
|
{{end}}
|
|
|
|
|
|
{{- if .Opcode "send"}}
|
|
;-------------------------------------------------------------------------------
|
|
; SEND opcode: adds the signal to a port
|
|
;-------------------------------------------------------------------------------
|
|
; Mono: adds signal to a memory address, defined by a word in VAL stream
|
|
; Stereo: also add right signal to the following address
|
|
;-------------------------------------------------------------------------------
|
|
{{.Func "su_op_send" "Opcode"}}
|
|
lodsw
|
|
mov {{.CX}}, [{{.Stack "Voice"}}] ; load pointer to voice
|
|
{{- if .StereoAndMono "send"}}
|
|
jnc su_op_send_mono
|
|
{{- end}}
|
|
{{- if .Stereo "send"}}
|
|
mov {{.DI}}, {{.AX}}
|
|
inc {{.AX}} ; send the right channel first
|
|
fxch ; r l
|
|
call su_op_send_mono ; (r) l
|
|
mov {{.AX}}, {{.DI}} ; move back to original address
|
|
test {{.AX}}, 0x8 ; if r was not popped and is still in the stack
|
|
jnz su_op_send_mono
|
|
fxch ; swap them back: l r
|
|
su_op_send_mono:
|
|
{{- end}}
|
|
{{- if .HasParamValueOtherThan "send" "voice" 0}}
|
|
test {{.AX}}, 0x8000
|
|
jz su_op_send_skipglobal
|
|
mov {{.CX}}, [{{.Stack "Synth"}}]
|
|
su_op_send_skipglobal:
|
|
{{- end}}
|
|
test {{.AX}}, 0x8 ; if the SEND_POP bit is not set
|
|
jnz su_op_send_skippush
|
|
fld st0 ; duplicate the signal on stack: s s
|
|
su_op_send_skippush: ; there is signal s, but maybe also another: s (s)
|
|
fld dword [{{.Input "send" "amount"}}] ; a l (l)
|
|
{{- .Float 0.5 | .Prepare | indent 4}}
|
|
fsub dword [{{.Float 0.5 | .Use}}] ; a-.5 l (l)
|
|
fadd st0 ; g=2*a-1 l (l)
|
|
and ah, 0x7f ; eax = send address, clear the global bit
|
|
or al, 0x8 ; set the POP bit always, at the same time shifting to ports instead of wrk
|
|
fmulp st1, st0 ; g*l (l)
|
|
fadd dword [{{.CX}} + {{.AX}}*4] ; g*l+L (l),where L is the current value
|
|
fstp dword [{{.CX}} + {{.AX}}*4] ; (l)
|
|
ret
|
|
{{end}}
|