lzssdecoder.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <algorithm>
00024
00025
00026
00027
00028 #include "vfs/raw/rawdata.h"
00029 #include "util/base/exception.h"
00030
00031 #include "lzssdecoder.h"
00032
00033
00034 namespace FIFE {
00035
00036 LZSSDecoder::LZSSDecoder() {}
00037 LZSSDecoder::~LZSSDecoder() {}
00038
00039
00040 void LZSSDecoder::decode(RawData* input, uint8_t* output, const uint32_t outputsize) {
00041
00042 m_outindex = 0;
00043 m_outlen = outputsize;
00044
00045 while (m_outindex < outputsize) {
00046 uint16_t blockdesc = input->read16Big();
00047 uint16_t bytesToRead = blockdesc & 0x7fff;
00048
00049 if (blockdesc & 0x8000) {
00050 input->readInto(output + m_outindex, bytesToRead);
00051 m_outindex += bytesToRead;
00052 } else {
00053
00054
00055 std::vector<uint8_t> indata(bytesToRead + 2);
00056 input->readInto(&indata[0], bytesToRead);
00057 LZSSDecode(&indata[0], bytesToRead, output);
00058
00059 }
00060
00061 }
00062 }
00063
00064 void LZSSDecoder::LZSSDecode(uint8_t* in , long len, uint8_t* out) {
00065 const long c_nRingBufferSize = 4096;
00066 const long c_nMatchLengthUpperLimit = 18;
00067 const long c_nThreshold = 2;
00068
00069 char buffer[c_nRingBufferSize + c_nMatchLengthUpperLimit - 1];
00070 int ibuf = 0;
00071 int c;
00072
00073 int i;
00074 int j;
00075 int k;
00076 int r;
00077
00078 unsigned int flags;
00079
00080 for (i = 0; i < c_nRingBufferSize - c_nMatchLengthUpperLimit; i++) {
00081 buffer[i] = ' ';
00082 }
00083
00084 r = c_nRingBufferSize - c_nMatchLengthUpperLimit;
00085 flags = 0;
00086 while ( ibuf < len ) {
00087 if (((flags >>= 1) & 256) == 0) {
00088 c = in[ibuf++];
00089 flags = c | 0xff00;
00090 }
00091
00092 if (flags & 1) {
00093 c = in[ibuf++];
00094 out[m_outindex++] = c;
00095
00096 buffer[r++] = c;
00097 r &= (c_nRingBufferSize - 1);
00098 } else {
00099 i = in[ibuf++];
00100 j = in[ibuf++];
00101
00102 i |= ((j & 0xf0) << 4);
00103 j = (j & 0x0f) + c_nThreshold;
00104
00105 for (k = 0; k <= j; k++) {
00106 c = buffer[(i + k) & (c_nRingBufferSize - 1)];
00107
00108 out[m_outindex++] = c;
00109
00110 buffer[r++] = c;
00111 r &= (c_nRingBufferSize - 1);
00112 }
00113 }
00114 }
00115 }
00116
00117
00118 }