37 type = data & 0x000000FF;
70 while (outSize < size) {
73 flags = (small.
readByte() << 8) | 0x00FF;
82 const uint8 length = (data1 >> 4) + 3;
83 const uint16 offset = (((data1 & 0x0F) << 8) | data2) + 1;
86 uint32 copyOffset = bufferPos +
sizeof(buffer) - offset;
89 for (
uint8 i = 0; i < length; i++, copyOffset++) {
90 if ((copyOffset %
sizeof(buffer)) >= outSize)
93 const byte data = buffer[copyOffset %
sizeof(buffer)];
98 buffer[bufferPos] = data;
99 bufferPos = (bufferPos + 1) %
sizeof(buffer);
110 buffer[bufferPos] = data;
111 bufferPos = (bufferPos + 1) %
sizeof(buffer);
139 const byte *oldPtr,
size_t oldLength,
140 size_t &displacement,
size_t minDisplacement = 1) {
144 if ((minDisplacement > oldLength) || (newLength == 0))
147 size_t maxLength = 0;
148 for (
size_t i = 0; i < oldLength - minDisplacement; i++) {
152 const byte *currentOldPtr = oldPtr + i;
153 size_t currentLength = 0;
157 for (
size_t j = 0; j < newLength; j++, currentLength++)
158 if (currentOldPtr[j] != newPtr[j])
161 if (currentLength > maxLength) {
163 maxLength = currentLength;
164 displacement = oldLength - i;
167 if (maxLength == newLength)
184 if (in.
read(inBuffer.
get(), size) != size)
188 byte outBuffer[8 * 2 + 1] = { 0 };
189 size_t bufferedBlocks = 0, bufferLength = 1;
192 while (inRead < size) {
194 if (bufferedBlocks == 8) {
195 if (small.
write(outBuffer, bufferLength) != bufferLength)
210 const size_t newLength = MIN<size_t>(size - inRead, 0x12);
211 const size_t oldLength = MIN<size_t>(inRead, 0x1000);
213 size_t displacement = 0;
214 const size_t length =
216 inBuffer.
get() + inRead - oldLength, oldLength,
227 outBuffer[0] |= 1 << (7 - bufferedBlocks);
229 outBuffer[bufferLength ] = ((length - 3) << 4) & 0xF0;
230 outBuffer[bufferLength++] |= ((displacement - 1) >> 8) & 0x0F;
231 outBuffer[bufferLength++] = (displacement - 1) & 0xFF;
233 outBuffer[bufferLength++] = inBuffer[inRead++];
239 if (bufferedBlocks > 0)
240 if (small.
write(outBuffer, bufferLength) != bufferLength)
249 else if (type == 0x10)
262 e.
add(
"Failed to decompress \"small\" file");
276 const size_t pos = in->pos();
287 e.
add(
"Failed to decompress \"small\" file");
291 out.setDisposable(
false);
304 e.
add(
"Failed to decompress \"small\" file");
320 const size_t size = in.
size() - in.
pos();
321 if (size >= 0xFFFFFF)
329 const size_t size = in.
size() - in.
pos();
330 if (size >= 0xFFFFFF)
void add(const char *s,...) GCC_PRINTF(2
static void compress10(Common::SeekableReadStream &in, Common::WriteStream &small)
Compress this stream into a small file of type 0x10.
size_t getOccurrenceLength(const byte *newPtr, size_t newLength, const byte *oldPtr, size_t oldLength, size_t &displacement, size_t minDisplacement=1)
Determine the maximum size of an LZSS-compressed block.
uint32 readUint32LE()
Read an unsigned 32-bit word stored in little endian (LSB first) order from the stream and return it...
static void compress10(Common::ReadStream &in, Common::WriteStream &small, uint32 size)
Generic interface for a readable data stream.
static void decompress10(Common::ReadStream &small, Common::WriteStream &out, uint32 size)
A stream that dynamically grows as it's written to.
static void decompress(Common::ReadStream &small, Common::WriteStream &out)
PointerType release()
Returns the plain pointer value and releases ScopedPtr.
Implementing the reading stream interfaces for plain memory blocks.
static void readSmallHeader(Common::ReadStream &small, uint32 &type, uint32 &size)
Exception that provides a stack of explanations.
A simple scoped smart pointer template.
size_t size() const
Return the number of bytes written to this stream in total.
Basic exceptions to throw.
static void decompress(Common::ReadStream &small, Common::WriteStream &out, uint32 type, uint32 size)
Implementing the writing stream interfaces for memory blocks.
static void decompress00(Common::ReadStream &small, Common::WriteStream &out, uint32 size)
static void writeSmallHeader(Common::WriteStream &small, uint32 type, uint32 size)
virtual size_t read(void *dataPtr, size_t dataSize)=0
Read data from the stream.
Simple memory based 'stream', which implements the ReadStream interface for a plain memory block...
const Exception kWriteError("Write error")
Exception when writing to a stream failed.
const Exception kReadError("Read error")
Exception when reading from a stream failed.
void setDisposable(bool disposeMemory)
static void compress00(Common::SeekableReadStream &in, Common::WriteStream &small)
"Compress" this stream into an uncompressed small file.
virtual size_t write(const void *dataPtr, size_t dataSize)=0
Write data into the stream.
void writeByte(byte value)
virtual size_t size() const =0
Obtains the total size of the stream, measured in bytes.
virtual size_t pos() const =0
Obtains the current value of the stream position indicator of the stream.
Generic interface for a writable data stream.
PointerType get() const
Returns the plain pointer value.
Decompressing "small" files, Nintendo DS LZSS (types 0x00 and 0x10), found in Sonic.
static void compress00(Common::ReadStream &in, Common::WriteStream &small, uint32 size)
size_t writeStream(ReadStream &stream, size_t n)
Copy n bytes of the given stream into the stream.
SeekableSubReadStream provides access to a SeekableReadStream restricted to the range [begin...
Interface for a seekable & readable data stream.
void writeUint32LE(uint32 value)
byte readByte()
Read an unsigned byte from the stream and return it.