home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga ACS 1998 #6
/
amigaacscoverdisc1998-061998.iso
/
games
/
descent
/
source
/
main
/
soscodec.asm
< prev
next >
Wrap
Assembly Source File
|
1998-06-08
|
24KB
|
690 lines
;THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
;SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
;END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
;ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
;IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
;SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
;FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
;CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
;AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
;COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
;
; $Source: f:/miner/source/main/rcs/soscodec.asm $
; $Revision: 2.0 $
; $Author: john $
; $Date: 1995/02/27 11:29:36 $
;
; Routines for compressing digital sounds.
;
; $Log: soscodec.asm $
; Revision 2.0 1995/02/27 11:29:36 john
; New version 2.0, which has no anonymous unions, builds with
; Watcom 10.0, and doesn't require parsing BITMAPS.TBL.
;
; Revision 1.2 1994/11/30 14:08:46 john
; First version.
;
; Revision 1.1 1994/11/29 14:33:51 john
; Initial revision
;
;
.386
option oldstructs
.nolist
include types.inc
include psmacros.inc
.list
assume cs:_TEXT, ds:_DATA
_DATA segment dword public USE32 'DATA'
rcsid db "$Id: soscodec.asm 2.0 1995/02/27 11:29:36 john Exp $"
align 4
; public declarations
public sosCODECDecompressData_
public sosCODECCompressData_
public sosCODECInitStream_
; structure definitions
sCompressInfo struc
Source dd 0 ; pointer to compressed data
Dest dd 0 ; pointer to uncompressed data
dwCompSize dd 0 ; compressed size
dwUnCompSize dd 0 ; uncompressed size
dwSampleIndex dd 0 ; index into sample
dwPredicted dd 0 ; next predicted value
dwDifference dd 0 ; difference from last sample
wCodeBuf dw 0 ; holds 2 nibbles for decompression
wCode dw 0 ; current 4 bit code
wStep dw 0 ; step value in table
wIndex dw 0 ; index into step table
wBitSize dw 0 ; bit size for decompression
sCompressInfo ends
; 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
wCODECStepTab dw 7, 8, 9, 10, 11, 12, 13, 14
dw 16, 17, 19, 21, 23, 25, 28
dw 31, 34, 37, 41, 45, 50, 55
dw 60, 66, 73, 80, 88, 97, 107
dw 118, 130, 143, 157, 173, 190, 209
dw 230, 253, 279, 307, 337, 371, 408
dw 449, 494, 544, 598, 658, 724, 796
dw 876, 963,1060,1166,1282,1411,1552
dw 1707,1878
dw 2066,2272,2499,2749,3024,3327,3660,4026
dw 4428,4871,5358,5894,6484,7132,7845,8630
dw 9493,10442,11487,12635,13899,15289,16818
dw 18500,20350,22385,24623,27086,29794,32767
; byte index counter
wCODECByteIndex dd 0
; total bytes processed
wCODECBytesProcessed dd 0
; current mask value
wCODECMask dw 0
; temp step value
dwCODECTempStep dd 0
_DATA ends
_TEXT segment dword public USE32 'CODE'
sosCODECInitStream_:
; save used registers
push ebx
;
; set up pointer to _SOS_COMPRESS_INFO
; structure in EBX.
;
mov ebx, eax
;
; init members of compression stream
;
mov word ptr [ ebx ].wIndex, 0
mov word ptr [ ebx ].wStep, 7
mov dword ptr [ ebx ].dwPredicted, 0
mov dword ptr [ ebx ].dwSampleIndex, 0
; restore registers
pop ebx
ret
;
; DWORD sosCODECDecompressData( _SOS_COMPRESS_INFO * sSOSInfo, DWORD wBytes )
;
; decompress data from a 4:1 ADPCM compressed file. the number of
; bytes decompressed is returned.
;
;
sosCODECDecompressData_:
; eax = sSOSInfo
; edx = wBytes
;
; save registers used
;
push esi
push edi
push ebx
push ecx
push edx
;
; set up EBX as a pointer to
; info structure.
;
mov ebx, eax
;
; set up byte counter. if 16 bit data
; divide bytes by two since we will
; spit out two bytes @ a time.
;
mov eax, edx
mov wCODECBytesProcessed, eax
mov wCODECByteIndex, eax
;
; set up source and destination
; pointers
;
mov esi, [ ebx ].Source
mov edi, [ ebx ].Dest
Decompmainloop:
;
; determine if sample index is even
; or odd. this will determine if we
; need to get a new token or not.
;
test dword ptr [ ebx ].dwSampleIndex, 1
je short DecompfetchToken
;
; get token
;
movzx eax, word ptr [ ebx ].wCodeBuf
shr eax, 4
and eax, 000fh
mov word ptr [ ebx ].wCode, ax
jmp short DecompcalcDifference
DecompfetchToken:
;
; fetch new token
;
xor eax, eax
mov al, byte ptr [ esi ]
mov word ptr [ ebx ].wCodeBuf, ax
inc esi
and eax, 000fh
mov word ptr [ ebx ].wCode, ax
DecompcalcDifference:
;
; reset difference
;
mov dword ptr [ ebx ].dwDifference, 0
;
; set up ECX as the step value
;
movzx ecx, word ptr [ ebx ].wStep
;
; check for wCode & 4
;
test eax, 4
je short Decompno4
; add wStep
add dword ptr [ ebx ].dwDifference, ecx
Decompno4:
;
; check for wCode & 2
;
test eax, 2
je short Decompno2
; add wStep >> 1
mov edx, ecx
shr edx, 1
add dword ptr [ ebx ].dwDifference, edx
Decompno2:
;
; check for wCode & 1
;
test eax, 1
je short Decompno1
; add wStep >> 2
mov edx, ecx
shr edx, 2
add dword ptr [ ebx ].dwDifference, edx
Decompno1:
;
; add in wStep >> 3
;
mov edx, ecx
shr edx, 3
add dword ptr [ ebx ].dwDifference, edx
;
; check for wCode & 8
;
test eax, 8
je short Decompno8
; negate difference
neg dword ptr [ ebx ].dwDifference
Decompno8:
;
; add difference to predicted
; value.
;
mov eax, [ ebx ].dwPredicted
add eax, [ ebx ].dwDifference
;
; make sure there is no under or
; overflow.
;
cmp eax, 7fffh
jl short DecompnoOverflow
mov eax, 7fffh
DecompnoOverflow:
cmp eax, 0ffff8000h
jg short DecompnoUnderflow
mov eax, 0ffff8000h
DecompnoUnderflow:
mov dword ptr [ ebx ].dwPredicted, eax
;
; output 8 bit sample
;
xor ah, 80h
mov al, ah
stosb
;
; adjust index
;
movzx ecx, word ptr [ ebx ].wCode
movzx eax, word ptr wCODECIndexTab[ ecx * 2 ]
add word ptr [ ebx ].wIndex, ax
;
; check if wIndex < 0
;
cmp word ptr [ ebx ].wIndex, 8000h
jb short DecompcheckOverflow
; reset index to zero
mov word ptr [ ebx ].wIndex, 0
jmp short DecompadjustStep
DecompcheckOverflow:
;
; check if wIndex > 88
;
cmp word ptr [ ebx ].wIndex, 88
jbe short DecompadjustStep
; reset index to 88
mov word ptr [ ebx ].wIndex, 88
DecompadjustStep:
;
; fetch wIndex so we can fetch
; new step value
;
movzx ecx, word ptr [ ebx ].wIndex
movzx eax, word ptr wCODECStepTab[ ecx * 2 ]
;
; advance index and store step value
;
add dword ptr [ ebx ].dwSampleIndex, 1
mov word ptr [ ebx ].wStep, ax
;
; decrement bytes processed
; and loop back.
;
dec wCODECByteIndex
jne Decompmainloop
;
; save off ESI and EDI back into
; compress info structure.
;
mov dword ptr [ ebx ].Source, esi
mov dword ptr [ ebx ].Dest, edi
;
; set up return value for number
; of bytes processed.
;
mov eax, wCODECBytesProcessed
;
; restore registers
;
pop edx
pop ecx
pop ebx
pop edi
pop esi
ret
;
; DWORD sosCODECCompressData( _SOS_COMPRESS_INFO * sSOSInfo, DWORD wBytes )
;
; Compresses a data stream into 4:1 ADPCM. 16 bit data is compressed 4:1
; 8 bit data is compressed 2:1.
;
;
sosCODECCompressData_:
; eax = sSOSInfo
; edx = wBytes
;
; save registers used
;
push esi
push edi
push ebx
push ecx
push edx
;
; set up EBX as a pointer to
; info structure.
;
mov ebx, eax
;
; set up byte counter. if 16 bit data
; divide bytes by two since we will
; spit out two bytes @ a time.
;
mov eax, edx
mov wCODECBytesProcessed, eax
;
; check for 16 bit decompression
;
cmp word ptr [ ebx ].wBitSize, 16
jne short CompskipByteDivide
;
; divide size requested by two
;
shr eax, 1
CompskipByteDivide:
mov wCODECByteIndex, eax
;
; set up source and destination
; pointers
;
mov esi, [ ebx ].Source
mov edi, [ ebx ].Dest
Compmainloop:
;
; determine bit size for input
;
cmp word ptr [ ebx ].wBitSize, 16
jne short Compinput8Bit
;
; get 16 bit sample
;
movsx eax, word ptr [ esi ]
add esi, 2
jmp short CompcomputeDiff
Compinput8Bit:
;
; get 8 bit sample
;
mov ah, byte ptr [ esi ]
inc esi
xor al, al
xor ah, 80h
movsx eax, ax
CompcomputeDiff:
;
; compute difference
;
movsx ecx, word ptr [ ebx ].dwPredicted
sub eax, ecx
;
; check if dwDifference > 0. ECX is the
; sign bit, it is initialized to positive.
;
xor ecx, ecx
cmp eax, 0
jge Comppositive
;
; negate difference
;
neg eax
or ecx, 8
Comppositive:
;
; store code value
;
mov word ptr [ ebx ].wCode, cx
;
; set up to quantize difference. initialize
; wCODECTempStep = step value.
;
movsx ecx, word ptr [ ebx ].wStep
mov dwCODECTempStep, ecx
mov edx, 4
mov ecx, 3
CompquantizeLoop:
;
; check to see if difference > tempstep
; value.
;
cmp eax, dwCODECTempStep
jl short CompnextQLoop
;
; OR in mask value into code and
; adjust difference.
;
or word ptr [ ebx ].wCode, dx
sub eax, dwCODECTempStep
CompnextQLoop:
;
; shift down tempstep and mask
;
shr dwCODECTempStep, 1
shr edx, 1
loop CompquantizeLoop
;
; store off new difference value
;
mov dword ptr [ 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 dword ptr [ ebx ].dwSampleIndex, 1
jne short CompstoreToken
;
; get token
;
movzx eax, word ptr [ ebx ].wCode
and eax, 0fh
mov word ptr [ ebx ].wCodeBuf, ax
jmp short CompcalcDifference
CompstoreToken:
;
; fetch new token
;
movzx eax, word ptr [ ebx ].wCode
shl eax, 4
or ax, word ptr [ ebx ].wCodeBuf
mov byte ptr [ edi ], al
inc edi
CompcalcDifference:
;
; reset difference
;
mov dword ptr [ ebx ].dwDifference, 0
;
; set up ECX as the step value
;
movzx ecx, word ptr [ ebx ].wStep
;
; get code in AX
;
movzx eax, word ptr [ ebx ].wCode
;
; check for wCode & 4
;
test eax, 4
je short Compno4
; add wStep
add dword ptr [ ebx ].dwDifference, ecx
Compno4:
;
; check for wCode & 2
;
test eax, 2
je short Compno2
; add wStep >> 1
mov edx, ecx
shr edx, 1
add dword ptr [ ebx ].dwDifference, edx
Compno2:
;
; check for wCode & 1
;
test eax, 1
je short Compno1
; add wStep >> 2
mov edx, ecx
shr edx, 2
add dword ptr [ ebx ].dwDifference, edx
Compno1:
;
; add in wStep >> 3
;
mov edx, ecx
shr edx, 3
add dword ptr [ ebx ].dwDifference, edx
;
; check for wCode & 8
;
test eax, 8
je short Compno8
; negate difference
neg dword ptr [ ebx ].dwDifference
Compno8:
;
; add difference to predicted
; value.
;
mov eax, [ ebx ].dwPredicted
add eax, [ ebx ].dwDifference
;
; make sure there is no under or
; overflow.
;
cmp eax, 7fffh
jl short CompnoOverflow
mov eax, 7fffh
CompnoOverflow:
cmp eax, 0ffff8000h
jg short CompnoUnderflow
mov eax, 0ffff8000h
CompnoUnderflow:
mov dword ptr [ ebx ].dwPredicted, eax
;
; adjust index
;
movzx ecx, word ptr [ ebx ].wCode
movzx eax, word ptr wCODECIndexTab[ ecx * 2 ]
add word ptr [ ebx ].wIndex, ax
;
; check if wIndex < 0
;
cmp word ptr [ ebx ].wIndex, 8000h
jb short CompcheckOverflow
; reset index to zero
mov word ptr [ ebx ].wIndex, 0
jmp short CompadjustStep
CompcheckOverflow:
;
; check if wIndex > 88
;
cmp word ptr [ ebx ].wIndex, 88
jbe short CompadjustStep
; reset index to 88
mov word ptr [ ebx ].wIndex, 88
CompadjustStep:
;
; fetch wIndex so we can fetch
; new step value
;
movzx ecx, word ptr [ ebx ].wIndex
movzx eax, word ptr wCODECStepTab[ ecx * 2 ]
;
; advance index and store step value
;
add dword ptr [ ebx ].dwSampleIndex, 1
mov word ptr [ ebx ].wStep, ax
;
; decrement bytes processed
; and loop back.
;
dec wCODECByteIndex
jne Compmainloop
;
; save off ESI and EDI back into
; compress info structure.
;
mov dword ptr [ ebx ].Source, esi
mov dword ptr [ ebx ].Dest, edi
;
; set up return value for number
; of bytes processed.
;
mov eax, wCODECBytesProcessed
shr eax, 2
;
; restore registers
;
pop edx
pop ecx
pop ebx
pop edi
pop esi
ret
_TEXT ends
end