all repos — mgba @ 341ebd04356360cfff3e217bf7a419e43b534ef1

mGBA Game Boy Advance Emulator

src/third-party/lzma/Lzma2Dec.c (view raw)

  1/* Lzma2Dec.c -- LZMA2 Decoder
  22010-12-15 : Igor Pavlov : Public domain */
  3
  4/* #define SHOW_DEBUG_INFO */
  5
  6#include "Precomp.h"
  7
  8#ifdef SHOW_DEBUG_INFO
  9#include <stdio.h>
 10#endif
 11
 12#include <string.h>
 13
 14#include "Lzma2Dec.h"
 15
 16/*
 1700000000  -  EOS
 1800000001 U U  -  Uncompressed Reset Dic
 1900000010 U U  -  Uncompressed No Reset
 20100uuuuu U U P P  -  LZMA no reset
 21101uuuuu U U P P  -  LZMA reset state
 22110uuuuu U U P P S  -  LZMA reset state + new prop
 23111uuuuu U U P P S  -  LZMA reset state + new prop + reset dic
 24
 25  u, U - Unpack Size
 26  P - Pack Size
 27  S - Props
 28*/
 29
 30#define LZMA2_CONTROL_LZMA (1 << 7)
 31#define LZMA2_CONTROL_COPY_NO_RESET 2
 32#define LZMA2_CONTROL_COPY_RESET_DIC 1
 33#define LZMA2_CONTROL_EOF 0
 34
 35#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0)
 36
 37#define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3)
 38#define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2)
 39
 40#define LZMA2_LCLP_MAX 4
 41#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
 42
 43#ifdef SHOW_DEBUG_INFO
 44#define PRF(x) x
 45#else
 46#define PRF(x)
 47#endif
 48
 49typedef enum
 50{
 51  LZMA2_STATE_CONTROL,
 52  LZMA2_STATE_UNPACK0,
 53  LZMA2_STATE_UNPACK1,
 54  LZMA2_STATE_PACK0,
 55  LZMA2_STATE_PACK1,
 56  LZMA2_STATE_PROP,
 57  LZMA2_STATE_DATA,
 58  LZMA2_STATE_DATA_CONT,
 59  LZMA2_STATE_FINISHED,
 60  LZMA2_STATE_ERROR
 61} ELzma2State;
 62
 63static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
 64{
 65  UInt32 dicSize;
 66  if (prop > 40)
 67    return SZ_ERROR_UNSUPPORTED;
 68  dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
 69  props[0] = (Byte)LZMA2_LCLP_MAX;
 70  props[1] = (Byte)(dicSize);
 71  props[2] = (Byte)(dicSize >> 8);
 72  props[3] = (Byte)(dicSize >> 16);
 73  props[4] = (Byte)(dicSize >> 24);
 74  return SZ_OK;
 75}
 76
 77SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
 78{
 79  Byte props[LZMA_PROPS_SIZE];
 80  RINOK(Lzma2Dec_GetOldProps(prop, props));
 81  return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
 82}
 83
 84SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
 85{
 86  Byte props[LZMA_PROPS_SIZE];
 87  RINOK(Lzma2Dec_GetOldProps(prop, props));
 88  return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
 89}
 90
 91void Lzma2Dec_Init(CLzma2Dec *p)
 92{
 93  p->state = LZMA2_STATE_CONTROL;
 94  p->needInitDic = True;
 95  p->needInitState = True;
 96  p->needInitProp = True;
 97  LzmaDec_Init(&p->decoder);
 98}
 99
100static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
101{
102  switch(p->state)
103  {
104    case LZMA2_STATE_CONTROL:
105      p->control = b;
106      PRF(printf("\n %4X ", p->decoder.dicPos));
107      PRF(printf(" %2X", b));
108      if (p->control == 0)
109        return LZMA2_STATE_FINISHED;
110      if (LZMA2_IS_UNCOMPRESSED_STATE(p))
111      {
112        if ((p->control & 0x7F) > 2)
113          return LZMA2_STATE_ERROR;
114        p->unpackSize = 0;
115      }
116      else
117        p->unpackSize = (UInt32)(p->control & 0x1F) << 16;
118      return LZMA2_STATE_UNPACK0;
119    
120    case LZMA2_STATE_UNPACK0:
121      p->unpackSize |= (UInt32)b << 8;
122      return LZMA2_STATE_UNPACK1;
123    
124    case LZMA2_STATE_UNPACK1:
125      p->unpackSize |= (UInt32)b;
126      p->unpackSize++;
127      PRF(printf(" %8d", p->unpackSize));
128      return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
129    
130    case LZMA2_STATE_PACK0:
131      p->packSize = (UInt32)b << 8;
132      return LZMA2_STATE_PACK1;
133
134    case LZMA2_STATE_PACK1:
135      p->packSize |= (UInt32)b;
136      p->packSize++;
137      PRF(printf(" %8d", p->packSize));
138      return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:
139        (p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);
140
141    case LZMA2_STATE_PROP:
142    {
143      int lc, lp;
144      if (b >= (9 * 5 * 5))
145        return LZMA2_STATE_ERROR;
146      lc = b % 9;
147      b /= 9;
148      p->decoder.prop.pb = b / 5;
149      lp = b % 5;
150      if (lc + lp > LZMA2_LCLP_MAX)
151        return LZMA2_STATE_ERROR;
152      p->decoder.prop.lc = lc;
153      p->decoder.prop.lp = lp;
154      p->needInitProp = False;
155      return LZMA2_STATE_DATA;
156    }
157  }
158  return LZMA2_STATE_ERROR;
159}
160
161static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
162{
163  memcpy(p->dic + p->dicPos, src, size);
164  p->dicPos += size;
165  if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
166    p->checkDicSize = p->prop.dicSize;
167  p->processedPos += (UInt32)size;
168}
169
170void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState);
171
172SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
173    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
174{
175  SizeT inSize = *srcLen;
176  *srcLen = 0;
177  *status = LZMA_STATUS_NOT_SPECIFIED;
178
179  while (p->state != LZMA2_STATE_FINISHED)
180  {
181    SizeT dicPos = p->decoder.dicPos;
182    if (p->state == LZMA2_STATE_ERROR)
183      return SZ_ERROR_DATA;
184    if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
185    {
186      *status = LZMA_STATUS_NOT_FINISHED;
187      return SZ_OK;
188    }
189    if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
190    {
191      if (*srcLen == inSize)
192      {
193        *status = LZMA_STATUS_NEEDS_MORE_INPUT;
194        return SZ_OK;
195      }
196      (*srcLen)++;
197      p->state = Lzma2Dec_UpdateState(p, *src++);
198      continue;
199    }
200    {
201      SizeT destSizeCur = dicLimit - dicPos;
202      SizeT srcSizeCur = inSize - *srcLen;
203      ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
204      
205      if (p->unpackSize <= destSizeCur)
206      {
207        destSizeCur = (SizeT)p->unpackSize;
208        curFinishMode = LZMA_FINISH_END;
209      }
210
211      if (LZMA2_IS_UNCOMPRESSED_STATE(p))
212      {
213        if (*srcLen == inSize)
214        {
215          *status = LZMA_STATUS_NEEDS_MORE_INPUT;
216          return SZ_OK;
217        }
218
219        if (p->state == LZMA2_STATE_DATA)
220        {
221          Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
222          if (initDic)
223            p->needInitProp = p->needInitState = True;
224          else if (p->needInitDic)
225            return SZ_ERROR_DATA;
226          p->needInitDic = False;
227          LzmaDec_InitDicAndState(&p->decoder, initDic, False);
228        }
229
230        if (srcSizeCur > destSizeCur)
231          srcSizeCur = destSizeCur;
232
233        if (srcSizeCur == 0)
234          return SZ_ERROR_DATA;
235
236        LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);
237
238        src += srcSizeCur;
239        *srcLen += srcSizeCur;
240        p->unpackSize -= (UInt32)srcSizeCur;
241        p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
242      }
243      else
244      {
245        SizeT outSizeProcessed;
246        SRes res;
247
248        if (p->state == LZMA2_STATE_DATA)
249        {
250          int mode = LZMA2_GET_LZMA_MODE(p);
251          Bool initDic = (mode == 3);
252          Bool initState = (mode > 0);
253          if ((!initDic && p->needInitDic) || (!initState && p->needInitState))
254            return SZ_ERROR_DATA;
255          
256          LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
257          p->needInitDic = False;
258          p->needInitState = False;
259          p->state = LZMA2_STATE_DATA_CONT;
260        }
261        if (srcSizeCur > p->packSize)
262          srcSizeCur = (SizeT)p->packSize;
263          
264        res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status);
265        
266        src += srcSizeCur;
267        *srcLen += srcSizeCur;
268        p->packSize -= (UInt32)srcSizeCur;
269
270        outSizeProcessed = p->decoder.dicPos - dicPos;
271        p->unpackSize -= (UInt32)outSizeProcessed;
272
273        RINOK(res);
274        if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
275          return res;
276
277        if (srcSizeCur == 0 && outSizeProcessed == 0)
278        {
279          if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ||
280              p->unpackSize != 0 || p->packSize != 0)
281            return SZ_ERROR_DATA;
282          p->state = LZMA2_STATE_CONTROL;
283        }
284        if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
285          *status = LZMA_STATUS_NOT_FINISHED;
286      }
287    }
288  }
289  *status = LZMA_STATUS_FINISHED_WITH_MARK;
290  return SZ_OK;
291}
292
293SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
294{
295  SizeT outSize = *destLen, inSize = *srcLen;
296  *srcLen = *destLen = 0;
297  for (;;)
298  {
299    SizeT srcSizeCur = inSize, outSizeCur, dicPos;
300    ELzmaFinishMode curFinishMode;
301    SRes res;
302    if (p->decoder.dicPos == p->decoder.dicBufSize)
303      p->decoder.dicPos = 0;
304    dicPos = p->decoder.dicPos;
305    if (outSize > p->decoder.dicBufSize - dicPos)
306    {
307      outSizeCur = p->decoder.dicBufSize;
308      curFinishMode = LZMA_FINISH_ANY;
309    }
310    else
311    {
312      outSizeCur = dicPos + outSize;
313      curFinishMode = finishMode;
314    }
315
316    res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status);
317    src += srcSizeCur;
318    inSize -= srcSizeCur;
319    *srcLen += srcSizeCur;
320    outSizeCur = p->decoder.dicPos - dicPos;
321    memcpy(dest, p->decoder.dic + dicPos, outSizeCur);
322    dest += outSizeCur;
323    outSize -= outSizeCur;
324    *destLen += outSizeCur;
325    if (res != 0)
326      return res;
327    if (outSizeCur == 0 || outSize == 0)
328      return SZ_OK;
329  }
330}
331
332SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
333    Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc)
334{
335  CLzma2Dec p;
336  SRes res;
337  SizeT outSize = *destLen, inSize = *srcLen;
338  *destLen = *srcLen = 0;
339  *status = LZMA_STATUS_NOT_SPECIFIED;
340  Lzma2Dec_Construct(&p);
341  RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc));
342  p.decoder.dic = dest;
343  p.decoder.dicBufSize = outSize;
344  Lzma2Dec_Init(&p);
345  *srcLen = inSize;
346  res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
347  *destLen = p.decoder.dicPos;
348  if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
349    res = SZ_ERROR_INPUT_EOF;
350  Lzma2Dec_FreeProbs(&p, alloc);
351  return res;
352}