725 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
			
		
		
	
	
			725 lines
		
	
	
		
			20 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)
 | ||
| ;*     Jonathan Lanier
 | ||
| ;*
 | ||
| ;* DATE
 | ||
| ;*     Febuary 15, 1995
 | ||
| ;*
 | ||
| ;* LAST MODIFIED
 | ||
| ;*     08/07/95 [jdl] - Rewrote/optimized sosCODECDecompressData
 | ||
| ;*
 | ||
| ;*---------------------------------------------------------------------------
 | ||
| ;*
 | ||
| ;* PUBLIC
 | ||
| ;*
 | ||
| ;****************************************************************************
 | ||
| 
 | ||
| 	IDEAL
 | ||
| 	P386
 | ||
| 	MODEL	USE32 FLAT
 | ||
| 	LOCALS	??
 | ||
| 
 | ||
| DPMI_INTR		equ	31h
 | ||
| IF_LOCKED_PM_CODE	equ	1h		; Locked PM code for DPMI.
 | ||
| IF_LOCKED_PM_DATA	equ	2h		; Locked PM code for DPMI.
 | ||
| 
 | ||
| STRUC	sCompInfo
 | ||
| lpSource		DD	?	;Compressed data pointer
 | ||
| lpDest			DD	?	;Uncompressed data pointer
 | ||
| dwCompSize		DD	?	;Compressed size
 | ||
| dwUnCompSize		DD	?	;Uncompressed size
 | ||
| 
 | ||
| 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
 | ||
| 
 | ||
| wBitSize		DW	?	;Bit size for decompression
 | ||
| wChannels		DW	?    	;number of channels
 | ||
| ENDS	sCompInfo
 | ||
| 
 | ||
| 
 | ||
| 	DATASEG
 | ||
| 
 | ||
| 
 | ||
| InitFlags	DD	0		; Flags to indicate what has been initialized.
 | ||
| 
 | ||
| 
 | ||
| LABEL	LockedDataStart	BYTE
 | ||
| 
 | ||
| ;* Index table for stepping into step table
 | ||
| 
 | ||
| INCLUDE		"difftb.inc"
 | ||
| INCLUDE		"indextb.inc"
 | ||
| INCLUDE		"nybbtb.inc"
 | ||
| 
 | ||
| LABEL	LockedDataEnd	BYTE
 | ||
| 
 | ||
| 	CODESEG
 | ||
| 
 | ||
| LABEL	LockedCodeStart	BYTE
 | ||
| 
 | ||
| ;****************************************************************************
 | ||
| ;*
 | ||
| ;* 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	sosCODECInitStream:NEAR
 | ||
| 	PROC	sosCODECInitStream C NEAR
 | ||
| 
 | ||
| 	ARG	sSOSInfo:NEAR PTR
 | ||
| 
 | ||
| 	mov	eax,[sSOSInfo]
 | ||
| 	mov	[(sCompInfo eax).wIndex],0 		; starting index 0
 | ||
| 	mov	[(sCompInfo eax).dwPredicted],0 	; no predicted value
 | ||
| 	mov	[(sCompInfo eax).wIndex2],0 		; starting index 0
 | ||
| 	mov	[(sCompInfo eax).dwPredicted2],0 	; no predicted value
 | ||
| 	ret
 | ||
| 
 | ||
| 	ENDP	sosCODECInitStream
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| ;****************************************************************************
 | ||
| ;*
 | ||
| ;* 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 decompress.
 | ||
| ;*
 | ||
| ;* RESULT
 | ||
| ;*     Size - Size of decompressed data.
 | ||
| ;*
 | ||
| ;*
 | ||
| ;* NOTES
 | ||
| ;*     This routine has been optimized for pipelining on both
 | ||
| ;*     486 and Pentium processors.  Changing, inserting, or moving any
 | ||
| ;*     instructions will most likely slow down the code, in some cases by
 | ||
| ;*     as much as 20%.  It can burst-decompress 16384 samples in about
 | ||
| ;*     1940<34>s on a Pentium 90Mhz, and about 3960<36>s on a 486 66Mhz.
 | ||
| ;*     Instruction reordering could bring this down to below 1870<37>s on
 | ||
| ;*     the Pentium, but this would cause a great degradation in 486
 | ||
| ;*     performance.  Since slow 486's are the reason this code was
 | ||
| ;*     written to be fast, it has been optimized for the Pentium only where
 | ||
| ;*     it would not degrade 486 performance.  So, be careful when changing
 | ||
| ;*     ANY of this code, because it is very carefully balanced...
 | ||
| ;****************************************************************************
 | ||
| 
 | ||
| 	GLOBAL	C sosCODECDecompressData:NEAR
 | ||
| 	PROC	sosCODECDecompressData C NEAR
 | ||
| 
 | ||
| 	ARG	sSOSInfo:NEAR PTR
 | ||
| 	ARG	wBytes:DWORD
 | ||
| 
 | ||
| 	push	esi
 | ||
| 	push	edi
 | ||
| 	push	ebx
 | ||
| 	push	ecx
 | ||
| 	push	edx			;save all the regs
 | ||
| 
 | ||
| 	mov	ebx,[sSOSInfo]		;get base of sCompInfo struct
 | ||
| 	mov	cx,[(sCompInfo ebx).wBitSize] ;check the bit size
 | ||
| 	mov	dx,[(sCompInfo ebx).wChannels] ;check the number of channels
 | ||
| ;
 | ||
| ;
 | ||
| ; Determine the correct routine to use for decoding
 | ||
| ; (for now only ADPCM 4:1 Mono 16-bit is implemented)
 | ||
| 	cmp	cx,8
 | ||
| 	jne	??do16Bits
 | ||
| 
 | ||
| ??do8Bits:
 | ||
| 	cmp	dx,2
 | ||
| 	jne	??not8Stereo
 | ||
| ;	jmp	??decomp8Stereo
 | ||
| 	jmp	??byeBye
 | ||
| 
 | ||
| ??not8Stereo:
 | ||
| 	cmp	dx,1
 | ||
| 	jne	??byeBye
 | ||
| ;	jmp	decomp8Mono
 | ||
| 	jmp	??byeBye
 | ||
| 
 | ||
| ??do16Bits:
 | ||
| 	cmp	cx,16
 | ||
| 	jne	??byeBye
 | ||
| 
 | ||
| 	cmp	dx,2
 | ||
| 	jne	??not16Stereo
 | ||
| ;	jmp	??decomp16Stereo
 | ||
| 	jmp	??byeBye
 | ||
| 
 | ||
| ??not16Stereo:
 | ||
| 	cmp	dx,1
 | ||
| 	jne	??byeBye
 | ||
| 
 | ||
| 	push	ebp
 | ||
| ;
 | ||
| ;
 | ||
| ; 16 bit ADPCM 4:1 Mono pre-loop initialization
 | ||
| ??decomp16Mono:
 | ||
| 	push	ebx			;save struct base
 | ||
| 	xor	edx,edx			;clear index
 | ||
| 	mov	eax,[(sCompInfo ebx).dwPredicted]	;get last sample
 | ||
| 	mov	dx,[(sCompInfo ebx).wIndex]	;get last index value
 | ||
| 	mov	esi,[(sCompInfo ebx).lpSource]	;get source address
 | ||
| 	mov	edi,[(sCompInfo ebx).lpDest]	;get dest address
 | ||
| 
 | ||
| 	mov	ebp,[wBytes]		;get the number of dest. bytes
 | ||
| 	cmp	ebp,16			;less than 16? (less than 8 samples)
 | ||
| 	jl	??fixAlign16Mono0	;if so, don't bother with alignment
 | ||
| ;
 | ||
| ;
 | ||
| ; Check to see if we need to fix an alignment problem on the source buffer
 | ||
| ; (non-aligned buffers are MUCH slower; if we're given a non-DWORD aligned
 | ||
| ; source address, we do as many samples as needed to get to the nearest
 | ||
| ; DWORD boundary, then finish the bulk as a DWORD-aligned decompress).
 | ||
| 	mov	ebx,esi			;get source address
 | ||
| 	and	ebx,03h			;check LSB
 | ||
| 	jnz	??fixalign16Mono	;if non-zero, need to align for
 | ||
| 					;warp speed
 | ||
| ??fixAlign16Mono0:
 | ||
| 	push	ebp			;save for later
 | ||
| 	shr	ebp,4			;divide by 16 for 16-bit,
 | ||
| 					;because we do 8 nybbles per loop,
 | ||
| 					;and there are two samples per
 | ||
| 					;byte, so there are n/16 iterations
 | ||
| 					;required
 | ||
| 	xor	ebx,ebx			;clear our nybble index
 | ||
| 	or	ebp,ebp			;set flags for EBP
 | ||
| 	jmp	??start16Mono		;start with test... don't go if
 | ||
| 					;we have zero bytes to do
 | ||
| ??fixalign16Mono:
 | ||
| 	jmp	[DWORD PTR dwMono16AlignJmpTable+ebx*4] ;do non-aligned first
 | ||
| 
 | ||
| 	align	4
 | ||
| ??fixAlign16Mono1:
 | ||
| 	sub	ebp,12			;adjust # of dest. bytes
 | ||
| 	push	ebp			;save it
 | ||
| 	shr	ebp,4			;divide by 16 to get samples/8
 | ||
| 	xor	ebx,ebx			;clear our nybble index
 | ||
| 	inc	ebp			;adjust ebp for loop
 | ||
| 	jmp	??finish16Mono6		;borrow exit code to go through a
 | ||
| 					;piece of a loop
 | ||
| 	align	4
 | ||
| ??fixAlign16Mono2:
 | ||
| 	sub	ebp,8			;adjust # of dest. bytes
 | ||
| 	push	ebp			;save it
 | ||
| 	shr	ebp,4			;divide by 16 to get samples/8
 | ||
| 	xor	ebx,ebx			;clear our nybble index
 | ||
| 	inc	ebp			;adjust ebp for loop
 | ||
| 	jmp	??finish16Mono4		;borrow exit code to go through a
 | ||
| 					;piece of a loop
 | ||
| 	align	4
 | ||
| ??fixAlign16Mono3:
 | ||
| 	sub	ebp,4			;adjust # of dest. bytes
 | ||
| 	push	ebp			;save it
 | ||
| 	shr	ebp,4			;divide by 16 to get samples/8
 | ||
| 	xor	ebx,ebx			;clear our nybble index
 | ||
| 	inc	ebp			;adjust ebp for loop
 | ||
| 	jmp	??finish16Mono2		;borrow exit code to go through a
 | ||
| 					;piece of a loop
 | ||
| ; "The Loop"
 | ||
| ;
 | ||
| ; Process 1st nybble
 | ||
| 	align	4
 | ||
| ??loop16Mono:
 | ||
| 	add	eax,[dwDiffTable+edx*2]	;add difference to prev. sample
 | ||
| 	mov	dx,[wIndexTable+edx]	;adjust dx to next index base
 | ||
| 	cmp	eax,00007FFFh		;check for overflow
 | ||
| 	jg	??fix1Smp16MonoO
 | ||
| 	cmp	eax,0FFFF8000h		;check for underflow
 | ||
| 	jl	??fix1Smp16MonoU
 | ||
| ??fixed1Smp16Mono:
 | ||
| 	or	dl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble
 | ||
| 	mov	[edi],ax		;save the sample
 | ||
| ;
 | ||
| ;
 | ||
| ; Process 2nd nybble
 | ||
| ??finish7Smp16Mono:
 | ||
| 	mov	bl,ch			;get next 2 nybbles in ebx
 | ||
| 	add	eax,[dwDiffTable+edx*2]	;add difference to prev. sample
 | ||
| 	mov	dx,[wIndexTable+edx]	;adjust dx to next index base
 | ||
| 	cmp	eax,00007FFFh		;check for overflow
 | ||
| 	jg	??fix2Smp16MonoO
 | ||
| 	cmp	eax,0FFFF8000h		;check for underflow
 | ||
| 	jl	??fix2Smp16MonoU
 | ||
| ??fixed2Smp16Mono:
 | ||
| 	or	dl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble
 | ||
| 	mov	[edi+02h],ax		;save the sample
 | ||
| 	shr	ecx,16			;move top four nybbles into bottom
 | ||
| ;
 | ||
| ;
 | ||
| ; Process 3rd nybble
 | ||
| ??finish6Smp16Mono:
 | ||
| 	add	eax,[dwDiffTable+edx*2]	;add difference to prev. sample
 | ||
| 	mov	dx,[wIndexTable+edx]	;adjust dx to next index base
 | ||
| 	cmp	eax,00007FFFh		;check for overflow
 | ||
| 	jg	??fix3Smp16MonoO
 | ||
| 	cmp	eax,0FFFF8000h		;check for underflow
 | ||
| 	jl	??fix3Smp16MonoU
 | ||
| ??fixed3Smp16Mono:
 | ||
| 	or	dl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble
 | ||
| 	mov	[edi+04h],ax		;save the sample
 | ||
| ;
 | ||
| ;
 | ||
| ; Process 4th nybble
 | ||
| ??finish5Smp16Mono:
 | ||
| 	mov	bl,cl
 | ||
| 	add	eax,[dwDiffTable+edx*2]	;add difference to prev. sample
 | ||
| 	mov	dx,[wIndexTable+edx]	;adjust dx to next index base
 | ||
| 	cmp	eax,00007FFFh		;check for overflow
 | ||
| 	jg	??fix4Smp16MonoO
 | ||
| 	cmp	eax,0FFFF8000h		;check for underflow
 | ||
| 	jl	??fix4Smp16MonoU
 | ||
| ??fixed4Smp16Mono:
 | ||
| 	or	dl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble
 | ||
| 	mov	[edi+06h],ax		;save the sample
 | ||
| ;
 | ||
| ;
 | ||
| ; Process 5th nybble
 | ||
| ??finish4Smp16Mono:
 | ||
| 	add	eax,[dwDiffTable+edx*2]	;add difference to prev. sample
 | ||
| 	mov	dx,[wIndexTable+edx]	;adjust dx to next index base
 | ||
| 	cmp	eax,00007FFFh		;check for overflow
 | ||
| 	jg	??fix5Smp16MonoO
 | ||
| 	cmp	eax,0FFFF8000h		;check for underflow
 | ||
| 	jl	??fix5Smp16MonoU
 | ||
| ??fixed5Smp16Mono:
 | ||
| 	or	dl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble
 | ||
| 	mov	[edi+08h],ax		;save the sample
 | ||
| ;
 | ||
| ;
 | ||
| ; Process 6th nybble
 | ||
| ??finish3Smp16Mono:
 | ||
| 	mov	bl,ch
 | ||
| 	add	eax,[dwDiffTable+edx*2]	;add difference to prev. sample
 | ||
| 	mov	dx,[wIndexTable+edx]	;adjust dx to next index base
 | ||
| 	cmp	eax,00007FFFh		;check for overflow
 | ||
| 	jg	??fix6Smp16MonoO
 | ||
| 	cmp	eax,0FFFF8000h		;check for underflow
 | ||
| 	jl	??fix6Smp16MonoU
 | ||
| ??fixed6Smp16Mono:
 | ||
| 	or	dl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble
 | ||
| 	mov	[edi+0Ah],ax		;save the sample
 | ||
| ;
 | ||
| ;
 | ||
| ; Process 7th nybble
 | ||
| ??finish2Smp16Mono:
 | ||
| 	add	eax,[dwDiffTable+edx*2]	;add difference to prev. sample
 | ||
| 	mov	dx,[wIndexTable+edx]	;adjust dx to next index base
 | ||
| 	cmp	eax,00007FFFh		;check for overflow
 | ||
| 	jg	??fix7Smp16MonoO
 | ||
| 	cmp	eax,0FFFF8000h		;check for underflow
 | ||
| 	jl	??fix7Smp16MonoU
 | ||
| ??fixed7Smp16Mono:
 | ||
| 	or	dl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble
 | ||
| 	mov	[edi+0Ch],ax		;save the sample
 | ||
| ;
 | ||
| ;
 | ||
| ; Process 8th nybble
 | ||
| ??finish1Smp16Mono:
 | ||
| 	add	eax,[dwDiffTable+edx*2]	;add difference to prev. sample
 | ||
| 	mov	dx,[wIndexTable+edx]	;adjust dx to next index base
 | ||
| 	cmp	eax,00007FFFh		;check for overflow
 | ||
| 	jg	??fix8Smp16MonoO
 | ||
| 	cmp	eax,0FFFF8000h		;check for underflow
 | ||
| 	jl	??fix8Smp16MonoU
 | ||
| ;
 | ||
| ;
 | ||
| ; Loop cleanup for next pass
 | ||
| ??fixed8Smp16Mono:
 | ||
| 	mov	[edi+0Eh],ax		;save the sample
 | ||
| 	add	esi,04h			;bump esi to point to next longword
 | ||
| 	add	edi,10h			;incr. the destination buffer ptr
 | ||
| 	dec	ebp			;count down the number of samples/8
 | ||
| ??start16Mono:
 | ||
| 	jng	??cleanup16Mono		;if done, clean up
 | ||
| 	mov	ecx,[esi]		;get 4 nybbles in one whack (whee!)
 | ||
| 	mov	bl,cl			;get next 2 nybbles in ebx
 | ||
| 	or	dl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble
 | ||
| 	jmp	??loop16Mono		;loop until done
 | ||
| 
 | ||
| ??cleanup16Mono:
 | ||
| 	jnz	??done16Mono		;if ebp is non-zero, we're DONE
 | ||
| 					;if exactly zero, finish the tail-end
 | ||
| 					;of the conversion (may be a non-
 | ||
| 					;multiple of 8 nybbles)
 | ||
| ;
 | ||
| ;
 | ||
| ; Loop cleanup for last (incomplete) pass
 | ||
| 	pop	ecx			;restore # of words
 | ||
| 	shr	ecx,1			;divide by two to get samples
 | ||
| 	and	ecx,07h			;get # of samples we missed
 | ||
| 	jmp	[DWORD PTR dwMono16JmpTable+ecx*4] ;go finish the job...
 | ||
| ;
 | ||
| ;
 | ||
| ; Structure cleanup
 | ||
| ??done16Mono:
 | ||
| 	pop	ebx			;restore struct base
 | ||
| 	pop	ebp			;restore stack frame pointer
 | ||
| 	mov	[(sCompInfo ebx).dwPredicted],eax ;save last sample
 | ||
| 	mov	[(sCompInfo ebx).wIndex],dx ;save last index value
 | ||
| 	mov	eax,[wBytes]		;get # of bytes we did
 | ||
| ??byeBye:
 | ||
| 	pop	edx			;restore all the regs
 | ||
| 	pop	ecx
 | ||
| 	pop	ebx
 | ||
| 	pop	edi
 | ||
| 	pop	esi
 | ||
| 	ret
 | ||
| ;
 | ||
| ;
 | ||
| ; Jumps for -32768/+32767 bounds check go to these vvvv
 | ||
| 	align	4
 | ||
| ??fix1Smp16MonoO:
 | ||
| 	mov	eax,00007FFFh		;Overflow - truncate to +32767
 | ||
| 	jmp	??fixed1Smp16Mono	;go back
 | ||
| 
 | ||
| 	align	4
 | ||
| ??fix1Smp16MonoU:
 | ||
| 	mov	eax,0FFFF8000h		;Underflow - truncate to -32768
 | ||
| 	jmp	??fixed1Smp16Mono	;go back
 | ||
| 
 | ||
| 	align	4
 | ||
| ??fix2Smp16MonoO:
 | ||
| 	mov	eax,00007FFFh		;Overflow - truncate to +32767
 | ||
| 	jmp	??fixed2Smp16Mono	;go back
 | ||
| 
 | ||
| 	align	4
 | ||
| ??fix2Smp16MonoU:
 | ||
| 	mov	eax,0FFFF8000h		;Underflow - truncate to -32768
 | ||
| 	jmp	??fixed2Smp16Mono	;go back
 | ||
| 
 | ||
| 	align	4
 | ||
| ??fix3Smp16MonoO:
 | ||
| 	mov	eax,00007FFFh		;Overflow - truncate to +32767
 | ||
| 	jmp	??fixed3Smp16Mono	;go back
 | ||
| 
 | ||
| 	align	4
 | ||
| ??fix3Smp16MonoU:
 | ||
| 	mov	eax,0FFFF8000h		;Underflow - truncate to -32768
 | ||
| 	jmp	??fixed3Smp16Mono	;go back
 | ||
| 
 | ||
| 	align	4
 | ||
| ??fix4Smp16MonoO:
 | ||
| 	mov	eax,00007FFFh		;Overflow - truncate to +32767
 | ||
| 	jmp	??fixed4Smp16Mono	;go back
 | ||
| 
 | ||
| 	align	4
 | ||
| ??fix4Smp16MonoU:
 | ||
| 	mov	eax,0FFFF8000h		;Underflow - truncate to -32768
 | ||
| 	jmp	??fixed4Smp16Mono	;go back
 | ||
| 
 | ||
| 	align	4
 | ||
| ??fix5Smp16MonoO:
 | ||
| 	mov	eax,00007FFFh		;Overflow - truncate to +32767
 | ||
| 	jmp	??fixed5Smp16Mono	;go back
 | ||
| 
 | ||
| 	align	4
 | ||
| ??fix5Smp16MonoU:
 | ||
| 	mov	eax,0FFFF8000h		;Underflow - truncate to -32768
 | ||
| 	jmp	??fixed5Smp16Mono	;go back
 | ||
| 
 | ||
| 	align	4
 | ||
| ??fix6Smp16MonoO:
 | ||
| 	mov	eax,00007FFFh		;Overflow - truncate to +32767
 | ||
| 	jmp	??fixed6Smp16Mono	;go back
 | ||
| 
 | ||
| 	align	4
 | ||
| ??fix6Smp16MonoU:
 | ||
| 	mov	eax,0FFFF8000h		;Underflow - truncate to -32768
 | ||
| 	jmp	??fixed6Smp16Mono	;go back
 | ||
| 
 | ||
| 	align	4
 | ||
| ??fix7Smp16MonoO:
 | ||
| 	mov	eax,00007FFFh		;Overflow - truncate to +32767
 | ||
| 	jmp	??fixed7Smp16Mono	;go back
 | ||
| 
 | ||
| 	align	4
 | ||
| ??fix7Smp16MonoU:
 | ||
| 	mov	eax,0FFFF8000h		;Underflow - truncate to -32768
 | ||
| 	jmp	??fixed7Smp16Mono	;go back
 | ||
| 
 | ||
| 	align	4
 | ||
| ??fix8Smp16MonoO:
 | ||
| 	mov	eax,00007FFFh		;Overflow - truncate to +32767
 | ||
| 	jmp	??fixed8Smp16Mono	;go back
 | ||
| 
 | ||
| 	align	4
 | ||
| ??fix8Smp16MonoU:
 | ||
| 	mov	eax,0FFFF8000h		;Underflow - truncate to -32768
 | ||
| 	jmp	??fixed8Smp16Mono	;go back
 | ||
| ;
 | ||
| ;
 | ||
| ; Jump tables for cleanup after loop unroll point to these vvvv
 | ||
| 	align	4
 | ||
| ??finish16Mono1:
 | ||
| 	xor	ecx,ecx			;clear nybble bucket
 | ||
| 	mov	ch,[esi]		;get 1 nybble (1 byte)
 | ||
| 	shl	ch,4			;move it over
 | ||
| 	mov	bl,ch			;get nybble in ebx
 | ||
| 	sub	edi,0Eh			;back edi up
 | ||
| 	or	dl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble
 | ||
| 	jmp	??finish1Smp16Mono	;go finish it
 | ||
| 
 | ||
| 	align	4
 | ||
| ??finish16Mono2:
 | ||
| 	xor	ecx,ecx			;clear nybble bucket
 | ||
| 	mov	ch,[esi]		;get 2 nybbles (1 byte)
 | ||
| 	mov	bl,ch			;get nybbles in ebx
 | ||
| 	sub	edi,0Ch			;back edi up
 | ||
| 	sub	esi,3			;adjust esi (used for dword aligning)
 | ||
| 	or	dl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble
 | ||
| 	jmp	??finish2Smp16Mono	;go finish it
 | ||
| 
 | ||
| 	align	4
 | ||
| ??finish16Mono3:
 | ||
| 	xor	ecx,ecx			;clear nybble bucket
 | ||
| 	mov	cx,[esi]		;get 3 nybbles (2 bytes)
 | ||
| 	shl	cx,4			;move it over
 | ||
| 	mov	bl,cl			;get nybbles in ebx
 | ||
| 	sub	edi,0Ah			;back edi up
 | ||
| 	or	dl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble
 | ||
| 	jmp	??finish3Smp16Mono	;go finish it
 | ||
| 
 | ||
| 	align	4
 | ||
| ??finish16Mono4:
 | ||
| 	xor	ecx,ecx			;clear nybble bucket
 | ||
| 	mov	cx,[esi]		;get 4 nybbles (2 bytes)
 | ||
| 	mov	bl,cl			;get nybbles in ebx
 | ||
| 	sub	edi,08h			;back edi up
 | ||
| 	sub	esi,2			;adjust esi (used for dword aligning)
 | ||
| 	or	dl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble
 | ||
| 	jmp	??finish4Smp16Mono	;go finish it
 | ||
| 
 | ||
| 	align	4
 | ||
| ??finish16Mono5:
 | ||
| 	xor	ecx,ecx			;clear nybble bucket
 | ||
| 	mov	cl,[esi+2]		;get 1 nybble (1 byte)
 | ||
| 	shl	ecx,16			;shift it over
 | ||
| 	mov	cx,[esi]		;get 4 nybbles (2 bytes)
 | ||
| 	mov	bl,cl			;get nybbles in ebx
 | ||
| 	shr	ecx,4			;move it over
 | ||
| 	shl	bl,4			;move it over
 | ||
| 	sub	edi,06h			;back edi up
 | ||
| 	or	dl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble
 | ||
| 	jmp	??finish5Smp16Mono	;go finish it
 | ||
| 
 | ||
| 	align	4
 | ||
| ??finish16Mono6:
 | ||
| 	xor	ecx,ecx			;clear nybble bucket
 | ||
| 	mov	cl,[esi+2]		;get 2 nybbles (1 byte)
 | ||
| 	shl	ecx,16			;move it over
 | ||
| 	mov	cx,[esi]		;get 4 nybbles (2 bytes)
 | ||
| 	mov	bl,cl			;get nybbles in ebx
 | ||
| 	shr	ecx,8			;move it over
 | ||
| 	sub	esi,1			;adjust esi (used for dword aligning)
 | ||
| 	sub	edi,04h			;back edi up
 | ||
| 	or	dl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble
 | ||
| 	jmp	??finish6Smp16Mono	;go finish it
 | ||
| 
 | ||
| 	align	4
 | ||
| ??finish16Mono7:
 | ||
| 	xor	ecx,ecx			;clear nybble bucket
 | ||
| 	mov	ecx,[esi]		;get 7 nybbles (4 bytes)
 | ||
| 	shl	ecx,4			;move it over
 | ||
| 	mov	bl,cl			;get nybbles in ebx
 | ||
| 	sub	edi,02h			;back edi up
 | ||
| 	or	dl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble
 | ||
| 	jmp	??finish7Smp16Mono	;go finish it
 | ||
| ;
 | ||
| ;
 | ||
| ; Jump Tables
 | ||
| 			align 4
 | ||
| 
 | ||
| dwMono16JmpTable	DD	??done16Mono
 | ||
| 			DD	??finish16Mono1
 | ||
| 			DD	??finish16Mono2
 | ||
| 			DD	??finish16Mono3
 | ||
| 			DD	??finish16Mono4
 | ||
| 			DD	??finish16Mono5
 | ||
| 			DD	??finish16Mono6
 | ||
| 			DD	??finish16Mono7
 | ||
| 
 | ||
| 			align 4
 | ||
| dwMono16AlignJmpTable	DD	??fixAlign16Mono0
 | ||
| 			DD	??fixAlign16Mono1
 | ||
| 			DD	??fixAlign16Mono2
 | ||
| 			DD	??fixAlign16Mono3
 | ||
| 
 | ||
| 	ENDP	sosCODECDecompressData
 | ||
| 
 | ||
| LABEL	LockedCodeEnd	BYTE
 | ||
| 
 | ||
| ;***************************************************************************
 | ||
| ;* sosCODEC_LOCK -- locks the JLB audio decompression code		   *
 | ||
| ;*                                                                         *
 | ||
| ;* INPUT:	none                                                       *
 | ||
| ;*                                                                         *
 | ||
| ;* OUTPUT:      BOOL true is lock sucessful, false otherwise		   *
 | ||
| ;*                                                                         *
 | ||
| ;* PROTO:       BOOL sosCODEC_Lock(void);                         	   *
 | ||
| ;*                                                                         *
 | ||
| ;* HISTORY:								   *
 | ||
| ;*   06/26/1995 PWG : Created.                                             *
 | ||
| ;*=========================================================================*
 | ||
| 	GLOBAL	sosCODEC_Lock:NEAR
 | ||
| 	PROC	sosCODEC_Lock C NEAR USES ebx ecx edx esi edi
 | ||
| 
 | ||
| 	;
 | ||
| 	; Lock the code that is used by the sos decompression method.
 | ||
| 	;
 | ||
| 	mov	eax,0600h			; function number.
 | ||
| 	mov	ecx,OFFSET LockedCodeStart	; ecx must have start of memory.
 | ||
| 	mov	edi,OFFSET LockedCodeEnd	; edi will have size of region in bytes.
 | ||
| 	shld	ebx,ecx,16
 | ||
| 	sub	edi, ecx
 | ||
| 	shld	esi,edi,16
 | ||
|   	int	DPMI_INTR			; do call.
 | ||
| 	jc	??error
 | ||
| 	or	[InitFlags], IF_LOCKED_PM_CODE
 | ||
| 
 | ||
| 	;
 | ||
| 	; Lock the data used by the sos decompression method.
 | ||
| 	;
 | ||
| 	mov	eax,0600h			; function number.
 | ||
| 	mov	ecx,OFFSET LockedDataStart	; ecx must have start of memory.
 | ||
| 	mov	edi,OFFSET LockedDataEnd	; edi will have size of region in bytes.
 | ||
| 	shld	ebx,ecx,16
 | ||
| 	sub	edi, ecx
 | ||
| 	shld	esi,edi,16
 | ||
|    	int	DPMI_INTR			; do call.
 | ||
| 	jc	??error				; eax = 8 if mem err, eax = 9 if invalid mem region.
 | ||
| 	or	[InitFlags], IF_LOCKED_PM_DATA
 | ||
| 
 | ||
| 	mov	eax,1
 | ||
| 	jmp	??exit
 | ||
| ??error:
 | ||
| 	xor	eax,eax
 | ||
| ??exit:
 | ||
| 	ret
 | ||
| 	ENDP	sosCODEC_Lock
 | ||
| 
 | ||
| ;***************************************************************************
 | ||
| ;* DECOMPRESS_FRAME_UNLOCK -- Unlocks the JLB audio compression code       *
 | ||
| ;*                                                                         *
 | ||
| ;* INPUT:	none                                                       *
 | ||
| ;*                                                                         *
 | ||
| ;* OUTPUT:      BOOL true is unlock sucessful, false otherwise		   *
 | ||
| ;*                                                                         *
 | ||
| ;* PROTO:	BOOL sosCODEC_Unlock(void);                        	   *
 | ||
| ;*                                                                         *
 | ||
| ;* HISTORY:								   *
 | ||
| ;*   06/26/1995 PWG : Created.                                             *
 | ||
| ;*=========================================================================*
 | ||
| 	GLOBAL	sosCODEC_Unlock:NEAR
 | ||
| 	PROC	sosCODEC_Unlock C NEAR USES ebx ecx edx esi edi
 | ||
| 
 | ||
| 	test	[InitFlags],IF_LOCKED_PM_CODE
 | ||
| 	jz	??code_not_locked
 | ||
| 
 | ||
| 	mov	eax , 0601h
 | ||
| 	mov	ecx,OFFSET LockedCodeStart	; ecx must have start of memory.
 | ||
| 	mov	edi,OFFSET LockedCodeEnd	; edx will have size of region in bytes.
 | ||
| 	sub	edi,ecx				;  - figure size.
 | ||
| 	shld	ebx , ecx , 16
 | ||
| 	shld	esi , edi , 16
 | ||
| 	int	DPMI_INTR			; do call.
 | ||
| 	jc	??error
 | ||
| 
 | ||
| ??code_not_locked:
 | ||
| 	test	[InitFlags],IF_LOCKED_PM_DATA
 | ||
| 	jz	??data_not_locked
 | ||
| 
 | ||
| 	mov	ax,0601h				; set es to descriptor of data.
 | ||
| 	mov	ecx,OFFSET LockedDataStart	; ecx must have start of memory.
 | ||
| 	mov	edi,OFFSET LockedDataEnd	; edx will have size of region in bytes.
 | ||
| 	sub	edi,ecx				;  - figure size.
 | ||
| 	shld	ebx , ecx , 16
 | ||
| 	shld	esi , edi , 16
 | ||
| 	int	DPMI_INTR			; do call.
 | ||
| 	jc	??error				; eax = 8 if mem err, eax = 9 if invalid mem region.
 | ||
| 
 | ||
| ??data_not_locked:
 | ||
| 	mov	[InitFlags],0
 | ||
| 	mov	eax,1
 | ||
| 	jmp	??exit
 | ||
| ??error:
 | ||
| 	xor	eax,eax
 | ||
| ??exit:
 | ||
| 	ret
 | ||
| 	ENDP	sosCODEC_Unlock
 | ||
| 
 | ||
| 	END
 | ||
| 
 | 
