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
|
|||
|
|
|||
|
|