LZO1X_D.CPP (4827B)
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 /* lzo1x_d.c -- standalone LZO1X decompressor 17 18 This file is part of the LZO real-time data compression library. 19 20 Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer 21 22 The LZO library is free software; you can redistribute it and/or 23 modify it under the terms of the GNU Library General Public 24 License as published by the Free Software Foundation; either 25 version 2 of the License, or (at your option) any later version. 26 27 The LZO library is distributed in the hope that it will be useful, 28 but WITHOUT ANY WARRANTY; without even the implied warranty of 29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 30 Library General Public License for more details. 31 32 You should have received a copy of the GNU Library General Public 33 License along with the LZO library; see the file COPYING.LIB. 34 If not, write to the Free Software Foundation, Inc., 35 675 Mass Ave, Cambridge, MA 02139, USA. 36 37 Markus F.X.J. Oberhumer 38 markus.oberhumer@jk.uni-linz.ac.at 39 */ 40 41 42 #include "lzo1x.h" 43 #ifndef NDEBUG 44 #define NDEBUG 45 #endif 46 #include <assert.h> 47 48 #if !defined(LZO1X) && !defined(LZO1Y) 49 # define LZO1X 50 #endif 51 52 #if 1 53 # define TEST_IP 1 54 #else 55 # define TEST_IP (ip < ip_end) 56 #endif 57 58 59 /*********************************************************************** 60 // decompress a block of data. 61 ************************************************************************/ 62 63 int lzo1x_decompress ( const lzo_byte *in , lzo_uint in_len, 64 lzo_byte *out, lzo_uint *out_len, 65 lzo_voidp ) 66 { 67 register lzo_byte *op; 68 register const lzo_byte *ip; 69 register lzo_uint t; 70 register const lzo_byte *m_pos; 71 const lzo_byte * const ip_end = in + in_len; 72 73 *out_len = 0; 74 75 op = out; 76 ip = in; 77 78 if (*ip > 17) 79 { 80 t = *ip++ - 17; 81 goto first_literal_run; 82 } 83 84 while (TEST_IP) 85 { 86 t = *ip++; 87 if (t >= 16) 88 goto match; 89 /* a literal run */ 90 if (t == 0) 91 { 92 t = 15; 93 while (*ip == 0) 94 t += 255, ip++; 95 t += *ip++; 96 } 97 /* copy literals */ 98 *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; 99 first_literal_run: 100 do *op++ = *ip++; while (--t > 0); 101 102 103 t = *ip++; 104 105 if (t >= 16) 106 goto match; 107 #if defined(LZO1X) 108 m_pos = op - 1 - 0x800; 109 #elif defined(LZO1Y) 110 m_pos = op - 1 - 0x400; 111 #endif 112 m_pos -= t >> 2; 113 m_pos -= *ip++ << 2; 114 *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos++; 115 goto match_done; 116 117 118 /* handle matches */ 119 while (TEST_IP) 120 { 121 if (t < 16) /* a M1 match */ 122 { 123 m_pos = op - 1; 124 m_pos -= t >> 2; 125 m_pos -= *ip++ << 2; 126 *op++ = *m_pos++; *op++ = *m_pos++; 127 } 128 else 129 { 130 match: 131 if (t >= 64) /* a M2 match */ 132 { 133 m_pos = op - 1; 134 #if defined(LZO1X) 135 m_pos -= (t >> 2) & 7; 136 m_pos -= *ip++ << 3; 137 t = (t >> 5) - 1; 138 #elif defined(LZO1Y) 139 m_pos -= (t >> 2) & 3; 140 m_pos -= *ip++ << 2; 141 t = (t >> 4) - 3; 142 #endif 143 } 144 else if (t >= 32) /* a M3 match */ 145 { 146 t &= 31; 147 if (t == 0) 148 { 149 t = 31; 150 while (*ip == 0) 151 t += 255, ip++; 152 t += *ip++; 153 } 154 m_pos = op - 1; 155 m_pos -= *ip++ >> 2; 156 m_pos -= *ip++ << 6; 157 } 158 else /* a M4 match */ 159 { 160 m_pos = op; 161 m_pos -= (t & 8) << 11; 162 t &= 7; 163 if (t == 0) 164 { 165 t = 7; 166 while (*ip == 0) 167 t += 255, ip++; 168 t += *ip++; 169 } 170 m_pos -= *ip++ >> 2; 171 m_pos -= *ip++ << 6; 172 if (m_pos == op) 173 goto eof_found; 174 m_pos -= 0x4000; 175 } 176 *op++ = *m_pos++; *op++ = *m_pos++; 177 do *op++ = *m_pos++; while (--t > 0); 178 } 179 180 match_done: 181 t = ip[-2] & 3; 182 if (t == 0) 183 break; 184 /* copy literals */ 185 do *op++ = *ip++; while (--t > 0); 186 t = *ip++; 187 } 188 } 189 190 /* ip == ip_end and no EOF code was found */ 191 192 //Unreachable - ST 9/5/96 5:07PM 193 //*out_len = op - out; 194 //return (ip == ip_end ? LZO_E_EOF_NOT_FOUND : LZO_E_ERROR); 195 196 eof_found: 197 assert(t == 1); 198 *out_len = op - out; 199 return (ip == ip_end ? LZO_E_OK : LZO_E_ERROR); 200 } 201 202 203 /* 204 vi:ts=4 205 */