all repos — mgba @ dab12cf5c674542cae0db7708c333035255fbc65

mGBA Game Boy Advance Emulator

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

  1/* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder
  22015-11-08 : Igor Pavlov : Public domain */
  3
  4#include "Precomp.h"
  5
  6#include <string.h>
  7
  8#include "Lzma86.h"
  9
 10#include "Alloc.h"
 11#include "Bra.h"
 12#include "LzmaEnc.h"
 13
 14#define SZE_OUT_OVERFLOW SZE_DATA_ERROR
 15
 16static void *SzAlloc(void *p, size_t size) { UNUSED_VAR(p); return MyAlloc(size); }
 17static void SzFree(void *p, void *address) { UNUSED_VAR(p); MyFree(address); }
 18
 19int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
 20    int level, UInt32 dictSize, int filterMode)
 21{
 22  ISzAlloc g_Alloc = { SzAlloc, SzFree };
 23  size_t outSize2 = *destLen;
 24  Byte *filteredStream;
 25  Bool useFilter;
 26  int mainResult = SZ_ERROR_OUTPUT_EOF;
 27  CLzmaEncProps props;
 28  LzmaEncProps_Init(&props);
 29  props.level = level;
 30  props.dictSize = dictSize;
 31  
 32  *destLen = 0;
 33  if (outSize2 < LZMA86_HEADER_SIZE)
 34    return SZ_ERROR_OUTPUT_EOF;
 35
 36  {
 37    int i;
 38    UInt64 t = srcLen;
 39    for (i = 0; i < 8; i++, t >>= 8)
 40      dest[LZMA86_SIZE_OFFSET + i] = (Byte)t;
 41  }
 42
 43  filteredStream = 0;
 44  useFilter = (filterMode != SZ_FILTER_NO);
 45  if (useFilter)
 46  {
 47    if (srcLen != 0)
 48    {
 49      filteredStream = (Byte *)MyAlloc(srcLen);
 50      if (filteredStream == 0)
 51        return SZ_ERROR_MEM;
 52      memcpy(filteredStream, src, srcLen);
 53    }
 54    {
 55      UInt32 x86State;
 56      x86_Convert_Init(x86State);
 57      x86_Convert(filteredStream, srcLen, 0, &x86State, 1);
 58    }
 59  }
 60
 61  {
 62    size_t minSize = 0;
 63    Bool bestIsFiltered = False;
 64
 65    /* passes for SZ_FILTER_AUTO:
 66        0 - BCJ + LZMA
 67        1 - LZMA
 68        2 - BCJ + LZMA agaian, if pass 0 (BCJ + LZMA) is better.
 69    */
 70    int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1;
 71
 72    int i;
 73    for (i = 0; i < numPasses; i++)
 74    {
 75      size_t outSizeProcessed = outSize2 - LZMA86_HEADER_SIZE;
 76      size_t outPropsSize = 5;
 77      SRes curRes;
 78      Bool curModeIsFiltered = (numPasses > 1 && i == numPasses - 1);
 79      if (curModeIsFiltered && !bestIsFiltered)
 80        break;
 81      if (useFilter && i == 0)
 82        curModeIsFiltered = True;
 83      
 84      curRes = LzmaEncode(dest + LZMA86_HEADER_SIZE, &outSizeProcessed,
 85          curModeIsFiltered ? filteredStream : src, srcLen,
 86          &props, dest + 1, &outPropsSize, 0,
 87          NULL, &g_Alloc, &g_Alloc);
 88      
 89      if (curRes != SZ_ERROR_OUTPUT_EOF)
 90      {
 91        if (curRes != SZ_OK)
 92        {
 93          mainResult = curRes;
 94          break;
 95        }
 96        if (outSizeProcessed <= minSize || mainResult != SZ_OK)
 97        {
 98          minSize = outSizeProcessed;
 99          bestIsFiltered = curModeIsFiltered;
100          mainResult = SZ_OK;
101        }
102      }
103    }
104    dest[0] = (Byte)(bestIsFiltered ? 1 : 0);
105    *destLen = LZMA86_HEADER_SIZE + minSize;
106  }
107  if (useFilter)
108    MyFree(filteredStream);
109  return mainResult;
110}