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