Comment &
─────────────────────────────────────────────────────────────────────────────
Gus play routine V 1.5 by Robert Adolfsson - CASCADA
Not for release! <- Really? Why was it on ftp.uwp.edu then?
And it even came with a text file from Cascada
Spooky.
NoiseTracker/SoundTracker/StarTrekker/FastTracker/OctaComposer
compatible
Hacked for Turbo/Borland Pascal interfacing by Juggler/BTL.
I also fixed some spelling errors, added and altered comments.
Send me mail at bre@os.is or chat with me on the IRC.
AND!! I added the Renaissance code in here somewhere.. one big
happy bit of assembler. Find it by scanning for "Renaissance", or
just the next Comment. My code is at the very end of the file.
(Copyrighted too! :-P nyah nyah nyah..)
..Tabs should be set to 8 spaces..
─────────────────────────────────────────────────────────────────────────────
&
Jumps
.286
.model tpascal
.CODE
; Publics
;Public MainVolume,PlayingPattern,RealPPattern,PatternRow,RealRow,OrderLen,ChanOn,NumChans,Time,SampChans,Bar,BasePort,ErrorCode
Public ClearMem, StartPlaying, StopPlaying, InitDevice, Init
Public U_Peek, U_Poke, U_SetFreq, U_SetBalance, U_SetVolume, U_SetLoopMode
Public U_StopVoice, U_StartVoice, U_ReadPos, U_ChangeInOut
Public U_DumpSampleToDRAM, U_DumpDRAMToMemory
Public GetVariables, LoadModule, ProtSampAdd, ProtSampPlay, ProtSampPop
; Structures
ChanSize Equ 52
ChanInfo Struc
SampOff dd 0
FreqVal dw 0
Vol dw 0
OldVol dw 0
Fine dw 0
Repeat dw 0
RepLen dw 0
Len dw 0
Amiga dw 0
Effect dw 0
VibratoPek dw 0
OldVibrato dw 0
PortTo dw 0
OldPortTo dw 0
EffectTime dw 0
CurrSamp dw 0
OldSamp dw 0
Arp dw 0,0,0
ArpCounter dw 0
InstSet dw 0
LoopOnOff dw 0
OffsetAdd dw 0
Bar dw 0
ChanInfo EndS
; Pointers to local data, for the Pascal interface.
;
ProgData Struc
BasePortP dd 0 ; GUS Base port
ErrorP dd 0 ; Error codes..
VarP dd 0 ; Misc variables, following MainVolume
TimerP dd 0 ; Timer
GMemP dd 0 ; Top of .MOD samples
GMemProtP dd 0 ; Top of protected samples
ChanInfoP dd 0 ; An array of ChanInfo structs (0..7?)
GusVolP dd 0 ; Pointer to the volume table
; Module sample data (arrays of 0..31)
MSOffset dd 0 ; Offset in GUS mem
MSLen dd 0 ; Sample length
MSVol dd 0 ; Sample volume
MSRep dd 0 ; Loop beginning (ofs from MSOffset)
MSRepLen dd 0 ; Loop length
; Protected sample data (arrays of 0..63)
PSOffset dd 0 ; Offset in GUS mem
PSLen dd 0 ; Sample length
PSVol dd 0 ; Sample volume
PSRep dd 0 ; Loop beginning (ofs from PSOffset)
PSRepLen dd 0 ; Loop length
ProgData EndS
; UltraSound Ports
StatusPort Equ 6h
TimerCtrlPort Equ 8h
TimerDataPort Equ 9h
MidiCtrlPort Equ 100h
MidiDataPort Equ 101h
ActiveVoicePort Equ 102h
CommandPort Equ 103h
DataLowPort Equ 104h
DataHighPort Equ 105h
DRAMIOPort Equ 107h
; UltraSound Commands
WriteVoiceMode Equ 00h
SetVoiceFreq Equ 01h ; Value=Freq/Divisor
LoopStartLo Equ 02h
LoopStartHi Equ 03h
SampleEndLo Equ 04h
SampleEndHi Equ 05h
VolRampRate Equ 06h
VolRampStart Equ 07h
VolRampEnd Equ 08h
SetVolume Equ 09h
SampleStartLo Equ 0Ah
SampleStartHi Equ 0Bh
VoiceBalance Equ 0Ch
VolumeCtrl Equ 0Dh
VoicesActive Equ 0Eh
DMACtrl Equ 41h
DRAMAddrLo Equ 43h
DRAMAddrHi Equ 44h
TimerCtrl Equ 45h
TimerCount1 Equ 46h
TimerCount2 Equ 47h
SampleFreq Equ 48h
SampleCtrl Equ 49h
Initialize Equ 4Ch
Read Equ 80h
ReadVolume Equ Read+SetVolume ; 89h
VoicePosLo Equ Read+SampleStartLo ; 8Ah
VoicePosHi Equ Read+SampleStartHi ; 8Bh
ReadVolCtrl Equ Read+VolumeCtrl ; 8Dh
IRQStatus Equ 8Fh
; Divisors
Voices14 Equ 4300
Voices15 Equ 4000
Voices16 Equ 3700
Voices17 Equ 3500
Voices18 Equ 3300
Voices19 Equ 3100
Voices20 Equ 3030
Voices21 Equ 2800
Voices22 Equ 2700
Voices23 Equ 2600
Voices24 Equ 2500
Voices25 Equ 2400
Voices26 Equ 2300
Voices27 Equ 2200
Voices28 Equ 2100
Voices29 Equ 2000
Voices30 Equ 2000
Voices31 Equ 1900
Voices32 Equ 1800
; Number of voices to use
NumVoices Equ 20
DivVoices Equ Voices20
; Variables
MKSign db 'M.K.FLT46CHN8CHNOCTA'
MKMod db 0
Info db 1084 dup (0)
OrderLen db 0
Restart db 0
PatternOrder db 128 dup (0)
SinTab db 0,25,50,74,98,120,142,162,180,197,212,225,236
db 244,250,254,255,254,250,244,236,225,212,197,180
db 162,142,120,98,74,50,25
ArpTable db 70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70
db 70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,68,68,68,68,68,68,68,66,66,66,66,66,66,66,64,64,64,64,64,64,64,64,62,62,62,62,62,62,62,62,60,60,60,60,60,60,60,60,58,58,58,58,58,58
db 58,58,58,56,56,56,56,56,56,56,56,56,56,54,54,54,54,54,54,54,54,54,54,52,52,52,52,52,52,52,52,52,52,50,50,50,50,50,50,50,50,50,50,50,50,48,48,48,48,48,48,48,48,48,48,48,48,46,46,46,46,46,46,46,46,46,46,46,46,44,44,44,44,44,44,44,44,44,44
db 44,44,44,44,42,42,42,42,42,42,42,42,42,42,42,42,42,42,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,34,34,34,34,34,34,34,34,34,34,34,34,34
db 34,34,34,34,34,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,26,26,26,26,26,26,26,26,26,26,26,26,26
db 26,26,26,26,26,26,26,26,26,26,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20
db 20,20,20,20,20,20,20,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,14,14,14,14,14,14,14,14,14,14,14,14,14,14
db 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10
db 10,10,10,10,10,10,10,10,10,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
PanRegs db 6,8,8,6 ,7,7,7,7,7,7,7,7,7,7,7,7
db 6,6,8,8,8,6 ,7,7,7,7,7,7,7,7,7,7
db 6,6,8,8,8,8,6,6 ,7,7,7,7,7,7,7,7
EvenData
AmigaVals dw 856,808,762,720,678,640,604,570,538,508,480,453 ;C-1 to B-1 Finetune +0.
dw 428,404,381,360,339,320,302,285,269,254,240,226 ;C-2 to B-2 Finetune +0.
dw 214,202,190,180,170,160,151,143,135,127,120,113 ;C-3 to B-3 Finetune +0.
dw 850,802,757,715,674,637,601,567,535,505,477,450 ;C-1 to B-1 Finetune +1.
dw 425,401,379,357,337,318,300,284,268,253,239,225 ;C-2 to B-2 Finetune +1.
dw 213,201,189,179,169,159,150,142,134,126,119,113 ;C-3 to B-3 Finetune +1.
dw 844,796,752,709,670,632,597,563,532,502,474,447 ;C-1 to B-1 Finetune +2.
dw 422,398,376,355,335,316,298,282,266,251,237,224 ;C-2 to B-2 Finetune +2.
dw 211,199,188,177,167,158,149,141,133,125,118,112 ;C-3 to B-3 Finetune +2.
dw 838,791,746,704,665,628,592,559,528,498,470,444 ;C-1 to B-1 Finetune +3.
dw 419,395,373,352,332,314,296,280,264,249,235,222 ;C-2 to B-2 Finetune +3.
dw 209,198,187,176,166,157,148,140,132,125,118,111 ;C-3 to B-3 Finetune +3.
dw 832,785,741,699,660,623,588,555,524,495,467,441 ;C-1 to B-1 Finetune +4.
dw 416,392,370,350,330,312,294,278,262,247,233,220 ;C-2 to B-2 Finetune +4.
dw 208,196,185,175,165,156,147,139,131,124,117,110 ;C-3 to B-3 Finetune +4.
dw 826,779,736,694,655,619,584,551,520,491,463,437 ;C-1 to B-1 Finetune +5.
dw 413,390,368,347,328,309,292,276,260,245,232,219 ;C-2 to B-2 Finetune +5.
dw 206,195,184,174,164,155,146,138,130,123,116,109 ;C-3 to B-3 Finetune +5.
dw 820,774,730,689,651,614,580,547,516,487,460,434 ;C-1 to B-1 Finetune +6.
dw 410,387,365,345,325,307,290,274,258,244,230,217 ;C-2 to B-2 Finetune +6.
dw 205,193,183,172,163,154,145,137,129,122,115,109 ;C-3 to B-3 Finetune +6.
dw 814,768,725,684,646,610,575,543,513,484,457,431 ;C-1 to B-1 Finetune +7.
dw 407,384,363,342,323,305,288,272,256,242,228,216 ;C-2 to B-2 Finetune +7.
dw 204,192,181,171,161,152,144,136,128,121,114,108 ;C-3 to B-3 Finetune +7.
dw 907,856,808,762,720,678,640,604,570,538,504,480 ;C-1 to B-1 Finetune -8.
dw 453,428,404,381,360,339,320,302,285,269,254,240 ;C-2 to B-2 Finetune -8.
dw 226,214,202,190,180,170,160,151,143,135,127,120 ;C-3 to B-3 Finetune -8.
dw 900,850,802,757,715,675,636,601,567,535,505,477 ;C-1 to B-1 Finetune -7.
dw 450,425,401,379,357,337,318,300,284,268,253,238 ;C-2 to B-2 Finetune -7.
dw 225,212,200,189,179,169,159,150,142,134,126,119 ;C-3 to B-3 Finetune -7.
dw 894,844,796,752,709,670,632,597,563,532,502,474 ;C-1 to B-1 Finetune -6.
dw 447,422,398,376,355,335,316,298,282,266,251,237 ;C-2 to B-2 Finetune -6.
dw 223,211,199,188,177,167,158,149,141,133,125,118 ;C-3 to B-3 Finetune -6.
dw 887,838,791,746,704,665,628,592,559,528,498,470 ;C-1 to B-1 Finetune -5.
dw 444,419,395,373,352,332,314,296,280,264,249,235 ;C-2 to B-2 Finetune -5.
dw 222,209,198,187,176,166,157,148,140,132,125,118 ;C-3 to B-3 Finetune -5.
dw 881,832,785,741,699,660,623,588,555,524,494,467 ;C-1 to B-1 Finetune -4.
dw 441,416,392,370,350,330,312,294,278,262,247,233 ;C-2 to B-2 Finetune -4.
dw 220,208,196,185,175,165,156,147,139,131,123,117 ;C-3 to B-3 Finetune -4.
dw 875,826,779,736,694,655,619,584,551,520,491,463 ;C-1 to B-1 Finetune -3.
dw 437,413,390,368,347,338,309,292,276,260,245,232 ;C-2 to B-2 Finetune -3.
dw 219,206,195,184,174,164,155,146,138,130,123,116 ;C-3 to B-3 Finetune -3.
dw 868,820,774,730,689,651,614,580,547,516,487,460 ;C-1 to B-1 Finetune -2.
dw 434,410,387,365,345,325,307,290,274,258,244,230 ;C-2 to B-2 Finetune -2.
dw 217,205,193,183,172,163,154,145,137,129,122,115 ;C-3 to B-3 Finetune -2.
dw 862,814,768,725,684,646,610,575,543,513,484,457 ;C-1 to B-1 Finetune -1.
dw 431,407,384,363,342,323,305,288,272,256,242,228 ;C-2 to B-2 Finetune -1.
dw 216,203,192,181,171,161,152,144,136,128,121,114 ;C-3 to B-3 Finetune -1.
GusVol dw 20000,39120,41376,42656,43936,45072,45696,46240,46848,47408
dw 47952,48528,49072,49360,49632,49920,50160,50432,50704,50928
dw 51168,51424,51680,51952,52160,52448,52672,52912,53152,53312
dw 53440,53584,53664,53808,53952,54048,54144,54288,54400,54496
dw 54608,54720,54832,54944,55072,55184,55312,55440,55552,55696
dw 55760,55888,56016,56096,56240,56304,56448,56528,56672,56752
dw 56896,56976,57136,57216
SampOffset dd 31 dup (0)
SampLen dw 31 dup (0)
SampVol dw 31 dup (0)
SampFine dw 31 dup (0)
SampRep dw 31 dup (0)
SampRepLen dw 31 dup (0)
ProtSampOffset dd 63 dup (0)
ProtSampLen dw 63 dup (0)
ProtSampVol dw 63 dup (0)
ProtSampRep dw 63 dup (0)
ProtSampRepLen dw 63 dup (0)
; MainVolume,PlayingPattern,RealPPattern,PatternRow,RealRow
; ChanOn,NumChans,ProtSampNum,ProtMainVolume,NextVoice
MainVolume dw 64
PlayingPattern dw 0
RealPPattern dw 0
PatternRow dw 0
RealRow dw 0
ChanOn dw 0FFh
NumChans dw 4 ; 4,6 or 8 (Default = 4)
ProtSampNum dw 0 ; Number of protected samples.
ProtMainVolume dw 64
NextVoice dw 8 ; Next voice 2 use 4 playback (prot)
BasePort dw 220h ; Default GUS base address
ErrorCode dw 0
FileHandle dw 0
ChanOnCount dw 0
PatternSpeed dw 0
PatternCount dw 0
TempVol dw 0
FreqTable dw 908 dup (0)
PatternPek equ this DWord
BytePattern dw 0
SegPattern dw 0
SampMem dw 0
PatternMem dw 0
BreakData dw 0
OldTimer dd 0
GUSMemProt dd 0 ; Top of protected sample data
GUSMem dd 0 ; Top of module sample data
Speed dd 0
SpeedAdd dd 0
Counter dw 0
Time dd 0
JumpOldTimer dw 0
SampChans ChanInfo 8 dup (<>)
; Macros
NopLoop Macro Nops
Local NopLoop
push cx
mov cx,Nops
NopLoop:
nop
loop NopLoop
pop cx
EndM
; The Code
Pattern Proc Near
pusha
push ds
push es
mov ax,cs
mov ds,ax
mov al,20h
out 20h,al
sti
clc
add Word Ptr [Time],1
adc Word Ptr [Time+2],0
inc [Counter]
mov ax,Word Ptr [Speed+2]
clc
add Word Ptr [SpeedAdd+2],ax
mov ax,Word Ptr [Speed]
adc Word Ptr [SpeedAdd],ax
jc JumpPattern
cmp [Counter],4
je ClearNotes
cmp [Counter],5
je SetNotes
jmp EndPattern
ClearNotes:
mov di,offset [SampChans]
mov cx,[NumChans]
mov dx,[BasePort]
add dx,CommandPort
StopVoices:
dec dx
mov al,Byte Ptr [NumChans]
sub al,cl
out dx,al
inc dx
cmp [di.InstSet],2
je VoiceOff1
cmp [di.InstSet],1
je VoiceOff2
cmp [di.OffsetAdd],0
jne VoiceOff1
jmp NoVoiceOff
VoiceOff2:
mov ax,[di.CurrSamp]
cmp ax,[di.OldSamp]
jne VoiceOff1
jmp NoVoiceOff
VoiceOff1:
mov ax,[di.OldVol]
mov [di.OldVol],0
mov bx,[MainVolume]
mul bx
shr ax,6
adc ax,0
mov bx,ax
shl bx,1
mov bx,[GusVol+bx]
mov dx,[BasePort]
add dx,CommandPort
mov al,VolumeCtrl
out dx,al
add dx,2
mov al,3
out dx,al
sub dx,2
mov bp,[GusVol]
mov ah,0
cmp bx,bp
jb NoFixVolDir1
mov ah,01000000b
xchg bx,bp
NoFixVolDir1:
mov al,VolRampStart
out dx,al
xchg ax,bx
inc dx
out dx,ax
dec dx
mov al,VolRampEnd
out dx,al
mov ax,bp
inc dx
out dx,ax
dec dx
mov al,VolumeCtrl
out dx,al
mov al,bh
add dx,2
out dx,al
sub dx,2
NoVoiceOff:
add di,ChanSize
dec cx
jnz StopVoices
jmp EndPattern
SetNotes:
mov [Counter],1
mov di,offset [SampChans]
mov cx,[NumChans]
mov dx,[BasePort]
add dx,CommandPort
ChangeSamps:
dec dx
mov al,Byte Ptr [NumChans]
sub al,cl
out dx,al
inc dx
cmp [di.InstSet],2
je SampChange1
cmp [di.InstSet],1
je SampChange2
cmp [di.OffsetAdd],0
jne ChangeOffset
jmp NoChangeSamp
ChangeOffset:
mov al,SampleStartLo
out dx,al
inc dx
mov ax,Word Ptr [di.SampOff]
mov bp,Word Ptr [di.SampOff+2]
add ax,[di.OffsetAdd]
adc bp,0
shr ax,7
shl bp,9
or ax,bp
out dx,ax
dec dx
mov al,SampleStartHi
out dx,al
inc dx
mov ax,Word Ptr [di.SampOff]
add ax,[di.OffsetAdd]
shl ax,9
out dx,ax
dec dx
sub dx,CommandPort
Rept 6
in al,dx
EndM
add dx,CommandPort
jmp NoChangeSamp
SampChange1:
mov al,WriteVoiceMode
out dx,al
add dx,2
mov al,3
out dx,al
sub dx,DataHighPort
Rept 6
in al,dx
EndM
add dx,CommandPort
mov al,SampleStartLo
out dx,al
inc dx
mov ax,Word Ptr [di.SampOff]
mov bp,Word Ptr [di.SampOff+2]
add ax,[di.OffsetAdd]
adc bp,0
shr ax,7
shl bp,9
or ax,bp
out dx,ax
dec dx
mov al,SampleStartHi
out dx,al
inc dx
mov ax,Word Ptr [di.SampOff]
add ax,[di.OffsetAdd]
shl ax,9
out dx,ax
sub dx,DataLowPort
Rept 6
in al,dx
EndM
add dx,CommandPort
mov ax,[di.OldSamp]
cmp ax,[di.CurrSamp]
je NoChangeSamp
mov al,SampleEndLo
out dx,al
inc dx
mov ax,Word Ptr [di.SampOff]
mov bp,Word Ptr [di.SampOff+2]
add ax,[di.Len]
adc bp,0
shr ax,7
shl bp,9
or ax,bp
out dx,ax
dec dx
mov al,SampleEndHi
out dx,al
inc dx
mov ax,Word Ptr [di.SampOff]
add ax,[di.Len]
shl ax,9
out dx,ax
dec dx
mov al,LoopStartLo
out dx,al
inc dx
mov ax,Word Ptr [di.SampOff]
mov bp,Word Ptr [di.SampOff+2]
add ax,[di.Repeat]
adc bp,0
shr ax,7
shl bp,9
or ax,bp
out dx,ax
dec dx
mov al,LoopStartHi
out dx,al
inc dx
mov ax,Word Ptr [di.SampOff]
add ax,[di.Repeat]
shl ax,9
out dx,ax
dec dx
mov al,WriteVoiceMode
out dx,al
add dx,2
mov al,3
out dx,al
sub dx,2
jmp NoChangeSamp
SampChange2:
mov ax,[di.OldSamp]
cmp ax,[di.CurrSamp]
je NoChangeSamp
mov al,VoicePosLo
out dx,al
inc dx
in ax,dx
mov bx,ax
dec dx
mov al,VoicePosHi
out dx,al
inc dx
in ax,dx
dec dx
xchg ax,bx
shl ax,7
shr bx,9
and bx,7Fh
or ax,bx
mov bx,[di.OldSamp]
dec bx
shl bx,2
sub ax,Word Ptr [SampOffset+bx]
mov bx,ax
cmp bx,[di.Len]
jb NoFixStart
mov bx,[di.Len]
dec bx
NoFixStart:
cmp [di.OffsetAdd],0
jne NoOffsetEff
mov [di.OffsetAdd],bx
NoOffsetEff:
mov al,SampleStartLo
out dx,al
inc dx
mov ax,Word Ptr [di.SampOff]
mov bp,Word Ptr [di.SampOff+2]
add ax,[di.OffsetAdd]
adc bp,0
shr ax,7
shl bp,9
or ax,bp
out dx,ax
dec dx
mov al,SampleStartHi
out dx,al
inc dx
mov ax,Word Ptr [di.SampOff]
add ax,[di.OffsetAdd]
shl ax,9
out dx,ax
sub dx,DataLowPort
Rept 6
in al,dx
EndM
add dx,CommandPort
mov al,SampleEndLo
out dx,al
inc dx
mov ax,Word Ptr [di.SampOff]
mov bp,Word Ptr [di.SampOff+2]
add ax,[di.Len]
adc bp,0
shr ax,7
shl bp,9
or ax,bp
out dx,ax
dec dx
mov al,SampleEndHi
out dx,al
inc dx
mov ax,Word Ptr [di.SampOff]
add ax,[di.Len]
shl ax,9
out dx,ax
dec dx
mov al,LoopStartLo
out dx,al
inc dx
mov ax,Word Ptr [di.SampOff]
mov bp,Word Ptr [di.SampOff+2]
add ax,[di.Repeat]
adc bp,0
shr ax,7
shl bp,9
or ax,bp
out dx,ax
dec dx
mov al,LoopStartHi
out dx,al
inc dx
mov ax,Word Ptr [di.SampOff]
add ax,[di.Repeat]
shl ax,9
out dx,ax
dec dx
mov al,WriteVoiceMode
out dx,al
add dx,2
mov al,Byte Ptr [di.LoopOnOff]
out dx,al
sub dx,DataHighPort
Rept 6
in al,dx
EndM
add dx,CommandPort
NoChangeSamp:
mov ax,[di.Vol]
cmp ax,[di.OldVol]
je NoSetBar
mov [di.Bar],ax
NoSetBar:
mov [TempVol],ax
mov ax,[Counter]
test [ChanOn],ax
jnz NoChanOff
mov [TempVol],0
mov [di.Bar],0
NoChanOff:
mov ax,[di.OldVol]
mov bx,[MainVolume]
mul bx
shr ax,6
adc ax,0
mov bx,ax
shl bx,1
mov bx,[GusVol+bx]
mov ax,[TempVol]
mov bp,[MainVolume]
mul bp
shr ax,6
adc ax,0
mov bp,ax
shl bp,1
mov bp,[GusVol+bp]
mov dx,bp
mov dl,bh
cmp dl,dh
jne SetVol
mov dx,[BasePort]
add dx,CommandPort
mov al,VolumeCtrl
out dx,al
add dx,2
mov al,3
out dx,al
sub dx,2
mov al,SetVolume
out dx,al
mov ax,bp
inc dx
out dx,ax
dec dx
jmp NoSetVol
SetVol:
mov dx,[BasePort]
add dx,CommandPort
mov al,VolumeCtrl
out dx,al
add dx,2
mov al,3
out dx,al
sub dx,2
mov ah,0
cmp bx,bp
jb NoFixVolDir
mov ah,01000000b
xchg bx,bp
NoFixVolDir:
mov dx,[BasePort]
add dx,CommandPort
mov al,VolRampStart
out dx,al
xchg ax,bx
inc dx
out dx,ax
dec dx
mov al,VolRampEnd
out dx,al
mov ax,bp
inc dx
out dx,ax
dec dx
mov al,VolumeCtrl
out dx,al
mov al,bh
add dx,2
out dx,al
sub dx,2
NoSetVol:
mov al,SetVoiceFreq
out dx,al
inc dx
mov ax,[di.FreqVal]
out dx,ax
dec dx
shl [Counter],1
add di,ChanSize
dec cx
jnz ChangeSamps
mov di,offset [SampChans]
mov cx,[NumChans]
StartVoices:
dec dx
mov al,Byte Ptr [NumChans]
sub al,cl
out dx,al
inc dx
cmp [di.InstSet],2
jne NoVoiceStart
mov al,WriteVoiceMode
out dx,al
add dx,2
mov al,Byte Ptr [di.LoopOnOff]
out dx,al
sub dx,DataHighPort
Rept 6
in al,dx
EndM
add dx,CommandPort
NoVoiceStart:
mov [di.InstSet],0
mov [di.OffsetAdd],0
add di,ChanSize
dec cx
jnz StartVoices
jmp EndPattern
JumpPattern:
mov [Counter],0
dec Word Ptr [PatternCount]
jnz DoEffects
jmp DoPattern
DoEffects:
mov di,offset [SampChans]
mov cx,[NumChans]
EffectLoop:
mov ax,[di.Vol]
mov [di.OldVol],ax
inc [di.EffectTime]
add [di.ArpCounter],2
cmp [di.ArpCounter],6
jb NoWrapArp
mov [di.ArpCounter],0
NoWrapArp:
mov ax,[di.Effect]
cmp ax,0
jne DoEffect
jmp NoEffect
DoEffect:
mov bl,al
mov bh,0
cmp bl,0Eh
je DoEEffects
shl bx,1
jmp cs:[EffectJumps+bx]
DoEEffects:
mov bl,ah
and ah,0Fh
shr bl,4
shl bx,1
jmp cs:[EEffectJumps+bx]
Arpeggio:
mov bx,[di.ArpCounter]
mov bx,[di.Arp+bx]
shl bx,1
mov ax,Word Ptr [FreqTable+bx]
mov [di.FreqVal],ax
jmp NoEffect
PortUp:
xchg ah,al
mov ah,0
mov bp,[di.Fine]
mov bp,[AmigaVals+35*2+bp]
mov bx,[di.Amiga]
sub bx,ax
jnc NoFix1
mov bx,bp
NoFix1:
cmp bx,bp
jae NotSmall1
mov bx,bp
NotSmall1:
mov [di.Amiga],bx
shl bx,1
mov ax,[FreqTable+bx]
mov [di.FreqVal],ax
jmp NoEffect
PortDown:
xchg ah,al
mov ah,0
mov bp,[di.Fine]
mov bp,[AmigaVals+bp]
mov bx,[di.Amiga]
add bx,ax
cmp bx,bp
jbe NotBig1
mov bx,bp
NotBig1:
mov [di.Amiga],bx
shl bx,1
mov ax,[FreqTable+bx]
mov [di.FreqVal],ax
jmp NoEffect
PortToTone:
xchg ah,al
xor ah,ah
mov dx,[di.PortTo]
mov bx,[di.Amiga]
cmp bx,dx
jae NoPortToUp
add bx,ax
cmp bx,dx
jna NoPortToUp
mov [di.Amiga],dx
NoPortToUp:
cmp bx,dx
jbe NoPortToDown
sub bx,ax
jnc NoPortToError
mov bx,dx
NoPortToError:
cmp bx,dx
jnb NoPortToDown
mov bx,dx
NoPortToDown:
mov [di.Amiga],bx
shl bx,1
mov ax,[FreqTable+bx]
mov [di.FreqVal],ax
jmp NoEffect
Vibrato:
mov bp,[di.Fine]
mov si,[AmigaVals+bp]
mov bp,[AmigaVals+35*2+bp]
mov dl,ah
and ah,0F0h
shr ah,2
and dl,0Fh
mov bl,Byte Ptr [di.VibratoPek]
add bl,ah
mov Byte Ptr [di.VibratoPek],bl
shr bl,2
and bx,1Fh
mov al,[SinTab+bx]
mul dl
rol ax,1
xchg ah,al
and ah,1
test Byte Ptr [di.VibratoPek],128
jne VibUp1
neg ax
VibUp1:
add ax,[di.Amiga]
cmp ax,bp
jae NoHighVibrato1
mov ax,bp
NoHighVibrato1:
cmp ax,si
jbe NoLowVibrato1
mov ax,si
NoLowVibrato1:
shl ax,1
mov bx,ax
mov ax,[FreqTable+bx]
mov [di.FreqVal],ax
jmp NoEffect
PortToVSlide:
mov al,ah
and ah,0Fh
shr al,4
sub ah,al
mov al,Byte Ptr [di.Vol]
sub al,ah
jns NoSlideLow2
mov al,0
NoSlideLow2:
cmp al,40h
jb NoSlideHigh2
mov al,3Fh
NoSlideHigh2:
mov Byte Ptr [di.Vol],al
mov ax,[di.OldPortTo]
mov dx,[di.PortTo]
mov bx,[di.Amiga]
cmp bx,dx
jae NoPortToUp2
add bx,ax
cmp bx,dx
jna NoPortToUp2
mov [di.Amiga],dx
NoPortToUp2:
cmp bx,dx
jbe NoPortToDown2
sub bx,ax
jnc NoPortToError2
mov bx,0
NoPortToError2:
cmp bx,dx
jnb NoPortToDown2
mov bx,dx
NoPortToDown2:
mov [di.Amiga],bx
shl bx,1
mov ax,Word Ptr [FreqTable+bx]
mov [di.FreqVal],ax
jmp NoEffect
VibratoVSlide:
mov al,ah
and ah,0Fh
shr al,4
sub ah,al
mov al,Byte Ptr [di.Vol]
sub al,ah
jns NoSlideLow3
mov al,0
NoSlideLow3:
cmp al,40h
jb NoSlideHigh3
mov al,3Fh
NoSlideHigh3:
mov Byte Ptr [di.Vol],al
mov bp,[di.Fine]
mov si,[AmigaVals+bp]
mov bp,[AmigaVals+35*2+bp]
mov ah,Byte Ptr [di.OldVibrato]
or ah,Byte Ptr [di.OldVibrato+1]
mov dl,ah
and ah,0F0h
shr ah,2
and dl,0Fh
mov bl,Byte Ptr [di.VibratoPek]
add bl,ah
mov Byte Ptr [di.VibratoPek],bl
shr bl,2
and bx,1Fh
mov al,[SinTab+bx]
mul dl
rol ax,1
xchg ah,al
and ah,1
test Byte Ptr [di.VibratoPek],128
jne VibUp2
neg ax
VibUp2:
add ax,[di.Amiga]
cmp ax,bp
jae NoHighVibrato2
mov ax,bp
NoHighVibrato2:
cmp ax,si
jbe NoLowVibrato2
mov ax,si
NoLowVibrato2:
shl ax,1
mov bx,ax
mov ax,[FreqTable+bx]
mov [di.FreqVal],ax
jmp NoEffect
VolSlide:
mov al,ah
and ah,0Fh
shr al,4
cmp al,0
je NoVolSlideUp
neg al
mov ah,al
NoVolSlideUp:
mov al,Byte Ptr [di.Vol]
sub al,ah
jns NoSlideLow1
mov al,0
NoSlideLow1:
cmp al,40h
jb NoSlideHigh1
mov al,3Fh
NoSlideHigh1:
mov Byte Ptr [di.Vol],al
jmp NoEffect
RetrigNote:
cmp ah,Byte Ptr [di.EffectTime]
jne NoRetrig
mov [di.EffectTime],0
mov [di.InstSet],2
NoRetrig:
jmp NoEffect
CutNote:
cmp ah,Byte Ptr [di.EffectTime]
jne NoCutNote
mov [di.Amiga],0
mov [di.FreqVal],0
NoCutNote:
jmp NoEffect
DelayNote:
cmp ah,Byte Ptr [di.EffectTime]
jne NoDelayNote
mov [di.InstSet],2
mov [di.VibratoPek],0
mov bx,[di.PortTo]
mov [di.Amiga],bx
shl bx,1
mov bx,[FreqTable+bx]
mov [di.FreqVal],bx
NoDelayNote:
jmp NoEffect
NoEffect:
add di,ChanSize
dec cx
jz EndEffects
jmp EffectLoop
EndEffects:
jmp EndPattern
DoPattern:
mov ax,[PatternSpeed]
mov [PatternCount],ax
cmp [PatternRow],64
jb NoPatternWrap
mov ax,[PlayingPattern]
cmp al,[OrderLen]
jb NoTrackWrap
mov ax,0
cmp [Restart],78h
jae NoRestart
mov al,[Restart]
NoRestart:
mov [PlayingPattern],ax
NoTrackWrap:
mov bx,[PlayingPattern]
mov [RealPPattern],bx
inc [RealPPattern]
mov ah,0
mov al,[PatternOrder+bx]
mov dx,[NumChans]
shl dx,8
mul dx
shl dx,12
add dx,[PatternMem]
mov [SegPattern],dx
mov [BytePattern],ax
mov ax,[BreakData]
mov [PatternRow],ax
shl ax,4
add [BytePattern],ax
mov [BreakData],0
inc [PlayingPattern]
NoPatternWrap:
les si,[PatternPek]
mov di,offset [SampChans]
mov cx,[NumChans]
mov ax,[PatternRow]
mov [RealRow],ax
PattLoop:
mov ax,[di.Vol]
mov [di.OldVol],ax
mov bh,es:[si] ; New Sample
mov bl,es:[si+2]
and bh,0F0h
shr bl,4
add bl,bh
je NoNewSample
mov bh,Byte Ptr [di.CurrSamp]
mov Byte Ptr [di.OldSamp],bh
mov Byte Ptr [di.CurrSamp],bl
mov bh,0
dec bx
shl bx,1
mov ax,[SampVol+bx]
cmp ax,40h
jb NoHighVol
mov ax,3Fh
NoHighVol:
mov [di.Vol],ax
mov [di.InstSet],1
shl bx,1
mov ax,Word Ptr [SampOffset+bx]
mov Word Ptr [di.SampOff],ax
mov ax,Word Ptr [SampOffset+bx+2]
mov Word Ptr [di.SampOff+2],ax
shr bx,1
mov ax,[SampFine+bx]
shl ax,3
mov [di.Fine],ax
shl ax,3
add [di.Fine],ax
mov [di.LoopOnOff],0
mov ax,[SampLen+bx]
mov [di.Len],ax
mov ax,[SampRep+bx]
mov [di.Repeat],ax
mov ax,[SampRepLen+bx]
mov [di.RepLen],ax
cmp ax,2
jbe NoNewSample
mov [di.LoopOnOff],8
mov ax,[di.Repeat]
add ax,[di.RepLen]
cmp ax,[di.Len]
ja NoNewSample
mov [di.Len],ax
NoNewSample:
mov bx,es:[si]
xchg bh,bl
and bx,0FFFh
je NoNewNote
mov bl,[ArpTable+bx]
mov bh,0
add bx,[di.Fine]
mov bx,[AmigaVals+bx]
mov [di.PortTo],bx
mov ax,es:[si+2]
and al,0Fh
and ah,0F0h
cmp al,03h
je PortToP
cmp al,05h
je PortToP
jmp NoPortToP
PortToP:
push cx
neg cx
add cx,[NumChans]
mov ax,1
shl ax,cl
test ax,[ChanOn]
je NoSetPortBar
mov ax,[di.Vol]
mov [di.Bar],ax
NoSetPortBar:
pop cx
jmp NoNewNote
NoPortToP:
cmp ax,0D00Eh
jne NewNote
mov al,es:[si+2]
cmp al,0
je NewNote
mov [di.InstSet],0
jmp NoNewNote
NewNote:
mov [di.InstSet],2
mov [di.VibratoPek],0
mov [di.Amiga],bx
shl bx,1
mov bx,[FreqTable+bx]
mov [di.FreqVal],bx
NoNewNote:
mov [di.ArpCounter],0
mov ax,es:[si+2]
and al,0Fh
mov [di.Effect],ax
cmp al,7
jb NoSetOldFreq
mov bx,ax
and bh,0F0h
cmp bx,0C00Eh
je NoSetOldFreq
cmp bx,0D00Eh
je NoSetOldFreq
mov bx,[di.Amiga]
shl bx,1
mov bx,[FreqTable+bx]
mov [di.FreqVal],bx
NoSetOldFreq:
mov bh,0
mov bl,al
cmp bl,0Eh
je DoEPattEffects
shl bx,1
jmp cs:[PattJumps+bx]
DoEPattEffects:
mov bl,ah
and ah,0Fh
shr bl,4
shl bx,1
jmp cs:[EPattJumps+bx]
ArpeggioFix:
mov bx,[di.Amiga]
mov bl,[ArpTable+bx]
mov bh,0
mov bp,bx
add bx,[di.Fine]
mov dx,[AmigaVals+bx]
mov [di.Arp],dx
xchg ah,al
mov ah,0
mov dx,ax
shr dx,4
and ax,0Fh
shl dx,1
shl ax,1
mov bx,bp
add bx,dx
cmp bx,70
jbe NoWrapArp1
mov bx,70
NoWrapArp1:
add bx,[di.Fine]
mov dx,[AmigaVals+bx]
mov [di.Arp+2],dx
mov bx,bp
add bx,ax
cmp bx,70
jbe NoWrapArp2
mov bx,70
NoWrapArp2:
add bx,[di.Fine]
mov dx,[AmigaVals+bx]
mov [di.Arp+4],dx
jmp NoPattEffect
PortToFix:
cmp ah,0
jne NoPortPekFix
mov ah,Byte Ptr [di.OldPortTo]
NoPortPekFix:
mov Byte Ptr [di.OldPortTo],ah
mov Byte Ptr [di.Effect+1],ah
jmp NoPattEffect
VibratoFix:
mov al,ah
and al,0Fh
and ah,0F0h
cmp al,0
jne NoVibratoFix1
mov al,Byte Ptr [di.OldVibrato]
NoVibratoFix1:
cmp ah,0
jne NoVibratoFix2
mov ah,Byte Ptr [di.OldVibrato+1]
NoVibratoFix2:
mov Byte Ptr [di.OldVibrato],al
mov Byte Ptr [di.OldVibrato+1],ah
or al,ah
mov Byte Ptr [di.Effect+1],al
jmp NoPattEffect
SampleOff:
mov al,0
cmp ax,[di.Len]
jb NoFixOffset
mov ax,[di.Len]
dec ax
NoFixOffset:
mov [di.OffsetAdd],ax
jmp NoPattEffect
PosJump:
mov [PatternRow],63
mov Byte Ptr [PlayingPattern],ah
jmp NoPattEffect
Volume:
cmp ah,40h
jb NoFixVol1
mov ah,3Fh
NoFixVol1:
mov Byte Ptr [di.Vol],ah
jmp NoPattEffect
BreakPatt:
mov [PatternRow],63
cmp ah,64h
jb NoFixBreak
mov ah,63h
NoFixBreak:
mov al,ah
and al,0Fh
shr ah,4
shl ah,1
mov Byte Ptr [BreakData],al
add Byte Ptr [BreakData],ah
shl ah,2
add Byte Ptr [BreakData],ah
jmp NoPattEffect
SpeedSet:
cmp ah,0
je NoPattEffect
cmp ah,1Fh
jbe UsualSpeed
xchg ah,al
mov ah,0
shl ax,1 ;
mov bl,5 ; Denna bit är för att ställa
div bl ; Effects till annat än 50Hz
mov dl,al ; Detta ger automatiskt en annan
mov dh,0 ; patternspeed.; Hz=2*BPM/5
mov ax,0
mov bx,1000
div bx
mov Word Ptr cs:[Speed],ax
mov ax,0
div bx
mov Word Ptr cs:[Speed+2],ax
jmp NoPattEffect
UsualSpeed:
mov Byte Ptr [PatternSpeed],ah
mov Byte Ptr [PatternCount],ah
jmp NoPattEffect
FinePortUp:
xchg ah,al
mov ah,0
sub [di.Amiga],ax
mov bx,[di.Fine]
mov bx,[AmigaVals+35*2+bx]
cmp [di.Amiga],bx
jae NoFixFineUp
mov [di.Amiga],bx
NoFixFineUp:
jmp NoPattEffect
FinePortDown:
xchg ah,al
mov ah,0
add [di.Amiga],ax
mov bx,[di.Fine]
mov bx,[AmigaVals+bx]
cmp [di.Amiga],bx
jbe NoFixFineDown
mov [di.Amiga],bx
NoFixFineDown:
jmp NoPattEffect
FineVolUp:
add Byte Ptr [di.Vol],ah
cmp Byte Ptr [di.Vol],3Fh
jbe NoFixFineVolUp
mov Byte Ptr [di.Vol],3Fh
NoFixFineVolUp:
jmp NoPattEffect
FineVolDown:
sub Byte Ptr [di.Vol],ah
jnc NoFixFineVolDown
mov Byte Ptr [di.Vol],0
NoFixFineVolDown:
jmp NoPattEffect
NoPattEffect:
add si,4
jnc NoChangeSeg1
mov dx,es
add dx,1000h
mov es,dx
NoChangeSeg1:
mov [di.EffectTime],0
add di,ChanSize
dec cx
jz EndChannels
jmp PattLoop
EndChannels:
inc [PatternRow]
mov ax,[NumChans]
shl ax,2
add [BytePattern],ax
jnc EndPattern
add [SegPattern],1000h
EndPattern:
dec [JumpOldTimer]
jnz NoJumpOld
mov [JumpOldTimer],55
pop es
pop ds
popa
jmp DWord Ptr cs:[OldTimer]
NoJumpOld:
pop es
pop ds
popa
iret
Pattern EndP
PattJumps dw offset cs:[ArpeggioFix] ; 0
dw offset cs:[NoPattEffect] ; 1
dw offset cs:[NoPattEffect] ; 2
dw offset cs:[PortToFix] ; 3
dw offset cs:[VibratoFix] ; 4
dw offset cs:[NoPattEffect] ; 5
dw offset cs:[NoPattEffect] ; 6
dw offset cs:[NoPattEffect] ; 7
dw offset cs:[NoPattEffect] ; 8
dw offset cs:[SampleOff] ; 9
dw offset cs:[NoPattEffect] ; A
dw offset cs:[PosJump] ; B
dw offset cs:[Volume] ; C
dw offset cs:[BreakPatt] ; D
dw offset cs:[NoPattEffect] ; E
dw offset cs:[SpeedSet] ; F
EPattJumps dw offset cs:[NoPattEffect] ; 0
dw offset cs:[FinePortUp] ; 1
dw offset cs:[FinePortDown] ; 2
dw offset cs:[NoPattEffect] ; 3
dw offset cs:[NoPattEffect] ; 4
dw offset cs:[NoPattEffect] ; 5
dw offset cs:[NoPattEffect] ; 6
dw offset cs:[NoPattEffect] ; 7
dw offset cs:[NoPattEffect] ; 8
dw offset cs:[NoPattEffect] ; 9
dw offset cs:[FineVolUp] ; A
dw offset cs:[FineVolDown] ; B
dw offset cs:[NoPattEffect] ; C
dw offset cs:[NoPattEffect] ; D
dw offset cs:[NoPattEffect] ; E
dw offset cs:[NoPattEffect] ; F
EffectJumps dw offset cs:[Arpeggio] ; 0
dw offset cs:[PortUp] ; 1
dw offset cs:[PortDown] ; 2
dw offset cs:[PortToTone] ; 3
dw offset cs:[Vibrato] ; 4
dw offset cs:[PortToVSlide] ; 5
dw offset cs:[VibratoVSlide] ; 6
dw offset cs:[NoEffect] ; 7
dw offset cs:[NoEffect] ; 8
dw offset cs:[NoEffect] ; 9
dw offset cs:[VolSlide] ; A
dw offset cs:[NoEffect] ; B
dw offset cs:[NoEffect] ; C
dw offset cs:[NoEffect] ; D
dw offset cs:[NoEffect] ; E
dw offset cs:[NoEffect] ; F
EEffectJumps dw offset cs:[NoEffect] ; 0
dw offset cs:[NoEffect] ; 1
dw offset cs:[NoEffect] ; 2
dw offset cs:[NoEffect] ; 3
dw offset cs:[NoEffect] ; 4
dw offset cs:[NoEffect] ; 5
dw offset cs:[NoEffect] ; 6
dw offset cs:[NoEffect] ; 7
dw offset cs:[NoEffect] ; 8
dw offset cs:[RetrigNote] ; 9
dw offset cs:[NoEffect] ; A
dw offset cs:[NoEffect] ; B
dw offset cs:[CutNote] ; C
dw offset cs:[DelayNote] ; D
dw offset cs:[NoEffect] ; E
dw offset cs:[NoEffect] ; F
assume ds:nothing
StartPlaying Proc Far
pusha
push ds
push es
cli
mov [JumpOldTimer],55
mov di,offset cs:[SampChans]
mov cx,cs:[NumChans]
ClearVarLoop:
mov cs:[di.FreqVal],0
mov cs:[di.Vol],0
add di,ChanSize
loop ClearVarLoop
mov ax,0
mov es,ax
mov bx,es:[20h]
mov ax,es:[22h]
mov Word Ptr cs:[OldTimer],bx
mov Word Ptr cs:[OldTimer+2],ax
push cs
pop ds
mov dx,offset cs:[Pattern]
mov es:[20h],dx
mov es:[22h],ds
mov al,36h
out 43h,al
mov al,169
out 40h,al
mov al,4
out 40h,al
mov ax,0
mov dx,50
mov bx,1000
div bx
mov Word Ptr cs:[Speed],ax
mov ax,0
div bx
mov Word Ptr cs:[Speed+2],ax
mov Word Ptr cs:[SpeedAdd],0
mov Word Ptr cs:[SpeedAdd+2],0
mov [Counter],20
mov Word Ptr [Time],0
mov Word Ptr [Time+2],0
; mov dx,cs:[BasePort] ; Speaker On!!!
; mov al,00000001b
; out dx,al
sti
pop es
pop ds
popa
ret
StartPlaying EndP
StopPlaying Proc Far
pusha
push ds
push es
cli
; mov dx,cs:[BasePort] ; Speaker Off!!!
; mov al,00000011b
; out dx,al ; We don't REALLY want to
; turn it off.. do we?
mov ax,0
mov es,ax
mov al,36h
out 43h,al
mov al,0
out 40h,al
mov al,0
out 40h,al
mov dx,Word Ptr cs:[OldTimer]
mov ds,Word Ptr cs:[OldTimer+2]
mov es:[20h],dx
mov es:[22h],ds
sti
mov dx,cs:[BasePort]
add dx,ActiveVoicePort
; mov cx,NumVoices ; Wouldn't wanna turn of the SFX..
mov cx,cs:[NumChans]
VoiceClearL:
mov al,cl
dec al
out dx,al
inc dx
mov al,0
out dx,al
add dx,2
mov al,3 ; Voice Off
out dx,al
sub dx,2
mov al,0Dh
out dx,al
add dx,2
mov al,3 ; Ramp Off
out dx,al
sub dx,3
loop VoiceClearL
pop es
pop ds
popa
ret
StopPlaying EndP
Init Proc Far
pusha
push ds
push es
mov cs:[PatternRow],64
mov cs:[PlayingPattern],0
mov cs:[PatternSpeed],6
mov cs:[PatternCount],1
pop es
pop ds
popa
ret
Init EndP
InitDevice Proc Far
pusha
push es
push ds
mov si,108*2
mov bp,108
mov cx,908-108+1
CountLoop:
mov dx,36h
mov ax,9DE4h
div bp
mov dx,100
mul dx
mov bx,DivVoices
div bx
shr bx,1
adc bx,0
cmp dx,bx
jb NoHigherFreq
inc ax
NoHigherFreq:
mov Word Ptr cs:[FreqTable+si],ax
inc bp
add si,2
loop CountLoop
; Init the UltraSound
cli
mov bx,cs:[BasePort]
mov cx,bx
mov dx,bx
mov al,00000011b
out dx,al ; Speaker off...
add bx,CommandPort
add cx,DataHighPort
mov dx,bx
mov al,Initialize
out dx,al
mov dx,cx
mov al,00000000b
out dx,al ; Enter RESET state.
mov dx,cs:[BasePort]
Rept 6
in al,dx
EndM
mov dx,bx
mov al,Initialize
out dx,al
mov dx,cx
mov al,00000001b
out dx,al ; Deactivate RESET state.
mov dx,cs:[BasePort]
Rept 6
in al,dx
EndM
mov dx,bx
mov al,DMACtrl
out dx,al
mov dx,cx
mov al,0
out dx,al ; Turn off DMA stuff
mov dx,bx
mov al,TimerCtrl ; 45h
out dx,al
mov dx,cx
mov al,0
out dx,al ; Turn off timer IRQ's
mov dx,bx
mov al,SampleCtrl ; 49h
out dx,al
mov dx,cx
mov al,0
out dx,al ; Disable sampling
mov dx,bx
mov al,VoicesActive
out dx,al
mov dx,cx
mov al,NumVoices
dec al
or al,0C0h
out dx,al ; Set active voices
mov dx,cs:[BasePort]
add dx,StatusPort
in al,dx
mov dx,bx
mov al,DMACtrl
out dx,al
mov dx,cx
in al,dx
mov dx,bx
mov al,SampleCtrl
out dx,al
mov dx,cx
in al,dx
mov dx,bx
mov al,IRQStatus ; 8Fh
out dx,al
mov dx,cx
in al,dx
push cx
mov cx,32
VoiceClearLoop:
mov dx,cs:[BasePort]
add dx,ActiveVoicePort
mov al,cl
dec al
out dx,al
inc dx
mov al,0
out dx,al
add dx,2
mov al,3 ; Voice Off
out dx,al
sub dx,2
mov al,VolumeCtrl
out dx,al
add dx,2
mov al,3 ; Ramp Off
out dx,al
loop VoiceClearLoop
pop cx
mov dx,bx
mov al,DMACtrl
out dx,al
mov dx,cx
in al,dx
mov dx,bx
mov al,SampleCtrl
out dx,al
mov dx,cx
in al,dx
mov dx,bx
mov al,IRQStatus
out dx,al
mov dx,cx
in al,dx
mov dx,bx
mov al,Initialize
out dx,al
mov dx,cx
mov al,00000011b ; Reset off, DAC on, IRQs OFF.
out dx,al
mov cx,NumVoices
SetRampRateLoop:
mov dx,cs:[BasePort]
add dx,ActiveVoicePort
mov al,NumVoices
sub al,cl
out dx,al
mov dx,cs:[BasePort]
add dx,CommandPort
mov al,VolRampRate
out dx,al
mov al,00111111b
mov dx,cs:[BasePort]
add dx,DataHighPort
out dx,al
mov dx,cs:[BasePort]
add dx,CommandPort
mov al,SetVolume
out dx,al
mov ax,cs:[GusVol]
mov dx,cs:[BasePort]
add dx,DataLowPort
out dx,ax
loop SetRampRateLoop
mov dx,cs:[BasePort]
mov al,00000000b
out dx,al ; Speaker On! (and line-in enabled)
sti
; Finished Initialize (Pheewww!!!!!!!!!!!!!)
pop ds
pop es
popa
ret
InitDevice EndP
ClearMem Proc Far
pusha
push es
mov es,cs:[PatternMem]
call DeAlloc
pop es
popa
ret
ClearMem EndP
LoadMod Proc Near
; Error if CF set! ax=errorcode.
; ax=1, File or path not found.
; ax=2, Error loading file.
; ax=3, Out of memory.
call FileOpen
jnc NoOpenError
mov ax,[ErrorCode]
jmp NoMod
NoOpenError:
call ModLoad
jnc NoLoadError
mov ax,[ErrorCode]
jmp NoMod
NoLoadError:
call FileClose
NoMod:
ret
LoadMod EndP
ModLoad Proc Near
pusha
push ds
push es
mov cs:[MainVolume],64
mov cx,1084
mov dx,offset cs:[Info]
push cs
pop ds
call FileRead
mov cs:[NumChans],4
mov bp,offset cs:[Info+1080]
mov bx,0
mov cx,4
TestInst1:
mov al,cs:[bp]
cmp al,cs:[MKSign+bx]
jne NoMK1
inc bp
inc bx
loop TestInst1
mov si,offset cs:[Info+952]
mov cs:[MKMod],1
jmp Load
NoMK1:
mov bp,offset cs:[Info+1080]
mov bx,4
mov cx,4
TestInst2:
mov al,cs:[bp]
cmp al,cs:[MKSign+bx]
jne NoMK2
inc bp
inc bx
loop TestInst2
mov si,offset cs:[Info+952]
mov cs:[MKMod],1
jmp Load
NoMK2:
mov bp,offset cs:[Info+1080]
mov bx,8
mov cx,4
TestInst3:
mov al,cs:[bp]
cmp al,cs:[MKSign+bx]
jne No6CHN2
inc bp
inc bx
loop TestInst3
mov cs:[MainVolume],48
mov cs:[NumChans],6
mov si,offset cs:[Info+952]
mov cs:[MKMod],1
jmp Load
No6CHN2:
mov bp,offset cs:[Info+1080]
mov bx,12
mov cx,4
TestInst4:
mov al,cs:[bp]
cmp al,cs:[MKSign+bx]
jne No8CHN3
inc bp
inc bx
loop TestInst4
mov cs:[MainVolume],32
mov cs:[NumChans],8
mov si,offset cs:[Info+952]
mov cs:[MKMod],1
jmp Load
No8CHN3:
mov bp,offset cs:[Info+1080]
mov bx,16
mov cx,4
TestInst5:
mov al,cs:[bp]
cmp al,cs:[MKSign+bx]
jne STMod
inc bp
inc bx
loop TestInst5
mov cs:[MainVolume],32
mov cs:[NumChans],8
mov si,offset cs:[Info+952]
mov cs:[MKMod],1
jmp Load
STMod:
call MovePoint
mov dx,offset cs:[Info]
mov cx,600
call FileRead
mov si,offset cs:[Info+472]
mov cs:[MKMod],0
Load:
mov ax,cs:[si-2]
mov Word Ptr cs:[OrderLen],ax
mov di,offset cs:[PatternOrder]
mov cx,128
CopyOrder:
mov al,cs:[si]
mov cs:[di],al
inc si
inc di
loop CopyOrder
mov si,offset cs:[PatternOrder]
mov cx,128
mov ax,0
CheckPatt:
mov al,cs:[si]
cmp al,ah
jb NoHigh
xchg ah,al
NoHigh:
inc si
loop CheckPatt
inc ah
xor al,al
mov bx,cs:[NumChans]
mul bx
mov si,dx
mov di,ax
mov bx,16
div bx
mov bx,ax
call Alloc
jnc NoOutHunk
stc
mov cs:[ErrorCode],3
jmp ErrorLoad ; Fixa nån slags error-flagga.
NoOutHunk:
mov cs:[PatternMem],ax
mov ds,ax
LoadLoop:
dec si
js EndBigLoad
mov dx,0
mov cx,65535
call FileRead
mov dx,65535
mov cx,1
call FileRead
mov dx,ds
add dx,1000h
mov ds,dx
jmp Short LoadLoop
EndBigLoad:
mov cx,di
mov dx,0
call FileRead
mov cx,15
cmp cs:[MKMod],1
jne NoMK
mov cx,31
NoMK:
mov bx,4096
call Alloc
mov cs:[SampMem],ax
push ax
mov ax, Word Ptr cs:[GUSMemProt]
mov Word Ptr cs:[GUSMem], ax
mov ax, Word Ptr cs:[GUSMemProt+2]
mov Word Ptr cs:[GUSMem+2], ax
pop ax
mov si,offset cs:[Info+42]
mov bp,0
LoadIns:
push cx
mov Word Ptr cs:[SampLen+bp],0
mov cx,cs:[si]
add si,2
xchg ch,cl
cmp cx,2
jbe NoIns
shl cx,1
mov cs:[SampLen+bp],cx
mov ds,cs:[SampMem]
mov dx,0
call FileRead
; Lets move the sample to the UltraSound!
push bp
mov cx,cs:[SampLen+bp]
shl bp,1
mov di,Word Ptr cs:[GUSMem]
mov bl,Byte Ptr cs:[GUSMem+2]
mov Word Ptr [SampOffset+bp],di
mov Byte Ptr [SampOffset+bp+2],bl
mov bp,di
mov di,0
mov dx,cs:[BasePort]
add dx,CommandPort
MSamp2GUS:
mov al,DRAMAddrLo
out dx,al
inc dx
mov ax,bp
out dx,ax
dec dx
mov al,DRAMAddrHi
out dx,al
add dx,2
mov al,bl
out dx,al
add dx,2
mov al,[di]
out dx,al
sub dx,4
inc di
add bp,1
adc bl,0
loop MSamp2GUS
dec di
mov al,DRAMAddrLo
out dx,al
inc dx
mov ax,bp
out dx,ax
dec dx
mov al,DRAMAddrHi
out dx,al
add dx,2
mov al,bl
out dx,al
add dx,2
mov al,[di]
out dx,al
sub dx,4
add bp,1
adc bl,0
mov Word Ptr cs:[GUSMem],bp
mov Byte Ptr cs:[GUSMem+2],bl
pop bp
NoIns:
mov ah,0
mov al,cs:[si]
inc si
mov cs:[SampFine+bp],ax
mov al,cs:[si]
inc si
mov Byte Ptr cs:[SampVol+bp],al
mov dx,cs:[SampLen+bp]
mov ax,cs:[si]
add si,2
xchg ah,al
mov cx,cs:[si]
add si,2
xchg ch,cl
cmp cs:[MKMod],1
jne STMod1
shl ax,1
shl cx,1
STMod1:
mov cs:[SampRepLen+bp],cx
add cx,ax
cmp cx,dx
jbe NoRepFix
mov cx,dx
sub cx,ax
mov cs:[SampRepLen+bp],cx
NoRepFix:
mov cs:[SampRep+bp],ax
add si,22
add bp,2
pop cx
dec cx
jz Loaded
jmp LoadIns
Loaded:
mov es,cs:[SampMem]
call DeAlloc
mov cs:[ErrorCode],0
clc
; Set Pan Regs!!
ErrorLoad:
mov cx,cs:[NumChans]
mov bx,cx
shr bx,1
sub bx,2
shl bx,4
mov cx,16 ; Bjarni
SetPanLoop:
mov dx,cs:[BasePort]
add dx,ActiveVoicePort
mov al,Byte Ptr cs:[NumChans]
sub al,cl
out dx,al
mov dx,cs:[BasePort]
add dx,CommandPort
mov al,VoiceBalance
out dx,al
mov dx,cs:[BasePort]
add dx,DataHighPort
mov al,cs:[PanRegs+bx]
out dx,al
inc bx
loop SetPanLoop
pop es
pop ds
popa
ret
ModLoad EndP
Alloc Proc Near
push bx
mov ax,4800h
int 21h
pop bx
ret
Alloc EndP
DeAlloc Proc Near
push ax
push es
mov ax,4900h
int 21h
pop es
pop ax
ret
DeAlloc EndP
FileRead Proc Near
push ax
push bx
push cx
push dx
push ds
mov ax,3F00h
mov bx,cs:[FileHandle]
int 21h
pop ds
pop dx
pop cx
pop bx
pop ax
ret
FileRead EndP
FileOpen Proc Near
push dx
push ds
mov ax,3D00h
int 21h
mov cs:[FileHandle],ax
jnc NoErrorOpen
mov cs:[ErrorCode],1
NoErrorOpen:
pop ds
pop dx
ret
FileOpen EndP
FileClose Proc Near
push ax
push bx
mov ax,3E00h
mov bx,cs:[FileHandle]
int 21h
pop bx
pop ax
ret
FileClose EndP
MovePoint Proc Near
push ax
push bx
push cx
push dx
mov ax,4200h
mov bx,cs:[FileHandle]
mov cx,0
mov dx,0
int 21h
pop dx
pop cx
pop bx
pop ax
ret
MovePoint EndP
Comment &
─────────────────────────────────────────────────────────────────────────────
These are the GUS routines distributed by Renaissance..
Slightly modified to work with the rest of it of course.
-- Juggler
─────────────────────────────────────────────────────────────────────────────
&
UDelay Proc Near
push dx
push ax
mov dx,300h
in al,dx
in al,dx
in al,dx
in al,dx
in al,dx
in al,dx
in al,dx
pop ax
pop dx
ret
UDelay EndP
; CX:AX - Number
; Destroys BX
RShift Proc Near
mov bx,cx
shr ax,7
shr cx,7
shl bx,9
or ax,bx
ret
RShift EndP
; BX:CX Set to whatever.
; AL Set set to value at BX:CX
; AH Destroyed
U_Peek Proc Far
push dx
mov dx,cs:[BasePort]
add dx,CommandPort
mov al,43h
out dx,al
inc dx ; DataLowPort
mov ax,cx
out dx,ax
dec dx ; CommandPort
mov al,44h
out dx,al
add dx,2
mov al,bl
out dx,al
add dx,2
in al,dx
pop dx
ret
U_Peek EndP
; BX:CX Set to whatever.
; AX Value to poke
U_Poke Proc Far
push dx
push ax
mov dx,cs:[BasePort]
add dx,CommandPort
mov al,DRAMAddrLo
out dx,al
inc dx ; DataLowPort
mov ax,cx
out dx,ax
dec dx ; CommandPort
mov al,DRAMAddrHi
out dx,al
add dx,2 ; DataHighPort
mov al,bl
out dx,al
add dx,2 ; DRAMIOPort
pop ax
out dx,al
pop dx
ret
U_Poke EndP
; BX - Voice
; AX - Frequency
; Destroys CX, DX
U_SetFreq Proc Far ; Close enough for me...
xor dx,dx
mov cx,DivVoices/100
div cx
push ax
mov dx,cs:[BasePort]
add dx,ActiveVoicePort
mov ax,bx
out dx,al
inc dx ; CommandPort
mov al,1
out dx,al
inc dx ; DataLowPort
pop ax
out dx,ax
ret
U_SetFreq EndP
; AX - Voice
; BX - Balance (0-f) 7 is middle
; Destroys DX
U_SetBalance Proc Far
mov dx,cs:[BasePort]
add dx,ActiveVoicePort
out dx,al
inc dx
mov al,VoiceBalance
out dx,al
add dx,2
mov ax,bx
out dx,al
ret
U_SetBalance EndP
; AX - Voice
; BX - Volume
; Destroys DX
U_SetVolume Proc Far
mov dx,cs:[BasePort]
add dx,ActiveVoicePort
out dx,al
inc dx ; CommandPort
mov al,SetVolume
out dx,al
inc dx ; DataLowPort
mov ax,bx
out dx,ax
ret
endp U_SetVolume
; AX - Voice
; BX - Mode
; bit 0: 0=voice on (along with bit 1)
; bit 1: 0=voice on (along with bit 0)
; bit 2: 0=8 bit data, 1=16 bit data
; bit 3: 0=No loop, 1=Loop
; bit 4: 0=Go forward, 1=Go backward
U_SetLoopMode Proc Far
mov dx,cs:[BasePort]
add dx,ActiveVoicePort
out dx,al
inc dx ; CommandPort
mov al,80h
add dx,2 ; DataHighPort
in al,dx
mov bh,al
sub dx,2 ; CommandPort
xor al,al
out dx,al
add dx,2 ; DataHighPort
and bh,0E7h
or bh,bl
mov al,bh
out dx,al
ret
U_SetLoopMode EndP
; AX - Voice
; Destroys DX, BX
U_StopVoice Proc Far
mov dx,cs:[BasePort]
add dx,ActiveVoicePort
out dx,al
inc dx ; CommandPort
mov al,80h
add dx,2 ; DataHighPort
in al,dx
mov bh,al
sub dx,2 ; CommandPort
xor al,al
out dx,al
add dx,2 ; DataHighPort
mov al,bh
and bh,0DFh
or al,3
out dx,al
call UDelay
sub dx,2 ; CommandPort
xor al,al
out dx,al
add dx,2 ; DataHighPort
mov al,bh
and bh,0DFh
or al,3
out dx,al
ret
U_StopVoice EndP
_SampleBegin dd 0 ; Start location in DRAM
; (apparently 32-byte aligned) NOT!
_SampleStart dd 0 ; Start location of loop
_SampleEnd dd 0 ; End of sample
; AX - Voice
; BX - Mode
_U_StartVoice Proc Near
push bx
mov dx,cs:[BasePort]
add dx,ActiveVoicePort
out dx,al
; ***** Send sample begin
inc dx ; CommandPort 103h
mov al,SampleStartLo
out dx,al
inc dx ; DataLowPort 104h
mov ax,Word Ptr cs:[_SampleBegin]
mov cx,Word Ptr cs:[_SampleBegin+2]
call RShift
out dx,ax
dec dx ; CommandPort 103h
mov al,SampleStartHi
out dx,al
inc dx ; DataLowPort 104h
mov ax,Word Ptr cs:[_SampleBegin]
shl ax,9
out dx,ax
; ***** Send sample start
dec dx ; CommandPort 103h
mov al,2
out dx,al
inc dx ; DataLowPort 104h
mov ax,Word Ptr cs:[_SampleStart]
mov cx,Word Ptr cs:[_SampleStart+2]
call RShift
out dx,ax
dec dx ; CommandPort 103h
mov al,3
out dx,al
inc dx ; DataLowPort 104h
mov ax,Word Ptr cs:[_SampleStart]
shl ax,9
out dx,ax
; ***** Send sample end
dec dx ; CommandPort 103h
mov al,4
out dx,al
inc dx ; DataLowPort 104h
mov ax,Word Ptr cs:[_SampleEnd]
mov cx,Word Ptr cs:[_SampleEnd+2]
call RShift
out dx,ax
dec dx ; CommandPort 103h
mov al,5
out dx,al
inc dx ; DataLowPort 104h
mov ax,Word Ptr cs:[_SampleEnd]
shl ax,9
out dx,ax
dec dx ; CommandPort 103h
; ***** Play it! (I hope)
mov al,0
out dx,al
pop ax
add dx,2 ; DataHighPort 105h
out dx,al
ret
endp _U_StartVoice
U_StartVoice Proc Far Voice:Word,LoopMode:Word,StartP:Dword,BeginP:Dword,SEndP:Dword
mov ax,Word Ptr [StartP]
mov bx,Word Ptr [StartP+2]
mov Word Ptr cs:[_SampleBegin ],ax
mov Word Ptr cs:[_SampleBegin+2],bx
ret
U_StartVoice EndP
; AX - Voice
; Returns: DX:AX - Position
; Wastes CX
U_ReadPos Proc Far
mov dx,cs:[BasePort]
add dx,ActiveVoicePort
out dx,al
inc dx ; CommandPort 103h
mov al,VoicePosLo
out dx,al
inc dx ; DataLowPort 104h
in ax,dx ; TEMP0
mov cx,ax
dec dx ; CommandPort 103h
mov al,VoicePosHi
out dx,al
inc dx ; DataLowPort 104h
in ax,dx ; TEMP1
shl cx,7
shr ax,9
and ax,7Fh
mov dx,ax
and dx,0Fh
mov ax,cx
ret
U_ReadPos EndP
; AX - Mixer control
; bit 0: 0=linein on, 1=linein off
; bit 1: 0=output on, 1=output off
; bit 2: 0=micin off, 1=micin on
U_ChangeInOut Proc Far
mov dx,cs:[BasePort]
out dx,al
ret
U_ChangeInOut EndP
; The only reason I do it this way is because I haven't figured out the dump
; RAM to DRAM via DMA yet.
;
; Dump sample to Ram
; ES:BX - Max 64k sample to dump to RAM.
; SI:DI - DRAM location to dump to.
; CX - Max bytes to dump.
; AH - Xor value for twos complement. Should actually be negated, but
; oh, well.
; Wastes BX, DX
;
; Approximate time to dump 1 megabyte of samples to DRAM (assuming they were
; all loaded in memory) is 5 seconds.
U_DumpSampleToDRAM Proc Far
push ds
mov dx,cs:[BasePort]
add dx,CommandPort
mov al,DRAMAddrHi ; Dump upper byte, only do
out dx,al ; it on carry from now on.
add dx,2 ; DataHighPort
push ax
mov ax,si
out dx,al
pop ax
sub dx,2 ; CommandPort
@@MainLoop:
mov al,DRAMAddrLo
out dx,al
inc dx ; DataLowPort
push ax
mov ax,di
out dx,ax
pop ax
dec dx ; CommandPort
add di,1
jnc @@DumpByte
inc si
mov al,DRAMAddrHi
out dx,al
add dx,2 ; DataHighPort
push ax
mov ax,si
out dx,al
pop ax
sub dx,2 ; CommandPort
@@DumpByte:
add dx,4 ; DRAMIOPort
mov al,es:[bx]
xor al,ah
inc bx
out dx,al
sub dx,4 ; CommandPort
loop @@MainLoop
pop ds
ret
U_DumpSampleToDRAM EndP
; Same as above, but strawkcab?
; Uncommented in the Ultradox..
;
U_DumpDRAMToMemory Proc Far
mov dx,cs:[BasePort]
add dx,CommandPort
mov al,DRAMAddrHi ; Dump upper byte, only do XXXXX
out dx,al ; it on carry from now on.
add dx,2 ; DataHighPort
mov ax,si
out dx,al
sub dx,2 ; CommandPort
@@MainLoop2:
mov al,DRAMAddrLo
out dx,al
inc dx ; DataLowPort
mov ax,di
out dx,ax
dec dx ; CommandPort
add di,1
jnc @@DumpByte2
inc si
mov al,DRAMAddrHi
out dx,al
add dx,2 ; DataHighPort
mov ax,si
out dx,al
sub dx,2 ; CommandPort
@@DumpByte2:
add dx,4 ; DRAMIOPort
in al,dx
mov es:[bx],al
inc bx
sub dx,4 ; CommandPort
loop @@MainLoop2
ret
U_DumpDRAMToMemory EndP
Comment &
─────────────────────────────────────────────────────────────────────────────
The following code is (C) Copyright, 1993 by Bjarni R. Einarsson
See GP15.DOX for more info.
The following routines I wrote/hacked to interface the GusPlay
and Renaissance code with Turbo/Borland Pascal and to handle
protected samples (sound effects)... with games in mind, of
course.
-- Juggler
P.S. I'm still pretty new to assembly, so don't be to harsh in
your judgements.. ;)
─────────────────────────────────────────────────────────────────────────────
&
; Dumps all sorts of pointers into the address pointed to by ProgDataP.
; See the ProgData structure for more info.
;
GetVariables Proc Far ProgDataP:DWord
push ds
pusha
les di,ProgDataP
mov ax,es
mov ds,ax
mov ax,cs
mov Word Ptr [di.BasePortP ],offset cs:[BasePort]
mov Word Ptr [di.BasePortP+2],ax
mov Word Ptr [di.ErrorP ],offset cs:[ErrorCode]
mov Word Ptr [di.ErrorP+2 ],ax
mov Word Ptr [di.VarP ],offset cs:[MainVolume]
mov Word Ptr [di.VarP+2 ],ax
mov Word Ptr [di.TimerP ],offset cs:[Time]
mov Word Ptr [di.TimerP+2 ],ax
mov Word Ptr [di.GMemP ],offset cs:[GUSMem]
mov Word Ptr [di.GMemP+2 ],ax
mov Word Ptr [di.GMemProtP ],offset cs:[GUSMemProt]
mov Word Ptr [di.GMemProtP+2],ax
mov Word Ptr [di.ChanInfoP ],offset cs:[SampChans]
mov Word Ptr [di.ChanInfoP+2],ax
mov Word Ptr [di.GusVolP ],offset cs:[GusVol]
mov Word Ptr [di.GusVolP+2 ],ax
mov Word Ptr [di.MSOffset ],offset cs:[SampOffset]
mov Word Ptr [di.MSOffset+2 ],ax
mov Word Ptr [di.MSLen ],offset cs:[SampLen]
mov Word Ptr [di.MSLen+2 ],ax
mov Word Ptr [di.MSVol ],offset cs:[SampVol]
mov Word Ptr [di.MSVol+2 ],ax
mov Word Ptr [di.MSRep ],offset cs:[SampRep]
mov Word Ptr [di.MSRep+2 ],ax
mov Word Ptr [di.MSRepLen ],offset cs:[SampRepLen]
mov Word Ptr [di.MSRepLen+2 ],ax
mov Word Ptr [di.PSOffset ],offset cs:[ProtSampOffset]
mov Word Ptr [di.PSOffset+2 ],ax
mov Word Ptr [di.PSLen ],offset cs:[ProtSampLen]
mov Word Ptr [di.PSLen+2 ],ax
mov Word Ptr [di.PSVol ],offset cs:[ProtSampVol]
mov Word Ptr [di.PSVol+2 ],ax
mov Word Ptr [di.PSRep ],offset cs:[ProtSampRep]
mov Word Ptr [di.PSRep+2 ],ax
mov Word Ptr [di.PSRepLen ],offset cs:[ProtSampRepLen]
mov Word Ptr [di.PSRepLen+2 ],ax
popa
pop ds
ret
GetVariables EndP
; Does what it says it does..
; seg:ofs points to the file name. (null terminated string)
; Returns the same error codes as LoadMod, 0 if successfull.
;
LoadModule Proc Far NameSeg:word,NameOfs:word
push ds
mov ax,cs
mov ds,ax
call Init
mov ax, NameSeg
mov dx, NameOfs
mov ds, ax
call LoadMod
jc l_Error
mov dx, 0
mov cs:[ErrorCode],dx
jmp l_StopLoad
l_Error:
mov dx, cs:[ErrorCode]
l_StopLoad:
pop ds
mov ax, dx
mov bx, ax
mov cx, ax
ret
LoadModule EndP
; This procedure loads (Amigafied?) samples to GUS DRAM and increments
; the protected memory marker.. so modules loaded AFTER this won't
; destroy it. If ya do this while a module is also in memory you'll get
; funny results. :-) Returns the number of the loaded sample (0-63).
;
ProtSampAdd Proc Far WData:dword,WLen:word,SVol:word,SRep:word,SRepLen:word,XORval:byte
push ds
mov bx,cs:[ProtSampNum]
cmp bx,63
ja TooManySamples
shl bx,1
inc cs:[ProtSampNum]
mov cx,WLen
mov Word Ptr cs:[ProtSampLen+bx], cx
push cx
shr cx,2
add cx,1
shl cx,2 ; Forces dword alignment, wastes 1-4 bytes.
mov ax,SVol
cmp ax,63
jna OK_volume
mov ax,63
OK_volume:
mov Word Ptr cs:[ProtSampVol+bx], ax
mov ax,SRep
cmp ax,WLen
jna OK_Rep
mov ax,WLen
OK_Rep:
mov Word Ptr cs:[ProtSampRep+bx], ax
mov ax,SRepLen
cmp ax,0
ja OK_RepLen
mov ax,WLen
OK_RepLen:
mov Word Ptr cs:[ProtSampRepLen+bx], ax
shl bx,1
mov di,Word Ptr cs:[GUSMemProt]
mov si,Word Ptr cs:[GUSMemProt+2]
add Word Ptr cs:[GUSMemProt],cx
adc Word Ptr cs:[GUSMemProt+2],0
mov Word Ptr cs:[ProtSampOffset+bx],di
mov Word Ptr cs:[ProtSampOffset+bx+2],si
les bx,Wdata
mov al,XORval
mov ah,al
pop cx
call U_DumpSampleToDRAM
mov ax,cs:[ProtSampNum]
dec ax
mov bx, ax
mov dx, ax ; I forget which damn register
mov cx, ax ; is the return value :)
jmp PSA_End
TooManySamples:
mov ax, 0FFFFh ; Returns FFFF hex if there are too many
mov dx, ax ; samples, otherwise it returns the number
mov bx, ax ; of the sample. (0-63)
mov cx, ax
PSA_End:
pop ds
ret
ProtSampAdd EndP
_PSP_Voice dw 0
_PSP_Freq dw 0
_PSP_LoopMode dw 0
_PSP_Balance dw 0
; Play back a sample previously loaded by ProtSampAdd.
; Snum is the number ProtSampAdd returned.
; Uses one of 8 voices, and rotates the voice counter, so the next call
; to this routine won't try to use the same GUS voice.
;
ProtSampPlay Proc Far Snum:Word,Freq:Word,Balance:Word,LoopMode:Word
push ds
push bp
mov ax,Freq
mov bx,LoopMode
mov cx,Balance
mov cs:[_PSP_Freq],ax
mov cs:[_PSP_LoopMode],bx
mov cs:[_PSP_Balance],cx
mov ax,Snum
cmp ax,cs:[ProtSampNum]
jae ForgetIt
mov bp,ax
mov ax,cs:[NextVoice]
mov cs:[_PSP_Voice], ax
inc ax
cmp ax,19
jna NoWrapVoices
mov ax,8
NoWrapVoices:
mov cs:[NextVoice], ax ; Rotate playback voices..
shl bp,2
mov ax,Word Ptr cs:[ProtSampOffset+bp ]
mov cx,Word Ptr cs:[ProtSampOffset+bp+2]
shr bp,1
mov bx,Word Ptr cs:[ProtSampLen+bp]
mov dx,Word Ptr cs:[ProtSampRep+bp]
push dx
add dx,Word Ptr cs:[ProtSampRepLen+bp]
jc NoChangeLen
cmp bx,dx
jb NoChangeLen
mov bx,dx
NoChangeLen:
pop dx
mov Word Ptr cs:[_SampleBegin ],ax
mov Word Ptr cs:[_SampleBegin+2],cx
mov Word Ptr cs:[_SampleStart ],ax
mov Word Ptr cs:[_SampleStart+2],cx
clc
add Word Ptr cs:[_SampleStart ],dx
adc Word Ptr cs:[_SampleStart+2],0
mov Word Ptr cs:[_SampleEnd ],ax
mov Word Ptr cs:[_SampleEnd+2 ],cx
clc
add Word Ptr cs:[_SampleEnd ],bx ; Set up variables
adc Word Ptr cs:[_SampleEnd+2 ],0 ; for _U_StartVoice
mov bx,Word Ptr cs:[_PSP_Voice]
mov ax,Word Ptr cs:[_PSP_Freq]
call U_SetFreq
mov ax,Word Ptr cs:[_PSP_Voice]
mov bx,Word Ptr cs:[_PSP_Balance]
call U_SetBalance
mov bx,Word Ptr cs:[_PSP_Voice]
mov ax,Word Ptr cs:[ProtSampVol+bp]
mov cx,Word Ptr cs:[ProtMainVolume]
xor dx,dx
mul cx
shr ax,6
adc ax,0
shl ax,1
xchg ax,bx
mov bx,Word Ptr cs:[GusVol+bx]
call U_SetVolume
mov ax,Word Ptr cs:[_PSP_Voice]
mov bx,Word Ptr cs:[_PSP_LoopMode]
call _U_StartVoice
ForgetIt:
pop bp
pop ds
ret
ProtSampPlay EndP
; Pop the most recently loaded protected sample off the sample stack.
; Preserves all registers.
;
ProtSampPop Proc Far
cmp Word Ptr cs:[ProtSampNum],1
jb AtBottom
push ax
push cx
push bx
dec Word Ptr cs:[ProtSampNum]
mov bx,cs:[ProtSampNum]
shl bx,2
mov ax,Word Ptr cs:[ProtSampOffset+bx]
mov cx,Word Ptr cs:[ProtSampOffset+bx+2]
mov Word Ptr cs:[GUSMemProt ],ax
mov Word Ptr cs:[GUSMemProt+2],cx
pop bx
pop cx
pop ax
AtBottom:
ret
ProtSampPop EndP
End