CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

LCWUNCMP.ASM (6887B)


      1 ;
      2 ; Copyright 2020 Electronic Arts Inc.
      3 ;
      4 ; TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 ; software: you can redistribute it and/or modify it under the terms of 
      6 ; the GNU General Public License as published by the Free Software Foundation, 
      7 ; either version 3 of the License, or (at your option) any later version.
      8 
      9 ; TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 ; in the hope that it will be useful, but with permitted additional restrictions 
     11 ; under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 ; distributed with this program. You should have received a copy of the 
     13 ; GNU General Public License along with permitted additional restrictions 
     14 ; with this program. If not, see [https://github.com/electronicarts/CnC_Remastered_Collection]>.
     15 
     16 ; $Header: g:/library/wwlib32/misc/rcs/lcwuncmp.asm 1.1 1994/04/11 15:31:21 jeff_wilson Exp $
     17 ;***************************************************************************
     18 ;**   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   **
     19 ;***************************************************************************
     20 ;*                                                                         *
     21 ;*                 Project Name : Library routine                          *
     22 ;*                                                                         *
     23 ;*                    File Name : UNCOMP.ASM                               *
     24 ;*                                                                         *
     25 ;*                   Programmer : Christopher Yates                        *
     26 ;*                                                                         *
     27 ;*                  Last Update : 20 August, 1990   [CY]                   *
     28 ;*                                                                         *
     29 ;*-------------------------------------------------------------------------*
     30 ;* Functions:                                                              *
     31 ;*                                                                         *
     32 ; ULONG LCW_Uncompress(BYTE *source, BYTE *dest, ULONG length);		   *
     33 ;*                                                                         *
     34 ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
     35 
     36 ;IDEAL
     37 ;P386
     38 ;MODEL USE32 FLAT
     39 .MODEL FLAT
     40 
     41 ;GLOBAL            C LCW_Uncompress          :NEAR
     42 externdef C LCW_Uncompress:NEAR
     43 
     44 ;CODESEG
     45 .code
     46 
     47 ; ----------------------------------------------------------------
     48 ;
     49 ; Here are prototypes for the routines defined within this module:
     50 ;
     51 ; ULONG LCW_Uncompress(BYTE *source, BYTE *dest, ULONG length);
     52 ;
     53 ; ----------------------------------------------------------------
     54 
     55 
     56 
     57 LCW_Uncompress proc C source:DWORD, dest:DWORD, _length:DWORD
     58 
     59 	;USES ebx,ecx,edx,edi,esi
     60 
     61 	;ARG	source:DWORD
     62 	;ARG	dest:DWORD
     63 	;ARG	length:DWORD
     64 ;LOCALS
     65 	LOCAL a1stdest:DWORD
     66 	LOCAL maxlen:DWORD
     67 	LOCAL lastbyte:DWORD
     68 	;LOCAL lastcom:DWORD
     69 	;LOCAL lastcom1:DWORD
     70 
     71 
     72 	pushad
     73 
     74 	mov	edi,[dest]
     75 	mov	esi,[source]
     76 	mov	edx,[_length]
     77 
     78 ;
     79 ;
     80 ; uncompress data to the following codes in the format b = byte, w = word
     81 ; n = byte code pulled from compressed data
     82 ;   Bit field of n		command		description
     83 ; n=0xxxyyyy,yyyyyyyy		short run	back y bytes and run x+3
     84 ; n=10xxxxxx,n1,n2,...,nx+1	med length	copy the next x+1 bytes
     85 ; n=11xxxxxx,w1			med run		run x+3 bytes from offset w1
     86 ; n=11111111,w1,w2		long copy	copy w1 bytes from offset w2
     87 ; n=11111110,w1,b1		long run	run byte b1 for w1 bytes
     88 ; n=10000000			end		end of data reached
     89 ;
     90 
     91 	mov	[a1stdest],edi
     92 	add	edx,edi
     93 	mov	[lastbyte],edx
     94 	cld			; make sure all lod and sto are forward
     95 	mov	ebx,esi		; save the source offset
     96 
     97 ??loop:
     98 	mov	eax,[lastbyte]
     99 	sub	eax,edi		; get the remaining byte to uncomp
    100 	jz	short ??out		; were done
    101 
    102 	mov	[maxlen],eax	; save for string commands
    103 	mov	esi,ebx		; mov in the source index
    104 
    105 	xor	eax,eax
    106 	mov	al,[esi]
    107 	inc	esi
    108 	test	al,al		; see if its a short run
    109 	js	short ??notshort
    110 
    111 	mov	ecx,eax		;put count nibble in cl
    112 
    113 	mov	ah,al		; put rel offset high nibble in ah
    114 	and	ah,0Fh		; only 4 bits count
    115 
    116 	shr	cl,4		; get run -3
    117 	add	ecx,3		; get actual run length
    118 
    119 	cmp	ecx,[maxlen]	; is it too big to fit?
    120 	jbe	short ??rsok		; if not, its ok
    121 
    122 	mov	ecx,[maxlen]	; if so, max it out so it dosen't overrun
    123 
    124 ??rsok:
    125 	mov	al,[esi]	; get rel offset low byte
    126 	lea	ebx,[esi+1]	; save the source offset
    127 	mov	esi,edi		; get the current dest
    128 	sub	esi,eax		; get relative offset
    129 
    130 	rep	movsb
    131 
    132 	jmp	??loop
    133 
    134 ??notshort:
    135 	test	al,40h		; is it a length?
    136 	jne	short ??notlength	; if not it could be med or long run
    137 
    138 	cmp	al,80h		; is it the end?
    139 	je	short ??out		; if so its over
    140 
    141 	mov	cl,al		; put the byte in count register
    142 	and	ecx,3Fh		; and off the extra bits
    143 
    144 	cmp	ecx,[maxlen]	; is it too big to fit?
    145 	jbe	short ??lenok		; if not, its ok
    146 
    147 	mov	ecx,[maxlen]	; if so, max it out so it dosen't overrun
    148 
    149 ??lenok:
    150 	rep movsb
    151 
    152 	mov	ebx,esi		; save the source offset
    153 	jmp	??loop
    154 
    155 ??out:
    156       	mov	eax,edi
    157 	sub	eax,[a1stdest]
    158 	jmp	??exit
    159 
    160 ??notlength:
    161 	mov	cl,al		; get the entire code
    162 	and	ecx,3Fh		; and off all but the size -3
    163 	add	ecx,3		; add 3 for byte count
    164 
    165 	cmp	al,0FEh
    166 	jne	short ??notrunlength
    167 
    168 	xor	ecx,ecx
    169 	mov	cx,[esi]
    170 
    171 	xor	eax,eax
    172 	mov	al,[esi+2]
    173 	lea	ebx,[esi+3]	;save the source offset
    174 
    175 	cmp	ecx,[maxlen]	; is it too big to fit?
    176 	jbe	short ??runlenok		; if not, its ok
    177 
    178 	mov	ecx,[maxlen]	; if so, max it out so it dosen't overrun
    179 
    180 ??runlenok:
    181 	test	ecx,0ffe0h
    182 	jnz	??dont_use_stosb
    183 	rep	stosb
    184 	jmp	??loop
    185 
    186 
    187 ??dont_use_stosb:
    188 	mov	ah,al
    189 	mov	edx,eax
    190 	shl	eax,16
    191 	or	eax,edx
    192 
    193 	test	edi,3
    194 	jz	??aligned
    195 
    196 	mov	[edi],eax
    197 	mov	edx,edi
    198 	and	edi,0fffffffch
    199 	lea	edi,[edi+4]
    200 	and	edx,3
    201 	dec	dl
    202 	xor	dl,3
    203 	sub	ecx,edx
    204 
    205 ??aligned:
    206 	mov	edx,ecx
    207 	shr	ecx,2
    208 	rep	stosd
    209 
    210 	and	edx,3
    211 	jz	??loop
    212 	mov	ecx,edx
    213 	rep	stosb
    214 	jmp	??loop
    215 
    216 
    217 
    218 
    219 
    220 
    221 ??notrunlength:
    222 	cmp	al,0FFh		; is it a long run?
    223 	jne	short ??notlong	; if not use the code as the size
    224 
    225 	xor     ecx,ecx
    226 	xor	eax,eax
    227 	mov	cx,[esi]	; if so, get the size
    228 	lea	esi,[esi+2]
    229 
    230 ??notlong:
    231 	mov	ax,[esi]	;get the real index
    232 	add	eax,[a1stdest]	;add in the 1st index
    233 	lea	ebx,[esi+2]	;save the source offset
    234 	cmp	ecx,[maxlen]	;compare for overrun
    235 	mov	esi,eax		;use eax as new source
    236 	jbe	short ??runok	; if not, its ok
    237 
    238 	mov	ecx,[maxlen]	; if so, max it out so it dosen't overrun
    239 
    240 ??runok:
    241 	test	ecx,0ffe0h
    242 	jnz	??dont_use_movsb
    243 	rep	movsb
    244 	jmp	??loop
    245 
    246 
    247 
    248 
    249 ??dont_use_movsb:
    250 	lea	edx,[edi+0fffffffch]
    251 	cmp	esi,edx
    252 	ja	??use_movsb
    253 
    254 	test	edi,3
    255 	jz	??aligned2
    256 
    257 	mov	eax,[esi]
    258 	mov	[edi],eax
    259 	mov	edx,edi
    260 	and	edi,0fffffffch
    261 	lea	edi,[edi+4]
    262 	and	edx,3
    263 	dec	dl
    264 	xor	dl,3
    265 	sub	ecx,edx
    266 	add	esi,edx
    267 
    268 ??aligned2:
    269 	mov	edx,ecx
    270 	shr	ecx,2
    271 	and	edx,3
    272 	rep	movsd
    273 	mov	ecx,edx
    274 ??use_movsb:
    275 	rep	movsb
    276 	jmp	??loop
    277 
    278 
    279 
    280 
    281 ??exit:
    282 	mov	eax,edi
    283 	mov	ebx,[dest]
    284 	sub	eax,ebx
    285 
    286 	popad
    287 	ret
    288 
    289 LCW_Uncompress endp
    290 
    291 ;***********************************************************
    292 
    293 
    294 	END