| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- ;
- ; 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
- ;*
- ;*---------------------------------------------------------------------------
- ;*
- ;* FILE
- ;* lcwuncmp.asm
- ;*
- ;* DESCRIPTION
- ;* LCW uncompress routine. (32-Bit protected mode)
- ;*
- ;* PROGRAMMER
- ;* Chris Yates
- ;* Denzil E. Long, Jr.
- ;*
- ;* DATE
- ;* January 26, 1995
- ;*
- ;*---------------------------------------------------------------------------
- ;*
- ;* PUBLIC
- ;* LCW_Uncompress - Uncompress LCW encoded data.
- ;*
- ;****************************************************************************
- IDEAL
- P386
- MODEL USE32 FLAT
- LOCALS ??
- CODESEG
- ;****************************************************************************
- ;*
- ;* NAME
- ;* LCW_Uncompress - Uncompress LCW encoded data.
- ;*
- ;* SYNOPSIS
- ;* Size = LCW_Uncompress(Source, Dest, Length)
- ;*
- ;* LONG LCW_Uncompress(void *, void *, long);
- ;*
- ;* FUNCTION
- ;* Uncompress data to the following codes in the format b = byte,
- ;* w = word, n = byte code pulled from compressed data.
- ;*
- ;* Bit field of n Command Description
- ;* ------------------------------------------------------------------
- ;* n=0xxxyyyy,yyyyyyyy short run back y bytes and run x+3
- ;* n=10xxxxxx,n1,n2,..,nx+1 med length copy the next x+1 bytes
- ;* n=11xxxxxx,w1 med run run x+3 bytes from offset w1
- ;* n=11111111,w1,w2 long copy copy w1 bytes from offset w2
- ;* n=11111110,w1,b1 long run run byte b1 for w1 bytes
- ;* n=10000000 end end of data reached
- ;*
- ;* INPUTS
- ;* Source - Pointer to LCW encoded data.
- ;* Dest - Pointer to buffer to uncompress into.
- ;* Length -
- ;*
- ;* RESULT
- ;* Size - Size of uncompressed data in bytes.
- ;*
- ;****************************************************************************
- GLOBAL C LCW_Uncompress:NEAR
- PROC LCW_Uncompress C NEAR USES ebx ecx edx esi edi
- ARG source:DWORD
- ARG dest:DWORD
- ARG length:DWORD
- LOCAL a1stdest:DWORD
- LOCAL maxlen:DWORD
- LOCAL lastbyte:DWORD
- LOCAL lastcom:DWORD
- LOCAL lastcom1:DWORD
- mov esi,[source] ;ESI - Source address
- mov edi,[dest] ;EDI - Destination address
- mov edx,[length] ;EDX - Maximum length
- mov [a1stdest],edi ;Save dest address
- add edx,edi ;Last address (Dest + length)
- mov [lastbyte],edx
- cld ;Forward direction
- mov ebx,esi ;Save source address
- ??loop:
- ; Exit if no bytes are remaining.
- mov eax,[lastbyte]
- sub eax,edi
- jz short ??out
- mov [maxlen],eax ;Save for string commands
- mov esi,ebx ;Restore source address
- lodsb
- or al,al ;See if its a short run
- js short ??notshort
- mov ah,al ;Put rel offset high nibble in ah
- and ah,0Fh ; Only 4 bits count
- sub ecx,ecx
- mov ch,al ;Put count nibble in ch
- shr ch,4
- mov cl,ch
- xor ch,ch
- add ecx,3 ;Get actual run length
- cmp ecx,[maxlen] ;Is it too big to fit?
- jbe short ??rsok ;If not, its ok
- mov ecx,[maxlen] ;If so, max it out so it dosen't overrun
- ??rsok:
- lodsb ;Get rel offset low byte
- mov ebx,esi ;Save the source address
- mov esi,edi ;Get the current dest
- sub esi,eax ;Get relative offset
- rep movsb
- jmp ??loop
- ??notshort:
- test al,40h ;Is it a length?
- jne short ??notlength ;If not it could be med or long run
- ; If end code then exit.
- cmp al,80h
- je short ??out
- mov cl,al ;Put the byte in count register
- and ecx,3Fh ;Mask off the extra bits
- cmp ecx,[maxlen] ;Is it too big to fit?
- jbe short ??lenok ;If not, its ok
- mov ecx,[maxlen] ;If so, max it out so it dosen't overrun
- ??lenok:
- rep movsb
- mov ebx,esi ;Save the source offset
- jmp ??loop
- ??out:
- mov eax,edi
- sub eax,[a1stdest]
- jmp short ??exit
- ??notlength:
- mov cl,al ;Get the entire code
- and ecx,3Fh ;Mask off all but the size -3
- add ecx,3 ;Add 3 for byte count
- cmp al,0FEh
- jne short ??notrunlength
- sub eax,eax
- lodsw
- mov ecx,eax
- sub eax,eax
- lodsb
- mov ebx,esi ;Save the source offset
- cmp ecx,[maxlen] ;Is it too big to fit?
- jbe short ??runlenok ;If not, its ok
- mov ecx,[maxlen] ;If so, max it out so it dosen't overrun
- ??runlenok:
- rep stosb
- jmp ??loop
- ??notrunlength:
- cmp al,0FFh ;Is it a long run?
- jne short ??notlong ;If not use the code as the size
- sub eax,eax
- lodsw ;If so, get the size
- mov ecx,eax ;Put int the count byte
- ??notlong:
- lodsw ;Get the rel index
- mov ebx,esi ;Save the source offset
- add eax,[a1stdest] ;Add in the first index
- mov esi,eax ;Use this as a source
- cmp ecx,[maxlen] ;Is it too big to fit?
- jbe short ??runok ;If not, its ok
- mov ecx,[maxlen] ;If so, max it out so it dosen't overrun
- ??runok:
- rep movsb
- jmp ??loop
- ??exit:
- mov eax,edi
- mov ebx,[dest]
- sub eax,ebx ;Calculate bytes uncompressed.
- ret
- ENDP LCW_Uncompress
- END
-
|