1272 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
			
		
		
	
	
			1272 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
;
 | 
						||
;	Command & Conquer Red Alert(tm)
 | 
						||
;	Copyright 2025 Electronic Arts Inc.
 | 
						||
;
 | 
						||
;	This program is free software: you can redistribute it and/or modify
 | 
						||
;	it under the terms of the GNU General Public License as published by
 | 
						||
;	the Free Software Foundation, either version 3 of the License, or
 | 
						||
;	(at your option) any later version.
 | 
						||
;
 | 
						||
;	This program is distributed in the hope that it will be useful,
 | 
						||
;	but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						||
;	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						||
;	GNU General Public License for more details.
 | 
						||
;
 | 
						||
;	You should have received a copy of the GNU General Public License
 | 
						||
;	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
						||
;
 | 
						||
 | 
						||
;****************************************************************************
 | 
						||
;*
 | 
						||
;*          Copyright (c) 1994, HMI, INC. All Rights Reserved
 | 
						||
;*
 | 
						||
;*---------------------------------------------------------------------------
 | 
						||
;*
 | 
						||
;* FILE
 | 
						||
;*     soscodec.asm
 | 
						||
;*
 | 
						||
;* DESCRIPTION
 | 
						||
;*     HMI SOS ADPCM compression/decompression.
 | 
						||
;*
 | 
						||
;* PROGRAMMER
 | 
						||
;*     Nick Skrepetos
 | 
						||
;*     Denzil E. Long, Jr. (Fixed bugs, rewrote for watcom)
 | 
						||
;*	   Bill Petro		   (Added stereo support)
 | 
						||
;* DATE
 | 
						||
;*     Febuary 15, 1995
 | 
						||
;*
 | 
						||
;*---------------------------------------------------------------------------
 | 
						||
;*
 | 
						||
;* PUBLIC
 | 
						||
;*
 | 
						||
;****************************************************************************
 | 
						||
 | 
						||
	IDEAL
 | 
						||
	P386
 | 
						||
	MODEL	USE32 FLAT
 | 
						||
	LOCALS	??
 | 
						||
 | 
						||
	STRUC	sCompInfo
 | 
						||
lpSource	DD	?	;Compressed data pointer
 | 
						||
lpDest	DD	?	;Uncompressed data pointer
 | 
						||
dwCompSize	DD	?	;Compressed size
 | 
						||
dwUnCompSize	DD	?	;Uncompressed size
 | 
						||
wBitSize	DW	?	;Bit size for decompression
 | 
						||
wChannels	DW	?	;number of channels
 | 
						||
 | 
						||
dwSampleIndex	DD	?	;Index into sample
 | 
						||
dwPredicted	DD	?	;Next predicted value
 | 
						||
dwDifference	DD	?	;Difference from last sample
 | 
						||
wCodeBuf	DW	?	;Holds 2 nibbles for decompression
 | 
						||
wCode	DW	?	;Current 4 bit code
 | 
						||
wStep	DW	?	;Step value in table
 | 
						||
wIndex	DW	?	;Index into step table
 | 
						||
 | 
						||
dwSampleIndex2	DD	?	;Index into sample
 | 
						||
dwPredicted2	DD	?	;Next predicted value
 | 
						||
dwDifference2	DD	?	;Difference from last sample
 | 
						||
wCodeBuf2 	DW	?	;Holds 2 nibbles for decompression
 | 
						||
wCode2	DW	?	;Current 4 bit code
 | 
						||
wStep2	DW	?	;Step value in table
 | 
						||
wIndex2	DW	?	;Index into step table
 | 
						||
	ENDS	sCompInfo
 | 
						||
 | 
						||
	DATASEG
 | 
						||
 | 
						||
;* Index table for stepping into step table
 | 
						||
 | 
						||
wCODECIndexTab	DW	-1,-1,-1,-1,2,4,6,8
 | 
						||
		DW	-1,-1,-1,-1,2,4,6,8
 | 
						||
 | 
						||
 | 
						||
;Lookup table of replacement values
 | 
						||
;The actual sound value is replaced with an index to lookup in this table
 | 
						||
;The index only takes up a nibble(4bits) and represents an int(16bits)
 | 
						||
;Essentially:
 | 
						||
;Get a value
 | 
						||
;compare it with the value before it
 | 
						||
;find closest value in table and store the index into the table
 | 
						||
;if i'm going down then negitize it
 | 
						||
;go to next byte.
 | 
						||
 | 
						||
;Theory for stereo:
 | 
						||
;1)handle stereo and mono in two seperate loops. cleaner...
 | 
						||
;start at byte 0 and skip every other byte(or word) both write and read
 | 
						||
;when we get done set start byte to 1 and do it again
 | 
						||
 | 
						||
 | 
						||
;This table essentialy round off to closes values in 3 distinct bands
 | 
						||
; precalculated and optimized(i guess) for human hearing.
 | 
						||
 | 
						||
wCODECStepTab	DW	7,8,9,10,11,12,13,14
 | 
						||
	DW	16,17,19,21,23,25,28,31
 | 
						||
	DW	34,37,41,45,50,55,60,66
 | 
						||
	DW	73,80,88,97,107,118,130,143
 | 
						||
	DW	157,173,190,209,230,253,279,307
 | 
						||
	DW	337,371,408,449,494,544,598,658
 | 
						||
	DW	724,796,876,963,1060,1166,1282,1411
 | 
						||
	DW	1552,1707,1878,2066,2272,2499,2749,3024
 | 
						||
	DW	3327,3660,4026,4428,4871,5358,5894,6484
 | 
						||
	DW	7132,7845,8630,9493,10442,11487,12635,13899
 | 
						||
	DW	15289,16818,18500,20350,22385,24623,27086,29794
 | 
						||
	DW	32767
 | 
						||
 | 
						||
dwCODECByteIndex		DD	0 ; this is when to stop compressing
 | 
						||
dwCODECBytesProcessed		DD	0 ; this is how many so far compressed
 | 
						||
dwCODECTempStep		DD	0 ; tempory storage for step value
 | 
						||
wCODECMask			DW	0 ; Current mask
 | 
						||
	CODESEG
 | 
						||
 | 
						||
;****************************************************************************
 | 
						||
;*
 | 
						||
;* NAME
 | 
						||
;*     sosCODECInitStream - Initialize compression stream.
 | 
						||
;*
 | 
						||
;* SYNOPSIS
 | 
						||
;*     sosCODECInitStream(CompInfo)
 | 
						||
;*
 | 
						||
;*     void sosCODECInitStream(_SOS_COMPRESS_INFO *);
 | 
						||
;*
 | 
						||
;* FUNCTION
 | 
						||
;*     Initialize compression stream for compression and decompression.
 | 
						||
;*
 | 
						||
;* INPUTS
 | 
						||
;*     CompInfo - Compression information structure.
 | 
						||
;*
 | 
						||
;* RESULT
 | 
						||
;*     NONE
 | 
						||
;*
 | 
						||
;****************************************************************************
 | 
						||
 | 
						||
	GLOBAL	C VQA_sosCODECInitStream:NEAR
 | 
						||
	PROC	VQA_sosCODECInitStream C NEAR
 | 
						||
 | 
						||
	ARG	sSOSInfo:NEAR PTR
 | 
						||
 | 
						||
	mov	eax,[sSOSInfo]
 | 
						||
	mov	[(sCompInfo eax).wIndex],0 		; starting index 0
 | 
						||
	mov	[(sCompInfo eax).wStep],7  		; start with a step of 7
 | 
						||
	mov	[(sCompInfo eax).dwPredicted],0 	; no predicted value
 | 
						||
	mov	[(sCompInfo eax).dwSampleIndex],0	;start at head of index
 | 
						||
	mov	[(sCompInfo eax).wIndex2],0 		; starting index 0
 | 
						||
	mov	[(sCompInfo eax).wStep2],7  		; start with a step of 7
 | 
						||
	mov	[(sCompInfo eax).dwPredicted2],0 	; no predicted value
 | 
						||
	mov	[(sCompInfo eax).dwSampleIndex2],0 	;start at head of index
 | 
						||
	ret
 | 
						||
 | 
						||
	ENDP	VQA_sosCODECInitStream
 | 
						||
 | 
						||
;****************************************************************************
 | 
						||
;*
 | 
						||
;* NAME
 | 
						||
;*     sosCODECCompressData - Compress audio data.
 | 
						||
;*
 | 
						||
;* SYNOPSIS
 | 
						||
;*     Size = sosCODECCompressData(CompInfo, NumBytes)
 | 
						||
;*
 | 
						||
;*     long sosCODECCompressData(_SOS_COMPRESS_INFO *, long);
 | 
						||
;*
 | 
						||
;* FUNCTION
 | 
						||
;*     Compress an audio data stream into 4:1 ADPCM. 16 bit data is
 | 
						||
;*     compressed 4:1, 8 bit data is compressed 2:1.
 | 
						||
;*
 | 
						||
;* INPUTS
 | 
						||
;*     CompInfo - Pointer to initialized compress information structure.
 | 
						||
;*     NumBytes - Number of bytes to compress.
 | 
						||
;*
 | 
						||
;* RESULT
 | 
						||
;*     Size - Size of compressed data.
 | 
						||
;*
 | 
						||
;****************************************************************************
 | 
						||
 | 
						||
	GLOBAL	C VQA_sosCODECCompressData:NEAR
 | 
						||
	PROC	VQA_sosCODECCompressData C NEAR
 | 
						||
	ARG	sSOSInfo:NEAR PTR
 | 
						||
	ARG	wBytes:DWORD
 | 
						||
 | 
						||
	push	esi
 | 
						||
	push	edi
 | 
						||
	push	ebx
 | 
						||
	push	ecx
 | 
						||
	push	edx
 | 
						||
 | 
						||
;*---------------------------------------------------------------------------
 | 
						||
;*	Initialize
 | 
						||
;*---------------------------------------------------------------------------
 | 
						||
 | 
						||
	mov	ebx,[sSOSInfo]
 | 
						||
	mov	eax,[wBytes]
 | 
						||
	mov	[dwCODECBytesProcessed],eax
 | 
						||
	mov	[(sCompInfo ebx).dwSampleIndex],0 	;start at head of index
 | 
						||
	mov	[(sCompInfo ebx).dwSampleIndex2],0	;start at head of index
 | 
						||
 | 
						||
;	Check for 16 bit decompression
 | 
						||
 | 
						||
	cmp	[(sCompInfo ebx).wBitSize],16		;16 bit requested?
 | 
						||
	jne	short ??skipByteDivide			;no so skip divide
 | 
						||
	shr	eax,1					;divide size by 2
 | 
						||
 | 
						||
??skipByteDivide:
 | 
						||
	mov	[dwCODECByteIndex],eax
 | 
						||
	mov	esi,[(sCompInfo ebx).lpSource]	;ESI = source
 | 
						||
	mov	edi,[(sCompInfo ebx).lpDest]		;EDI = dest
 | 
						||
 | 
						||
	cmp	[(sCompInfo ebx).wChannels],2		;stereo check
 | 
						||
	je	??mainloopl
 | 
						||
 | 
						||
;------------------------------------------------------------------------
 | 
						||
; Mono start
 | 
						||
;------------------------------------------------------------------------
 | 
						||
 | 
						||
??mainloop:
 | 
						||
	cmp	[(sCompInfo ebx).wBitSize],16  	;are we doing 16 bit
 | 
						||
	jne	short ??input8Bit	       		;no. goto 8 bit input
 | 
						||
 | 
						||
	movsx	eax,[word ptr esi]	       		;Get 16bit sample
 | 
						||
	add	esi,2
 | 
						||
	jmp	short ??computeDiff				;skip 8 bit load
 | 
						||
 | 
						||
??input8Bit:
 | 
						||
	mov	ah,[esi]					;Get 8bit sample
 | 
						||
	inc	esi
 | 
						||
	xor	al,al					;zero out low byte
 | 
						||
	xor	ah,80h					;flip sign bit
 | 
						||
	movsx	eax,ax
 | 
						||
 | 
						||
??computeDiff:
 | 
						||
	movsx	ecx,[word ptr (sCompInfo ebx).dwPredicted]
 | 
						||
	sub	eax,ecx					;sample-predicted
 | 
						||
	xor	ecx,ecx					;clear ecx
 | 
						||
	cmp	eax,0					;Diff > = 0
 | 
						||
	jge	??positive
 | 
						||
 | 
						||
	neg	eax					;else difference= -difference
 | 
						||
	or	ecx,8					;set nibble sign bit in ecx
 | 
						||
 | 
						||
??positive:
 | 
						||
	mov	[(sCompInfo ebx).wCode],cx		;Store code
 | 
						||
	movsx	ecx,[(sCompInfo ebx).wStep]   	;Get step value
 | 
						||
	mov	[dwCODECTempStep],ecx
 | 
						||
	mov	edx,4					;mask value (i think)
 | 
						||
	mov	ecx,3					;loop count
 | 
						||
 | 
						||
??quantizeLoop:
 | 
						||
	cmp	eax,[dwCODECTempStep]	  		;Diff < step ?
 | 
						||
	jl	short ??nextQLoop				;goto nextQloop
 | 
						||
 | 
						||
	; OR in mask value into code and adjust difference.
 | 
						||
 | 
						||
	or	[(sCompInfo ebx).wCode],dx		;else or mask into code
 | 
						||
	sub	eax,[dwCODECTempStep]			;difference-=tempstep
 | 
						||
 | 
						||
??nextQLoop:
 | 
						||
	shr	[dwCODECTempStep],1				; TempStep>>=1
 | 
						||
	shr	edx,1					; mask>>=1
 | 
						||
	loop	??quantizeLoop					; back to quatize loop
 | 
						||
 | 
						||
;-----------------------------------------------------------------------------------------
 | 
						||
; now i'v got the new diff and code is masked right
 | 
						||
;-----------------------------------------------------------------------------------------
 | 
						||
 | 
						||
	; store off new difference value
 | 
						||
 | 
						||
	mov	[(sCompInfo ebx).dwDifference],eax
 | 
						||
 | 
						||
	; determine if sample index is even or odd.
 | 
						||
	; this will determine if we need to get a new token or not.
 | 
						||
 | 
						||
	test	[(sCompInfo ebx).dwSampleIndex],1 	; is it even? (starts at 0)
 | 
						||
	jne	short ??storeToken			; if so goto store token
 | 
						||
 | 
						||
	; else its odd so get token
 | 
						||
 | 
						||
	xor	eax,eax
 | 
						||
	mov	ax,[(sCompInfo ebx).wCode]		;ax=wCode
 | 
						||
	and	eax,0Fh					;and off high nibble
 | 
						||
	mov	[(sCompInfo ebx).wCodeBuf],ax		;wCodeBuf=ax
 | 
						||
	jmp	short ??calcDifference			;goto calcDifference
 | 
						||
 | 
						||
??storeToken:
 | 
						||
	; fetch new token
 | 
						||
 | 
						||
	xor	eax,eax
 | 
						||
	mov	ax,[(sCompInfo ebx).wCode]		;ax=code
 | 
						||
	shl	eax,4					;shift low nibble to high
 | 
						||
	or	ax,[(sCompInfo ebx).wCodeBuf]		;or in the stored nibble
 | 
						||
	mov	[edi],al				;*dest=al
 | 
						||
	inc	edi					;dest++
 | 
						||
 | 
						||
??calcDifference:
 | 
						||
	mov	[(sCompInfo ebx).dwDifference],0	;dwDifference=0
 | 
						||
	xor	ecx,ecx					;ecx=0
 | 
						||
	mov	cx,[(sCompInfo ebx).wStep]		;cx=Step
 | 
						||
	xor	eax,eax					;eax=0
 | 
						||
	mov	ax,[(sCompInfo ebx).wCode]		;ax=wCode
 | 
						||
	test	eax,4					;Check 0100
 | 
						||
	je	short ??no4
 | 
						||
	add	[(sCompInfo ebx).dwDifference],ecx  	;difference+=step
 | 
						||
 | 
						||
??no4:
 | 
						||
	test	eax,2					;Check 0010
 | 
						||
	je	short ??no2
 | 
						||
	mov	edx,ecx					;edx=wStep
 | 
						||
	shr	edx,1					;edx>>1
 | 
						||
	add	[(sCompInfo ebx).dwDifference],edx 	;Difference=wstep>>1
 | 
						||
 | 
						||
??no2:
 | 
						||
	test	eax,1					;Check 0001
 | 
						||
	je	short ??no1
 | 
						||
	mov	edx,ecx					;edx=wStep
 | 
						||
	shr	edx,2					;edx>>2
 | 
						||
	add	[(sCompInfo ebx).dwDifference],edx 	;Difference=wstep>>2
 | 
						||
 | 
						||
??no1:
 | 
						||
	mov	edx,ecx
 | 
						||
	shr	edx,3
 | 
						||
	add	[(sCompInfo ebx).dwDifference],edx	;Difference=wstep>>3
 | 
						||
	test	eax,8					;Check 1000
 | 
						||
	je	short ??no8
 | 
						||
	neg	[(sCompInfo ebx).dwDifference]		;Negate diff because sign bit was set
 | 
						||
 | 
						||
??no8:
 | 
						||
	mov	eax,[(sCompInfo ebx).dwPredicted]
 | 
						||
	add	eax,[(sCompInfo ebx).dwDifference]	;eax=Preditcted+Difference
 | 
						||
	cmp	eax,7FFFh
 | 
						||
	jl	short ??noOverflow
 | 
						||
	mov	eax,7FFFh				;if overflow store 7fff in diff
 | 
						||
 | 
						||
??noOverflow:
 | 
						||
	cmp	eax,0FFFF8000h
 | 
						||
	jg	short ??noUnderflow
 | 
						||
	mov	eax,0FFFF8000h				;if overflow  0FFFF8000 in diff
 | 
						||
 | 
						||
??noUnderflow:
 | 
						||
	mov	[(sCompInfo ebx).dwPredicted],eax 	;store into predicted
 | 
						||
	xor	ecx,ecx
 | 
						||
	mov	cx,[(sCompInfo ebx).wCode]		;cx=Code
 | 
						||
	xor	eax,eax
 | 
						||
	shl	ecx,1					;cx<<1
 | 
						||
	mov	ax,[wCODECIndexTab + ecx]		;ax=Indextab[ecx]
 | 
						||
	add	[(sCompInfo ebx).wIndex],ax   		;wIndex+=ax
 | 
						||
	cmp	[(sCompInfo ebx).wIndex],8000h		; check if wIndex < 0
 | 
						||
	jb	short ??checkOverflow
 | 
						||
	mov	[(sCompInfo ebx).wIndex],0		; reset index to zero
 | 
						||
	jmp	short ??adjustStep
 | 
						||
 | 
						||
??checkOverflow:
 | 
						||
	cmp	[(sCompInfo ebx).wIndex],88		; check if wIndex > 88
 | 
						||
	jbe	short ??adjustStep
 | 
						||
	mov	[(sCompInfo ebx).wIndex],88		; reset index to 88
 | 
						||
 | 
						||
 | 
						||
??adjustStep:
 | 
						||
	; fetch wIndex so we can fetch new step value
 | 
						||
 | 
						||
	xor	ecx,ecx
 | 
						||
	mov	cx,[(sCompInfo ebx).wIndex]
 | 
						||
	xor	eax,eax
 | 
						||
	shl	ecx,1
 | 
						||
	mov	ax,[wCODECStepTab + ecx]
 | 
						||
 | 
						||
	; advance index and store step value
 | 
						||
 | 
						||
	add	[(sCompInfo ebx).dwSampleIndex],1
 | 
						||
	mov	[(sCompInfo ebx).wStep],ax
 | 
						||
 | 
						||
	; decrement bytes processed and loop back.
 | 
						||
 | 
						||
	dec	[dwCODECByteIndex]
 | 
						||
	jne	??mainloop		    		; }while !0
 | 
						||
 | 
						||
	jmp	??exitout
 | 
						||
;-----------------------------------------------------------------------
 | 
						||
;Stereo	Left Side
 | 
						||
;-----------------------------------------------------------------------
 | 
						||
 | 
						||
??mainloopl:
 | 
						||
; determine bit size for input				;do{
 | 
						||
 | 
						||
	cmp	[(sCompInfo ebx).wBitSize],16  		;are we doing 16 bit
 | 
						||
	jne	short ??input8Bitl	       		;no. goto 8 bit input		**
 | 
						||
 | 
						||
	movsx	eax,[word ptr esi]	       		;load next word from source
 | 
						||
	add	esi,4					;inc source by 2 words  		**
 | 
						||
	jmp	short ??computeDiffl			;skip 8 bit load			**
 | 
						||
 | 
						||
??input8Bitl:
 | 
						||
	mov	ah,[esi]				;Get 8 bit sample
 | 
						||
	add	esi,2   				;inc source by 2 bytes		**
 | 
						||
	xor	al,al					;zero out low byte
 | 
						||
	xor	ah,80h					;flip sign bit
 | 
						||
	movsx	eax,ax					;sign extend into eax
 | 
						||
 | 
						||
??computeDiffl:
 | 
						||
	; compute difference
 | 
						||
 | 
						||
	movsx	ecx,[word ptr (sCompInfo ebx).dwPredicted]
 | 
						||
							;load predicted (starts at 0)
 | 
						||
	sub	eax,ecx					;difference=sample-preditcted
 | 
						||
 | 
						||
	; check if dwDifference > 0.  ECX is the
 | 
						||
	; sign bit, it is initialized to positive.
 | 
						||
 | 
						||
	xor	ecx,ecx				       	;clear ecx
 | 
						||
	cmp	eax,0					;if(difference>=0)
 | 
						||
	jge	short ??positivel			;goto positive
 | 
						||
 | 
						||
	neg	eax					;else difference= -difference
 | 
						||
	or	ecx,8					;set nibble sign bit in ecx
 | 
						||
 | 
						||
??positivel:
 | 
						||
	mov	[(sCompInfo ebx).wCode],cx		;Store code from cx into struct
 | 
						||
 | 
						||
	; set up to quantize difference. initialize
 | 
						||
	; wCODECTempStep = step value.
 | 
						||
 | 
						||
	movsx	ecx,[(sCompInfo ebx).wStep]   		;ecx=step value(starts at 7)
 | 
						||
	mov	[dwCODECTempStep],ecx			;tempstep=step
 | 
						||
	mov	edx,4					;edx=4   mask value (i think)
 | 
						||
	mov	ecx,3					;ecx is loop number so loop 3 times
 | 
						||
 | 
						||
??quantizeLoopl:
 | 
						||
	; check to see if difference > tempstep value.
 | 
						||
 | 
						||
	cmp	eax,[dwCODECTempStep]	  		;if(difference < tempstep)
 | 
						||
	jl	short ??nextQLoopl			;goto nextQloop
 | 
						||
 | 
						||
	; OR in mask value into code and adjust difference.
 | 
						||
 | 
						||
	or	[(sCompInfo ebx).wCode],dx		;else or mask into code
 | 
						||
	sub	eax,[dwCODECTempStep]			;difference-=tempstep
 | 
						||
 | 
						||
??nextQLoopl:
 | 
						||
 | 
						||
	; shift down tempstep and mask
 | 
						||
 | 
						||
	shr	[dwCODECTempStep],1			; TempStep>>=1
 | 
						||
	shr	edx,1					; mask>>=1
 | 
						||
	loop	??quantizeLoopl				; back to quatize loop
 | 
						||
;------------------------------------------------------------------------------------------
 | 
						||
; now i'v got the new diff and code is masked right
 | 
						||
 | 
						||
	; store off new difference value
 | 
						||
 | 
						||
	mov	[(sCompInfo ebx).dwDifference],eax
 | 
						||
 | 
						||
	; determine if sample index is even or odd.
 | 
						||
	; this will determine if we need to get a new token or not.
 | 
						||
 | 
						||
	test	[(sCompInfo ebx).dwSampleIndex],1 	; is it even? (starts at 0)
 | 
						||
	jne	short ??storeTokenl			; if so goto store token		**
 | 
						||
 | 
						||
	; else its odd so get token
 | 
						||
 | 
						||
	xor	eax,eax
 | 
						||
	mov	ax,[(sCompInfo ebx).wCode]		;ax=wCode
 | 
						||
	and	eax,0Fh					;and off high nibble
 | 
						||
	mov	[(sCompInfo ebx).wCodeBuf],ax		;wCodeBuf=ax
 | 
						||
	jmp	short ??calcDifferencel			;goto calcDifference		**
 | 
						||
 | 
						||
??storeTokenl:
 | 
						||
	; fetch new token
 | 
						||
 | 
						||
	xor	eax,eax
 | 
						||
	mov	ax,[(sCompInfo ebx).wCode]		;ax=code
 | 
						||
	shl	eax,4					;shift low nibble to hign nibble
 | 
						||
	or	ax,[(sCompInfo ebx).wCodeBuf]		;or in the stored nibble
 | 
						||
	mov	[edi],al				;*dest=al
 | 
						||
	add	edi,2					;dest+=2					**
 | 
						||
 | 
						||
??calcDifferencel:
 | 
						||
	mov	[(sCompInfo ebx).dwDifference],0;dwDifference=0
 | 
						||
	xor	ecx,ecx					;ecx=0
 | 
						||
	mov	cx,[(sCompInfo ebx).wStep]		;cx=Step
 | 
						||
	xor	eax,eax					;eax=0
 | 
						||
	mov	ax,[(sCompInfo ebx).wCode]		;ax=wCode
 | 
						||
	test	eax,4					;Check 0100
 | 
						||
	je	short ??no4l				;						**
 | 
						||
	add	[(sCompInfo ebx).dwDifference],ecx  	;difference+=step
 | 
						||
 | 
						||
??no4l:
 | 
						||
	test	eax,2					;Check 0010
 | 
						||
	je	short ??no2l				;						**
 | 
						||
	mov	edx,ecx					;edx=wStep
 | 
						||
	shr	edx,1					;edx>>1
 | 
						||
	add	[(sCompInfo ebx).dwDifference],edx 	;Difference=wstep>>1
 | 
						||
 | 
						||
??no2l:
 | 
						||
	test	eax,1					;Check 0001
 | 
						||
	je	short ??no1l				;						**
 | 
						||
	mov	edx,ecx					;edx=wStep
 | 
						||
	shr	edx,2					;edx>>2
 | 
						||
	add	[(sCompInfo ebx).dwDifference],edx 	;Difference=wstep>>2
 | 
						||
 | 
						||
??no1l:
 | 
						||
	mov	edx,ecx
 | 
						||
	shr	edx,3
 | 
						||
	add	[(sCompInfo ebx).dwDifference],edx	;Difference=wstep>>3
 | 
						||
	test	eax,8					;Check 1000
 | 
						||
	je	short ??no8l
 | 
						||
 | 
						||
	;Negate diff because sign bit was set
 | 
						||
 | 
						||
	neg	[(sCompInfo ebx).dwDifference]
 | 
						||
 | 
						||
??no8l:
 | 
						||
	mov	eax,[(sCompInfo ebx).dwPredicted]
 | 
						||
	add	eax,[(sCompInfo ebx).dwDifference]	;eax=Preditcted+Difference
 | 
						||
	cmp	eax,7FFFh
 | 
						||
	jl	short ??noOverflowl
 | 
						||
	mov	eax,7FFFh				;if overflow store 7fff in diff
 | 
						||
 | 
						||
??noOverflowl:
 | 
						||
	cmp	eax,0FFFF8000h
 | 
						||
	jg	short ??noUnderflowl
 | 
						||
	mov	eax,0FFFF8000h				;if overflow  0FFFF8000 in diff
 | 
						||
 | 
						||
??noUnderflowl:
 | 
						||
	mov	[(sCompInfo ebx).dwPredicted],eax 	;store into predicted
 | 
						||
	xor	ecx,ecx					;adjust index
 | 
						||
	mov	cx,[(sCompInfo ebx).wCode]		;cx=Code
 | 
						||
	xor	eax,eax
 | 
						||
	shl	ecx,1					;cx<<1
 | 
						||
	mov	ax,[wCODECIndexTab + ecx]		;ax=Indextab[ecx]
 | 
						||
	add	[(sCompInfo ebx).wIndex],ax   		;wIndex+=ax
 | 
						||
 | 
						||
 | 
						||
	cmp	[(sCompInfo ebx).wIndex],8000h		;check if wIndex < 0
 | 
						||
	jb	short ??checkOverflowl			;								**
 | 
						||
	mov	[(sCompInfo ebx).wIndex],0		; reset index to zero
 | 
						||
	jmp	short ??adjustStepl			;							**
 | 
						||
 | 
						||
??checkOverflowl:
 | 
						||
	; check if wIndex > 88
 | 
						||
 | 
						||
	cmp	[(sCompInfo ebx).wIndex],88
 | 
						||
	jbe	short ??adjustStepl			;							**
 | 
						||
 | 
						||
	; reset index to 88
 | 
						||
 | 
						||
	mov	[(sCompInfo ebx).wIndex],88
 | 
						||
 | 
						||
??adjustStepl:
 | 
						||
	; fetch wIndex so we can fetch new step value
 | 
						||
 | 
						||
	xor	ecx,ecx
 | 
						||
	mov	cx,[(sCompInfo ebx).wIndex]
 | 
						||
	xor	eax,eax
 | 
						||
	shl	ecx,1
 | 
						||
	mov	ax,[wCODECStepTab + ecx]
 | 
						||
 | 
						||
	; advance index and store step value
 | 
						||
 | 
						||
	add	[(sCompInfo ebx).dwSampleIndex],1
 | 
						||
	mov	[(sCompInfo ebx).wStep],ax
 | 
						||
 | 
						||
	; decrement bytes processed and loop back.
 | 
						||
 | 
						||
	sub	[dwCODECByteIndex],2    ; sub 2 for stereo					**
 | 
						||
	jne	??mainloopl		    ; }while !0						**
 | 
						||
 | 
						||
;-------------------------------------------------------------------------
 | 
						||
;Right channel re-set up varibles
 | 
						||
;-------------------------------------------------------------------------
 | 
						||
 | 
						||
	mov	eax,[wBytes]
 | 
						||
	mov	esi,[(sCompInfo ebx).lpSource] 		; point to source buffer
 | 
						||
	mov	edi,[(sCompInfo ebx).lpDest]   		; point to destination buffer
 | 
						||
	inc esi						; skip first byte
 | 
						||
	inc edi						; ship first byte
 | 
						||
 | 
						||
;	Check for 16 bit compression
 | 
						||
 | 
						||
	cmp	[(sCompInfo ebx).wBitSize],16
 | 
						||
	je	short ??do16bit
 | 
						||
	mov	[dwCODECByteIndex],eax
 | 
						||
	jmp	short ??mainloopr
 | 
						||
 | 
						||
??do16bit:
 | 
						||
	shr	eax,1					;16 bit so half as many bytes
 | 
						||
	inc	esi					;16 bit so 1 more byte to skip
 | 
						||
	mov	[dwCODECByteIndex],eax
 | 
						||
 | 
						||
 | 
						||
;-----------------------------------------------------------------------
 | 
						||
;Start of Stereo Right Side
 | 
						||
;-----------------------------------------------------------------------
 | 
						||
 | 
						||
??mainloopr:
 | 
						||
; determine bit size for input				;do{
 | 
						||
 | 
						||
	cmp	[(sCompInfo ebx).wBitSize],16  		;are we doing 16 bit
 | 
						||
	jne	short ??input8Bitr	       		;no. goto 8 bit input		**
 | 
						||
 | 
						||
	movsx	eax,[word ptr esi]	       		;load next word from source
 | 
						||
	add	esi,4					;inc source by 2 words  		**
 | 
						||
	jmp	short ??computeDiffr			;skip 8 bit load			**
 | 
						||
 | 
						||
??input8Bitr:
 | 
						||
	mov	ah,[esi]				;Get 8 bit sample
 | 
						||
	add	esi,2   				;inc source by 2 bytes		**
 | 
						||
	xor	al,al					;zero out low byte
 | 
						||
	xor	ah,80h					;flip sign bit
 | 
						||
	movsx eax,ax					;sign extend into eax
 | 
						||
 | 
						||
??computeDiffr:
 | 
						||
	; compute difference
 | 
						||
 | 
						||
	movsx ecx,[word ptr (sCompInfo ebx).dwPredicted2]
 | 
						||
							;load predicted (starts at 0)
 | 
						||
	sub	eax,ecx					;difference=sample-preditcted
 | 
						||
 | 
						||
	; check if dwDifference > 0.  ECX is the
 | 
						||
	; sign bit, it is initialized to positive.
 | 
						||
 | 
						||
	xor	ecx,ecx					;clear ecx
 | 
						||
	cmp	eax,0					;if(difference>=0)
 | 
						||
	jge	short ??positiver 			;goto positive
 | 
						||
 | 
						||
	neg	eax					;else difference= -difference
 | 
						||
	or	ecx,8					;set nibble sign bit in ecx
 | 
						||
 | 
						||
??positiver:
 | 
						||
	mov	[(sCompInfo ebx).wCode2],cx		;Store code from cx into struct
 | 
						||
 | 
						||
	; set up to quantize difference. initialize
 | 
						||
	; wCODECTempStep = step value.
 | 
						||
 | 
						||
	movsx	ecx,[(sCompInfo ebx).wStep2]   		;ecx=step value(starts at 7)
 | 
						||
	mov	[dwCODECTempStep],ecx			;tempstep=step
 | 
						||
	mov	edx,4					;edx=4   mask value (i think)
 | 
						||
	mov	ecx,3					;ecx is loop number so loop 3 times
 | 
						||
 | 
						||
??quantizeLoopr:
 | 
						||
	; check to see if difference > tempstep value.
 | 
						||
 | 
						||
	cmp	eax,[dwCODECTempStep]	  		;if(difference < tempstep)
 | 
						||
	jl	short ??nextQLoopr			;goto nextQloop
 | 
						||
 | 
						||
	; OR in mask value into code and adjust difference.
 | 
						||
 | 
						||
	or	[(sCompInfo ebx).wCode2],dx		;else or mask into code
 | 
						||
	sub	eax,[dwCODECTempStep]			;difference-=tempstep
 | 
						||
 | 
						||
??nextQLoopr:
 | 
						||
 | 
						||
	; shift down tempstep and mask
 | 
						||
 | 
						||
	shr	[dwCODECTempStep],1			; TempStep>>=1
 | 
						||
	shr	edx,1					; mask>>=1
 | 
						||
	loop	??quantizeLoopr				; back to quatize loop
 | 
						||
;------------------------------------------------------------------------------------------
 | 
						||
; now i'v got the new diff and code is masked right
 | 
						||
 | 
						||
	; store off new difference value
 | 
						||
 | 
						||
	mov	[(sCompInfo ebx).dwDifference2],eax
 | 
						||
 | 
						||
	; determine if sample index is even or odd.
 | 
						||
	; this will determine if we need to get a new token or not.
 | 
						||
 | 
						||
	test	[(sCompInfo ebx).dwSampleIndex2],1	; is it even? (starts at 0)
 | 
						||
	jne	short ??storeTokenr			; if so goto store token		**
 | 
						||
 | 
						||
	; else its odd so get token
 | 
						||
 | 
						||
	xor	eax,eax
 | 
						||
	mov	ax,[(sCompInfo ebx).wCode2]		;ax=wCode
 | 
						||
	and	eax,0Fh					;and off high nibble
 | 
						||
	mov	[(sCompInfo ebx).wCodeBuf2],ax		;wCodeBuf=ax
 | 
						||
	jmp	short ??calcDifferencer			;goto calcDifference		**
 | 
						||
 | 
						||
??storeTokenr:
 | 
						||
	xor	eax,eax
 | 
						||
	mov	ax,[(sCompInfo ebx).wCode2]		;ax=code
 | 
						||
	shl	eax,4					;shift low nibble to hign nibble
 | 
						||
	or	ax,[(sCompInfo ebx).wCodeBuf2]		;or in the stored nibble
 | 
						||
	mov	[edi],al				;*dest=al
 | 
						||
	add	edi,2					;dest+=2					**
 | 
						||
 | 
						||
??calcDifferencer:
 | 
						||
	mov	[(sCompInfo ebx).dwDifference2],0	;dwDifference=0
 | 
						||
	xor	ecx,ecx					;ecx=0
 | 
						||
	mov	cx,[(sCompInfo ebx).wStep2]		;cx=Step
 | 
						||
	xor	eax,eax					;eax=0
 | 
						||
	mov	ax,[(sCompInfo ebx).wCode2]		;ax=wCode
 | 
						||
	test	eax,4					;Check 0100
 | 
						||
	je	short ??no4r
 | 
						||
	add	[(sCompInfo ebx).dwDifference2],ecx  	;difference+=step
 | 
						||
 | 
						||
??no4r:
 | 
						||
	test	eax,2					;Check 0010
 | 
						||
	je	short ??no2r
 | 
						||
	mov	edx,ecx					;edx=wStep
 | 
						||
	shr	edx,1					;edx>>1
 | 
						||
	add	[(sCompInfo ebx).dwDifference2],edx ;Difference=wstep>>1
 | 
						||
 | 
						||
??no2r:
 | 
						||
	test	eax,1					;Check 0001
 | 
						||
	je	short ??no1r
 | 
						||
	mov	edx,ecx					;edx=wStep
 | 
						||
	shr	edx,2					;edx>>2
 | 
						||
	add	[(sCompInfo ebx).dwDifference2],edx 	;Difference=wstep>>2
 | 
						||
 | 
						||
??no1r:
 | 
						||
	mov	edx,ecx
 | 
						||
	shr	edx,3
 | 
						||
	add	[(sCompInfo ebx).dwDifference2],edx	;Difference=wstep>>3
 | 
						||
	test	eax,8					;Check 1000
 | 
						||
	je	short ??no8r
 | 
						||
	neg	[(sCompInfo ebx).dwDifference2]
 | 
						||
 | 
						||
??no8r:
 | 
						||
	; add difference to predicted value.
 | 
						||
	mov	eax,[(sCompInfo ebx).dwPredicted2]
 | 
						||
	add	eax,[(sCompInfo ebx).dwDifference2]	;eax=Preditcted+Difference
 | 
						||
	cmp	eax,7FFFh
 | 
						||
	jl	short ??noOverflowr
 | 
						||
	mov	eax,7FFFh				;if overflow store 7fff in diff
 | 
						||
 | 
						||
??noOverflowr:
 | 
						||
	cmp	eax,0FFFF8000h
 | 
						||
	jg	short ??noUnderflowr
 | 
						||
	mov	eax,0FFFF8000h				;if overflow  0FFFF8000 in diff
 | 
						||
 | 
						||
??noUnderflowr:
 | 
						||
	mov	[(sCompInfo ebx).dwPredicted2],eax 	;store into predicted
 | 
						||
	xor	ecx,ecx					;adjust index
 | 
						||
	mov	cx,[(sCompInfo ebx).wCode2]		;cx=Code
 | 
						||
	xor	eax,eax
 | 
						||
	shl	ecx,1					;cx<<1
 | 
						||
	mov	ax,[wCODECIndexTab + ecx]		;ax=Indextab[ecx]
 | 
						||
	add	[(sCompInfo ebx).wIndex2],ax   		;wIndex+=ax
 | 
						||
	cmp	[(sCompInfo ebx).wIndex2],8000h		;check if wIndex < 0
 | 
						||
	jb	short ??checkOverflowr
 | 
						||
	mov	[(sCompInfo ebx).wIndex2],0		;reset index to zero
 | 
						||
	jmp	short ??adjustStepr
 | 
						||
 | 
						||
??checkOverflowr:
 | 
						||
 | 
						||
	cmp	[(sCompInfo ebx).wIndex2],88		;check if wIndex > 88
 | 
						||
	jbe	short ??adjustStepr
 | 
						||
	mov	[(sCompInfo ebx).wIndex2],88		;reset index to 88
 | 
						||
 | 
						||
 | 
						||
??adjustStepr:
 | 
						||
	; fetch wIndex so we can fetch new step value
 | 
						||
 | 
						||
	xor	ecx,ecx
 | 
						||
	mov	cx,[(sCompInfo ebx).wIndex2]
 | 
						||
	xor	eax,eax
 | 
						||
	shl	ecx,1
 | 
						||
	mov	ax,[wCODECStepTab + ecx]
 | 
						||
 | 
						||
	; advance index and store step value
 | 
						||
 | 
						||
	add	[(sCompInfo ebx).dwSampleIndex2],1
 | 
						||
	mov	[(sCompInfo ebx).wStep2],ax
 | 
						||
 | 
						||
	; decrement bytes processed and loop back.
 | 
						||
 | 
						||
	sub	[dwCODECByteIndex],2    		; sub 2 for stereo
 | 
						||
	jne	??mainloopr		    		; }while !0
 | 
						||
 | 
						||
 | 
						||
;-------------------------------------------------------------------------
 | 
						||
;Final clean up
 | 
						||
;-------------------------------------------------------------------------
 | 
						||
 | 
						||
??exitout:
 | 
						||
	; save off ESI and EDI back into compress info structure.
 | 
						||
 | 
						||
;	mov	[(sCompInfo ebx).lpSource],esi
 | 
						||
;	mov	[(sCompInfo ebx).lpDest],edi
 | 
						||
 | 
						||
	; set up return value for number of bytes processed.
 | 
						||
 | 
						||
	mov	eax,[dwCODECBytesProcessed]
 | 
						||
	shr	eax,1
 | 
						||
	cmp	[(sCompInfo ebx).wBitSize],16
 | 
						||
	jne	??leave
 | 
						||
	shr	eax,1					;if not 16 bit then div/2
 | 
						||
 | 
						||
??leave:
 | 
						||
	pop	edx
 | 
						||
	pop	ecx
 | 
						||
	pop	ebx
 | 
						||
	pop	edi
 | 
						||
	pop	esi
 | 
						||
	ret
 | 
						||
 | 
						||
	ENDP	VQA_sosCODECCompressData
 | 
						||
 | 
						||
 | 
						||
;****************************************************************************
 | 
						||
;*
 | 
						||
;* NAME
 | 
						||
;*     sosCODECDecompressData - Decompress audio data.
 | 
						||
;*
 | 
						||
;* SYNOPSIS
 | 
						||
;*     Size = sosCODECDecompressData(CompInfo, NumBytes)
 | 
						||
;*
 | 
						||
;*     long sosCODECDecompressData(_SOS_COMPRESS_INFO *, long);
 | 
						||
;*
 | 
						||
;* FUNCTION
 | 
						||
;*     Decompress data from a 4:1 ADPCM compressed stream. The number of
 | 
						||
;*     bytes decompressed is returned.
 | 
						||
;*
 | 
						||
;* INPUTS
 | 
						||
;*     CompInfo - Compress information structure.
 | 
						||
;*     NumBytes - Number of bytes to compress.
 | 
						||
;*
 | 
						||
;* RESULT
 | 
						||
;*     Size - Size of decompressed data.
 | 
						||
;*
 | 
						||
;****************************************************************************
 | 
						||
 | 
						||
	GLOBAL	C VQA_sosCODECDecompressData:NEAR
 | 
						||
	PROC	VQA_sosCODECDecompressData C NEAR
 | 
						||
 | 
						||
	ARG	sSOSInfo:NEAR PTR
 | 
						||
	ARG	wBytes:DWORD
 | 
						||
 | 
						||
	push	esi
 | 
						||
	push	edi
 | 
						||
	push	ebx
 | 
						||
	push	ecx
 | 
						||
	push	edx
 | 
						||
 | 
						||
;*---------------------------------------------------------------------------
 | 
						||
;*	Initialize
 | 
						||
;*---------------------------------------------------------------------------
 | 
						||
 | 
						||
	mov	ebx,[sSOSInfo]
 | 
						||
	mov	eax,[wBytes]
 | 
						||
	mov	[dwCODECBytesProcessed],eax
 | 
						||
	mov	[(sCompInfo ebx).dwSampleIndex],0 	;start at head of index
 | 
						||
	mov	[(sCompInfo ebx).dwSampleIndex2],0 	;start at head of index
 | 
						||
 | 
						||
;*	Check for 16 bit decompression
 | 
						||
 | 
						||
	cmp	[(sCompInfo ebx).wBitSize],16
 | 
						||
	jne	short ??skipByteDivide
 | 
						||
	shr	eax,1
 | 
						||
 | 
						||
??skipByteDivide:
 | 
						||
	mov	[dwCODECByteIndex],eax
 | 
						||
	mov	esi,[(sCompInfo ebx).lpSource]
 | 
						||
	mov	edi,[(sCompInfo ebx).lpDest]
 | 
						||
	cmp	[(sCompInfo ebx).wChannels],2		;stereo check
 | 
						||
	je	??mainloopl				;do left side first
 | 
						||
 | 
						||
;	Determine if sample index is even or odd. This will determine
 | 
						||
;	if we need to get a new token or not.
 | 
						||
 | 
						||
;*---------------------------------------------------------------------------
 | 
						||
;*	Main Mono Loop
 | 
						||
;*---------------------------------------------------------------------------
 | 
						||
 | 
						||
??mainloop:
 | 
						||
	test	[(sCompInfo ebx).dwSampleIndex],1	;odd ??
 | 
						||
	je	short ??fetchToken				;if so get new token
 | 
						||
	xor	eax,eax					;else shift int codebuf
 | 
						||
	mov	ax,[(sCompInfo ebx).wCodeBuf]		;ored with Code
 | 
						||
	shr	eax,4
 | 
						||
	and	eax,000Fh
 | 
						||
	mov	[(sCompInfo ebx).wCode],ax
 | 
						||
	jmp	short ??calcDifference
 | 
						||
 | 
						||
??fetchToken:
 | 
						||
	xor	eax,eax					;get a new token
 | 
						||
	mov	al,[esi]					;put in codebuf
 | 
						||
	mov	[(sCompInfo ebx).wCodeBuf],ax
 | 
						||
	inc	esi
 | 
						||
	and	eax,000Fh
 | 
						||
	mov	[(sCompInfo ebx).wCode],ax		;and then code
 | 
						||
 | 
						||
??calcDifference:
 | 
						||
	mov	[(sCompInfo ebx).dwDifference],0	;reset diff
 | 
						||
	xor	ecx,ecx
 | 
						||
	mov	cx,[(sCompInfo ebx).wStep]		;cx is step value
 | 
						||
	test	eax,4					;Check for wCode & 4
 | 
						||
	je	short ??no4
 | 
						||
	add	[(sCompInfo ebx).dwDifference],ecx	;Add wStep
 | 
						||
 | 
						||
??no4:
 | 
						||
	test	eax,2					;Check for wCode & 2
 | 
						||
	je	short ??no2
 | 
						||
	mov	edx,ecx					;Add wStep >> 1
 | 
						||
	shr	edx,1
 | 
						||
	add	[(sCompInfo ebx).dwDifference],edx
 | 
						||
 | 
						||
??no2:
 | 
						||
	test	eax,1					;Check for wCode & 1
 | 
						||
	je	short ??no1
 | 
						||
	mov	edx,ecx					;Add wStep >> 2
 | 
						||
	shr	edx,2
 | 
						||
	add	[(sCompInfo ebx).dwDifference],edx
 | 
						||
 | 
						||
??no1:
 | 
						||
	mov	edx,ecx					;Add in wStep >> 3
 | 
						||
	shr	edx,3
 | 
						||
	add	[(sCompInfo ebx).dwDifference],edx
 | 
						||
	test	eax,8					;Check for wCode & 8
 | 
						||
	je	short ??no8
 | 
						||
	neg	[(sCompInfo ebx).dwDifference]	;Negate diff
 | 
						||
 | 
						||
??no8:
 | 
						||
	; add difference to predicted value.
 | 
						||
 | 
						||
	mov	eax,[(sCompInfo ebx).dwPredicted]
 | 
						||
	add	eax,[(sCompInfo ebx).dwDifference]
 | 
						||
 | 
						||
	; make sure there is no under or  overflow.
 | 
						||
 | 
						||
	cmp	eax,7FFFh
 | 
						||
	jl	short ??noOverflow
 | 
						||
	mov	eax,7FFFh
 | 
						||
 | 
						||
??noOverflow:
 | 
						||
	cmp	eax,0FFFF8000h
 | 
						||
	jg	short ??noUnderflow
 | 
						||
	mov	eax,0FFFF8000h
 | 
						||
 | 
						||
??noUnderflow:
 | 
						||
	mov	[(sCompInfo ebx).dwPredicted],eax
 | 
						||
	cmp	[(sCompInfo ebx).wBitSize],16
 | 
						||
	jne	short ??output8Bit
 | 
						||
	mov	[edi],ax				;Output 16bit sample
 | 
						||
	add	edi,2
 | 
						||
	jmp	short ??adjustIndex
 | 
						||
 | 
						||
??output8Bit:
 | 
						||
	; output 8 bit sample
 | 
						||
 | 
						||
	xor	ah,80h
 | 
						||
	mov	[edi],ah
 | 
						||
	inc	edi
 | 
						||
 | 
						||
??adjustIndex:
 | 
						||
	xor	ecx,ecx
 | 
						||
	mov	cx,[(sCompInfo ebx).wCode]
 | 
						||
	xor	eax,eax
 | 
						||
	shl	ecx,1
 | 
						||
	mov	ax,[wCODECIndexTab + ecx]
 | 
						||
	add	[(sCompInfo ebx).wIndex],ax 		;check if wIndex < 0
 | 
						||
	cmp	[(sCompInfo ebx).wIndex],8000h
 | 
						||
	jb	short ??checkOverflow
 | 
						||
	mov	[(sCompInfo ebx).wIndex],0		;reset index to zero
 | 
						||
	jmp	short ??adjustStep
 | 
						||
 | 
						||
??checkOverflow:
 | 
						||
	cmp	[(sCompInfo ebx).wIndex],88		;check if wIndex > 88
 | 
						||
	jbe	short ??adjustStep
 | 
						||
	mov	[(sCompInfo ebx).wIndex],88		;reset index to 88
 | 
						||
 | 
						||
??adjustStep:
 | 
						||
	; fetch wIndex so we can fetch new step value
 | 
						||
 | 
						||
	xor	ecx,ecx
 | 
						||
	mov	cx,[(sCompInfo ebx).wIndex]
 | 
						||
	xor	eax,eax
 | 
						||
	shl	ecx,1
 | 
						||
	mov	ax,[wCODECStepTab + ecx]
 | 
						||
 | 
						||
	; advance index and store step value
 | 
						||
 | 
						||
	add	[(sCompInfo ebx).dwSampleIndex],1
 | 
						||
	mov	[(sCompInfo ebx).wStep],ax
 | 
						||
 | 
						||
	; decrement bytes processed and loop back.
 | 
						||
 | 
						||
	dec	[dwCODECByteIndex]
 | 
						||
	jne	??mainloop
 | 
						||
	jmp	??exitout
 | 
						||
 | 
						||
;--------------------------------------------------------------------------
 | 
						||
;Left Channel Start
 | 
						||
;--------------------------------------------------------------------------
 | 
						||
 | 
						||
 | 
						||
??mainloopl:
 | 
						||
	test	[(sCompInfo ebx).dwSampleIndex],1
 | 
						||
	je	short ??fetchTokenl
 | 
						||
 | 
						||
	xor	eax,eax
 | 
						||
	mov	ax,[(sCompInfo ebx).wCodeBuf]
 | 
						||
	shr	eax,4
 | 
						||
	and	eax,000Fh
 | 
						||
	mov	[(sCompInfo ebx).wCode],ax
 | 
						||
	jmp	short ??calcDifferencel
 | 
						||
 | 
						||
??fetchTokenl:
 | 
						||
	xor	eax,eax
 | 
						||
	mov	al,[esi]
 | 
						||
	mov	[(sCompInfo ebx).wCodeBuf],ax
 | 
						||
	add	esi,2					;2 for stereo
 | 
						||
	and	eax,000Fh
 | 
						||
	mov	[(sCompInfo ebx).wCode],ax
 | 
						||
 | 
						||
??calcDifferencel:
 | 
						||
							; reset difference
 | 
						||
 | 
						||
	mov	[(sCompInfo ebx).dwDifference],0
 | 
						||
	xor	ecx,ecx
 | 
						||
	mov	cx,[(sCompInfo ebx).wStep]
 | 
						||
	test	eax,4					;Check for wCode & 4
 | 
						||
	je	short ??no4l
 | 
						||
	add	[(sCompInfo ebx).dwDifference],ecx	;Add wStep
 | 
						||
 | 
						||
??no4l:
 | 
						||
	test	eax,2					;Check for wCode & 2
 | 
						||
	je	short ??no2l
 | 
						||
	mov	edx,ecx					;Add wStep >> 1
 | 
						||
	shr	edx,1
 | 
						||
	add	[(sCompInfo ebx).dwDifference],edx
 | 
						||
 | 
						||
??no2l:
 | 
						||
	test	eax,1					;Check for wCode & 1
 | 
						||
	je	short ??no1l
 | 
						||
	mov	edx,ecx					;Add wStep >> 2
 | 
						||
	shr	edx,2
 | 
						||
	add	[(sCompInfo ebx).dwDifference],edx
 | 
						||
 | 
						||
??no1l:
 | 
						||
	mov	edx,ecx					;Add in wStep >> 3
 | 
						||
	shr	edx,3
 | 
						||
	add	[(sCompInfo ebx).dwDifference],edx
 | 
						||
	test	eax,8					;Check for wCode & 8
 | 
						||
	je	short ??no8l
 | 
						||
	neg	[(sCompInfo ebx).dwDifference]		;Negate diff
 | 
						||
 | 
						||
??no8l:
 | 
						||
		; add difference to predicted value.
 | 
						||
 | 
						||
	mov	eax,[(sCompInfo ebx).dwPredicted]
 | 
						||
	add	eax,[(sCompInfo ebx).dwDifference]
 | 
						||
 | 
						||
		; make sure there is no under or  overflow.
 | 
						||
 | 
						||
	cmp	eax,7FFFh
 | 
						||
	jl	short ??noOverflowl
 | 
						||
	mov	eax,7FFFh
 | 
						||
 | 
						||
??noOverflowl:
 | 
						||
	cmp	eax,0FFFF8000h
 | 
						||
	jg	short ??noUnderflowl
 | 
						||
	mov	eax,0FFFF8000h
 | 
						||
 | 
						||
??noUnderflowl:
 | 
						||
	mov	[(sCompInfo ebx).dwPredicted],eax
 | 
						||
	cmp	[(sCompInfo ebx).wBitSize],16
 | 
						||
	jne	short ??output8Bitl
 | 
						||
	mov	[edi],ax				;Output 16bit sample
 | 
						||
	add	edi,4					;4 for stereo
 | 
						||
	jmp	short ??adjustIndexl
 | 
						||
 | 
						||
??output8Bitl:
 | 
						||
	; output 8 bit sample
 | 
						||
 | 
						||
	xor	ah,80h
 | 
						||
	mov	[edi],ah
 | 
						||
	add	edi,2					;2 for stereo
 | 
						||
 | 
						||
??adjustIndexl:
 | 
						||
	xor	ecx,ecx
 | 
						||
	mov	cx,[(sCompInfo ebx).wCode]
 | 
						||
	xor	eax,eax
 | 
						||
	shl	ecx,1
 | 
						||
	mov	ax,[wCODECIndexTab + ecx]
 | 
						||
	add	[(sCompInfo ebx).wIndex],ax
 | 
						||
							; check if wIndex < 0
 | 
						||
	cmp	[(sCompInfo ebx).wIndex],8000h
 | 
						||
	jb	short ??checkOverflowl
 | 
						||
	mov	[(sCompInfo ebx).wIndex],0
 | 
						||
	jmp	short ??adjustStepl			;reset index to zero
 | 
						||
 | 
						||
 | 
						||
??checkOverflowl:
 | 
						||
 | 
						||
	cmp	[(sCompInfo ebx).wIndex],88		; check if wIndex > 88
 | 
						||
	jbe	short ??adjustStepl
 | 
						||
	mov	[(sCompInfo ebx).wIndex],88		; reset index to 88
 | 
						||
 | 
						||
??adjustStepl:
 | 
						||
	; fetch wIndex so we can fetch new step value
 | 
						||
 | 
						||
	xor	ecx,ecx
 | 
						||
	mov	cx,[(sCompInfo ebx).wIndex]
 | 
						||
	xor	eax,eax
 | 
						||
	shl	ecx,1
 | 
						||
	mov	ax,[wCODECStepTab + ecx]
 | 
						||
 | 
						||
	; advance index and store step value
 | 
						||
 | 
						||
	add	[(sCompInfo ebx).dwSampleIndex],1
 | 
						||
	mov	[(sCompInfo ebx).wStep],ax
 | 
						||
 | 
						||
	; decrement bytes processed and loop back.
 | 
						||
 | 
						||
	sub	[dwCODECByteIndex],2
 | 
						||
	jne	??mainloopl
 | 
						||
;----------------------------------------------------------------------------
 | 
						||
; Right Side Setup
 | 
						||
;----------------------------------------------------------------------------
 | 
						||
	mov	eax,[wBytes]
 | 
						||
	mov	[dwCODECBytesProcessed],eax
 | 
						||
	mov	esi,[(sCompInfo ebx).lpSource]
 | 
						||
	mov	edi,[(sCompInfo ebx).lpDest]
 | 
						||
	inc	esi					; skip left channel
 | 
						||
	inc	edi				     	; skip left channel
 | 
						||
	cmp	[(sCompInfo ebx).wBitSize],16		;16 bit ??
 | 
						||
	je	short ??doByteDivide
 | 
						||
	mov	[dwCODECByteIndex],eax
 | 
						||
	jmp  short ??mainloopr
 | 
						||
 | 
						||
??doByteDivide:
 | 
						||
	shr	eax,1 					;Divide size by two
 | 
						||
	inc	edi   					; 16 bit so skip 1 more
 | 
						||
	mov	[dwCODECByteIndex],eax
 | 
						||
 | 
						||
 | 
						||
;--------------------------------------------------------------------------
 | 
						||
;Right Channel Start
 | 
						||
;--------------------------------------------------------------------------
 | 
						||
 | 
						||
 | 
						||
??mainloopr:
 | 
						||
	test	[(sCompInfo ebx).dwSampleIndex2],1
 | 
						||
	je	short ??fetchTokenr
 | 
						||
	xor	eax,eax
 | 
						||
	mov	ax,[(sCompInfo ebx).wCodeBuf2]
 | 
						||
	shr	eax,4
 | 
						||
	and	eax,000Fh
 | 
						||
	mov	[(sCompInfo ebx).wCode2],ax
 | 
						||
	jmp	short ??calcDifferencer
 | 
						||
 | 
						||
??fetchTokenr:
 | 
						||
	xor	eax,eax
 | 
						||
	mov	al,[esi]
 | 
						||
	mov	[(sCompInfo ebx).wCodeBuf2],ax
 | 
						||
	add	esi,2				     	;2 for stereo
 | 
						||
	and	eax,000Fh
 | 
						||
	mov	[(sCompInfo ebx).wCode2],ax
 | 
						||
 | 
						||
??calcDifferencer:
 | 
						||
							; reset difference
 | 
						||
 | 
						||
	mov	[(sCompInfo ebx).dwDifference2],0
 | 
						||
	xor	ecx,ecx
 | 
						||
	mov	cx,[(sCompInfo ebx).wStep2]
 | 
						||
	test	eax,4					;Check for wCode & 4
 | 
						||
	je	short ??no4r
 | 
						||
	add	[(sCompInfo ebx).dwDifference2],ecx	;Add wStep
 | 
						||
 | 
						||
??no4r:
 | 
						||
	test	eax,2					;Check for wCode & 2
 | 
						||
	je	short ??no2r
 | 
						||
	mov	edx,ecx					;Add wStep >> 1
 | 
						||
	shr	edx,1
 | 
						||
	add	[(sCompInfo ebx).dwDifference2],edx
 | 
						||
 | 
						||
??no2r:
 | 
						||
	test	eax,1					;Check for wCode & 1
 | 
						||
	je	short ??no1r
 | 
						||
	mov	edx,ecx					;Add wStep >> 2
 | 
						||
	shr	edx,2
 | 
						||
	add	[(sCompInfo ebx).dwDifference2],edx
 | 
						||
 | 
						||
??no1r:
 | 
						||
	mov	edx,ecx					;Add in wStep >> 3
 | 
						||
	shr	edx,3
 | 
						||
	add	[(sCompInfo ebx).dwDifference2],edx
 | 
						||
	test	eax,8					;Check for wCode & 8
 | 
						||
	je	short ??no8r
 | 
						||
	neg	[(sCompInfo ebx).dwDifference2]		;Negate diff
 | 
						||
 | 
						||
??no8r:
 | 
						||
	; add difference to predicted value.
 | 
						||
	mov	eax,[(sCompInfo ebx).dwPredicted2]
 | 
						||
	add	eax,[(sCompInfo ebx).dwDifference2]
 | 
						||
	cmp	eax,7FFFh
 | 
						||
	jl	short ??noOverflowr
 | 
						||
	mov	eax,7FFFh
 | 
						||
 | 
						||
??noOverflowr:
 | 
						||
	cmp	eax,0FFFF8000h
 | 
						||
	jg	short ??noUnderflowr
 | 
						||
	mov	eax,0FFFF8000h
 | 
						||
 | 
						||
??noUnderflowr:
 | 
						||
	mov	[(sCompInfo ebx).dwPredicted2],eax
 | 
						||
	cmp	[(sCompInfo ebx).wBitSize],16
 | 
						||
	jne	short ??output8Bitr
 | 
						||
	mov	[edi],ax				;Output 16bit sample
 | 
						||
	add	edi,4					;4 for stereo		***
 | 
						||
	jmp	short ??adjustIndexr
 | 
						||
 | 
						||
??output8Bitr:
 | 
						||
							; output 8 bit sample
 | 
						||
	xor	ah,80h
 | 
						||
	mov	[edi],ah
 | 
						||
	add	edi,2					;2 for stereo
 | 
						||
 | 
						||
??adjustIndexr:
 | 
						||
	xor	ecx,ecx
 | 
						||
	mov	cx,[(sCompInfo ebx).wCode2]
 | 
						||
	xor	eax,eax
 | 
						||
	shl	ecx,1
 | 
						||
	mov	ax,[wCODECIndexTab + ecx]
 | 
						||
	add	[(sCompInfo ebx).wIndex2],ax
 | 
						||
							; check if wIndex < 0
 | 
						||
	cmp	[(sCompInfo ebx).wIndex2],8000h
 | 
						||
	jb	short ??checkOverflowr
 | 
						||
							; reset index to zero
 | 
						||
	mov	[(sCompInfo ebx).wIndex2],0
 | 
						||
	jmp	short ??adjustStepr
 | 
						||
 | 
						||
??checkOverflowr:
 | 
						||
							; check if wIndex > 88
 | 
						||
	cmp	[(sCompInfo ebx).wIndex2],88
 | 
						||
	jbe	short ??adjustStepr
 | 
						||
	mov	[(sCompInfo ebx).wIndex2],88		; reset index to 88
 | 
						||
 | 
						||
??adjustStepr:
 | 
						||
	; fetch wIndex so we can fetch new step value
 | 
						||
 | 
						||
	xor	ecx,ecx
 | 
						||
	mov	cx,[(sCompInfo ebx).wIndex2]
 | 
						||
	xor	eax,eax
 | 
						||
	shl	ecx,1
 | 
						||
	mov	ax,[wCODECStepTab + ecx]
 | 
						||
 | 
						||
	; advance index and store step value
 | 
						||
 | 
						||
	add	[(sCompInfo ebx).dwSampleIndex2],1
 | 
						||
	mov	[(sCompInfo ebx).wStep2],ax
 | 
						||
 | 
						||
	; decrement bytes processed and loop back.
 | 
						||
 | 
						||
	sub	[dwCODECByteIndex],2
 | 
						||
	jne	??mainloopr
 | 
						||
 | 
						||
 | 
						||
??exitout:
 | 
						||
;		don't think we need this but just in case i'll leave it here!!
 | 
						||
 | 
						||
;	mov	[(sCompInfo ebx).lpSource],esi
 | 
						||
;	mov	[(sCompInfo ebx).lpDest],edi
 | 
						||
	; set up return value for number of bytes processed.
 | 
						||
	mov	eax,[dwCODECBytesProcessed]
 | 
						||
	pop	edx
 | 
						||
	pop	ecx
 | 
						||
	pop	ebx
 | 
						||
	pop	edi
 | 
						||
	pop	esi
 | 
						||
	ret
 | 
						||
 | 
						||
	ENDP	VQA_sosCODECDecompressData
 | 
						||
	END
 | 
						||
 | 
						||
 |