| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- ;
- ; 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/>.
- ;
- ; $Header: g:/library/wwlib32/misc/rcs/lcwuncmp.asm 1.1 1994/04/11 15:31:21 jeff_wilson Exp $
- ;***************************************************************************
- ;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
- ;***************************************************************************
- ;* *
- ;* Project Name : Library routine *
- ;* *
- ;* File Name : UNCOMP.ASM *
- ;* *
- ;* Programmer : Christopher Yates *
- ;* *
- ;* Last Update : 20 August, 1990 [CY] *
- ;* *
- ;*-------------------------------------------------------------------------*
- ;* Functions: *
- ;* *
- ; ULONG LCW_Uncompress(BYTE *source, BYTE *dest, ULONG length); *
- ;* *
- ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
- IDEAL
- P386
- MODEL USE32 FLAT
- GLOBAL C LCW_Uncompress :NEAR
- CODESEG
- ; ----------------------------------------------------------------
- ;
- ; Here are prototypes for the routines defined within this module:
- ;
- ; ULONG LCW_Uncompress(BYTE *source, BYTE *dest, ULONG length);
- ;
- ; ----------------------------------------------------------------
- PROC LCW_Uncompress C near
- USES ebx,ecx,edx,edi,esi
- ARG source:DWORD
- ARG dest:DWORD
- ARG length:DWORD
- ;LOCALS
- LOCAL a1stdest:DWORD
- LOCAL maxlen:DWORD
- LOCAL lastbyte:DWORD
- LOCAL lastcom:DWORD
- LOCAL lastcom1:DWORD
- mov edi,[dest]
- mov esi,[source]
- mov edx,[length]
- ;
- ;
- ; 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
- ;
- mov [a1stdest],edi
- add edx,edi
- mov [lastbyte],edx
- cld ; make sure all lod and sto are forward
- mov ebx,esi ; save the source offset
- ??loop:
- mov eax,[lastbyte]
- sub eax,edi ; get the remaining byte to uncomp
- jz short ??out ; were done
- mov [maxlen],eax ; save for string commands
- mov esi,ebx ; mov in the source index
- xor eax,eax
- mov al,[esi]
- inc esi
- test al,al ; see if its a short run
- js short ??notshort
- mov ecx,eax ;put count nibble in cl
- mov ah,al ; put rel offset high nibble in ah
- and ah,0Fh ; only 4 bits count
- shr cl,4 ; get run -3
- 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:
- mov al,[esi] ; get rel offset low byte
- lea ebx,[esi+1] ; save the source offset
- 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
- cmp al,80h ; is it the end?
- je short ??out ; if so its over
- mov cl,al ; put the byte in count register
- and ecx,3Fh ; and 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 ??exit
- ??notlength:
- mov cl,al ; get the entire code
- and ecx,3Fh ; and off all but the size -3
- add ecx,3 ; add 3 for byte count
- cmp al,0FEh
- jne short ??notrunlength
- xor ecx,ecx
- mov cx,[esi]
- xor eax,eax
- mov al,[esi+2]
- lea ebx,[esi+3] ;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:
- test ecx,0ffe0h
- jnz ??dont_use_stosb
- rep stosb
- jmp ??loop
- ??dont_use_stosb:
- mov ah,al
- mov edx,eax
- shl eax,16
- or eax,edx
- test edi,3
- jz ??aligned
- mov [edi],eax
- mov edx,edi
- and edi,0fffffffch
- lea edi,[edi+4]
- and edx,3
- dec dl
- xor dl,3
- sub ecx,edx
- ??aligned:
- mov edx,ecx
- shr ecx,2
- rep stosd
- and edx,3
- jz ??loop
- mov ecx,edx
- rep stosb
- jmp ??loop
- ??notrunlength:
- cmp al,0FFh ; is it a long run?
- jne short ??notlong ; if not use the code as the size
- xor ecx,ecx
- xor eax,eax
- mov cx,[esi] ; if so, get the size
- lea esi,[esi+2]
- ??notlong:
- mov ax,[esi] ;get the real index
- add eax,[a1stdest] ;add in the 1st index
- lea ebx,[esi+2] ;save the source offset
- cmp ecx,[maxlen] ;compare for overrun
- mov esi,eax ;use eax as new source
- jbe short ??runok ; if not, its ok
- mov ecx,[maxlen] ; if so, max it out so it dosen't overrun
- ??runok:
- test ecx,0ffe0h
- jnz ??dont_use_movsb
- rep movsb
- jmp ??loop
- ??dont_use_movsb:
- lea edx,[edi+0fffffffch]
- cmp esi,edx
- ja ??use_movsb
- test edi,3
- jz ??aligned2
- mov eax,[esi]
- mov [edi],eax
- mov edx,edi
- and edi,0fffffffch
- lea edi,[edi+4]
- and edx,3
- dec dl
- xor dl,3
- sub ecx,edx
- add esi,edx
- ??aligned2:
- mov edx,ecx
- shr ecx,2
- and edx,3
- rep movsd
- mov ecx,edx
- ??use_movsb:
- rep movsb
- jmp ??loop
- ??exit:
- mov eax,edi
- mov ebx,[dest]
- sub eax,ebx
- ret
- ENDP LCW_Uncompress
- ;***********************************************************
- END
|