;°±²ÛßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÛ²±°
;°±²Û  ASIO package				   Driver for StereoThing  Û²±°
;°±²Û  (C)opyright 1992 by FRIENDS software	      All rights reserved  Û²±°
;°±²ÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛ²±°

		.186

Driver          Segment Byte
                Assume  cs:Driver, ds:Driver
                ORG     65*256-20-20-2-2-2-26

; Driver header. Note that it isn't loaded into memory and must be ignored
; by driver itself.
DriverDescr	db	'Stereo Thing/10 bit',0
Programmer	db	'Andrew Zabolotny',0,0,0,0
DeviceFlags     dw      1000000000000010b       ; Two voices
MemoryNeed	dw	offset DriverEnd
StartOffset     dw      65*256                  ; Preserve 16k of memory for
                                                ; volume table.
OffsetTable     dw      offset Init
                dw      offset SetPorts
                dw      offset SetTempo
                dw      offset StartPlay
                dw      offset SetFreq
                dw      offset SetVolume
                dw      offset SetSample
                dw      offset SetGlobalVolume
                dw      offset GetSamples
		dw	offset Dummy
		dw	offset Dummy
                dw      offset Dummy
                dw      offset Dummy

VolTable        equ     0                       ; Offset of volume table

TimerFreq       dw      04Bh                    ; Frequence of IRQ0
Samples 	dw	0,0			; Four pointers
		dw	0,0			; to samples for
		dw	0,0			; each voice.
		dw	0,0
CFreq		dw	0,0,0,0
InsFB		dw	0,0,0,0 		; Offset of first byte
						; in loop for each sample
InsLB		dw	0,0,0,0 		; 0FFFFh if no loop or offset
						; of last byte in loop.
ShutDown        dw      0,0                     ; Pointer to a array of flags
                                                ; that mean that sample are
                                                ; finished.
GVolume         db      64                      ; Global volume
Temp		dw	0
DecTemp 	dw	0
;Û Offsets of variables in self-modifying code Û
;Û     Segment of this variables is CS:        Û
FreqOfs 	dw	offset Freq1,offset Freq2
		dw	offset Freq3,offset Freq4
InsEOfs 	dw	offset InsE1,offset InsE2
		dw	offset InsE3,offset InsE4
HWordOfs	dw	offset HiWord1,offset HiWord2
		dw	offset HiWord3,offset HiWord4
LVolumeOfs	dw	offset LVolume1,offset LVolume2
		dw	offset LVolume3,offset LVolume4
RVolumeOfs	dw	offset RVolume1,offset RVolume2
                dw      offset RVolume3,offset RVolume4

Init            proc    far
                pusha
                push    es
                mov     word ptr cs:ShutDown,bx ; Save pointer to array of
                mov     word ptr cs:ShutDown+2,es; flags...
                call    InitTable
                clc                             ; StereoThing can't be detected,
                pop     es                      ; so,assume that it's all right.
                popa
                ret
Init		endp

SetPorts        proc    far
                mov     cs:LeftDAC,bx
                mov     cs:RightDAC,dx
                retf
SetPorts	endp

SetTempo        proc    far
                mov     byte ptr cs:TimerFreq,al
                mov     cs:Temp,cx
                mov     cs:DecTemp,cx
                retf
SetTempo	endp

StartPlay       proc    far
                mov     cs:DecTemp,1
                mov     word ptr cs:Handler,dx
                mov     word ptr cs:Handler+2,es
		call	TimerInit
                retf
StartPlay	endp

SetFreq         proc    far
                push    bx
                push    di
                xor     bh,bh
		shl	bx,1
                mov     di,cs:FreqOfs[bx]
                mov     cs:[di],cx
                mov     di,cs:HWordOfs[bx]
                mov     cs:[di],dx
                pop     di
                pop     bx
                retf
SetFreq 	endp

SetVolume	proc	far
                push    ax
                push    bx
		push	di
                xor     bh,bh
		shl	bx,1
                mov     al,cs:GVolume
		mul	ch
		shr	ax,6
                cmp     al,40h
                jbe     @SV1
                mov     al,040h
@SV1:		mov	di,cs:LVolumeOfs[bx]
		mov	cs:[di],al
                mov     al,cs:GVolume
		mul	cl
		shr	ax,6
                cmp     al,40h
		jbe	@SV2
                mov     al,040h
@SV2:		mov	di,cs:RVolumeOfs[bx]
                mov     cs:[di],al
		pop	di
		pop	bx
                pop     ax
                retf
SetVolume       endp

SetSample       proc    far
                push    ax
                push    bx
                push    si
                push    ds
                mov     ax,cs
                mov     ds,ax
                xor     bh,bh
                shl     bx,1
                mov     si,HWordOfs[bx]         ; Better dont't touch
                mov     word ptr [si],0         ; this sequence
                mov     si,FreqOfs[bx]          ; because on low-speed
                mov     word ptr [si],0         ; machines can appear
                shl     bx,1                    ; some truobles.
                mov     Samples[bx],di
                mov     Samples[bx+2],es
                shr     bx,1
                mov     InsLB[bx],cx
                mov     InsFB[bx],dx
                cmp     dx,0FFFFh
                jne     @@O1
                mov     InsLB[bx],dx
@@O1:           mov     si,InsEOfs[bx]
                mov     [si],cx
                pop     ds
                pop     si
                pop     bx
                pop     ax
                retf
SetSample       endp

SetGlobalVolume proc    far
                mov     cs:GVolume,al
                retf
SetGlobalVolume endp

GetSamples      proc
                push    cx
                push    di
                push    si
                push    ds
                push    cs
                pop     ds
                cld
                mov     si,offset Samples
                mov     cx,4*4
                rep     movsb
                pop     ds
                pop     si
                pop     di
                pop     cx
                retf
GetSamples      endp

Dummy		proc
		retf
Dummy           endp

Int08Entry      proc    far
@ResetV1:	cmp	word ptr InsLB[0],0FFFFh
                je      @C1
                mov     bx,word ptr InsFB[0]
                mov     word ptr Samples[0],bx
                jmp     @L1
@C1:            xor     bx,bx
		mov	byte ptr LVolume1,bl
		mov	byte ptr RVolume1,bl
                mov     word ptr Samples[0],bx
                les     bx,dword ptr ShutDown
                mov     byte ptr es:[bx],0
                jmp     @L1

@ResetV2:	cmp	word ptr InsLB[2],0FFFFh
                je      @C2
                mov     bx,word ptr InsFB[2]
                mov     word ptr Samples[4],bx
                jmp     @L2
@C2:            xor     bx,bx
		mov	byte ptr LVolume2,bl
		mov	byte ptr RVolume2,bl
                mov     word ptr Samples[4],bx
                les     bx,dword ptr ShutDown
                mov     byte ptr es:[bx+1],0
                jmp     @L2

IntProc:	push	ax
                push    bx
		push	cx
                push    dx
		push	ds
		push	es
                mov     ax,cs
		mov	ds,ax
;	      Û Voice 1 Û
		add	word ptr CFreq[0],0DEADh
Freq1		equ	word ptr $-2
		adc	word ptr Samples[0],0FACEh
HiWord1 	equ	word ptr $-2
                les     bx,dword ptr Samples[0]
                cmp     bx,0DEADh
InsE1		equ	word ptr $-2
		jae	@ResetV1
@L1:            mov     bl,byte ptr es:[bx]
                mov     bh,00h
LVolume1	equ	byte ptr $-1
                mov     al,[bx]
		mov	ah,0
		mov	bh,00h
RVolume1	equ	byte ptr $-1
		mov	cl,[bx]
		mov	ch,0

;	      Û Voice 2 Û
		add	word ptr CFreq[2],0DEADh
Freq2		equ	word ptr $-2
		adc	word ptr Samples[4],0FACEh
HiWord2 	equ	word ptr $-2
                les     bx,dword ptr Samples[4]
                cmp     bx,0DEADh
InsE2		equ	word ptr $-2
		jae	@ResetV2
@L2:            mov     bl,byte ptr es:[bx]
                mov     bh,00h
LVolume2	equ	byte ptr $-1
                add     al,[bx]
		adc	ah,0
		mov	bh,00h
RVolume2	equ	byte ptr $-1
		add	cl,[bx]
		adc	ch,0

;	      Û Voice 3 Û
		add	word ptr CFreq[4],0DEADh
Freq3		equ	word ptr $-2
		adc	word ptr Samples[8],0FACEh
HiWord3 	equ	word ptr $-2
                les     bx,dword ptr Samples[8]
                cmp     bx,0DEADh
InsE3		equ	word ptr $-2
		jae	@ResetV3
@L3:            mov     bl,byte ptr es:[bx]
                mov     bh,00h
LVolume3	equ	byte ptr $-1
		add	al,[bx]
		adc	ah,0
		mov	bh,00h
RVolume3	equ	byte ptr $-1
		add	cl,[bx]
		adc	ch,0

;	      Û Voice 4 Û
		add	word ptr CFreq[6],0DEADh
Freq4		equ	word ptr $-2
		adc	word ptr Samples[12],0FACEh
HiWord4 	equ	word ptr $-2
                les     bx,dword ptr Samples[12]
                cmp     bx,0DEADh
InsE4		equ	word ptr $-2
		jae	@ResetV4
@L4:            mov     bl,byte ptr es:[bx]
                mov     bh,00h
LVolume4	equ	byte ptr $-1
                add     al,[bx]
		adc	ah,0
		mov	bh,00h
RVolume4	equ	byte ptr $-1
		add	cl,[bx]
		adc	ch,0

		xor	ah,2
		xor	ch,2
		mov	dx,5FE0h
LeftDAC         equ     word ptr $-2
		out	dx,ax
                mov     dx,5FE2h
RightDAC        equ     word ptr $-2
		mov	ax,cx
		out	dx,ax
		dec	word ptr DecTemp
                jz      @DoHandler
@Play:		pop	es
		pop	ds
                pop     dx
		pop	cx
                pop     bx
                mov     al,020h
                out     020h,al
                pop     ax
                iret

@ResetV3:	cmp	word ptr InsLB[4],0FFFFh
                je      @C3
                mov     bx,word ptr InsFB[4]
                mov     word ptr Samples[8],bx
                jmp     @L3
@C3:            xor     bx,bx
		mov	byte ptr LVolume3,bl
		mov	byte ptr RVolume3,bl
                mov     word ptr Samples[8],bx
                les     bx,dword ptr ShutDown
                mov     byte ptr es:[bx+2],0
                jmp     @L3

@ResetV4:       cmp     word ptr InsLB[6],0FFFFh
                je      @C4
                mov     bx,word ptr InsFB[6]
                mov     word ptr Samples[12],bx
                jmp     @L4
@C4:            xor     bx,bx
		mov	byte ptr LVolume4,bl
		mov	byte ptr RVolume4,bl
                mov     word ptr Samples[12],bx
                les     bx,dword ptr ShutDown
                mov     byte ptr es:[bx+3],0
                jmp     @L4

@DoHandler:     mov     ax,Temp
                mov     DecTemp,ax
                db      09Ah
Handler         dw      0,0
                jmp     @Play
Int08Entry      endp

TimerInit	proc	near
                push    es
		cli
		mov	al,036h
		out	43h,al
                mov     al,byte ptr cs:TimerFreq
		out	40h,al
		mov	al,0
		out	40h,al
                xor     ax,ax
                mov     es,ax
                mov     word ptr es:[8*4],offset IntProc
                mov     word ptr es:[8*4+2],cs
                pop     es
                sti
		retn
TimerInit	endp

InitTable	proc	near
                mov     di,VolTable
		cld
                push    cs
		pop	es
		mov	ch,0
@M1:		mov	cl,0
@M2:		mov	al,cl
		cmp	al,0
		jge	@M3
		cmp	al,-125
		jl	@M3
		sub	al,3
@M3:		imul	ch
		shl	ax,2
		mov	al,ah
		stosb
		inc	cl
		jne	@M2
		inc	ch
                cmp     ch,65
		jb	@M1
		retn
InitTable	endp

DriverEnd       label   near
Driver          ends
		end
