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