438 lines
10 KiB
NASM
438 lines
10 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/>.
|
|
;
|
|
|
|
;***************************************************************************
|
|
;** 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
|