;
;	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/>.
;

;***************************************************************************
;**      C O N F I D E N T I A L --- W E S T W O O D   S T U D I O S      **
;***************************************************************************
;*                                                                         *
;*                 Project Name : Westwood 32 bit Audio Library            *
;*                                                                         *
;*                    File Name : AUDUNCMP.ASM                             *
;*                                                                         *
;*                   Programmer : Phil W. Gorrow                           *
;*                                                                         *
;*                   Start Date : March 14, 1995                           *
;*                                                                         *
;*                  Last Update : June 26, 1995   [PWG]                    *
;*                                                                         *
;*-------------------------------------------------------------------------*
;* Functions:                                                              *
;*   Decompress_Frame_Lock -- locks the JLB audio decompression code       *
;*   Decompress_Frame_Unlock -- Unlocks the JLB audio compression code     *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *

	IDEAL
	P386
	MODEL	USE32 FLAT
	LOCALS	??
	CODESEG

DPMI_INTR		equ	31h	

LABEL 	LockedCodeStart	BYTE

CODE_2BIT	EQU	0
CODE_4BIT	EQU	1
CODE_RAW	EQU	2
CODE_SILENCE	EQU	3
MAGICNUMBER	EQU	00000DEAFh
MAGICNUMBER2	EQU	0BABEBABEh

_2bitdecode	DB	-2,-1,0,1
_4bitdecode	DB	-9,-8,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,8


;***************************************************************************
;* DECOMPRESS_FRAME -- Uncompresses a WW compressed audio frame            *
;*                                                                         *
;* INPUT:	void * source - pointer to encoded audio data              *
;*		void * dest   - pointer to decompression area		   *
;*		long size     - the maximum size of destination buffer	   *
;*                                                                         *
;* OUTPUT:      long - the number of bytes we uncompressed                 *
;*                                                                         *
;* PROTO:	long Decompress_Frame(void *, void *, long);		   *
;*                                                                         *
;* HISTORY:                                                                *
;*   03/14/1995 PWG : Created.                                             *
;*=========================================================================*

	GLOBAL	Decompress_Frame:NEAR
	PROC	Decompress_Frame C NEAR USES ebx ecx edx esi edi

	ARG	source:DWORD
	ARG	dest:DWORD
	ARG	count:DWORD

	LOCAL	previous:BYTE
	LOCAL	incount:DWORD

	pushf
	cld
	mov	[incount],0	;Bytes read from source


;	Source, Dest and count must be valid.

	cmp	[source],0
	je	??fini

	cmp	[dest],0
	je	??fini

	cmp	[count],0
	je	??fini

	mov	esi,[source]	;Pointer to source data.
	mov	edi,[dest]	;Pointer to destination data.
	mov	ecx,[count]	;Number of bytes to fill dest buffer.
	mov	dl,080h	;Previous sample (starting value).

??mainloop:
	cmp	ecx,0	;If dest full then exit
	jle	??fini

	xor	eax,eax
	mov	al,[esi]	;Get code byte
	inc	[incount]
	inc	esi
	shl	eax,2	;AH contains code.
	shr	al,2	;AL contains sub-code data.

	cmp	ah,CODE_RAW	;Raw sequence?
	jne	short ??try4bit

;	The code contains either a 5 bit delta or a count of
;	raw samples to dump out.

	test	al,00100000b
	je	short ??justraw

;	The lower 5 bits are actually a signed delta.
;	Sign extend the delta and add it to the stream.

	shl	al,3
	sar	al,3
	add	dl,al
	mov	[edi],dl
	dec	ecx
	inc	edi
	jmp	??mainloop

;	The lower 5 bits hold a count of the number of raw
;	samples that follow this code. Dump these samples to
;	the output buffer.

??justraw:
	mov	ebx,ecx
	xor	ah,ah
	inc	al
	mov	ecx,eax
	shr	ecx,1
	rep	movsw
	adc	ecx,ecx
	rep	movsb
	mov	ecx,ebx
	add	[incount],eax
	sub	ecx,eax
	dec	edi
	mov	dl,[edi]	;Set "previous" value.
	inc	edi
	jmp	??mainloop

;	Check to see if this is a 4 bit delta code sequence.

??try4bit:
	inc	al	;Following codes use AL+1
	cmp	ah,CODE_4BIT
	jne	short ??try2bit

;	A sequence of 4bit deltas follow. AL equals the
;	number of nibble packed delta bytes to process.

??bit4loop:
	mov	ah,[esi]	;Fetch nibble packed delta codes
	mov	bl,ah
	inc	[incount]
	inc	esi

;	Add first delta to 'previous' sample already in DL.

	and	ebx,00001111b
	add	dl,[_4bitdecode+ebx]
	pushf
	cmp	[_4bitdecode+ebx],0
	jl	short ??neg1

	popf
	jnc	short ??ok1
	mov	dl,0FFh
	jmp	short ??ok1

??neg1:
	popf
	jc	short ??ok1

	xor	dl,dl

??ok1:
	mov	dh,dl	;DH now holds new 'previous' sample.
	mov	bl,ah
	shr	bl,4
	add	dh,[_4bitdecode+ebx]
	pushf
	cmp	[_4bitdecode+ebx],0
	jl	short ??neg2

	popf
	jnc	short ??ok2

	mov	dh,0FFh
	jmp	short ??ok2

??neg2:
	popf
	jc	short ??ok2

	xor	dh,dh

??ok2:
	mov	[edi],dx	;Output the two sample bytes
	sub	ecx,2
	add	edi,2

;	Put the correct 'previous' sample in DL where it belongs.

	mov	dl,dh

;	If there are more deltas to process then loop back.

	dec	al
	jnz	short ??bit4loop
	jmp	??mainloop

;	Check to see if 2 bit deltas need to be processed.

??try2bit:
	cmp	ah,CODE_2BIT
	jne	??zerodelta

;	A sequence of 2bit deltas follow.  AL equals the number of 
;	packed delta bytes to process.

??bit2loop:
	mov	ah,[esi]	;Fetch packed delat codes
	inc	[incount]
	inc	esi

;	Add first delta to 'previous' sample already in DL.

	mov	bl,ah
	and	ebx,000011b
	add	dl,[_2bitdecode+ebx]
	pushf
	cmp	[_2bitdecode+ebx],0
	jl	short ??neg3

	popf
	jnc	short ??ok3

	mov	dl,0FFh
	jmp	short ??ok3

??neg3:
	popf
	jc	short ??ok3
	xor	dl,dl

??ok3:
	mov	dh,dl
	ror	edx,8
	mov	bl,ah
	shr	ebx,2
	and	bl,00000011b
	add	dl,[_2bitdecode+ebx]
	pushf
	cmp	[_2bitdecode+ebx],0
	jl	short ??neg4

	popf
	jnc	short ??ok4

	mov	dl,0FFh
	jmp	short ??ok4

??neg4:
	popf
	jc	short ??ok4

	xor	dl,dl

??ok4:
	mov	dh,dl
	ror	edx,8
	mov	bl,ah
	shr	ebx,4
	and	bl,00000011b
	add	dl,[_2bitdecode+ebx]
	pushf
	cmp	[_2bitdecode+ebx],0
	jl	short ??neg5

	popf
	jnc	short ??ok5

	mov	dl,0FFh
	jmp	short ??ok5

??neg5:
	popf
	jc	short ??ok5

	xor	dl,dl

??ok5:
	mov	dh,dl
	ror	edx,8
	mov	bl,ah
	shr	ebx,6
	and	bl,00000011b
	add	dl,[_2bitdecode+ebx]
	pushf
	cmp	[_2bitdecode+ebx],0
	jl	short ??neg6

	popf
	jnc	short ??ok6

	mov	dl,0FFh
	jmp	short ??ok6

??neg6:
	popf
	jc	short ??ok6

	xor	dl,dl

??ok6:
	ror	edx,8
	mov	[edi],edx	;Output two sample bytes
	sub	ecx,4
	add	edi,4

;	Put the correct 'previous' sample in DL where it belongs.

	rol	edx,8

;	If there are more deltas to process then loop back.

	dec	al
	jnz	??bit2loop
	jmp	??mainloop

;	There is a run of zero deltas.  Zero deltas merely duplicate
;	the 'previous' sample the requested number of times.

??zerodelta:
	xor	ebx,ebx
	mov	bl,al
	mov	al,dl
	sub	ecx,ebx
	xchg	ecx,ebx
	rep	stosb
	mov	ecx,ebx
	jmp	??mainloop

??fini:
	popf
	mov	eax,[incount]
	ret

	ENDP	Decompress_Frame

LABEL 	LockedCodeEnd	BYTE


;***************************************************************************
;* DECOMPRESS_FRAME_LOCK -- locks the JLB audio decompression code         *
;*                                                                         *
;* INPUT:	none                                                       *
;*                                                                         *
;* OUTPUT:      BOOL true is lock sucessful, false otherwise		   *
;*                                                                         *
;* PROTO:       BOOL Decompress_Frame_Lock(void);                          *
;*                                                                         *
;* HISTORY:								   *
;*   06/26/1995 PWG : Created.                                             *
;*=========================================================================*
	GLOBAL	Decompress_Frame_Lock:NEAR
	PROC	Decompress_Frame_Lock C NEAR USES ebx ecx edx esi edi

	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
	mov	eax,1
	jmp	??exit
??error:
	xor	eax,eax
??exit:
	ret

	ENDP	Decompress_Frame_Lock

;***************************************************************************
;* DECOMPRESS_FRAME_UNLOCK -- Unlocks the JLB audio compression code       *
;*                                                                         *
;* INPUT:	none                                                       *
;*                                                                         *
;* OUTPUT:      BOOL true is unlock sucessful, false otherwise		   *
;*                                                                         *
;* PROTO:	BOOL Decompress_Frame_Unlock(void);                        *
;*                                                                         *
;* HISTORY:								   *
;*   06/26/1995 PWG : Created.                                             *
;*=========================================================================*
	GLOBAL	Decompress_Frame_Unlock:NEAR
	PROC	Decompress_Frame_Unlock C NEAR USES ebx ecx edx esi edi

	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
	mov	eax,1
	jmp	??exit
??error:
	xor	eax,eax
??exit:
	ret

	ENDP	Decompress_Frame_Unlock



	END
