FIFE 2008.0
lzssdecoder.cpp
00001 /***************************************************************************
00002  *   Copyright (C) 2005-2008 by the FIFE team                              *
00003  *   http://www.fifengine.de                                               *
00004  *   This file is part of FIFE.                                            *
00005  *                                                                         *
00006  *   FIFE is free software; you can redistribute it and/or                 *
00007  *   modify it under the terms of the GNU Lesser General Public            *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2.1 of the License, or (at your option) any later version.    *
00010  *                                                                         *
00011  *   This library is distributed in the hope that it will be useful,       *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00014  *   Lesser General Public License for more details.                       *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Lesser General Public      *
00017  *   License along with this library; if not, write to the                 *
00018  *   Free Software Foundation, Inc.,                                       *
00019  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
00020  ***************************************************************************/
00021 
00022 // Standard C++ library includes
00023 #include <algorithm>
00024 
00025 // 3rd party library includes
00026 
00027 // FIFE includes
00028 #include "vfs/raw/rawdata.h"
00029 #include "util/base/exception.h"
00030 
00031 #include "lzssdecoder.h"
00032 
00033 // just a quick&dirty wrapper around anchorites implementation - needs to be replaced with our own LZSS implementation
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) { // uncompressed
00050                 input->readInto(output + m_outindex, bytesToRead);
00051                 m_outindex += bytesToRead;
00052             } else {
00053                 // Allocate +2 bytes so that on corrupt data the LZSS
00054                 // decoder won't crash the input buffer.
00055                 std::vector<uint8_t> indata(bytesToRead + 2);
00056                 input->readInto(&indata[0], bytesToRead);
00057                 LZSSDecode(&indata[0], bytesToRead, output);
00058                 // Note outindex is advanced inside LZSSDecode.
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;/* uses higher byte cleverly to count eight */
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 }
 All Classes Namespaces Functions Variables Enumerations Enumerator