.global synth
.data
fc1:
.byte 0x00
.byte 0x00
.byte 0x53
.byte 0x40
fc2:
.byte 0x00
.byte 0x00
.byte 0xa3
.byte 0x3b
flt_fb:
.byte 0x66
.byte 0x66
.byte 0xa6
.byte 0x3f
flt_co:
.byte 0xcd
.byte 0xcc
.byte 0x4c
.byte 0x3e
flt_decay:
.byte 0xb9
.byte 0xfc
.byte 0x7f
.byte 0x3f
sq_mult:
.byte 0x00
.byte 0x00
.byte 0xc8
.byte 0x42
stereo_mod:
.byte 0x4e
.byte 0x62
.byte 0x80
.byte 0x3f
main_tune:
.byte 0xdb
.byte 0x65
.byte 0x42
.byte 0x3a
oct_semitones:
.long 12
order:
.byte 0
.byte 1
.byte 2
.byte 3
instr_data:
.byte 128
.byte 0
.byte 0
.byte 0
.byte 80
.byte 0
.byte 0
.byte 0
.byte 0
.byte 204
.byte 204
.byte 61
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 71
.byte 1
.byte 64
.byte 2
.byte 0
.byte 0
.byte 0
.byte 60
.byte 0
.byte 0
.byte 0
.byte 0
.byte 18
.byte 131
.byte 59
.byte 0
.byte 204
.byte 204
.byte 62
.byte 0
.byte 252
.byte 127
.byte 63
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 1
.byte 0
.byte 0
.byte 36
.byte 0
.byte 0
.byte 0
.byte 0
.byte 204
.byte 76
.byte 61
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 197
.byte 39
.byte 55
.byte 0
.byte 235
.byte 145
.byte 63
.byte 1
.byte 0
.byte 0
.byte 0
.byte 32
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 63
.byte 0
.byte 0
.byte 0
.byte 0
.byte 4
.byte 0
.byte 0
.byte 0
.byte 255
.byte 255
.byte 255
.byte 255
.byte 0
.byte 0
.byte 0
.byte 0
.byte 160
.byte 15
.byte 0
.byte 0
.byte 0
.byte 204
.byte 204
.byte 61
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 56
.byte 0
.byte 0
.byte 0
.byte 0
.byte 153
.byte 25
.byte 63
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 32
.byte 0
.byte 64
.byte 2
.byte 0
.byte 0
.byte 0
.byte 36
.byte 0
.byte 0
.byte 0
.byte 0
.byte 18
.byte 131
.byte 59
.byte 0
.byte 92
.byte 15
.byte 62
.byte 0
.byte 236
.byte 127
.byte 63
.byte 0
.byte 0
.byte 0
.byte 0
.byte 1
.byte 0
.byte 0
.byte 0
.byte 255
.byte 255
.byte 255
.byte 255
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 153
.byte 25
.byte 63
.byte 0
.byte 0
.byte 0
.byte 0
.byte 128
.byte 0
.byte 0
.byte 0
.byte 56
.byte 0
.byte 0
.byte 0
.byte 0
.byte 153
.byte 153
.byte 62
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 71
.byte 129
.byte 63
.byte 2
.byte 0
.byte 0
.byte 0
.byte 36
.byte 0
.byte 0
.byte 0
.byte 0
.byte 215
.byte 35
.byte 61
.byte 0
.byte 204
.byte 76
.byte 62
.byte 0
.byte 252
.byte 127
.byte 63
.byte 0
.byte 0
.byte 0
.byte 0
.byte 1
.byte 0
.byte 0
.byte 0
.byte 255
.byte 255
.byte 255
.byte 255
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 153
.byte 153
.byte 62
.byte 0
.byte 0
.byte 0
.byte 0
patterns:
.byte 21
.byte 0
.byte 149
.byte 180
.byte 0
.byte 40
.byte 149
.byte 0
.byte 0
.byte 0
.byte 45
.byte 0
.byte 21
.byte 0
.byte 0
.byte 0
.byte 0
.byte 40
.byte 0
.byte 0
.byte 0
.byte 0
.byte 45
.byte 0
.byte 21
.byte 0
.byte 149
.byte 176
.byte 0
.byte 40
.byte 149
.byte 0
.byte 0
.byte 0
.byte 45
.byte 0
.byte 21
.byte 0
.byte 0
.byte 176
.byte 0
.byte 40
.byte 0
.byte 180
.byte 0
.byte 0
.byte 45
.byte 176
.byte 18
.byte 0
.byte 146
.byte 173
.byte 0
.byte 37
.byte 146
.byte 0
.byte 0
.byte 0
.byte 42
.byte 0
.byte 18
.byte 0
.byte 0
.byte 0
.byte 0
.byte 37
.byte 0
.byte 0
.byte 0
.byte 0
.byte 42
.byte 0
.byte 18
.byte 0
.byte 158
.byte 0
.byte 0
.byte 37
.byte 146
.byte 0
.byte 0
.byte 0
.byte 42
.byte 0
.byte 18
.byte 0
.byte 0
.byte 176
.byte 0
.byte 37
.byte 0
.byte 0
.byte 0
.byte 0
.byte 42
.byte 173
.byte 17
.byte 0
.byte 145
.byte 169
.byte 0
.byte 24
.byte 145
.byte 0
.byte 0
.byte 145
.byte 29
.byte 0
.byte 17
.byte 0
.byte 0
.byte 0
.byte 0
.byte 24
.byte 0
.byte 0
.byte 0
.byte 0
.byte 29
.byte 0
.byte 17
.byte 0
.byte 145
.byte 0
.byte 0
.byte 24
.byte 145
.byte 0
.byte 0
.byte 0
.byte 29
.byte 0
.byte 17
.byte 0
.byte 0
.byte 0
.byte 0
.byte 24
.byte 0
.byte 173
.byte 0
.byte 0
.byte 29
.byte 169
.byte 14
.byte 0
.byte 154
.byte 170
.byte 0
.byte 21
.byte 154
.byte 0
.byte 0
.byte 0
.byte 26
.byte 0
.byte 14
.byte 0
.byte 0
.byte 0
.byte 0
.byte 21
.byte 0
.byte 0
.byte 0
.byte 0
.byte 26
.byte 0
.byte 14
.byte 0
.byte 154
.byte 173
.byte 0
.byte 21
.byte 142
.byte 0
.byte 0
.byte 0
.byte 26
.byte 170
.byte 14
.byte 0
.byte 0
.byte 0
.byte 0
.byte 21
.byte 0
.byte 166
.byte 0
.byte 0
.byte 26
.byte 0
.byte 21
.byte 0
.byte 0
.byte 164
.byte 0
.byte 28
.byte 0
.byte 0
.byte 0
.byte 0
.byte 33
.byte 0
.byte 21
.byte 0
.byte 0
.byte 0
.byte 0
.byte 28
.byte 0
.byte 0
.byte 0
.byte 0
.byte 33
.byte 0
.byte 21
.byte 0
.byte 0
.byte 0
.byte 0
.byte 28
.byte 0
.byte 0
.byte 0
.byte 0
.byte 33
.byte 0
.byte 19
.byte 0
.byte 0
.byte 163
.byte 0
.byte 26
.byte 0
.byte 166
.byte 0
.byte 0
.byte 31
.byte 163
.byte 18
.byte 0
.byte 0
.byte 161
.byte 0
.byte 25
.byte 0
.byte 0
.byte 0
.byte 0
.byte 30
.byte 0
.byte 18
.byte 0
.byte 0
.byte 0
.byte 0
.byte 25
.byte 0
.byte 0
.byte 0
.byte 0
.byte 30
.byte 0
.byte 18
.byte 0
.byte 0
.byte 0
.byte 0
.byte 25
.byte 0
.byte 0
.byte 0
.byte 0
.byte 30
.byte 168
.byte 18
.byte 0
.byte 0
.byte 0
.byte 0
.byte 25
.byte 0
.byte 173
.byte 0
.byte 0
.byte 30
.byte 0
.byte 17
.byte 0
.byte 0
.byte 175
.byte 0
.byte 24
.byte 0
.byte 0
.byte 0
.byte 0
.byte 29
.byte 0
.byte 17
.byte 0
.byte 0
.byte 176
.byte 0
.byte 24
.byte 0
.byte 0
.byte 0
.byte 0
.byte 29
.byte 173
.byte 17
.byte 0
.byte 0
.byte 0
.byte 0
.byte 24
.byte 0
.byte 0
.byte 0
.byte 0
.byte 29
.byte 0
.byte 17
.byte 0
.byte 0
.byte 171
.byte 0
.byte 24
.byte 0
.byte 0
.byte 0
.byte 0
.byte 29
.byte 0
.byte 14
.byte 0
.byte 0
.byte 173
.byte 0
.byte 17
.byte 0
.byte 0
.byte 0
.byte 0
.byte 26
.byte 166
.byte 14
.byte 0
.byte 0
.byte 0
.byte 0
.byte 21
.byte 0
.byte 173
.byte 0
.byte 0
.byte 26
.byte 0
.byte 19
.byte 0
.byte 0
.byte 175
.byte 0
.byte 26
.byte 0
.byte 0
.byte 0
.byte 0
.byte 31
.byte 166
.byte 19
.byte 0
.byte 0
.byte 0
.byte 0
.byte 26
.byte 0
.byte 175
.byte 0
.byte 0
.byte 31
.byte 0
trigger_points:
.long 0
.long 8
.long 0
.long 8
.long 0
.long 8
.long 0
.long 5
.bss
g_buffer:
bss_order_pos:
.space 1*4
bss_pattern_pos:
.space 1*4
bss_stereo_factor:
.space 1*4
bss_master_out:
.space 1*4
bss_tick_ctr:
.space 1*4
bss_temp1:
.space 1*4
bss_modules:
.space 264*4
bss_work:
.space 15859712*4
.text
module_oscillator:
pusha
fld1
flds 16(%esi)
flds 12(%esi)
fadd %st(2)
fmulp
flds bss_stereo_factor
fmulp
fxch %st(1)
flds 0(%ebp)
fadd %st(2),%st
fprem1
fstps 0(%ebp)
flds 20(%esi)
fmulp %st,%st(2)
flds 4(%ebp)
fadd %st(2),%st
fprem1
fsts 4(%ebp)
flds 0(%ebp)
faddp
fxch %st(2)
fstp %st
fstp %st
fmuls 8(%esi)
popa
osc_end:
ret
module_filter:
flds 16(%esi)
flds 12(%esi)
fmuls fc1
fsubs fc2
fmulp
flds 0(%ebp)
flds 4(%ebp)
fsubrp 
fmulp
fsin
flds 8(%esi)
flds 12(%esi)
fabs
fmulp
flds 0(%ebp)
fld1
flds 12(%esi)
fabs
fsubrp %st(1)
fmulp
faddp
faddp
fsts 0(%ebp)
flds 12(%esi)
fabs
fadd %st
fld1
fsub %st(1),%st
fmuls 4(%ebp)
fxch %st(1)
fmul %st(2),%st
faddp
fsts 4(%ebp)
fxch %st(1)
fstp %st
filter_end:
ret
module_envelope:
flds 0(%ebp)
movl 20(%esi),%eax
testl %eax,%eax
jnz module_envelope.in_decay
flds 8(%esi)
faddp
flds 12(%esi)
fcomip
jnc module_envelope.no_switch
incl %eax
movl %eax,20(%esi)
module_envelope.no_switch:
jmp module_envelope.no_decay
module_envelope.in_decay:
flds 16(%esi)
fmulp
module_envelope.no_decay:
fsts 0(%ebp)
envelope_end:
ret
module_delay:
flds 8(%esi)
movl 0(%ebp),%ebx
addl $4,%ebx
andl $0x7ffff,%ebx
movl %ebx,0(%ebp)
addl $4,%ebx
flds (%ebp,%ebx)
flds 16(%esi)
fmulp
faddp
fsts (%ebp,%ebx)
delay_end:
ret
synth:
pusha
movl %eax,%edi
movl %edx,%ecx
pusha
leal bss_modules,%edi
movl $4,%ecx
setup_loop:
pushl %ecx
leal instr_data,%esi
movl $6*4*11,%ecx
rep
movsb
popl %ecx
loop setup_loop
popa
synth_loop:
pushl %ecx
fldz
leal bss_modules,%esi
leal bss_work,%ebp
movl $4,%ecx
tracks_loop:
pushl %ecx
movl bss_tick_ctr,%ebx
testl %ebx,%ebx
jnz notick
movl bss_order_pos,%ebx
movb order(%ebx),%bl
imull $96,%ebx
movl bss_pattern_pos,%eax
addl %eax,%ebx
xorl %eax,%eax
movb patterns(%ebx),%al
cmpb $0,%al
je notrig
pushl %eax
andb $0x7f,%al
movb $12,%bl
divb %bl
movb %ah,bss_temp1
fildl bss_temp1
fildl oct_semitones
fdivrp 
f2xm1
fld1
faddp
movl $1,%ebx
movb %al,%cl
shl %cl,%ebx
movl %ebx,bss_temp1
fildl bss_temp1
fmulp
flds main_tune
fmulp
popl %eax
popl %ecx
pushl %ecx
pusha
negl %ecx
addl $4,%ecx
imull $8,%ecx
testb $0x80,%al
jz no_alt_instr
addl $4,%ecx
no_alt_instr:
addl $trigger_points, %ecx
movl (%ecx),%ecx
imull $6*4,%ecx
addl %ecx,%esi
fstps 16(%esi)
movl $0,6*4+20(%esi)
popa
notrig:
movl bss_pattern_pos,%eax
incl %eax
cmpl $96,%eax
jne no_advance
movl bss_order_pos,%eax
incl %eax
movl %eax,bss_order_pos
xorl %eax,%eax
no_advance:
movl %eax,bss_pattern_pos
notick:
movl $11,%ecx
element_loop:
pushl %ecx
movl (%esi),%eax
pushl %ebp
testl $0x4,%edi
fld1
jz element_loop.ch_left
testb $0x80,%al
jz element_loop.mono_only
flds stereo_mod
fmulp
element_loop.mono_only:
addl $65536*11,%ebp
element_loop.ch_left:
fstps bss_stereo_factor
andb $0x7f,%al
cmpb $0x00,%al
jne no_osc
call module_oscillator
no_osc:
cmpb $0x01,%al
jne no_filter
call module_filter
no_filter:
cmpb $0x02,%al
jne no_envelope
call module_envelope
no_envelope:
cmpb $0x04,%al
jne no_delay
call module_delay
no_delay:
movl 4(%esi),%ebx
cmpl $-1,%ebx
jne not_master_out
faddp
jmp was_master_out
not_master_out:
addl %esi,%ebx
cmpb $0,%ah
je no_op
flds (%ebx)
cmpb $2,%ah
jne no_op_mult
fmulp
no_op_mult:
cmpb $1,%ah
jne no_op_add
op_add:
faddp
no_op_add:
no_op:
fstps (%ebx)
was_master_out:
addl $6*4,%esi
popl %ebp
addl $65536*11*2,%ebp
popl %ecx
decl %ecx
jnz element_loop
popl %ecx
decl %ecx
jnz tracks_loop
movl bss_tick_ctr,%esi
decl %esi
jns was_master_out.no_newtick
movl $30000,%esi
was_master_out.no_newtick:
movl %esi,bss_tick_ctr
fstps (%edi)
addl $4,%edi
popl %ecx
decl %ecx
jnz synth_loop
popa
ret
