diff --git a/Utilities/ArchiveReader.cpp b/Utilities/ArchiveReader.cpp index e271ef9..2ed6951 100644 --- a/Utilities/ArchiveReader.cpp +++ b/Utilities/ArchiveReader.cpp @@ -12,11 +12,13 @@ ArchiveReader::~ArchiveReader() delete[] _buffer; } -bool ArchiveReader::GetStream(string filename, std::stringstream &stream) +bool ArchiveReader::GetStream(string filename, std::stringstream& stream) { - if(_initialized) { + if (_initialized) + { vector fileData; - if(ExtractFile(filename, fileData)) { + if (ExtractFile(filename, fileData)) + { stream.write((char*)fileData.data(), fileData.size()); return true; } @@ -26,17 +28,22 @@ bool ArchiveReader::GetStream(string filename, std::stringstream &stream) vector ArchiveReader::GetFileList(std::initializer_list extensions) { - if(extensions.size() == 0) { + if (extensions.size() == 0) + { return InternalGetFileList(); } vector filenames; - for(string filename : InternalGetFileList()) { + for (string filename : InternalGetFileList()) + { string lcFilename = filename; std::transform(lcFilename.begin(), lcFilename.end(), lcFilename.begin(), ::tolower); - for(string ext : extensions) { - if(lcFilename.size() >= ext.size()) { - if(lcFilename.substr(lcFilename.length() - ext.size(), ext.size()).compare(ext) == 0) { + for (string ext : extensions) + { + if (lcFilename.size() >= ext.size()) + { + if (lcFilename.substr(lcFilename.length() - ext.size(), ext.size()).compare(ext) == 0) + { filenames.push_back(filename); } } @@ -52,7 +59,7 @@ bool ArchiveReader::CheckFile(string filename) return std::find(files.begin(), files.end(), filename) != files.end(); } -bool ArchiveReader::LoadArchive(std::istream &in) +bool ArchiveReader::LoadArchive(std::istream& in) { in.seekg(0, std::ios::end); std::streampos filesize = in.tellg(); @@ -66,14 +73,15 @@ bool ArchiveReader::LoadArchive(std::istream &in) return result; } -bool ArchiveReader::LoadArchive(vector &data) +bool ArchiveReader::LoadArchive(vector& data) { return LoadArchive(data.data(), data.size()); } bool ArchiveReader::LoadArchive(void* buffer, size_t size) { - if(InternalLoadArchive(buffer, size)) { + if (InternalLoadArchive(buffer, size)) + { _initialized = true; return true; } @@ -83,26 +91,31 @@ bool ArchiveReader::LoadArchive(void* buffer, size_t size) bool ArchiveReader::LoadArchive(string filename) { ifstream in(filename, std::ios::binary | std::ios::in); - if(in.good()) { + if (in.good()) + { LoadArchive(in); in.close(); } return false; } -shared_ptr ArchiveReader::GetReader(std::istream &in) +shared_ptr ArchiveReader::GetReader(std::istream& in) { - uint8_t header[2] = { 0,0 }; + uint8_t header[2] = {0, 0}; in.read((char*)header, 2); shared_ptr reader; - if(memcmp(header, "PK", 2) == 0) { + if (memcmp(header, "PK", 2) == 0) + { reader.reset(new ZipReader()); - } else if(memcmp(header, "7z", 2) == 0) { + } + else if (memcmp(header, "7z", 2) == 0) + { reader.reset(new SZReader()); } - if(reader) { + if (reader) + { reader->LoadArchive(in); } return reader; @@ -111,8 +124,9 @@ shared_ptr ArchiveReader::GetReader(std::istream &in) shared_ptr ArchiveReader::GetReader(string filepath) { ifstream in(filepath, std::ios::in | std::ios::binary); - if(in) { + if (in) + { return GetReader(in); } return nullptr; -} \ No newline at end of file +} diff --git a/Utilities/ArchiveReader.h b/Utilities/ArchiveReader.h index a2076c8..790c23f 100644 --- a/Utilities/ArchiveReader.h +++ b/Utilities/ArchiveReader.h @@ -14,15 +14,15 @@ public: bool LoadArchive(void* buffer, size_t size); bool LoadArchive(vector& data); bool LoadArchive(string filename); - bool LoadArchive(std::istream &in); + bool LoadArchive(std::istream& in); - bool GetStream(string filename, std::stringstream &stream); + bool GetStream(string filename, std::stringstream& stream); vector GetFileList(std::initializer_list extensions = {}); bool CheckFile(string filename); - virtual bool ExtractFile(string filename, vector &output) = 0; + virtual bool ExtractFile(string filename, vector& output) = 0; - static shared_ptr GetReader(std::istream &in); + static shared_ptr GetReader(std::istream& in); static shared_ptr GetReader(string filepath); -}; \ No newline at end of file +}; diff --git a/Utilities/AutoResetEvent.cpp b/Utilities/AutoResetEvent.cpp index f04943c..e5b4ee3 100644 --- a/Utilities/AutoResetEvent.cpp +++ b/Utilities/AutoResetEvent.cpp @@ -15,10 +15,13 @@ AutoResetEvent::~AutoResetEvent() void AutoResetEvent::Wait(int timeoutDelay) { std::unique_lock lock(_mutex); - if(timeoutDelay == 0) { + if (timeoutDelay == 0) + { //Wait until signaled _signal.wait(lock, [this] { return _signaled; }); - } else { + } + else + { //Wait until signaled or timeout auto timeoutTime = std::chrono::system_clock::now() + std::chrono::duration(timeoutDelay); _signal.wait_until(lock, timeoutTime, [this] { return _signaled; }); diff --git a/Utilities/AutoResetEvent.h b/Utilities/AutoResetEvent.h index b272f1d..17269d2 100644 --- a/Utilities/AutoResetEvent.h +++ b/Utilities/AutoResetEvent.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include "stdafx.h" #include diff --git a/Utilities/AviRecorder.cpp b/Utilities/AviRecorder.cpp index ca0532f..fe39685 100644 --- a/Utilities/AviRecorder.cpp +++ b/Utilities/AviRecorder.cpp @@ -14,19 +14,23 @@ AviRecorder::AviRecorder(VideoCodec codec, uint32_t compressionLevel) AviRecorder::~AviRecorder() { - if(_recording) { + if (_recording) + { StopRecording(); } - if(_frameBuffer) { + if (_frameBuffer) + { delete[] _frameBuffer; _frameBuffer = nullptr; } } -bool AviRecorder::StartRecording(string filename, uint32_t width, uint32_t height, uint32_t bpp, uint32_t audioSampleRate, double fps) +bool AviRecorder::StartRecording(string filename, uint32_t width, uint32_t height, uint32_t bpp, + uint32_t audioSampleRate, double fps) { - if(!_recording) { + if (!_recording) + { _outputFile = filename; _sampleRate = audioSampleRate; _width = width; @@ -36,15 +40,20 @@ bool AviRecorder::StartRecording(string filename, uint32_t width, uint32_t heigh _frameBuffer = new uint8_t[_frameBufferLength]; _aviWriter.reset(new AviWriter()); - if(!_aviWriter->StartWrite(filename, _codec, width, height, bpp, (uint32_t)(_fps * 1000000), audioSampleRate, _compressionLevel)) { + if (!_aviWriter->StartWrite(filename, _codec, width, height, bpp, (uint32_t)(_fps * 1000000), audioSampleRate, + _compressionLevel)) + { _aviWriter.reset(); return false; } - _aviWriterThread = std::thread([=]() { - while(!_stopFlag) { + _aviWriterThread = std::thread([=]() + { + while (!_stopFlag) + { _waitFrame.Wait(); - if(_stopFlag) { + if (_stopFlag) + { break; } @@ -60,7 +69,8 @@ bool AviRecorder::StartRecording(string filename, uint32_t width, uint32_t heigh void AviRecorder::StopRecording() { - if(_recording) { + if (_recording) + { _recording = false; _stopFlag = true; @@ -74,10 +84,14 @@ void AviRecorder::StopRecording() void AviRecorder::AddFrame(void* frameBuffer, uint32_t width, uint32_t height, double fps) { - if(_recording) { - if(_width != width || _height != height || _fps != fps) { + if (_recording) + { + if (_width != width || _height != height || _fps != fps) + { StopRecording(); - } else { + } + else + { auto lock = _lock.AcquireSafe(); memcpy(_frameBuffer, frameBuffer, _frameBufferLength); _waitFrame.Signal(); @@ -87,11 +101,15 @@ void AviRecorder::AddFrame(void* frameBuffer, uint32_t width, uint32_t height, d void AviRecorder::AddSound(int16_t* soundBuffer, uint32_t sampleCount, uint32_t sampleRate) { - if(_recording) { - if(_sampleRate != sampleRate) { + if (_recording) + { + if (_sampleRate != sampleRate) + { auto lock = _lock.AcquireSafe(); StopRecording(); - } else { + } + else + { _aviWriter->AddSound(soundBuffer, sampleCount); } } @@ -105,4 +123,4 @@ bool AviRecorder::IsRecording() string AviRecorder::GetOutputFile() { return _outputFile; -} \ No newline at end of file +} diff --git a/Utilities/AviRecorder.h b/Utilities/AviRecorder.h index f79ecd4..396f634 100644 --- a/Utilities/AviRecorder.h +++ b/Utilities/AviRecorder.h @@ -12,14 +12,14 @@ class AviRecorder : public IVideoRecorder { private: std::thread _aviWriterThread; - + unique_ptr _aviWriter; string _outputFile; SimpleLock _lock; AutoResetEvent _waitFrame; - atomic _stopFlag; + atomic _stopFlag; bool _recording; uint8_t* _frameBuffer; uint32_t _frameBufferLength; @@ -36,7 +36,8 @@ public: AviRecorder(VideoCodec codec, uint32_t compressionLevel); virtual ~AviRecorder(); - bool StartRecording(string filename, uint32_t width, uint32_t height, uint32_t bpp, uint32_t audioSampleRate, double fps) override; + bool StartRecording(string filename, uint32_t width, uint32_t height, uint32_t bpp, uint32_t audioSampleRate, + double fps) override; void StopRecording() override; void AddFrame(void* frameBuffer, uint32_t width, uint32_t height, double fps) override; @@ -44,4 +45,4 @@ public: bool IsRecording() override; string GetOutputFile() override; -}; \ No newline at end of file +}; diff --git a/Utilities/AviWriter.cpp b/Utilities/AviWriter.cpp index fdd63fc..82f2ee2 100644 --- a/Utilities/AviWriter.cpp +++ b/Utilities/AviWriter.cpp @@ -28,15 +28,15 @@ #include "ZmbvCodec.h" #include "CamstudioCodec.h" -void AviWriter::WriteAviChunk(const char *tag, uint32_t size, void *data, uint32_t flags) +void AviWriter::WriteAviChunk(const char* tag, uint32_t size, void* data, uint32_t flags) { - uint8_t chunk[8] = { (uint8_t)tag[0], (uint8_t)tag[1], (uint8_t)tag[2], (uint8_t)tag[3] }; + uint8_t chunk[8] = {(uint8_t)tag[0], (uint8_t)tag[1], (uint8_t)tag[2], (uint8_t)tag[3]}; host_writed(&chunk[4], size); _file.write((char*)chunk, 8); - - uint32_t writesize = (size + 1)&~1; + + uint32_t writesize = (size + 1) & ~1; _file.write((char*)data, writesize); - + uint32_t pos = _written + 4; _written += writesize + 8; @@ -64,26 +64,33 @@ void AviWriter::host_writed(uint8_t* buffer, uint32_t value) buffer[3] = value >> 24; } -bool AviWriter::StartWrite(string filename, VideoCodec codec, uint32_t width, uint32_t height, uint32_t bpp, uint32_t fps, uint32_t audioSampleRate, uint32_t compressionLevel) +bool AviWriter::StartWrite(string filename, VideoCodec codec, uint32_t width, uint32_t height, uint32_t bpp, + uint32_t fps, uint32_t audioSampleRate, uint32_t compressionLevel) { _codecType = codec; _file.open(filename, std::ios::out | std::ios::binary); - if(!_file) { - return false; - } - - switch(_codecType) { - default: - case VideoCodec::None: _codec.reset(new RawCodec()); break; - case VideoCodec::ZMBV: _codec.reset(new ZmbvCodec()); break; - case VideoCodec::CSCD: _codec.reset(new CamstudioCodec()); break; - } - - if(!_codec->SetupCompress(width, height, compressionLevel)) { + if (!_file) + { return false; } - _frameBuffer = new uint8_t[width*height*bpp]; + switch (_codecType) + { + default: + case VideoCodec::None: _codec.reset(new RawCodec()); + break; + case VideoCodec::ZMBV: _codec.reset(new ZmbvCodec()); + break; + case VideoCodec::CSCD: _codec.reset(new CamstudioCodec()); + break; + } + + if (!_codec->SetupCompress(width, height, compressionLevel)) + { + return false; + } + + _frameBuffer = new uint8_t[width * height * bpp]; _aviIndex.clear(); _aviIndex.insert(_aviIndex.end(), 8, 0); @@ -95,7 +102,8 @@ bool AviWriter::StartWrite(string filename, VideoCodec codec, uint32_t width, ui _audiorate = audioSampleRate; - for(int i = 0; i < AviWriter::AviHeaderSize; i++) { + for (int i = 0; i < AviWriter::AviHeaderSize; i++) + { _file.put(0); } _frames = 0; @@ -116,100 +124,100 @@ void AviWriter::EndWrite() #define AVIOUTw(_S_) host_writew(&avi_header[header_pos], _S_);header_pos+=2; #define AVIOUTd(_S_) host_writed(&avi_header[header_pos], _S_);header_pos+=4; /* Try and write an avi header */ - AVIOUT4("RIFF"); // Riff header + AVIOUT4("RIFF"); // Riff header AVIOUTd(AviWriter::AviHeaderSize + _written - 8 + (uint32_t)_aviIndex.size()); AVIOUT4("AVI "); - AVIOUT4("LIST"); // List header + AVIOUT4("LIST"); // List header main_list = header_pos; - AVIOUTd(0); // TODO size of list + AVIOUTd(0); // TODO size of list AVIOUT4("hdrl"); AVIOUT4("avih"); - AVIOUTd(56); /* # of bytes to follow */ - AVIOUTd((uint32_t)(1000000 / _fps)); /* Microseconds per frame */ + AVIOUTd(56); /* # of bytes to follow */ + AVIOUTd((uint32_t)(1000000 / _fps)); /* Microseconds per frame */ AVIOUTd(0); - AVIOUTd(0); /* PaddingGranularity (whatever that might be) */ - AVIOUTd(0x110); /* Flags,0x10 has index, 0x100 interleaved */ - AVIOUTd(_frames); /* TotalFrames */ - AVIOUTd(0); /* InitialFrames */ - AVIOUTd(2); /* Stream count */ - AVIOUTd(0); /* SuggestedBufferSize */ - AVIOUTd(_width); /* Width */ - AVIOUTd(_height); /* Height */ - AVIOUTd(0); /* TimeScale: Unit used to measure time */ - AVIOUTd(0); /* DataRate: Data rate of playback */ - AVIOUTd(0); /* StartTime: Starting time of AVI data */ - AVIOUTd(0); /* DataLength: Size of AVI data chunk */ + AVIOUTd(0); /* PaddingGranularity (whatever that might be) */ + AVIOUTd(0x110); /* Flags,0x10 has index, 0x100 interleaved */ + AVIOUTd(_frames); /* TotalFrames */ + AVIOUTd(0); /* InitialFrames */ + AVIOUTd(2); /* Stream count */ + AVIOUTd(0); /* SuggestedBufferSize */ + AVIOUTd(_width); /* Width */ + AVIOUTd(_height); /* Height */ + AVIOUTd(0); /* TimeScale: Unit used to measure time */ + AVIOUTd(0); /* DataRate: Data rate of playback */ + AVIOUTd(0); /* StartTime: Starting time of AVI data */ + AVIOUTd(0); /* DataLength: Size of AVI data chunk */ - /* Video stream list */ + /* Video stream list */ AVIOUT4("LIST"); - AVIOUTd(4 + 8 + 56 + 8 + 40); /* Size of the list */ + AVIOUTd(4 + 8 + 56 + 8 + 40); /* Size of the list */ AVIOUT4("strl"); /* video stream header */ AVIOUT4("strh"); - AVIOUTd(56); /* # of bytes to follow */ - AVIOUT4("vids"); /* Type */ - AVIOUT4(_codec->GetFourCC()); /* Handler */ - AVIOUTd(0); /* Flags */ - AVIOUTd(0); /* Reserved, MS says: wPriority, wLanguage */ - AVIOUTd(0); /* InitialFrames */ - AVIOUTd(1000000); /* Scale */ - AVIOUTd(_fps); /* Rate: Rate/Scale == samples/second */ - AVIOUTd(0); /* Start */ - AVIOUTd(_frames); /* Length */ - AVIOUTd(0); /* SuggestedBufferSize */ - AVIOUTd(~0); /* Quality */ - AVIOUTd(0); /* SampleSize */ - AVIOUTd(0); /* Frame */ - AVIOUTd(0); /* Frame */ - /* The video stream format */ + AVIOUTd(56); /* # of bytes to follow */ + AVIOUT4("vids"); /* Type */ + AVIOUT4(_codec->GetFourCC()); /* Handler */ + AVIOUTd(0); /* Flags */ + AVIOUTd(0); /* Reserved, MS says: wPriority, wLanguage */ + AVIOUTd(0); /* InitialFrames */ + AVIOUTd(1000000); /* Scale */ + AVIOUTd(_fps); /* Rate: Rate/Scale == samples/second */ + AVIOUTd(0); /* Start */ + AVIOUTd(_frames); /* Length */ + AVIOUTd(0); /* SuggestedBufferSize */ + AVIOUTd(~0); /* Quality */ + AVIOUTd(0); /* SampleSize */ + AVIOUTd(0); /* Frame */ + AVIOUTd(0); /* Frame */ + /* The video stream format */ AVIOUT4("strf"); - AVIOUTd(40); /* # of bytes to follow */ - AVIOUTd(40); /* Size */ - AVIOUTd(_width); /* Width */ - AVIOUTd(_height); /* Height */ - // OUTSHRT(1); OUTSHRT(24); /* Planes, Count */ - AVIOUTw(1); //number of planes + AVIOUTd(40); /* # of bytes to follow */ + AVIOUTd(40); /* Size */ + AVIOUTd(_width); /* Width */ + AVIOUTd(_height); /* Height */ + // OUTSHRT(1); OUTSHRT(24); /* Planes, Count */ + AVIOUTw(1); //number of planes AVIOUTw(24); //bits for colors - AVIOUT4(_codec->GetFourCC()); /* Compression */ - AVIOUTd(_width * _height * 4); /* SizeImage (in bytes?) */ - AVIOUTd(0); /* XPelsPerMeter */ - AVIOUTd(0); /* YPelsPerMeter */ - AVIOUTd(0); /* ClrUsed: Number of colors used */ - AVIOUTd(0); /* ClrImportant: Number of colors important */ + AVIOUT4(_codec->GetFourCC()); /* Compression */ + AVIOUTd(_width * _height * 4); /* SizeImage (in bytes?) */ + AVIOUTd(0); /* XPelsPerMeter */ + AVIOUTd(0); /* YPelsPerMeter */ + AVIOUTd(0); /* ClrUsed: Number of colors used */ + AVIOUTd(0); /* ClrImportant: Number of colors important */ - /* Audio stream list */ + /* Audio stream list */ AVIOUT4("LIST"); - AVIOUTd(4 + 8 + 56 + 8 + 16); /* Length of list in bytes */ + AVIOUTd(4 + 8 + 56 + 8 + 16); /* Length of list in bytes */ AVIOUT4("strl"); /* The audio stream header */ AVIOUT4("strh"); - AVIOUTd(56); /* # of bytes to follow */ + AVIOUTd(56); /* # of bytes to follow */ AVIOUT4("auds"); - AVIOUTd(0); /* Format (Optionally) */ - AVIOUTd(0); /* Flags */ - AVIOUTd(0); /* Reserved, MS says: wPriority, wLanguage */ - AVIOUTd(0); /* InitialFrames */ - AVIOUTd(4); /* Scale */ - AVIOUTd(_audiorate * 4); /* Rate, actual rate is scale/rate */ - AVIOUTd(0); /* Start */ - if(!_audiorate) + AVIOUTd(0); /* Format (Optionally) */ + AVIOUTd(0); /* Flags */ + AVIOUTd(0); /* Reserved, MS says: wPriority, wLanguage */ + AVIOUTd(0); /* InitialFrames */ + AVIOUTd(4); /* Scale */ + AVIOUTd(_audiorate * 4); /* Rate, actual rate is scale/rate */ + AVIOUTd(0); /* Start */ + if (!_audiorate) _audiorate = 1; - AVIOUTd(_audiowritten / 4); /* Length */ - AVIOUTd(0); /* SuggestedBufferSize */ - AVIOUTd(~0); /* Quality */ - AVIOUTd(4); /* SampleSize */ - AVIOUTd(0); /* Frame */ - AVIOUTd(0); /* Frame */ - /* The audio stream format */ + AVIOUTd(_audiowritten / 4); /* Length */ + AVIOUTd(0); /* SuggestedBufferSize */ + AVIOUTd(~0); /* Quality */ + AVIOUTd(4); /* SampleSize */ + AVIOUTd(0); /* Frame */ + AVIOUTd(0); /* Frame */ + /* The audio stream format */ AVIOUT4("strf"); - AVIOUTd(16); /* # of bytes to follow */ - AVIOUTw(1); /* Format, WAVE_ZMBV_FORMAT_PCM */ - AVIOUTw(2); /* Number of channels */ - AVIOUTd(_audiorate); /* SamplesPerSec */ - AVIOUTd(_audiorate * 4); /* AvgBytesPerSec*/ - AVIOUTw(4); /* BlockAlign */ - AVIOUTw(16); /* BitsPerSample */ + AVIOUTd(16); /* # of bytes to follow */ + AVIOUTw(1); /* Format, WAVE_ZMBV_FORMAT_PCM */ + AVIOUTw(2); /* Number of channels */ + AVIOUTd(_audiorate); /* SamplesPerSec */ + AVIOUTd(_audiorate * 4); /* AvgBytesPerSec*/ + AVIOUTw(4); /* BlockAlign */ + AVIOUTw(16); /* BitsPerSample */ int nmain = header_pos - main_list - 4; /* Finish stream list, i.e. put number of bytes in the list to proper pos */ @@ -226,16 +234,17 @@ void AviWriter::EndWrite() /* First add the index table to the end */ memcpy(_aviIndex.data(), "idx1", 4); host_writed(_aviIndex.data() + 4, (uint32_t)_aviIndex.size() - 8); - + _file.write((char*)_aviIndex.data(), _aviIndex.size()); _file.seekp(std::ios::beg); _file.write((char*)avi_header, AviWriter::AviHeaderSize); _file.close(); } -void AviWriter::AddFrame(uint8_t *frameData) +void AviWriter::AddFrame(uint8_t* frameData) { - if(!_file) { + if (!_file) + { return; } @@ -243,17 +252,20 @@ void AviWriter::AddFrame(uint8_t *frameData) uint8_t* compressedData = nullptr; int written = _codec->CompressFrame(isKeyFrame, frameData, &compressedData); - if(written < 0) { + if (written < 0) + { return; } - if(_codecType == VideoCodec::None) { + if (_codecType == VideoCodec::None) + { isKeyFrame = true; } WriteAviChunk(_codecType == VideoCodec::None ? "00db" : "00dc", written, compressedData, isKeyFrame ? 0x10 : 0); _frames++; - if(_audioPos) { + if (_audioPos) + { auto lock = _audioLock.AcquireSafe(); WriteAviChunk("01wb", _audioPos, _audiobuf, 0); _audiowritten += _audioPos; @@ -261,13 +273,14 @@ void AviWriter::AddFrame(uint8_t *frameData) } } -void AviWriter::AddSound(int16_t *data, uint32_t sampleCount) +void AviWriter::AddSound(int16_t* data, uint32_t sampleCount) { - if(!_file) { + if (!_file) + { return; } auto lock = _audioLock.AcquireSafe(); - memcpy(_audiobuf+_audioPos/2, data, sampleCount * 4); + memcpy(_audiobuf + _audioPos / 2, data, sampleCount * 4); _audioPos += sampleCount * 4; -} \ No newline at end of file +} diff --git a/Utilities/AviWriter.h b/Utilities/AviWriter.h index 0af99ca..9cadb3c 100644 --- a/Utilities/AviWriter.h +++ b/Utilities/AviWriter.h @@ -40,18 +40,19 @@ private: uint8_t* _frameBuffer = nullptr; vector _aviIndex; - + SimpleLock _audioLock; private: void host_writew(uint8_t* buffer, uint16_t value); void host_writed(uint8_t* buffer, uint32_t value); - void WriteAviChunk(const char * tag, uint32_t size, void * data, uint32_t flags); + void WriteAviChunk(const char* tag, uint32_t size, void* data, uint32_t flags); public: void AddFrame(uint8_t* frameData); - void AddSound(int16_t * data, uint32_t sampleCount); + void AddSound(int16_t* data, uint32_t sampleCount); - bool StartWrite(string filename, VideoCodec codec, uint32_t width, uint32_t height, uint32_t bpp, uint32_t fps, uint32_t audioSampleRate, uint32_t compressionLevel); + bool StartWrite(string filename, VideoCodec codec, uint32_t width, uint32_t height, uint32_t bpp, uint32_t fps, + uint32_t audioSampleRate, uint32_t compressionLevel); void EndWrite(); -}; \ No newline at end of file +}; diff --git a/Utilities/Base64.h b/Utilities/Base64.h index eb6c6ec..d9a25af 100644 --- a/Utilities/Base64.h +++ b/Utilities/Base64.h @@ -9,16 +9,19 @@ public: std::string out; int val = 0, valb = -6; - for(uint8_t c : data) { + for (uint8_t c : data) + { val = (val << 8) + c; valb += 8; - while(valb >= 0) { + while (valb >= 0) + { out.push_back("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(val >> valb) & 0x3F]); valb -= 6; } } - if(valb>-6) out.push_back("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[((val << 8) >> (valb + 8)) & 0x3F]); - while(out.size() % 4) out.push_back('='); + if (valb > -6) out.push_back( + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[((val << 8) >> (valb + 8)) & 0x3F]); + while (out.size() % 4) out.push_back('='); return out; } @@ -27,14 +30,16 @@ public: vector out; vector T(256, -1); - for(int i = 0; i < 64; i++) T["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i]] = i; + for (int i = 0; i < 64; i++) T["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i]] = i; int val = 0, valb = -8; - for(uint8_t c : in) { - if(T[c] == -1) break; + for (uint8_t c : in) + { + if (T[c] == -1) break; val = (val << 6) + T[c]; valb += 6; - if(valb >= 0) { + if (valb >= 0) + { out.push_back(val >> valb); valb -= 8; } diff --git a/Utilities/BaseCodec.h b/Utilities/BaseCodec.h index 6133378..b7e2ebb 100644 --- a/Utilities/BaseCodec.h +++ b/Utilities/BaseCodec.h @@ -5,8 +5,10 @@ class BaseCodec { public: virtual bool SetupCompress(int width, int height, uint32_t compressionLevel) = 0; - virtual int CompressFrame(bool isKeyFrame, uint8_t *frameData, uint8_t** compressedData) = 0; + virtual int CompressFrame(bool isKeyFrame, uint8_t* frameData, uint8_t** compressedData) = 0; virtual const char* GetFourCC() = 0; - virtual ~BaseCodec() { } -}; \ No newline at end of file + virtual ~BaseCodec() + { + } +}; diff --git a/Utilities/BpsPatcher.cpp b/Utilities/BpsPatcher.cpp index f958f19..d1d378a 100644 --- a/Utilities/BpsPatcher.cpp +++ b/Utilities/BpsPatcher.cpp @@ -4,19 +4,22 @@ #include "BpsPatcher.h" #include "CRC32.h" -int64_t BpsPatcher::ReadBase128Number(std::istream &file) +int64_t BpsPatcher::ReadBase128Number(std::istream& file) { int64_t result = 0; int shift = 0; uint8_t buffer; - while(true) { + while (true) + { file.read((char*)&buffer, 1); - if(file.eof()) { + if (file.eof()) + { return -1; } result += (buffer & 0x7F) << shift; shift += 7; - if(buffer & 0x80) { + if (buffer & 0x80) + { break; } result += (int64_t)1 << shift; @@ -25,16 +28,17 @@ int64_t BpsPatcher::ReadBase128Number(std::istream &file) return result; } -bool BpsPatcher::PatchBuffer(string bpsFilepath, vector &input, vector &output) +bool BpsPatcher::PatchBuffer(string bpsFilepath, vector& input, vector& output) { ifstream bpsFile(bpsFilepath, std::ios::in | std::ios::binary); - if(bpsFile) { + if (bpsFile) + { return PatchBuffer(bpsFile, input, output); } return false; } -bool BpsPatcher::PatchBuffer(std::istream &bpsFile, vector &input, vector &output) +bool BpsPatcher::PatchBuffer(std::istream& bpsFile, vector& input, vector& output) { bpsFile.seekg(0, std::ios::end); size_t fileSize = (size_t)bpsFile.tellg(); @@ -42,14 +46,16 @@ bool BpsPatcher::PatchBuffer(std::istream &bpsFile, vector &input, vect char header[4]; bpsFile.read((char*)&header, 4); - if(memcmp((char*)&header, "BPS1", 4) != 0) { + if (memcmp((char*)&header, "BPS1", 4) != 0) + { //Invalid BPS file return false; } int64_t inputFileSize = ReadBase128Number(bpsFile); int64_t outputFileSize = ReadBase128Number(bpsFile); - if(inputFileSize == -1 || outputFileSize == -1) { + if (inputFileSize == -1 || outputFileSize == -1) + { //Invalid file return false; } @@ -62,66 +68,78 @@ bool BpsPatcher::PatchBuffer(std::istream &bpsFile, vector &input, vect uint32_t outputOffset = 0; uint32_t inputRelativeOffset = 0; uint32_t outputRelativeOffset = 0; - while((size_t)bpsFile.tellg() < fileSize - 12) { + while ((size_t)bpsFile.tellg() < fileSize - 12) + { int64_t data = ReadBase128Number(bpsFile); - if(data == -1) { + if (data == -1) + { //Invalid file return false; } uint8_t command = data & 0x03; uint64_t length = (data >> 2) + 1; - switch(command) { - case 0: - //SourceRead - while(length--) { - output[outputOffset] = input[outputOffset]; - outputOffset++; - } - break; + switch (command) + { + case 0: + //SourceRead + while (length--) + { + output[outputOffset] = input[outputOffset]; + outputOffset++; + } + break; - case 1: - //TargetRead - while(length--) { - uint8_t value = 0; - bpsFile.read((char*)&value, 1); + case 1: + //TargetRead + while (length--) + { + uint8_t value = 0; + bpsFile.read((char*)&value, 1); - output[outputOffset++] = value; - } - break; + output[outputOffset++] = value; + } + break; - case 2: { + case 2: + { //SourceCopy int32_t data = (int32_t)ReadBase128Number(bpsFile); inputRelativeOffset += (data & 1 ? -1 : +1) * (data >> 1); - while(length--) { + while (length--) + { output[outputOffset++] = input[inputRelativeOffset++]; } break; } - case 3: { + case 3: + { //TargetCopy int32_t data = (int32_t)ReadBase128Number(bpsFile); outputRelativeOffset += (data & 1 ? -1 : +1) * (data >> 1); - while(length--) { + while (length--) + { output[outputOffset++] = output[outputRelativeOffset++]; } break; } - } + } } uint8_t inputChecksum[4]; uint8_t outputChecksum[4]; bpsFile.read((char*)inputChecksum, 4); bpsFile.read((char*)outputChecksum, 4); - uint32_t patchInputCrc = inputChecksum[0] | (inputChecksum[1] << 8) | (inputChecksum[2] << 16) | (inputChecksum[3] << 24); - uint32_t patchOutputCrc = outputChecksum[0] | (outputChecksum[1] << 8) | (outputChecksum[2] << 16) | (outputChecksum[3] << 24); + uint32_t patchInputCrc = inputChecksum[0] | (inputChecksum[1] << 8) | (inputChecksum[2] << 16) | (inputChecksum[3] << + 24); + uint32_t patchOutputCrc = outputChecksum[0] | (outputChecksum[1] << 8) | (outputChecksum[2] << 16) | (outputChecksum[ + 3] << 24); uint32_t inputCrc = CRC32::GetCRC(input.data(), input.size()); uint32_t outputCrc = CRC32::GetCRC(output.data(), output.size()); - if(patchInputCrc != inputCrc || patchOutputCrc != outputCrc) { + if (patchInputCrc != inputCrc || patchOutputCrc != outputCrc) + { return false; } return true; diff --git a/Utilities/BpsPatcher.h b/Utilities/BpsPatcher.h index f10bb13..9648f71 100644 --- a/Utilities/BpsPatcher.h +++ b/Utilities/BpsPatcher.h @@ -5,9 +5,9 @@ class BpsPatcher { private: - static int64_t ReadBase128Number(std::istream &file); + static int64_t ReadBase128Number(std::istream& file); public: - static bool PatchBuffer(std::istream &bpsFile, vector &input, vector &output); - static bool PatchBuffer(string bpsFilepath, vector &input, vector &output); -}; \ No newline at end of file + static bool PatchBuffer(std::istream& bpsFile, vector& input, vector& output); + static bool PatchBuffer(string bpsFilepath, vector& input, vector& output); +}; diff --git a/Utilities/CRC32.cpp b/Utilities/CRC32.cpp index ef1e282..2462924 100644 --- a/Utilities/CRC32.cpp +++ b/Utilities/CRC32.cpp @@ -17,10 +17,10 @@ extern const uint32_t Crc32Lookup[MaxSlice][256]; // define endianess and some integer data types #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__aarch64__) - // Windows always little endian +// Windows always little endian #define __BYTE_ORDER __LITTLE_ENDIAN #else - // defines __BYTE_ORDER as __LITTLE_ENDIAN or __BIG_ENDIAN +// defines __BYTE_ORDER as __LITTLE_ENDIAN or __BIG_ENDIAN #if defined(__APPLE__) || defined(HAVE_LIBNX) #include #elif defined (__FreeBSD__) || defined(__DragonFly__) @@ -46,7 +46,8 @@ uint32_t CRC32::GetCRC(string filename) ifstream file(filename, std::ios::in | std::ios::binary); - if(file) { + if (file) + { file.seekg(0, std::ios::end); std::streamoff fileSize = file.tellg(); file.seekg(0, std::ios::beg); @@ -71,9 +72,11 @@ uint32_t CRC32::crc32_16bytes(const void* data, size_t length, uint32_t previous const size_t Unroll = 4; const size_t BytesAtOnce = 16 * Unroll; - while(length >= BytesAtOnce) { - for(size_t unrolling = 0; unrolling < Unroll; unrolling++) { - #if __BYTE_ORDER == __BIG_ENDIAN + while (length >= BytesAtOnce) + { + for (size_t unrolling = 0; unrolling < Unroll; unrolling++) + { +#if __BYTE_ORDER == __BIG_ENDIAN uint32_t one = *current++ ^ swap(crc); uint32_t two = *current++; uint32_t three = *current++; @@ -94,7 +97,7 @@ uint32_t CRC32::crc32_16bytes(const void* data, size_t length, uint32_t previous Crc32Lookup[13][(one >> 8) & 0xFF] ^ Crc32Lookup[14][(one >> 16) & 0xFF] ^ Crc32Lookup[15][(one >> 24) & 0xFF]; - #else +#else uint32_t one = *current++ ^ crc; uint32_t two = *current++; uint32_t three = *current++; @@ -115,7 +118,7 @@ uint32_t CRC32::crc32_16bytes(const void* data, size_t length, uint32_t previous Crc32Lookup[13][(one >> 16) & 0xFF] ^ Crc32Lookup[14][(one >> 8) & 0xFF] ^ Crc32Lookup[15][one & 0xFF]; - #endif +#endif } length -= BytesAtOnce; @@ -123,7 +126,7 @@ uint32_t CRC32::crc32_16bytes(const void* data, size_t length, uint32_t previous const uint8_t* currentChar = (const uint8_t*)current; // remaining 1 to 63 bytes (standard algorithm) - while(length-- != 0) + while (length-- != 0) crc = (crc >> 8) ^ Crc32Lookup[0][(crc & 0xFF) ^ *currentChar++]; return ~crc; // same as crc ^ 0xFFFFFFFF @@ -132,559 +135,559 @@ uint32_t CRC32::crc32_16bytes(const void* data, size_t length, uint32_t previous const uint32_t Crc32Lookup[MaxSlice][256] = { { - 0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535,0x9E6495A3, - 0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91, - 0x1DB71064,0x6AB020F2,0xF3B97148,0x84BE41DE,0x1ADAD47D,0x6DDDE4EB,0xF4D4B551,0x83D385C7, - 0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5, - 0x3B6E20C8,0x4C69105E,0xD56041E4,0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B, - 0x35B5A8FA,0x42B2986C,0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59, - 0x26D930AC,0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,0xCFBA9599,0xB8BDA50F, - 0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,0x2F6F7C87,0x58684C11,0xC1611DAB,0xB6662D3D, - 0x76DC4190,0x01DB7106,0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,0x9FBFE4A5,0xE8B8D433, - 0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,0x086D3D2D,0x91646C97,0xE6635C01, - 0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E,0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457, - 0x65B0D9C6,0x12B7E950,0x8BBEB8EA,0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65, - 0x4DB26158,0x3AB551CE,0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,0xA4D1C46D,0xD3D6F4FB, - 0x4369E96A,0x346ED9FC,0xAD678846,0xDA60B8D0,0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9, - 0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,0xCE61E49F, - 0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81,0xB7BD5C3B,0xC0BA6CAD, - 0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A,0xEAD54739,0x9DD277AF,0x04DB2615,0x73DC1683, - 0xE3630B12,0x94643B84,0x0D6D6A3E,0x7A6A5AA8,0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1, - 0xF00F9344,0x8708A3D2,0x1E01F268,0x6906C2FE,0xF762575D,0x806567CB,0x196C3671,0x6E6B06E7, - 0xFED41B76,0x89D32BE0,0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5, - 0xD6D6A3E8,0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B, - 0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,0x316E8EEF,0x4669BE79, - 0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,0xCC0C7795,0xBB0B4703,0x220216B9,0x5505262F, - 0xC5BA3BBE,0xB2BD0B28,0x2BB45A92,0x5CB36A04,0xC2D7FFA7,0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D, - 0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,0x9C0906A9,0xEB0E363F,0x72076785,0x05005713, - 0x95BF4A82,0xE2B87A14,0x7BB12BAE,0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21, - 0x86D3D2D4,0xF1D4E242,0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777, - 0x88085AE6,0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,0x616BFFD3,0x166CCF45, - 0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,0xA7672661,0xD06016F7,0x4969474D,0x3E6E77DB, - 0xAED16A4A,0xD9D65ADC,0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,0x47B2CF7F,0x30B5FFE9, - 0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693,0x54DE5729,0x23D967BF, - 0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D, - } - ,{ - 0x00000000,0x191B3141,0x32366282,0x2B2D53C3,0x646CC504,0x7D77F445,0x565AA786,0x4F4196C7, - 0xC8D98A08,0xD1C2BB49,0xFAEFE88A,0xE3F4D9CB,0xACB54F0C,0xB5AE7E4D,0x9E832D8E,0x87981CCF, - 0x4AC21251,0x53D92310,0x78F470D3,0x61EF4192,0x2EAED755,0x37B5E614,0x1C98B5D7,0x05838496, - 0x821B9859,0x9B00A918,0xB02DFADB,0xA936CB9A,0xE6775D5D,0xFF6C6C1C,0xD4413FDF,0xCD5A0E9E, - 0x958424A2,0x8C9F15E3,0xA7B24620,0xBEA97761,0xF1E8E1A6,0xE8F3D0E7,0xC3DE8324,0xDAC5B265, - 0x5D5DAEAA,0x44469FEB,0x6F6BCC28,0x7670FD69,0x39316BAE,0x202A5AEF,0x0B07092C,0x121C386D, - 0xDF4636F3,0xC65D07B2,0xED705471,0xF46B6530,0xBB2AF3F7,0xA231C2B6,0x891C9175,0x9007A034, - 0x179FBCFB,0x0E848DBA,0x25A9DE79,0x3CB2EF38,0x73F379FF,0x6AE848BE,0x41C51B7D,0x58DE2A3C, - 0xF0794F05,0xE9627E44,0xC24F2D87,0xDB541CC6,0x94158A01,0x8D0EBB40,0xA623E883,0xBF38D9C2, - 0x38A0C50D,0x21BBF44C,0x0A96A78F,0x138D96CE,0x5CCC0009,0x45D73148,0x6EFA628B,0x77E153CA, - 0xBABB5D54,0xA3A06C15,0x888D3FD6,0x91960E97,0xDED79850,0xC7CCA911,0xECE1FAD2,0xF5FACB93, - 0x7262D75C,0x6B79E61D,0x4054B5DE,0x594F849F,0x160E1258,0x0F152319,0x243870DA,0x3D23419B, - 0x65FD6BA7,0x7CE65AE6,0x57CB0925,0x4ED03864,0x0191AEA3,0x188A9FE2,0x33A7CC21,0x2ABCFD60, - 0xAD24E1AF,0xB43FD0EE,0x9F12832D,0x8609B26C,0xC94824AB,0xD05315EA,0xFB7E4629,0xE2657768, - 0x2F3F79F6,0x362448B7,0x1D091B74,0x04122A35,0x4B53BCF2,0x52488DB3,0x7965DE70,0x607EEF31, - 0xE7E6F3FE,0xFEFDC2BF,0xD5D0917C,0xCCCBA03D,0x838A36FA,0x9A9107BB,0xB1BC5478,0xA8A76539, - 0x3B83984B,0x2298A90A,0x09B5FAC9,0x10AECB88,0x5FEF5D4F,0x46F46C0E,0x6DD93FCD,0x74C20E8C, - 0xF35A1243,0xEA412302,0xC16C70C1,0xD8774180,0x9736D747,0x8E2DE606,0xA500B5C5,0xBC1B8484, - 0x71418A1A,0x685ABB5B,0x4377E898,0x5A6CD9D9,0x152D4F1E,0x0C367E5F,0x271B2D9C,0x3E001CDD, - 0xB9980012,0xA0833153,0x8BAE6290,0x92B553D1,0xDDF4C516,0xC4EFF457,0xEFC2A794,0xF6D996D5, - 0xAE07BCE9,0xB71C8DA8,0x9C31DE6B,0x852AEF2A,0xCA6B79ED,0xD37048AC,0xF85D1B6F,0xE1462A2E, - 0x66DE36E1,0x7FC507A0,0x54E85463,0x4DF36522,0x02B2F3E5,0x1BA9C2A4,0x30849167,0x299FA026, - 0xE4C5AEB8,0xFDDE9FF9,0xD6F3CC3A,0xCFE8FD7B,0x80A96BBC,0x99B25AFD,0xB29F093E,0xAB84387F, - 0x2C1C24B0,0x350715F1,0x1E2A4632,0x07317773,0x4870E1B4,0x516BD0F5,0x7A468336,0x635DB277, - 0xCBFAD74E,0xD2E1E60F,0xF9CCB5CC,0xE0D7848D,0xAF96124A,0xB68D230B,0x9DA070C8,0x84BB4189, - 0x03235D46,0x1A386C07,0x31153FC4,0x280E0E85,0x674F9842,0x7E54A903,0x5579FAC0,0x4C62CB81, - 0x8138C51F,0x9823F45E,0xB30EA79D,0xAA1596DC,0xE554001B,0xFC4F315A,0xD7626299,0xCE7953D8, - 0x49E14F17,0x50FA7E56,0x7BD72D95,0x62CC1CD4,0x2D8D8A13,0x3496BB52,0x1FBBE891,0x06A0D9D0, - 0x5E7EF3EC,0x4765C2AD,0x6C48916E,0x7553A02F,0x3A1236E8,0x230907A9,0x0824546A,0x113F652B, - 0x96A779E4,0x8FBC48A5,0xA4911B66,0xBD8A2A27,0xF2CBBCE0,0xEBD08DA1,0xC0FDDE62,0xD9E6EF23, - 0x14BCE1BD,0x0DA7D0FC,0x268A833F,0x3F91B27E,0x70D024B9,0x69CB15F8,0x42E6463B,0x5BFD777A, - 0xDC656BB5,0xC57E5AF4,0xEE530937,0xF7483876,0xB809AEB1,0xA1129FF0,0x8A3FCC33,0x9324FD72, - }, + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D, + }, + { + 0x00000000, 0x191B3141, 0x32366282, 0x2B2D53C3, 0x646CC504, 0x7D77F445, 0x565AA786, 0x4F4196C7, + 0xC8D98A08, 0xD1C2BB49, 0xFAEFE88A, 0xE3F4D9CB, 0xACB54F0C, 0xB5AE7E4D, 0x9E832D8E, 0x87981CCF, + 0x4AC21251, 0x53D92310, 0x78F470D3, 0x61EF4192, 0x2EAED755, 0x37B5E614, 0x1C98B5D7, 0x05838496, + 0x821B9859, 0x9B00A918, 0xB02DFADB, 0xA936CB9A, 0xE6775D5D, 0xFF6C6C1C, 0xD4413FDF, 0xCD5A0E9E, + 0x958424A2, 0x8C9F15E3, 0xA7B24620, 0xBEA97761, 0xF1E8E1A6, 0xE8F3D0E7, 0xC3DE8324, 0xDAC5B265, + 0x5D5DAEAA, 0x44469FEB, 0x6F6BCC28, 0x7670FD69, 0x39316BAE, 0x202A5AEF, 0x0B07092C, 0x121C386D, + 0xDF4636F3, 0xC65D07B2, 0xED705471, 0xF46B6530, 0xBB2AF3F7, 0xA231C2B6, 0x891C9175, 0x9007A034, + 0x179FBCFB, 0x0E848DBA, 0x25A9DE79, 0x3CB2EF38, 0x73F379FF, 0x6AE848BE, 0x41C51B7D, 0x58DE2A3C, + 0xF0794F05, 0xE9627E44, 0xC24F2D87, 0xDB541CC6, 0x94158A01, 0x8D0EBB40, 0xA623E883, 0xBF38D9C2, + 0x38A0C50D, 0x21BBF44C, 0x0A96A78F, 0x138D96CE, 0x5CCC0009, 0x45D73148, 0x6EFA628B, 0x77E153CA, + 0xBABB5D54, 0xA3A06C15, 0x888D3FD6, 0x91960E97, 0xDED79850, 0xC7CCA911, 0xECE1FAD2, 0xF5FACB93, + 0x7262D75C, 0x6B79E61D, 0x4054B5DE, 0x594F849F, 0x160E1258, 0x0F152319, 0x243870DA, 0x3D23419B, + 0x65FD6BA7, 0x7CE65AE6, 0x57CB0925, 0x4ED03864, 0x0191AEA3, 0x188A9FE2, 0x33A7CC21, 0x2ABCFD60, + 0xAD24E1AF, 0xB43FD0EE, 0x9F12832D, 0x8609B26C, 0xC94824AB, 0xD05315EA, 0xFB7E4629, 0xE2657768, + 0x2F3F79F6, 0x362448B7, 0x1D091B74, 0x04122A35, 0x4B53BCF2, 0x52488DB3, 0x7965DE70, 0x607EEF31, + 0xE7E6F3FE, 0xFEFDC2BF, 0xD5D0917C, 0xCCCBA03D, 0x838A36FA, 0x9A9107BB, 0xB1BC5478, 0xA8A76539, + 0x3B83984B, 0x2298A90A, 0x09B5FAC9, 0x10AECB88, 0x5FEF5D4F, 0x46F46C0E, 0x6DD93FCD, 0x74C20E8C, + 0xF35A1243, 0xEA412302, 0xC16C70C1, 0xD8774180, 0x9736D747, 0x8E2DE606, 0xA500B5C5, 0xBC1B8484, + 0x71418A1A, 0x685ABB5B, 0x4377E898, 0x5A6CD9D9, 0x152D4F1E, 0x0C367E5F, 0x271B2D9C, 0x3E001CDD, + 0xB9980012, 0xA0833153, 0x8BAE6290, 0x92B553D1, 0xDDF4C516, 0xC4EFF457, 0xEFC2A794, 0xF6D996D5, + 0xAE07BCE9, 0xB71C8DA8, 0x9C31DE6B, 0x852AEF2A, 0xCA6B79ED, 0xD37048AC, 0xF85D1B6F, 0xE1462A2E, + 0x66DE36E1, 0x7FC507A0, 0x54E85463, 0x4DF36522, 0x02B2F3E5, 0x1BA9C2A4, 0x30849167, 0x299FA026, + 0xE4C5AEB8, 0xFDDE9FF9, 0xD6F3CC3A, 0xCFE8FD7B, 0x80A96BBC, 0x99B25AFD, 0xB29F093E, 0xAB84387F, + 0x2C1C24B0, 0x350715F1, 0x1E2A4632, 0x07317773, 0x4870E1B4, 0x516BD0F5, 0x7A468336, 0x635DB277, + 0xCBFAD74E, 0xD2E1E60F, 0xF9CCB5CC, 0xE0D7848D, 0xAF96124A, 0xB68D230B, 0x9DA070C8, 0x84BB4189, + 0x03235D46, 0x1A386C07, 0x31153FC4, 0x280E0E85, 0x674F9842, 0x7E54A903, 0x5579FAC0, 0x4C62CB81, + 0x8138C51F, 0x9823F45E, 0xB30EA79D, 0xAA1596DC, 0xE554001B, 0xFC4F315A, 0xD7626299, 0xCE7953D8, + 0x49E14F17, 0x50FA7E56, 0x7BD72D95, 0x62CC1CD4, 0x2D8D8A13, 0x3496BB52, 0x1FBBE891, 0x06A0D9D0, + 0x5E7EF3EC, 0x4765C2AD, 0x6C48916E, 0x7553A02F, 0x3A1236E8, 0x230907A9, 0x0824546A, 0x113F652B, + 0x96A779E4, 0x8FBC48A5, 0xA4911B66, 0xBD8A2A27, 0xF2CBBCE0, 0xEBD08DA1, 0xC0FDDE62, 0xD9E6EF23, + 0x14BCE1BD, 0x0DA7D0FC, 0x268A833F, 0x3F91B27E, 0x70D024B9, 0x69CB15F8, 0x42E6463B, 0x5BFD777A, + 0xDC656BB5, 0xC57E5AF4, 0xEE530937, 0xF7483876, 0xB809AEB1, 0xA1129FF0, 0x8A3FCC33, 0x9324FD72, + }, - { - 0x00000000,0x01C26A37,0x0384D46E,0x0246BE59,0x0709A8DC,0x06CBC2EB,0x048D7CB2,0x054F1685, - 0x0E1351B8,0x0FD13B8F,0x0D9785D6,0x0C55EFE1,0x091AF964,0x08D89353,0x0A9E2D0A,0x0B5C473D, - 0x1C26A370,0x1DE4C947,0x1FA2771E,0x1E601D29,0x1B2F0BAC,0x1AED619B,0x18ABDFC2,0x1969B5F5, - 0x1235F2C8,0x13F798FF,0x11B126A6,0x10734C91,0x153C5A14,0x14FE3023,0x16B88E7A,0x177AE44D, - 0x384D46E0,0x398F2CD7,0x3BC9928E,0x3A0BF8B9,0x3F44EE3C,0x3E86840B,0x3CC03A52,0x3D025065, - 0x365E1758,0x379C7D6F,0x35DAC336,0x3418A901,0x3157BF84,0x3095D5B3,0x32D36BEA,0x331101DD, - 0x246BE590,0x25A98FA7,0x27EF31FE,0x262D5BC9,0x23624D4C,0x22A0277B,0x20E69922,0x2124F315, - 0x2A78B428,0x2BBADE1F,0x29FC6046,0x283E0A71,0x2D711CF4,0x2CB376C3,0x2EF5C89A,0x2F37A2AD, - 0x709A8DC0,0x7158E7F7,0x731E59AE,0x72DC3399,0x7793251C,0x76514F2B,0x7417F172,0x75D59B45, - 0x7E89DC78,0x7F4BB64F,0x7D0D0816,0x7CCF6221,0x798074A4,0x78421E93,0x7A04A0CA,0x7BC6CAFD, - 0x6CBC2EB0,0x6D7E4487,0x6F38FADE,0x6EFA90E9,0x6BB5866C,0x6A77EC5B,0x68315202,0x69F33835, - 0x62AF7F08,0x636D153F,0x612BAB66,0x60E9C151,0x65A6D7D4,0x6464BDE3,0x662203BA,0x67E0698D, - 0x48D7CB20,0x4915A117,0x4B531F4E,0x4A917579,0x4FDE63FC,0x4E1C09CB,0x4C5AB792,0x4D98DDA5, - 0x46C49A98,0x4706F0AF,0x45404EF6,0x448224C1,0x41CD3244,0x400F5873,0x4249E62A,0x438B8C1D, - 0x54F16850,0x55330267,0x5775BC3E,0x56B7D609,0x53F8C08C,0x523AAABB,0x507C14E2,0x51BE7ED5, - 0x5AE239E8,0x5B2053DF,0x5966ED86,0x58A487B1,0x5DEB9134,0x5C29FB03,0x5E6F455A,0x5FAD2F6D, - 0xE1351B80,0xE0F771B7,0xE2B1CFEE,0xE373A5D9,0xE63CB35C,0xE7FED96B,0xE5B86732,0xE47A0D05, - 0xEF264A38,0xEEE4200F,0xECA29E56,0xED60F461,0xE82FE2E4,0xE9ED88D3,0xEBAB368A,0xEA695CBD, - 0xFD13B8F0,0xFCD1D2C7,0xFE976C9E,0xFF5506A9,0xFA1A102C,0xFBD87A1B,0xF99EC442,0xF85CAE75, - 0xF300E948,0xF2C2837F,0xF0843D26,0xF1465711,0xF4094194,0xF5CB2BA3,0xF78D95FA,0xF64FFFCD, - 0xD9785D60,0xD8BA3757,0xDAFC890E,0xDB3EE339,0xDE71F5BC,0xDFB39F8B,0xDDF521D2,0xDC374BE5, - 0xD76B0CD8,0xD6A966EF,0xD4EFD8B6,0xD52DB281,0xD062A404,0xD1A0CE33,0xD3E6706A,0xD2241A5D, - 0xC55EFE10,0xC49C9427,0xC6DA2A7E,0xC7184049,0xC25756CC,0xC3953CFB,0xC1D382A2,0xC011E895, - 0xCB4DAFA8,0xCA8FC59F,0xC8C97BC6,0xC90B11F1,0xCC440774,0xCD866D43,0xCFC0D31A,0xCE02B92D, - 0x91AF9640,0x906DFC77,0x922B422E,0x93E92819,0x96A63E9C,0x976454AB,0x9522EAF2,0x94E080C5, - 0x9FBCC7F8,0x9E7EADCF,0x9C381396,0x9DFA79A1,0x98B56F24,0x99770513,0x9B31BB4A,0x9AF3D17D, - 0x8D893530,0x8C4B5F07,0x8E0DE15E,0x8FCF8B69,0x8A809DEC,0x8B42F7DB,0x89044982,0x88C623B5, - 0x839A6488,0x82580EBF,0x801EB0E6,0x81DCDAD1,0x8493CC54,0x8551A663,0x8717183A,0x86D5720D, - 0xA9E2D0A0,0xA820BA97,0xAA6604CE,0xABA46EF9,0xAEEB787C,0xAF29124B,0xAD6FAC12,0xACADC625, - 0xA7F18118,0xA633EB2F,0xA4755576,0xA5B73F41,0xA0F829C4,0xA13A43F3,0xA37CFDAA,0xA2BE979D, - 0xB5C473D0,0xB40619E7,0xB640A7BE,0xB782CD89,0xB2CDDB0C,0xB30FB13B,0xB1490F62,0xB08B6555, - 0xBBD72268,0xBA15485F,0xB853F606,0xB9919C31,0xBCDE8AB4,0xBD1CE083,0xBF5A5EDA,0xBE9834ED, - }, + { + 0x00000000, 0x01C26A37, 0x0384D46E, 0x0246BE59, 0x0709A8DC, 0x06CBC2EB, 0x048D7CB2, 0x054F1685, + 0x0E1351B8, 0x0FD13B8F, 0x0D9785D6, 0x0C55EFE1, 0x091AF964, 0x08D89353, 0x0A9E2D0A, 0x0B5C473D, + 0x1C26A370, 0x1DE4C947, 0x1FA2771E, 0x1E601D29, 0x1B2F0BAC, 0x1AED619B, 0x18ABDFC2, 0x1969B5F5, + 0x1235F2C8, 0x13F798FF, 0x11B126A6, 0x10734C91, 0x153C5A14, 0x14FE3023, 0x16B88E7A, 0x177AE44D, + 0x384D46E0, 0x398F2CD7, 0x3BC9928E, 0x3A0BF8B9, 0x3F44EE3C, 0x3E86840B, 0x3CC03A52, 0x3D025065, + 0x365E1758, 0x379C7D6F, 0x35DAC336, 0x3418A901, 0x3157BF84, 0x3095D5B3, 0x32D36BEA, 0x331101DD, + 0x246BE590, 0x25A98FA7, 0x27EF31FE, 0x262D5BC9, 0x23624D4C, 0x22A0277B, 0x20E69922, 0x2124F315, + 0x2A78B428, 0x2BBADE1F, 0x29FC6046, 0x283E0A71, 0x2D711CF4, 0x2CB376C3, 0x2EF5C89A, 0x2F37A2AD, + 0x709A8DC0, 0x7158E7F7, 0x731E59AE, 0x72DC3399, 0x7793251C, 0x76514F2B, 0x7417F172, 0x75D59B45, + 0x7E89DC78, 0x7F4BB64F, 0x7D0D0816, 0x7CCF6221, 0x798074A4, 0x78421E93, 0x7A04A0CA, 0x7BC6CAFD, + 0x6CBC2EB0, 0x6D7E4487, 0x6F38FADE, 0x6EFA90E9, 0x6BB5866C, 0x6A77EC5B, 0x68315202, 0x69F33835, + 0x62AF7F08, 0x636D153F, 0x612BAB66, 0x60E9C151, 0x65A6D7D4, 0x6464BDE3, 0x662203BA, 0x67E0698D, + 0x48D7CB20, 0x4915A117, 0x4B531F4E, 0x4A917579, 0x4FDE63FC, 0x4E1C09CB, 0x4C5AB792, 0x4D98DDA5, + 0x46C49A98, 0x4706F0AF, 0x45404EF6, 0x448224C1, 0x41CD3244, 0x400F5873, 0x4249E62A, 0x438B8C1D, + 0x54F16850, 0x55330267, 0x5775BC3E, 0x56B7D609, 0x53F8C08C, 0x523AAABB, 0x507C14E2, 0x51BE7ED5, + 0x5AE239E8, 0x5B2053DF, 0x5966ED86, 0x58A487B1, 0x5DEB9134, 0x5C29FB03, 0x5E6F455A, 0x5FAD2F6D, + 0xE1351B80, 0xE0F771B7, 0xE2B1CFEE, 0xE373A5D9, 0xE63CB35C, 0xE7FED96B, 0xE5B86732, 0xE47A0D05, + 0xEF264A38, 0xEEE4200F, 0xECA29E56, 0xED60F461, 0xE82FE2E4, 0xE9ED88D3, 0xEBAB368A, 0xEA695CBD, + 0xFD13B8F0, 0xFCD1D2C7, 0xFE976C9E, 0xFF5506A9, 0xFA1A102C, 0xFBD87A1B, 0xF99EC442, 0xF85CAE75, + 0xF300E948, 0xF2C2837F, 0xF0843D26, 0xF1465711, 0xF4094194, 0xF5CB2BA3, 0xF78D95FA, 0xF64FFFCD, + 0xD9785D60, 0xD8BA3757, 0xDAFC890E, 0xDB3EE339, 0xDE71F5BC, 0xDFB39F8B, 0xDDF521D2, 0xDC374BE5, + 0xD76B0CD8, 0xD6A966EF, 0xD4EFD8B6, 0xD52DB281, 0xD062A404, 0xD1A0CE33, 0xD3E6706A, 0xD2241A5D, + 0xC55EFE10, 0xC49C9427, 0xC6DA2A7E, 0xC7184049, 0xC25756CC, 0xC3953CFB, 0xC1D382A2, 0xC011E895, + 0xCB4DAFA8, 0xCA8FC59F, 0xC8C97BC6, 0xC90B11F1, 0xCC440774, 0xCD866D43, 0xCFC0D31A, 0xCE02B92D, + 0x91AF9640, 0x906DFC77, 0x922B422E, 0x93E92819, 0x96A63E9C, 0x976454AB, 0x9522EAF2, 0x94E080C5, + 0x9FBCC7F8, 0x9E7EADCF, 0x9C381396, 0x9DFA79A1, 0x98B56F24, 0x99770513, 0x9B31BB4A, 0x9AF3D17D, + 0x8D893530, 0x8C4B5F07, 0x8E0DE15E, 0x8FCF8B69, 0x8A809DEC, 0x8B42F7DB, 0x89044982, 0x88C623B5, + 0x839A6488, 0x82580EBF, 0x801EB0E6, 0x81DCDAD1, 0x8493CC54, 0x8551A663, 0x8717183A, 0x86D5720D, + 0xA9E2D0A0, 0xA820BA97, 0xAA6604CE, 0xABA46EF9, 0xAEEB787C, 0xAF29124B, 0xAD6FAC12, 0xACADC625, + 0xA7F18118, 0xA633EB2F, 0xA4755576, 0xA5B73F41, 0xA0F829C4, 0xA13A43F3, 0xA37CFDAA, 0xA2BE979D, + 0xB5C473D0, 0xB40619E7, 0xB640A7BE, 0xB782CD89, 0xB2CDDB0C, 0xB30FB13B, 0xB1490F62, 0xB08B6555, + 0xBBD72268, 0xBA15485F, 0xB853F606, 0xB9919C31, 0xBCDE8AB4, 0xBD1CE083, 0xBF5A5EDA, 0xBE9834ED, + }, - { - 0x00000000,0xB8BC6765,0xAA09C88B,0x12B5AFEE,0x8F629757,0x37DEF032,0x256B5FDC,0x9DD738B9, - 0xC5B428EF,0x7D084F8A,0x6FBDE064,0xD7018701,0x4AD6BFB8,0xF26AD8DD,0xE0DF7733,0x58631056, - 0x5019579F,0xE8A530FA,0xFA109F14,0x42ACF871,0xDF7BC0C8,0x67C7A7AD,0x75720843,0xCDCE6F26, - 0x95AD7F70,0x2D111815,0x3FA4B7FB,0x8718D09E,0x1ACFE827,0xA2738F42,0xB0C620AC,0x087A47C9, - 0xA032AF3E,0x188EC85B,0x0A3B67B5,0xB28700D0,0x2F503869,0x97EC5F0C,0x8559F0E2,0x3DE59787, - 0x658687D1,0xDD3AE0B4,0xCF8F4F5A,0x7733283F,0xEAE41086,0x525877E3,0x40EDD80D,0xF851BF68, - 0xF02BF8A1,0x48979FC4,0x5A22302A,0xE29E574F,0x7F496FF6,0xC7F50893,0xD540A77D,0x6DFCC018, - 0x359FD04E,0x8D23B72B,0x9F9618C5,0x272A7FA0,0xBAFD4719,0x0241207C,0x10F48F92,0xA848E8F7, - 0x9B14583D,0x23A83F58,0x311D90B6,0x89A1F7D3,0x1476CF6A,0xACCAA80F,0xBE7F07E1,0x06C36084, - 0x5EA070D2,0xE61C17B7,0xF4A9B859,0x4C15DF3C,0xD1C2E785,0x697E80E0,0x7BCB2F0E,0xC377486B, - 0xCB0D0FA2,0x73B168C7,0x6104C729,0xD9B8A04C,0x446F98F5,0xFCD3FF90,0xEE66507E,0x56DA371B, - 0x0EB9274D,0xB6054028,0xA4B0EFC6,0x1C0C88A3,0x81DBB01A,0x3967D77F,0x2BD27891,0x936E1FF4, - 0x3B26F703,0x839A9066,0x912F3F88,0x299358ED,0xB4446054,0x0CF80731,0x1E4DA8DF,0xA6F1CFBA, - 0xFE92DFEC,0x462EB889,0x549B1767,0xEC277002,0x71F048BB,0xC94C2FDE,0xDBF98030,0x6345E755, - 0x6B3FA09C,0xD383C7F9,0xC1366817,0x798A0F72,0xE45D37CB,0x5CE150AE,0x4E54FF40,0xF6E89825, - 0xAE8B8873,0x1637EF16,0x048240F8,0xBC3E279D,0x21E91F24,0x99557841,0x8BE0D7AF,0x335CB0CA, - 0xED59B63B,0x55E5D15E,0x47507EB0,0xFFEC19D5,0x623B216C,0xDA874609,0xC832E9E7,0x708E8E82, - 0x28ED9ED4,0x9051F9B1,0x82E4565F,0x3A58313A,0xA78F0983,0x1F336EE6,0x0D86C108,0xB53AA66D, - 0xBD40E1A4,0x05FC86C1,0x1749292F,0xAFF54E4A,0x322276F3,0x8A9E1196,0x982BBE78,0x2097D91D, - 0x78F4C94B,0xC048AE2E,0xD2FD01C0,0x6A4166A5,0xF7965E1C,0x4F2A3979,0x5D9F9697,0xE523F1F2, - 0x4D6B1905,0xF5D77E60,0xE762D18E,0x5FDEB6EB,0xC2098E52,0x7AB5E937,0x680046D9,0xD0BC21BC, - 0x88DF31EA,0x3063568F,0x22D6F961,0x9A6A9E04,0x07BDA6BD,0xBF01C1D8,0xADB46E36,0x15080953, - 0x1D724E9A,0xA5CE29FF,0xB77B8611,0x0FC7E174,0x9210D9CD,0x2AACBEA8,0x38191146,0x80A57623, - 0xD8C66675,0x607A0110,0x72CFAEFE,0xCA73C99B,0x57A4F122,0xEF189647,0xFDAD39A9,0x45115ECC, - 0x764DEE06,0xCEF18963,0xDC44268D,0x64F841E8,0xF92F7951,0x41931E34,0x5326B1DA,0xEB9AD6BF, - 0xB3F9C6E9,0x0B45A18C,0x19F00E62,0xA14C6907,0x3C9B51BE,0x842736DB,0x96929935,0x2E2EFE50, - 0x2654B999,0x9EE8DEFC,0x8C5D7112,0x34E11677,0xA9362ECE,0x118A49AB,0x033FE645,0xBB838120, - 0xE3E09176,0x5B5CF613,0x49E959FD,0xF1553E98,0x6C820621,0xD43E6144,0xC68BCEAA,0x7E37A9CF, - 0xD67F4138,0x6EC3265D,0x7C7689B3,0xC4CAEED6,0x591DD66F,0xE1A1B10A,0xF3141EE4,0x4BA87981, - 0x13CB69D7,0xAB770EB2,0xB9C2A15C,0x017EC639,0x9CA9FE80,0x241599E5,0x36A0360B,0x8E1C516E, - 0x866616A7,0x3EDA71C2,0x2C6FDE2C,0x94D3B949,0x090481F0,0xB1B8E695,0xA30D497B,0x1BB12E1E, - 0x43D23E48,0xFB6E592D,0xE9DBF6C3,0x516791A6,0xCCB0A91F,0x740CCE7A,0x66B96194,0xDE0506F1, - } - ,{ - 0x00000000,0x3D6029B0,0x7AC05360,0x47A07AD0,0xF580A6C0,0xC8E08F70,0x8F40F5A0,0xB220DC10, - 0x30704BC1,0x0D106271,0x4AB018A1,0x77D03111,0xC5F0ED01,0xF890C4B1,0xBF30BE61,0x825097D1, - 0x60E09782,0x5D80BE32,0x1A20C4E2,0x2740ED52,0x95603142,0xA80018F2,0xEFA06222,0xD2C04B92, - 0x5090DC43,0x6DF0F5F3,0x2A508F23,0x1730A693,0xA5107A83,0x98705333,0xDFD029E3,0xE2B00053, - 0xC1C12F04,0xFCA106B4,0xBB017C64,0x866155D4,0x344189C4,0x0921A074,0x4E81DAA4,0x73E1F314, - 0xF1B164C5,0xCCD14D75,0x8B7137A5,0xB6111E15,0x0431C205,0x3951EBB5,0x7EF19165,0x4391B8D5, - 0xA121B886,0x9C419136,0xDBE1EBE6,0xE681C256,0x54A11E46,0x69C137F6,0x2E614D26,0x13016496, - 0x9151F347,0xAC31DAF7,0xEB91A027,0xD6F18997,0x64D15587,0x59B17C37,0x1E1106E7,0x23712F57, - 0x58F35849,0x659371F9,0x22330B29,0x1F532299,0xAD73FE89,0x9013D739,0xD7B3ADE9,0xEAD38459, - 0x68831388,0x55E33A38,0x124340E8,0x2F236958,0x9D03B548,0xA0639CF8,0xE7C3E628,0xDAA3CF98, - 0x3813CFCB,0x0573E67B,0x42D39CAB,0x7FB3B51B,0xCD93690B,0xF0F340BB,0xB7533A6B,0x8A3313DB, - 0x0863840A,0x3503ADBA,0x72A3D76A,0x4FC3FEDA,0xFDE322CA,0xC0830B7A,0x872371AA,0xBA43581A, - 0x9932774D,0xA4525EFD,0xE3F2242D,0xDE920D9D,0x6CB2D18D,0x51D2F83D,0x167282ED,0x2B12AB5D, - 0xA9423C8C,0x9422153C,0xD3826FEC,0xEEE2465C,0x5CC29A4C,0x61A2B3FC,0x2602C92C,0x1B62E09C, - 0xF9D2E0CF,0xC4B2C97F,0x8312B3AF,0xBE729A1F,0x0C52460F,0x31326FBF,0x7692156F,0x4BF23CDF, - 0xC9A2AB0E,0xF4C282BE,0xB362F86E,0x8E02D1DE,0x3C220DCE,0x0142247E,0x46E25EAE,0x7B82771E, - 0xB1E6B092,0x8C869922,0xCB26E3F2,0xF646CA42,0x44661652,0x79063FE2,0x3EA64532,0x03C66C82, - 0x8196FB53,0xBCF6D2E3,0xFB56A833,0xC6368183,0x74165D93,0x49767423,0x0ED60EF3,0x33B62743, - 0xD1062710,0xEC660EA0,0xABC67470,0x96A65DC0,0x248681D0,0x19E6A860,0x5E46D2B0,0x6326FB00, - 0xE1766CD1,0xDC164561,0x9BB63FB1,0xA6D61601,0x14F6CA11,0x2996E3A1,0x6E369971,0x5356B0C1, - 0x70279F96,0x4D47B626,0x0AE7CCF6,0x3787E546,0x85A73956,0xB8C710E6,0xFF676A36,0xC2074386, - 0x4057D457,0x7D37FDE7,0x3A978737,0x07F7AE87,0xB5D77297,0x88B75B27,0xCF1721F7,0xF2770847, - 0x10C70814,0x2DA721A4,0x6A075B74,0x576772C4,0xE547AED4,0xD8278764,0x9F87FDB4,0xA2E7D404, - 0x20B743D5,0x1DD76A65,0x5A7710B5,0x67173905,0xD537E515,0xE857CCA5,0xAFF7B675,0x92979FC5, - 0xE915E8DB,0xD475C16B,0x93D5BBBB,0xAEB5920B,0x1C954E1B,0x21F567AB,0x66551D7B,0x5B3534CB, - 0xD965A31A,0xE4058AAA,0xA3A5F07A,0x9EC5D9CA,0x2CE505DA,0x11852C6A,0x562556BA,0x6B457F0A, - 0x89F57F59,0xB49556E9,0xF3352C39,0xCE550589,0x7C75D999,0x4115F029,0x06B58AF9,0x3BD5A349, - 0xB9853498,0x84E51D28,0xC34567F8,0xFE254E48,0x4C059258,0x7165BBE8,0x36C5C138,0x0BA5E888, - 0x28D4C7DF,0x15B4EE6F,0x521494BF,0x6F74BD0F,0xDD54611F,0xE03448AF,0xA794327F,0x9AF41BCF, - 0x18A48C1E,0x25C4A5AE,0x6264DF7E,0x5F04F6CE,0xED242ADE,0xD044036E,0x97E479BE,0xAA84500E, - 0x4834505D,0x755479ED,0x32F4033D,0x0F942A8D,0xBDB4F69D,0x80D4DF2D,0xC774A5FD,0xFA148C4D, - 0x78441B9C,0x4524322C,0x028448FC,0x3FE4614C,0x8DC4BD5C,0xB0A494EC,0xF704EE3C,0xCA64C78C, - }, + { + 0x00000000, 0xB8BC6765, 0xAA09C88B, 0x12B5AFEE, 0x8F629757, 0x37DEF032, 0x256B5FDC, 0x9DD738B9, + 0xC5B428EF, 0x7D084F8A, 0x6FBDE064, 0xD7018701, 0x4AD6BFB8, 0xF26AD8DD, 0xE0DF7733, 0x58631056, + 0x5019579F, 0xE8A530FA, 0xFA109F14, 0x42ACF871, 0xDF7BC0C8, 0x67C7A7AD, 0x75720843, 0xCDCE6F26, + 0x95AD7F70, 0x2D111815, 0x3FA4B7FB, 0x8718D09E, 0x1ACFE827, 0xA2738F42, 0xB0C620AC, 0x087A47C9, + 0xA032AF3E, 0x188EC85B, 0x0A3B67B5, 0xB28700D0, 0x2F503869, 0x97EC5F0C, 0x8559F0E2, 0x3DE59787, + 0x658687D1, 0xDD3AE0B4, 0xCF8F4F5A, 0x7733283F, 0xEAE41086, 0x525877E3, 0x40EDD80D, 0xF851BF68, + 0xF02BF8A1, 0x48979FC4, 0x5A22302A, 0xE29E574F, 0x7F496FF6, 0xC7F50893, 0xD540A77D, 0x6DFCC018, + 0x359FD04E, 0x8D23B72B, 0x9F9618C5, 0x272A7FA0, 0xBAFD4719, 0x0241207C, 0x10F48F92, 0xA848E8F7, + 0x9B14583D, 0x23A83F58, 0x311D90B6, 0x89A1F7D3, 0x1476CF6A, 0xACCAA80F, 0xBE7F07E1, 0x06C36084, + 0x5EA070D2, 0xE61C17B7, 0xF4A9B859, 0x4C15DF3C, 0xD1C2E785, 0x697E80E0, 0x7BCB2F0E, 0xC377486B, + 0xCB0D0FA2, 0x73B168C7, 0x6104C729, 0xD9B8A04C, 0x446F98F5, 0xFCD3FF90, 0xEE66507E, 0x56DA371B, + 0x0EB9274D, 0xB6054028, 0xA4B0EFC6, 0x1C0C88A3, 0x81DBB01A, 0x3967D77F, 0x2BD27891, 0x936E1FF4, + 0x3B26F703, 0x839A9066, 0x912F3F88, 0x299358ED, 0xB4446054, 0x0CF80731, 0x1E4DA8DF, 0xA6F1CFBA, + 0xFE92DFEC, 0x462EB889, 0x549B1767, 0xEC277002, 0x71F048BB, 0xC94C2FDE, 0xDBF98030, 0x6345E755, + 0x6B3FA09C, 0xD383C7F9, 0xC1366817, 0x798A0F72, 0xE45D37CB, 0x5CE150AE, 0x4E54FF40, 0xF6E89825, + 0xAE8B8873, 0x1637EF16, 0x048240F8, 0xBC3E279D, 0x21E91F24, 0x99557841, 0x8BE0D7AF, 0x335CB0CA, + 0xED59B63B, 0x55E5D15E, 0x47507EB0, 0xFFEC19D5, 0x623B216C, 0xDA874609, 0xC832E9E7, 0x708E8E82, + 0x28ED9ED4, 0x9051F9B1, 0x82E4565F, 0x3A58313A, 0xA78F0983, 0x1F336EE6, 0x0D86C108, 0xB53AA66D, + 0xBD40E1A4, 0x05FC86C1, 0x1749292F, 0xAFF54E4A, 0x322276F3, 0x8A9E1196, 0x982BBE78, 0x2097D91D, + 0x78F4C94B, 0xC048AE2E, 0xD2FD01C0, 0x6A4166A5, 0xF7965E1C, 0x4F2A3979, 0x5D9F9697, 0xE523F1F2, + 0x4D6B1905, 0xF5D77E60, 0xE762D18E, 0x5FDEB6EB, 0xC2098E52, 0x7AB5E937, 0x680046D9, 0xD0BC21BC, + 0x88DF31EA, 0x3063568F, 0x22D6F961, 0x9A6A9E04, 0x07BDA6BD, 0xBF01C1D8, 0xADB46E36, 0x15080953, + 0x1D724E9A, 0xA5CE29FF, 0xB77B8611, 0x0FC7E174, 0x9210D9CD, 0x2AACBEA8, 0x38191146, 0x80A57623, + 0xD8C66675, 0x607A0110, 0x72CFAEFE, 0xCA73C99B, 0x57A4F122, 0xEF189647, 0xFDAD39A9, 0x45115ECC, + 0x764DEE06, 0xCEF18963, 0xDC44268D, 0x64F841E8, 0xF92F7951, 0x41931E34, 0x5326B1DA, 0xEB9AD6BF, + 0xB3F9C6E9, 0x0B45A18C, 0x19F00E62, 0xA14C6907, 0x3C9B51BE, 0x842736DB, 0x96929935, 0x2E2EFE50, + 0x2654B999, 0x9EE8DEFC, 0x8C5D7112, 0x34E11677, 0xA9362ECE, 0x118A49AB, 0x033FE645, 0xBB838120, + 0xE3E09176, 0x5B5CF613, 0x49E959FD, 0xF1553E98, 0x6C820621, 0xD43E6144, 0xC68BCEAA, 0x7E37A9CF, + 0xD67F4138, 0x6EC3265D, 0x7C7689B3, 0xC4CAEED6, 0x591DD66F, 0xE1A1B10A, 0xF3141EE4, 0x4BA87981, + 0x13CB69D7, 0xAB770EB2, 0xB9C2A15C, 0x017EC639, 0x9CA9FE80, 0x241599E5, 0x36A0360B, 0x8E1C516E, + 0x866616A7, 0x3EDA71C2, 0x2C6FDE2C, 0x94D3B949, 0x090481F0, 0xB1B8E695, 0xA30D497B, 0x1BB12E1E, + 0x43D23E48, 0xFB6E592D, 0xE9DBF6C3, 0x516791A6, 0xCCB0A91F, 0x740CCE7A, 0x66B96194, 0xDE0506F1, + }, + { + 0x00000000, 0x3D6029B0, 0x7AC05360, 0x47A07AD0, 0xF580A6C0, 0xC8E08F70, 0x8F40F5A0, 0xB220DC10, + 0x30704BC1, 0x0D106271, 0x4AB018A1, 0x77D03111, 0xC5F0ED01, 0xF890C4B1, 0xBF30BE61, 0x825097D1, + 0x60E09782, 0x5D80BE32, 0x1A20C4E2, 0x2740ED52, 0x95603142, 0xA80018F2, 0xEFA06222, 0xD2C04B92, + 0x5090DC43, 0x6DF0F5F3, 0x2A508F23, 0x1730A693, 0xA5107A83, 0x98705333, 0xDFD029E3, 0xE2B00053, + 0xC1C12F04, 0xFCA106B4, 0xBB017C64, 0x866155D4, 0x344189C4, 0x0921A074, 0x4E81DAA4, 0x73E1F314, + 0xF1B164C5, 0xCCD14D75, 0x8B7137A5, 0xB6111E15, 0x0431C205, 0x3951EBB5, 0x7EF19165, 0x4391B8D5, + 0xA121B886, 0x9C419136, 0xDBE1EBE6, 0xE681C256, 0x54A11E46, 0x69C137F6, 0x2E614D26, 0x13016496, + 0x9151F347, 0xAC31DAF7, 0xEB91A027, 0xD6F18997, 0x64D15587, 0x59B17C37, 0x1E1106E7, 0x23712F57, + 0x58F35849, 0x659371F9, 0x22330B29, 0x1F532299, 0xAD73FE89, 0x9013D739, 0xD7B3ADE9, 0xEAD38459, + 0x68831388, 0x55E33A38, 0x124340E8, 0x2F236958, 0x9D03B548, 0xA0639CF8, 0xE7C3E628, 0xDAA3CF98, + 0x3813CFCB, 0x0573E67B, 0x42D39CAB, 0x7FB3B51B, 0xCD93690B, 0xF0F340BB, 0xB7533A6B, 0x8A3313DB, + 0x0863840A, 0x3503ADBA, 0x72A3D76A, 0x4FC3FEDA, 0xFDE322CA, 0xC0830B7A, 0x872371AA, 0xBA43581A, + 0x9932774D, 0xA4525EFD, 0xE3F2242D, 0xDE920D9D, 0x6CB2D18D, 0x51D2F83D, 0x167282ED, 0x2B12AB5D, + 0xA9423C8C, 0x9422153C, 0xD3826FEC, 0xEEE2465C, 0x5CC29A4C, 0x61A2B3FC, 0x2602C92C, 0x1B62E09C, + 0xF9D2E0CF, 0xC4B2C97F, 0x8312B3AF, 0xBE729A1F, 0x0C52460F, 0x31326FBF, 0x7692156F, 0x4BF23CDF, + 0xC9A2AB0E, 0xF4C282BE, 0xB362F86E, 0x8E02D1DE, 0x3C220DCE, 0x0142247E, 0x46E25EAE, 0x7B82771E, + 0xB1E6B092, 0x8C869922, 0xCB26E3F2, 0xF646CA42, 0x44661652, 0x79063FE2, 0x3EA64532, 0x03C66C82, + 0x8196FB53, 0xBCF6D2E3, 0xFB56A833, 0xC6368183, 0x74165D93, 0x49767423, 0x0ED60EF3, 0x33B62743, + 0xD1062710, 0xEC660EA0, 0xABC67470, 0x96A65DC0, 0x248681D0, 0x19E6A860, 0x5E46D2B0, 0x6326FB00, + 0xE1766CD1, 0xDC164561, 0x9BB63FB1, 0xA6D61601, 0x14F6CA11, 0x2996E3A1, 0x6E369971, 0x5356B0C1, + 0x70279F96, 0x4D47B626, 0x0AE7CCF6, 0x3787E546, 0x85A73956, 0xB8C710E6, 0xFF676A36, 0xC2074386, + 0x4057D457, 0x7D37FDE7, 0x3A978737, 0x07F7AE87, 0xB5D77297, 0x88B75B27, 0xCF1721F7, 0xF2770847, + 0x10C70814, 0x2DA721A4, 0x6A075B74, 0x576772C4, 0xE547AED4, 0xD8278764, 0x9F87FDB4, 0xA2E7D404, + 0x20B743D5, 0x1DD76A65, 0x5A7710B5, 0x67173905, 0xD537E515, 0xE857CCA5, 0xAFF7B675, 0x92979FC5, + 0xE915E8DB, 0xD475C16B, 0x93D5BBBB, 0xAEB5920B, 0x1C954E1B, 0x21F567AB, 0x66551D7B, 0x5B3534CB, + 0xD965A31A, 0xE4058AAA, 0xA3A5F07A, 0x9EC5D9CA, 0x2CE505DA, 0x11852C6A, 0x562556BA, 0x6B457F0A, + 0x89F57F59, 0xB49556E9, 0xF3352C39, 0xCE550589, 0x7C75D999, 0x4115F029, 0x06B58AF9, 0x3BD5A349, + 0xB9853498, 0x84E51D28, 0xC34567F8, 0xFE254E48, 0x4C059258, 0x7165BBE8, 0x36C5C138, 0x0BA5E888, + 0x28D4C7DF, 0x15B4EE6F, 0x521494BF, 0x6F74BD0F, 0xDD54611F, 0xE03448AF, 0xA794327F, 0x9AF41BCF, + 0x18A48C1E, 0x25C4A5AE, 0x6264DF7E, 0x5F04F6CE, 0xED242ADE, 0xD044036E, 0x97E479BE, 0xAA84500E, + 0x4834505D, 0x755479ED, 0x32F4033D, 0x0F942A8D, 0xBDB4F69D, 0x80D4DF2D, 0xC774A5FD, 0xFA148C4D, + 0x78441B9C, 0x4524322C, 0x028448FC, 0x3FE4614C, 0x8DC4BD5C, 0xB0A494EC, 0xF704EE3C, 0xCA64C78C, + }, - { - 0x00000000,0xCB5CD3A5,0x4DC8A10B,0x869472AE,0x9B914216,0x50CD91B3,0xD659E31D,0x1D0530B8, - 0xEC53826D,0x270F51C8,0xA19B2366,0x6AC7F0C3,0x77C2C07B,0xBC9E13DE,0x3A0A6170,0xF156B2D5, - 0x03D6029B,0xC88AD13E,0x4E1EA390,0x85427035,0x9847408D,0x531B9328,0xD58FE186,0x1ED33223, - 0xEF8580F6,0x24D95353,0xA24D21FD,0x6911F258,0x7414C2E0,0xBF481145,0x39DC63EB,0xF280B04E, - 0x07AC0536,0xCCF0D693,0x4A64A43D,0x81387798,0x9C3D4720,0x57619485,0xD1F5E62B,0x1AA9358E, - 0xEBFF875B,0x20A354FE,0xA6372650,0x6D6BF5F5,0x706EC54D,0xBB3216E8,0x3DA66446,0xF6FAB7E3, - 0x047A07AD,0xCF26D408,0x49B2A6A6,0x82EE7503,0x9FEB45BB,0x54B7961E,0xD223E4B0,0x197F3715, - 0xE82985C0,0x23755665,0xA5E124CB,0x6EBDF76E,0x73B8C7D6,0xB8E41473,0x3E7066DD,0xF52CB578, - 0x0F580A6C,0xC404D9C9,0x4290AB67,0x89CC78C2,0x94C9487A,0x5F959BDF,0xD901E971,0x125D3AD4, - 0xE30B8801,0x28575BA4,0xAEC3290A,0x659FFAAF,0x789ACA17,0xB3C619B2,0x35526B1C,0xFE0EB8B9, - 0x0C8E08F7,0xC7D2DB52,0x4146A9FC,0x8A1A7A59,0x971F4AE1,0x5C439944,0xDAD7EBEA,0x118B384F, - 0xE0DD8A9A,0x2B81593F,0xAD152B91,0x6649F834,0x7B4CC88C,0xB0101B29,0x36846987,0xFDD8BA22, - 0x08F40F5A,0xC3A8DCFF,0x453CAE51,0x8E607DF4,0x93654D4C,0x58399EE9,0xDEADEC47,0x15F13FE2, - 0xE4A78D37,0x2FFB5E92,0xA96F2C3C,0x6233FF99,0x7F36CF21,0xB46A1C84,0x32FE6E2A,0xF9A2BD8F, - 0x0B220DC1,0xC07EDE64,0x46EAACCA,0x8DB67F6F,0x90B34FD7,0x5BEF9C72,0xDD7BEEDC,0x16273D79, - 0xE7718FAC,0x2C2D5C09,0xAAB92EA7,0x61E5FD02,0x7CE0CDBA,0xB7BC1E1F,0x31286CB1,0xFA74BF14, - 0x1EB014D8,0xD5ECC77D,0x5378B5D3,0x98246676,0x852156CE,0x4E7D856B,0xC8E9F7C5,0x03B52460, - 0xF2E396B5,0x39BF4510,0xBF2B37BE,0x7477E41B,0x6972D4A3,0xA22E0706,0x24BA75A8,0xEFE6A60D, - 0x1D661643,0xD63AC5E6,0x50AEB748,0x9BF264ED,0x86F75455,0x4DAB87F0,0xCB3FF55E,0x006326FB, - 0xF135942E,0x3A69478B,0xBCFD3525,0x77A1E680,0x6AA4D638,0xA1F8059D,0x276C7733,0xEC30A496, - 0x191C11EE,0xD240C24B,0x54D4B0E5,0x9F886340,0x828D53F8,0x49D1805D,0xCF45F2F3,0x04192156, - 0xF54F9383,0x3E134026,0xB8873288,0x73DBE12D,0x6EDED195,0xA5820230,0x2316709E,0xE84AA33B, - 0x1ACA1375,0xD196C0D0,0x5702B27E,0x9C5E61DB,0x815B5163,0x4A0782C6,0xCC93F068,0x07CF23CD, - 0xF6999118,0x3DC542BD,0xBB513013,0x700DE3B6,0x6D08D30E,0xA65400AB,0x20C07205,0xEB9CA1A0, - 0x11E81EB4,0xDAB4CD11,0x5C20BFBF,0x977C6C1A,0x8A795CA2,0x41258F07,0xC7B1FDA9,0x0CED2E0C, - 0xFDBB9CD9,0x36E74F7C,0xB0733DD2,0x7B2FEE77,0x662ADECF,0xAD760D6A,0x2BE27FC4,0xE0BEAC61, - 0x123E1C2F,0xD962CF8A,0x5FF6BD24,0x94AA6E81,0x89AF5E39,0x42F38D9C,0xC467FF32,0x0F3B2C97, - 0xFE6D9E42,0x35314DE7,0xB3A53F49,0x78F9ECEC,0x65FCDC54,0xAEA00FF1,0x28347D5F,0xE368AEFA, - 0x16441B82,0xDD18C827,0x5B8CBA89,0x90D0692C,0x8DD55994,0x46898A31,0xC01DF89F,0x0B412B3A, - 0xFA1799EF,0x314B4A4A,0xB7DF38E4,0x7C83EB41,0x6186DBF9,0xAADA085C,0x2C4E7AF2,0xE712A957, - 0x15921919,0xDECECABC,0x585AB812,0x93066BB7,0x8E035B0F,0x455F88AA,0xC3CBFA04,0x089729A1, - 0xF9C19B74,0x329D48D1,0xB4093A7F,0x7F55E9DA,0x6250D962,0xA90C0AC7,0x2F987869,0xE4C4ABCC, - }, + { + 0x00000000, 0xCB5CD3A5, 0x4DC8A10B, 0x869472AE, 0x9B914216, 0x50CD91B3, 0xD659E31D, 0x1D0530B8, + 0xEC53826D, 0x270F51C8, 0xA19B2366, 0x6AC7F0C3, 0x77C2C07B, 0xBC9E13DE, 0x3A0A6170, 0xF156B2D5, + 0x03D6029B, 0xC88AD13E, 0x4E1EA390, 0x85427035, 0x9847408D, 0x531B9328, 0xD58FE186, 0x1ED33223, + 0xEF8580F6, 0x24D95353, 0xA24D21FD, 0x6911F258, 0x7414C2E0, 0xBF481145, 0x39DC63EB, 0xF280B04E, + 0x07AC0536, 0xCCF0D693, 0x4A64A43D, 0x81387798, 0x9C3D4720, 0x57619485, 0xD1F5E62B, 0x1AA9358E, + 0xEBFF875B, 0x20A354FE, 0xA6372650, 0x6D6BF5F5, 0x706EC54D, 0xBB3216E8, 0x3DA66446, 0xF6FAB7E3, + 0x047A07AD, 0xCF26D408, 0x49B2A6A6, 0x82EE7503, 0x9FEB45BB, 0x54B7961E, 0xD223E4B0, 0x197F3715, + 0xE82985C0, 0x23755665, 0xA5E124CB, 0x6EBDF76E, 0x73B8C7D6, 0xB8E41473, 0x3E7066DD, 0xF52CB578, + 0x0F580A6C, 0xC404D9C9, 0x4290AB67, 0x89CC78C2, 0x94C9487A, 0x5F959BDF, 0xD901E971, 0x125D3AD4, + 0xE30B8801, 0x28575BA4, 0xAEC3290A, 0x659FFAAF, 0x789ACA17, 0xB3C619B2, 0x35526B1C, 0xFE0EB8B9, + 0x0C8E08F7, 0xC7D2DB52, 0x4146A9FC, 0x8A1A7A59, 0x971F4AE1, 0x5C439944, 0xDAD7EBEA, 0x118B384F, + 0xE0DD8A9A, 0x2B81593F, 0xAD152B91, 0x6649F834, 0x7B4CC88C, 0xB0101B29, 0x36846987, 0xFDD8BA22, + 0x08F40F5A, 0xC3A8DCFF, 0x453CAE51, 0x8E607DF4, 0x93654D4C, 0x58399EE9, 0xDEADEC47, 0x15F13FE2, + 0xE4A78D37, 0x2FFB5E92, 0xA96F2C3C, 0x6233FF99, 0x7F36CF21, 0xB46A1C84, 0x32FE6E2A, 0xF9A2BD8F, + 0x0B220DC1, 0xC07EDE64, 0x46EAACCA, 0x8DB67F6F, 0x90B34FD7, 0x5BEF9C72, 0xDD7BEEDC, 0x16273D79, + 0xE7718FAC, 0x2C2D5C09, 0xAAB92EA7, 0x61E5FD02, 0x7CE0CDBA, 0xB7BC1E1F, 0x31286CB1, 0xFA74BF14, + 0x1EB014D8, 0xD5ECC77D, 0x5378B5D3, 0x98246676, 0x852156CE, 0x4E7D856B, 0xC8E9F7C5, 0x03B52460, + 0xF2E396B5, 0x39BF4510, 0xBF2B37BE, 0x7477E41B, 0x6972D4A3, 0xA22E0706, 0x24BA75A8, 0xEFE6A60D, + 0x1D661643, 0xD63AC5E6, 0x50AEB748, 0x9BF264ED, 0x86F75455, 0x4DAB87F0, 0xCB3FF55E, 0x006326FB, + 0xF135942E, 0x3A69478B, 0xBCFD3525, 0x77A1E680, 0x6AA4D638, 0xA1F8059D, 0x276C7733, 0xEC30A496, + 0x191C11EE, 0xD240C24B, 0x54D4B0E5, 0x9F886340, 0x828D53F8, 0x49D1805D, 0xCF45F2F3, 0x04192156, + 0xF54F9383, 0x3E134026, 0xB8873288, 0x73DBE12D, 0x6EDED195, 0xA5820230, 0x2316709E, 0xE84AA33B, + 0x1ACA1375, 0xD196C0D0, 0x5702B27E, 0x9C5E61DB, 0x815B5163, 0x4A0782C6, 0xCC93F068, 0x07CF23CD, + 0xF6999118, 0x3DC542BD, 0xBB513013, 0x700DE3B6, 0x6D08D30E, 0xA65400AB, 0x20C07205, 0xEB9CA1A0, + 0x11E81EB4, 0xDAB4CD11, 0x5C20BFBF, 0x977C6C1A, 0x8A795CA2, 0x41258F07, 0xC7B1FDA9, 0x0CED2E0C, + 0xFDBB9CD9, 0x36E74F7C, 0xB0733DD2, 0x7B2FEE77, 0x662ADECF, 0xAD760D6A, 0x2BE27FC4, 0xE0BEAC61, + 0x123E1C2F, 0xD962CF8A, 0x5FF6BD24, 0x94AA6E81, 0x89AF5E39, 0x42F38D9C, 0xC467FF32, 0x0F3B2C97, + 0xFE6D9E42, 0x35314DE7, 0xB3A53F49, 0x78F9ECEC, 0x65FCDC54, 0xAEA00FF1, 0x28347D5F, 0xE368AEFA, + 0x16441B82, 0xDD18C827, 0x5B8CBA89, 0x90D0692C, 0x8DD55994, 0x46898A31, 0xC01DF89F, 0x0B412B3A, + 0xFA1799EF, 0x314B4A4A, 0xB7DF38E4, 0x7C83EB41, 0x6186DBF9, 0xAADA085C, 0x2C4E7AF2, 0xE712A957, + 0x15921919, 0xDECECABC, 0x585AB812, 0x93066BB7, 0x8E035B0F, 0x455F88AA, 0xC3CBFA04, 0x089729A1, + 0xF9C19B74, 0x329D48D1, 0xB4093A7F, 0x7F55E9DA, 0x6250D962, 0xA90C0AC7, 0x2F987869, 0xE4C4ABCC, + }, - { - 0x00000000,0xA6770BB4,0x979F1129,0x31E81A9D,0xF44F2413,0x52382FA7,0x63D0353A,0xC5A73E8E, - 0x33EF4E67,0x959845D3,0xA4705F4E,0x020754FA,0xC7A06A74,0x61D761C0,0x503F7B5D,0xF64870E9, - 0x67DE9CCE,0xC1A9977A,0xF0418DE7,0x56368653,0x9391B8DD,0x35E6B369,0x040EA9F4,0xA279A240, - 0x5431D2A9,0xF246D91D,0xC3AEC380,0x65D9C834,0xA07EF6BA,0x0609FD0E,0x37E1E793,0x9196EC27, - 0xCFBD399C,0x69CA3228,0x582228B5,0xFE552301,0x3BF21D8F,0x9D85163B,0xAC6D0CA6,0x0A1A0712, - 0xFC5277FB,0x5A257C4F,0x6BCD66D2,0xCDBA6D66,0x081D53E8,0xAE6A585C,0x9F8242C1,0x39F54975, - 0xA863A552,0x0E14AEE6,0x3FFCB47B,0x998BBFCF,0x5C2C8141,0xFA5B8AF5,0xCBB39068,0x6DC49BDC, - 0x9B8CEB35,0x3DFBE081,0x0C13FA1C,0xAA64F1A8,0x6FC3CF26,0xC9B4C492,0xF85CDE0F,0x5E2BD5BB, - 0x440B7579,0xE27C7ECD,0xD3946450,0x75E36FE4,0xB044516A,0x16335ADE,0x27DB4043,0x81AC4BF7, - 0x77E43B1E,0xD19330AA,0xE07B2A37,0x460C2183,0x83AB1F0D,0x25DC14B9,0x14340E24,0xB2430590, - 0x23D5E9B7,0x85A2E203,0xB44AF89E,0x123DF32A,0xD79ACDA4,0x71EDC610,0x4005DC8D,0xE672D739, - 0x103AA7D0,0xB64DAC64,0x87A5B6F9,0x21D2BD4D,0xE47583C3,0x42028877,0x73EA92EA,0xD59D995E, - 0x8BB64CE5,0x2DC14751,0x1C295DCC,0xBA5E5678,0x7FF968F6,0xD98E6342,0xE86679DF,0x4E11726B, - 0xB8590282,0x1E2E0936,0x2FC613AB,0x89B1181F,0x4C162691,0xEA612D25,0xDB8937B8,0x7DFE3C0C, - 0xEC68D02B,0x4A1FDB9F,0x7BF7C102,0xDD80CAB6,0x1827F438,0xBE50FF8C,0x8FB8E511,0x29CFEEA5, - 0xDF879E4C,0x79F095F8,0x48188F65,0xEE6F84D1,0x2BC8BA5F,0x8DBFB1EB,0xBC57AB76,0x1A20A0C2, - 0x8816EAF2,0x2E61E146,0x1F89FBDB,0xB9FEF06F,0x7C59CEE1,0xDA2EC555,0xEBC6DFC8,0x4DB1D47C, - 0xBBF9A495,0x1D8EAF21,0x2C66B5BC,0x8A11BE08,0x4FB68086,0xE9C18B32,0xD82991AF,0x7E5E9A1B, - 0xEFC8763C,0x49BF7D88,0x78576715,0xDE206CA1,0x1B87522F,0xBDF0599B,0x8C184306,0x2A6F48B2, - 0xDC27385B,0x7A5033EF,0x4BB82972,0xEDCF22C6,0x28681C48,0x8E1F17FC,0xBFF70D61,0x198006D5, - 0x47ABD36E,0xE1DCD8DA,0xD034C247,0x7643C9F3,0xB3E4F77D,0x1593FCC9,0x247BE654,0x820CEDE0, - 0x74449D09,0xD23396BD,0xE3DB8C20,0x45AC8794,0x800BB91A,0x267CB2AE,0x1794A833,0xB1E3A387, - 0x20754FA0,0x86024414,0xB7EA5E89,0x119D553D,0xD43A6BB3,0x724D6007,0x43A57A9A,0xE5D2712E, - 0x139A01C7,0xB5ED0A73,0x840510EE,0x22721B5A,0xE7D525D4,0x41A22E60,0x704A34FD,0xD63D3F49, - 0xCC1D9F8B,0x6A6A943F,0x5B828EA2,0xFDF58516,0x3852BB98,0x9E25B02C,0xAFCDAAB1,0x09BAA105, - 0xFFF2D1EC,0x5985DA58,0x686DC0C5,0xCE1ACB71,0x0BBDF5FF,0xADCAFE4B,0x9C22E4D6,0x3A55EF62, - 0xABC30345,0x0DB408F1,0x3C5C126C,0x9A2B19D8,0x5F8C2756,0xF9FB2CE2,0xC813367F,0x6E643DCB, - 0x982C4D22,0x3E5B4696,0x0FB35C0B,0xA9C457BF,0x6C636931,0xCA146285,0xFBFC7818,0x5D8B73AC, - 0x03A0A617,0xA5D7ADA3,0x943FB73E,0x3248BC8A,0xF7EF8204,0x519889B0,0x6070932D,0xC6079899, - 0x304FE870,0x9638E3C4,0xA7D0F959,0x01A7F2ED,0xC400CC63,0x6277C7D7,0x539FDD4A,0xF5E8D6FE, - 0x647E3AD9,0xC209316D,0xF3E12BF0,0x55962044,0x90311ECA,0x3646157E,0x07AE0FE3,0xA1D90457, - 0x579174BE,0xF1E67F0A,0xC00E6597,0x66796E23,0xA3DE50AD,0x05A95B19,0x34414184,0x92364A30, - }, + { + 0x00000000, 0xA6770BB4, 0x979F1129, 0x31E81A9D, 0xF44F2413, 0x52382FA7, 0x63D0353A, 0xC5A73E8E, + 0x33EF4E67, 0x959845D3, 0xA4705F4E, 0x020754FA, 0xC7A06A74, 0x61D761C0, 0x503F7B5D, 0xF64870E9, + 0x67DE9CCE, 0xC1A9977A, 0xF0418DE7, 0x56368653, 0x9391B8DD, 0x35E6B369, 0x040EA9F4, 0xA279A240, + 0x5431D2A9, 0xF246D91D, 0xC3AEC380, 0x65D9C834, 0xA07EF6BA, 0x0609FD0E, 0x37E1E793, 0x9196EC27, + 0xCFBD399C, 0x69CA3228, 0x582228B5, 0xFE552301, 0x3BF21D8F, 0x9D85163B, 0xAC6D0CA6, 0x0A1A0712, + 0xFC5277FB, 0x5A257C4F, 0x6BCD66D2, 0xCDBA6D66, 0x081D53E8, 0xAE6A585C, 0x9F8242C1, 0x39F54975, + 0xA863A552, 0x0E14AEE6, 0x3FFCB47B, 0x998BBFCF, 0x5C2C8141, 0xFA5B8AF5, 0xCBB39068, 0x6DC49BDC, + 0x9B8CEB35, 0x3DFBE081, 0x0C13FA1C, 0xAA64F1A8, 0x6FC3CF26, 0xC9B4C492, 0xF85CDE0F, 0x5E2BD5BB, + 0x440B7579, 0xE27C7ECD, 0xD3946450, 0x75E36FE4, 0xB044516A, 0x16335ADE, 0x27DB4043, 0x81AC4BF7, + 0x77E43B1E, 0xD19330AA, 0xE07B2A37, 0x460C2183, 0x83AB1F0D, 0x25DC14B9, 0x14340E24, 0xB2430590, + 0x23D5E9B7, 0x85A2E203, 0xB44AF89E, 0x123DF32A, 0xD79ACDA4, 0x71EDC610, 0x4005DC8D, 0xE672D739, + 0x103AA7D0, 0xB64DAC64, 0x87A5B6F9, 0x21D2BD4D, 0xE47583C3, 0x42028877, 0x73EA92EA, 0xD59D995E, + 0x8BB64CE5, 0x2DC14751, 0x1C295DCC, 0xBA5E5678, 0x7FF968F6, 0xD98E6342, 0xE86679DF, 0x4E11726B, + 0xB8590282, 0x1E2E0936, 0x2FC613AB, 0x89B1181F, 0x4C162691, 0xEA612D25, 0xDB8937B8, 0x7DFE3C0C, + 0xEC68D02B, 0x4A1FDB9F, 0x7BF7C102, 0xDD80CAB6, 0x1827F438, 0xBE50FF8C, 0x8FB8E511, 0x29CFEEA5, + 0xDF879E4C, 0x79F095F8, 0x48188F65, 0xEE6F84D1, 0x2BC8BA5F, 0x8DBFB1EB, 0xBC57AB76, 0x1A20A0C2, + 0x8816EAF2, 0x2E61E146, 0x1F89FBDB, 0xB9FEF06F, 0x7C59CEE1, 0xDA2EC555, 0xEBC6DFC8, 0x4DB1D47C, + 0xBBF9A495, 0x1D8EAF21, 0x2C66B5BC, 0x8A11BE08, 0x4FB68086, 0xE9C18B32, 0xD82991AF, 0x7E5E9A1B, + 0xEFC8763C, 0x49BF7D88, 0x78576715, 0xDE206CA1, 0x1B87522F, 0xBDF0599B, 0x8C184306, 0x2A6F48B2, + 0xDC27385B, 0x7A5033EF, 0x4BB82972, 0xEDCF22C6, 0x28681C48, 0x8E1F17FC, 0xBFF70D61, 0x198006D5, + 0x47ABD36E, 0xE1DCD8DA, 0xD034C247, 0x7643C9F3, 0xB3E4F77D, 0x1593FCC9, 0x247BE654, 0x820CEDE0, + 0x74449D09, 0xD23396BD, 0xE3DB8C20, 0x45AC8794, 0x800BB91A, 0x267CB2AE, 0x1794A833, 0xB1E3A387, + 0x20754FA0, 0x86024414, 0xB7EA5E89, 0x119D553D, 0xD43A6BB3, 0x724D6007, 0x43A57A9A, 0xE5D2712E, + 0x139A01C7, 0xB5ED0A73, 0x840510EE, 0x22721B5A, 0xE7D525D4, 0x41A22E60, 0x704A34FD, 0xD63D3F49, + 0xCC1D9F8B, 0x6A6A943F, 0x5B828EA2, 0xFDF58516, 0x3852BB98, 0x9E25B02C, 0xAFCDAAB1, 0x09BAA105, + 0xFFF2D1EC, 0x5985DA58, 0x686DC0C5, 0xCE1ACB71, 0x0BBDF5FF, 0xADCAFE4B, 0x9C22E4D6, 0x3A55EF62, + 0xABC30345, 0x0DB408F1, 0x3C5C126C, 0x9A2B19D8, 0x5F8C2756, 0xF9FB2CE2, 0xC813367F, 0x6E643DCB, + 0x982C4D22, 0x3E5B4696, 0x0FB35C0B, 0xA9C457BF, 0x6C636931, 0xCA146285, 0xFBFC7818, 0x5D8B73AC, + 0x03A0A617, 0xA5D7ADA3, 0x943FB73E, 0x3248BC8A, 0xF7EF8204, 0x519889B0, 0x6070932D, 0xC6079899, + 0x304FE870, 0x9638E3C4, 0xA7D0F959, 0x01A7F2ED, 0xC400CC63, 0x6277C7D7, 0x539FDD4A, 0xF5E8D6FE, + 0x647E3AD9, 0xC209316D, 0xF3E12BF0, 0x55962044, 0x90311ECA, 0x3646157E, 0x07AE0FE3, 0xA1D90457, + 0x579174BE, 0xF1E67F0A, 0xC00E6597, 0x66796E23, 0xA3DE50AD, 0x05A95B19, 0x34414184, 0x92364A30, + }, - { - 0x00000000,0xCCAA009E,0x4225077D,0x8E8F07E3,0x844A0EFA,0x48E00E64,0xC66F0987,0x0AC50919, - 0xD3E51BB5,0x1F4F1B2B,0x91C01CC8,0x5D6A1C56,0x57AF154F,0x9B0515D1,0x158A1232,0xD92012AC, - 0x7CBB312B,0xB01131B5,0x3E9E3656,0xF23436C8,0xF8F13FD1,0x345B3F4F,0xBAD438AC,0x767E3832, - 0xAF5E2A9E,0x63F42A00,0xED7B2DE3,0x21D12D7D,0x2B142464,0xE7BE24FA,0x69312319,0xA59B2387, - 0xF9766256,0x35DC62C8,0xBB53652B,0x77F965B5,0x7D3C6CAC,0xB1966C32,0x3F196BD1,0xF3B36B4F, - 0x2A9379E3,0xE639797D,0x68B67E9E,0xA41C7E00,0xAED97719,0x62737787,0xECFC7064,0x205670FA, - 0x85CD537D,0x496753E3,0xC7E85400,0x0B42549E,0x01875D87,0xCD2D5D19,0x43A25AFA,0x8F085A64, - 0x562848C8,0x9A824856,0x140D4FB5,0xD8A74F2B,0xD2624632,0x1EC846AC,0x9047414F,0x5CED41D1, - 0x299DC2ED,0xE537C273,0x6BB8C590,0xA712C50E,0xADD7CC17,0x617DCC89,0xEFF2CB6A,0x2358CBF4, - 0xFA78D958,0x36D2D9C6,0xB85DDE25,0x74F7DEBB,0x7E32D7A2,0xB298D73C,0x3C17D0DF,0xF0BDD041, - 0x5526F3C6,0x998CF358,0x1703F4BB,0xDBA9F425,0xD16CFD3C,0x1DC6FDA2,0x9349FA41,0x5FE3FADF, - 0x86C3E873,0x4A69E8ED,0xC4E6EF0E,0x084CEF90,0x0289E689,0xCE23E617,0x40ACE1F4,0x8C06E16A, - 0xD0EBA0BB,0x1C41A025,0x92CEA7C6,0x5E64A758,0x54A1AE41,0x980BAEDF,0x1684A93C,0xDA2EA9A2, - 0x030EBB0E,0xCFA4BB90,0x412BBC73,0x8D81BCED,0x8744B5F4,0x4BEEB56A,0xC561B289,0x09CBB217, - 0xAC509190,0x60FA910E,0xEE7596ED,0x22DF9673,0x281A9F6A,0xE4B09FF4,0x6A3F9817,0xA6959889, - 0x7FB58A25,0xB31F8ABB,0x3D908D58,0xF13A8DC6,0xFBFF84DF,0x37558441,0xB9DA83A2,0x7570833C, - 0x533B85DA,0x9F918544,0x111E82A7,0xDDB48239,0xD7718B20,0x1BDB8BBE,0x95548C5D,0x59FE8CC3, - 0x80DE9E6F,0x4C749EF1,0xC2FB9912,0x0E51998C,0x04949095,0xC83E900B,0x46B197E8,0x8A1B9776, - 0x2F80B4F1,0xE32AB46F,0x6DA5B38C,0xA10FB312,0xABCABA0B,0x6760BA95,0xE9EFBD76,0x2545BDE8, - 0xFC65AF44,0x30CFAFDA,0xBE40A839,0x72EAA8A7,0x782FA1BE,0xB485A120,0x3A0AA6C3,0xF6A0A65D, - 0xAA4DE78C,0x66E7E712,0xE868E0F1,0x24C2E06F,0x2E07E976,0xE2ADE9E8,0x6C22EE0B,0xA088EE95, - 0x79A8FC39,0xB502FCA7,0x3B8DFB44,0xF727FBDA,0xFDE2F2C3,0x3148F25D,0xBFC7F5BE,0x736DF520, - 0xD6F6D6A7,0x1A5CD639,0x94D3D1DA,0x5879D144,0x52BCD85D,0x9E16D8C3,0x1099DF20,0xDC33DFBE, - 0x0513CD12,0xC9B9CD8C,0x4736CA6F,0x8B9CCAF1,0x8159C3E8,0x4DF3C376,0xC37CC495,0x0FD6C40B, - 0x7AA64737,0xB60C47A9,0x3883404A,0xF42940D4,0xFEEC49CD,0x32464953,0xBCC94EB0,0x70634E2E, - 0xA9435C82,0x65E95C1C,0xEB665BFF,0x27CC5B61,0x2D095278,0xE1A352E6,0x6F2C5505,0xA386559B, - 0x061D761C,0xCAB77682,0x44387161,0x889271FF,0x825778E6,0x4EFD7878,0xC0727F9B,0x0CD87F05, - 0xD5F86DA9,0x19526D37,0x97DD6AD4,0x5B776A4A,0x51B26353,0x9D1863CD,0x1397642E,0xDF3D64B0, - 0x83D02561,0x4F7A25FF,0xC1F5221C,0x0D5F2282,0x079A2B9B,0xCB302B05,0x45BF2CE6,0x89152C78, - 0x50353ED4,0x9C9F3E4A,0x121039A9,0xDEBA3937,0xD47F302E,0x18D530B0,0x965A3753,0x5AF037CD, - 0xFF6B144A,0x33C114D4,0xBD4E1337,0x71E413A9,0x7B211AB0,0xB78B1A2E,0x39041DCD,0xF5AE1D53, - 0x2C8E0FFF,0xE0240F61,0x6EAB0882,0xA201081C,0xA8C40105,0x646E019B,0xEAE10678,0x264B06E6, - } - ,{ - 0x00000000,0x177B1443,0x2EF62886,0x398D3CC5,0x5DEC510C,0x4A97454F,0x731A798A,0x64616DC9, - 0xBBD8A218,0xACA3B65B,0x952E8A9E,0x82559EDD,0xE634F314,0xF14FE757,0xC8C2DB92,0xDFB9CFD1, - 0xACC04271,0xBBBB5632,0x82366AF7,0x954D7EB4,0xF12C137D,0xE657073E,0xDFDA3BFB,0xC8A12FB8, - 0x1718E069,0x0063F42A,0x39EEC8EF,0x2E95DCAC,0x4AF4B165,0x5D8FA526,0x640299E3,0x73798DA0, - 0x82F182A3,0x958A96E0,0xAC07AA25,0xBB7CBE66,0xDF1DD3AF,0xC866C7EC,0xF1EBFB29,0xE690EF6A, - 0x392920BB,0x2E5234F8,0x17DF083D,0x00A41C7E,0x64C571B7,0x73BE65F4,0x4A335931,0x5D484D72, - 0x2E31C0D2,0x394AD491,0x00C7E854,0x17BCFC17,0x73DD91DE,0x64A6859D,0x5D2BB958,0x4A50AD1B, - 0x95E962CA,0x82927689,0xBB1F4A4C,0xAC645E0F,0xC80533C6,0xDF7E2785,0xE6F31B40,0xF1880F03, - 0xDE920307,0xC9E91744,0xF0642B81,0xE71F3FC2,0x837E520B,0x94054648,0xAD887A8D,0xBAF36ECE, - 0x654AA11F,0x7231B55C,0x4BBC8999,0x5CC79DDA,0x38A6F013,0x2FDDE450,0x1650D895,0x012BCCD6, - 0x72524176,0x65295535,0x5CA469F0,0x4BDF7DB3,0x2FBE107A,0x38C50439,0x014838FC,0x16332CBF, - 0xC98AE36E,0xDEF1F72D,0xE77CCBE8,0xF007DFAB,0x9466B262,0x831DA621,0xBA909AE4,0xADEB8EA7, - 0x5C6381A4,0x4B1895E7,0x7295A922,0x65EEBD61,0x018FD0A8,0x16F4C4EB,0x2F79F82E,0x3802EC6D, - 0xE7BB23BC,0xF0C037FF,0xC94D0B3A,0xDE361F79,0xBA5772B0,0xAD2C66F3,0x94A15A36,0x83DA4E75, - 0xF0A3C3D5,0xE7D8D796,0xDE55EB53,0xC92EFF10,0xAD4F92D9,0xBA34869A,0x83B9BA5F,0x94C2AE1C, - 0x4B7B61CD,0x5C00758E,0x658D494B,0x72F65D08,0x169730C1,0x01EC2482,0x38611847,0x2F1A0C04, - 0x6655004F,0x712E140C,0x48A328C9,0x5FD83C8A,0x3BB95143,0x2CC24500,0x154F79C5,0x02346D86, - 0xDD8DA257,0xCAF6B614,0xF37B8AD1,0xE4009E92,0x8061F35B,0x971AE718,0xAE97DBDD,0xB9ECCF9E, - 0xCA95423E,0xDDEE567D,0xE4636AB8,0xF3187EFB,0x97791332,0x80020771,0xB98F3BB4,0xAEF42FF7, - 0x714DE026,0x6636F465,0x5FBBC8A0,0x48C0DCE3,0x2CA1B12A,0x3BDAA569,0x025799AC,0x152C8DEF, - 0xE4A482EC,0xF3DF96AF,0xCA52AA6A,0xDD29BE29,0xB948D3E0,0xAE33C7A3,0x97BEFB66,0x80C5EF25, - 0x5F7C20F4,0x480734B7,0x718A0872,0x66F11C31,0x029071F8,0x15EB65BB,0x2C66597E,0x3B1D4D3D, - 0x4864C09D,0x5F1FD4DE,0x6692E81B,0x71E9FC58,0x15889191,0x02F385D2,0x3B7EB917,0x2C05AD54, - 0xF3BC6285,0xE4C776C6,0xDD4A4A03,0xCA315E40,0xAE503389,0xB92B27CA,0x80A61B0F,0x97DD0F4C, - 0xB8C70348,0xAFBC170B,0x96312BCE,0x814A3F8D,0xE52B5244,0xF2504607,0xCBDD7AC2,0xDCA66E81, - 0x031FA150,0x1464B513,0x2DE989D6,0x3A929D95,0x5EF3F05C,0x4988E41F,0x7005D8DA,0x677ECC99, - 0x14074139,0x037C557A,0x3AF169BF,0x2D8A7DFC,0x49EB1035,0x5E900476,0x671D38B3,0x70662CF0, - 0xAFDFE321,0xB8A4F762,0x8129CBA7,0x9652DFE4,0xF233B22D,0xE548A66E,0xDCC59AAB,0xCBBE8EE8, - 0x3A3681EB,0x2D4D95A8,0x14C0A96D,0x03BBBD2E,0x67DAD0E7,0x70A1C4A4,0x492CF861,0x5E57EC22, - 0x81EE23F3,0x969537B0,0xAF180B75,0xB8631F36,0xDC0272FF,0xCB7966BC,0xF2F45A79,0xE58F4E3A, - 0x96F6C39A,0x818DD7D9,0xB800EB1C,0xAF7BFF5F,0xCB1A9296,0xDC6186D5,0xE5ECBA10,0xF297AE53, - 0x2D2E6182,0x3A5575C1,0x03D84904,0x14A35D47,0x70C2308E,0x67B924CD,0x5E341808,0x494F0C4B, - }, + { + 0x00000000, 0xCCAA009E, 0x4225077D, 0x8E8F07E3, 0x844A0EFA, 0x48E00E64, 0xC66F0987, 0x0AC50919, + 0xD3E51BB5, 0x1F4F1B2B, 0x91C01CC8, 0x5D6A1C56, 0x57AF154F, 0x9B0515D1, 0x158A1232, 0xD92012AC, + 0x7CBB312B, 0xB01131B5, 0x3E9E3656, 0xF23436C8, 0xF8F13FD1, 0x345B3F4F, 0xBAD438AC, 0x767E3832, + 0xAF5E2A9E, 0x63F42A00, 0xED7B2DE3, 0x21D12D7D, 0x2B142464, 0xE7BE24FA, 0x69312319, 0xA59B2387, + 0xF9766256, 0x35DC62C8, 0xBB53652B, 0x77F965B5, 0x7D3C6CAC, 0xB1966C32, 0x3F196BD1, 0xF3B36B4F, + 0x2A9379E3, 0xE639797D, 0x68B67E9E, 0xA41C7E00, 0xAED97719, 0x62737787, 0xECFC7064, 0x205670FA, + 0x85CD537D, 0x496753E3, 0xC7E85400, 0x0B42549E, 0x01875D87, 0xCD2D5D19, 0x43A25AFA, 0x8F085A64, + 0x562848C8, 0x9A824856, 0x140D4FB5, 0xD8A74F2B, 0xD2624632, 0x1EC846AC, 0x9047414F, 0x5CED41D1, + 0x299DC2ED, 0xE537C273, 0x6BB8C590, 0xA712C50E, 0xADD7CC17, 0x617DCC89, 0xEFF2CB6A, 0x2358CBF4, + 0xFA78D958, 0x36D2D9C6, 0xB85DDE25, 0x74F7DEBB, 0x7E32D7A2, 0xB298D73C, 0x3C17D0DF, 0xF0BDD041, + 0x5526F3C6, 0x998CF358, 0x1703F4BB, 0xDBA9F425, 0xD16CFD3C, 0x1DC6FDA2, 0x9349FA41, 0x5FE3FADF, + 0x86C3E873, 0x4A69E8ED, 0xC4E6EF0E, 0x084CEF90, 0x0289E689, 0xCE23E617, 0x40ACE1F4, 0x8C06E16A, + 0xD0EBA0BB, 0x1C41A025, 0x92CEA7C6, 0x5E64A758, 0x54A1AE41, 0x980BAEDF, 0x1684A93C, 0xDA2EA9A2, + 0x030EBB0E, 0xCFA4BB90, 0x412BBC73, 0x8D81BCED, 0x8744B5F4, 0x4BEEB56A, 0xC561B289, 0x09CBB217, + 0xAC509190, 0x60FA910E, 0xEE7596ED, 0x22DF9673, 0x281A9F6A, 0xE4B09FF4, 0x6A3F9817, 0xA6959889, + 0x7FB58A25, 0xB31F8ABB, 0x3D908D58, 0xF13A8DC6, 0xFBFF84DF, 0x37558441, 0xB9DA83A2, 0x7570833C, + 0x533B85DA, 0x9F918544, 0x111E82A7, 0xDDB48239, 0xD7718B20, 0x1BDB8BBE, 0x95548C5D, 0x59FE8CC3, + 0x80DE9E6F, 0x4C749EF1, 0xC2FB9912, 0x0E51998C, 0x04949095, 0xC83E900B, 0x46B197E8, 0x8A1B9776, + 0x2F80B4F1, 0xE32AB46F, 0x6DA5B38C, 0xA10FB312, 0xABCABA0B, 0x6760BA95, 0xE9EFBD76, 0x2545BDE8, + 0xFC65AF44, 0x30CFAFDA, 0xBE40A839, 0x72EAA8A7, 0x782FA1BE, 0xB485A120, 0x3A0AA6C3, 0xF6A0A65D, + 0xAA4DE78C, 0x66E7E712, 0xE868E0F1, 0x24C2E06F, 0x2E07E976, 0xE2ADE9E8, 0x6C22EE0B, 0xA088EE95, + 0x79A8FC39, 0xB502FCA7, 0x3B8DFB44, 0xF727FBDA, 0xFDE2F2C3, 0x3148F25D, 0xBFC7F5BE, 0x736DF520, + 0xD6F6D6A7, 0x1A5CD639, 0x94D3D1DA, 0x5879D144, 0x52BCD85D, 0x9E16D8C3, 0x1099DF20, 0xDC33DFBE, + 0x0513CD12, 0xC9B9CD8C, 0x4736CA6F, 0x8B9CCAF1, 0x8159C3E8, 0x4DF3C376, 0xC37CC495, 0x0FD6C40B, + 0x7AA64737, 0xB60C47A9, 0x3883404A, 0xF42940D4, 0xFEEC49CD, 0x32464953, 0xBCC94EB0, 0x70634E2E, + 0xA9435C82, 0x65E95C1C, 0xEB665BFF, 0x27CC5B61, 0x2D095278, 0xE1A352E6, 0x6F2C5505, 0xA386559B, + 0x061D761C, 0xCAB77682, 0x44387161, 0x889271FF, 0x825778E6, 0x4EFD7878, 0xC0727F9B, 0x0CD87F05, + 0xD5F86DA9, 0x19526D37, 0x97DD6AD4, 0x5B776A4A, 0x51B26353, 0x9D1863CD, 0x1397642E, 0xDF3D64B0, + 0x83D02561, 0x4F7A25FF, 0xC1F5221C, 0x0D5F2282, 0x079A2B9B, 0xCB302B05, 0x45BF2CE6, 0x89152C78, + 0x50353ED4, 0x9C9F3E4A, 0x121039A9, 0xDEBA3937, 0xD47F302E, 0x18D530B0, 0x965A3753, 0x5AF037CD, + 0xFF6B144A, 0x33C114D4, 0xBD4E1337, 0x71E413A9, 0x7B211AB0, 0xB78B1A2E, 0x39041DCD, 0xF5AE1D53, + 0x2C8E0FFF, 0xE0240F61, 0x6EAB0882, 0xA201081C, 0xA8C40105, 0x646E019B, 0xEAE10678, 0x264B06E6, + }, + { + 0x00000000, 0x177B1443, 0x2EF62886, 0x398D3CC5, 0x5DEC510C, 0x4A97454F, 0x731A798A, 0x64616DC9, + 0xBBD8A218, 0xACA3B65B, 0x952E8A9E, 0x82559EDD, 0xE634F314, 0xF14FE757, 0xC8C2DB92, 0xDFB9CFD1, + 0xACC04271, 0xBBBB5632, 0x82366AF7, 0x954D7EB4, 0xF12C137D, 0xE657073E, 0xDFDA3BFB, 0xC8A12FB8, + 0x1718E069, 0x0063F42A, 0x39EEC8EF, 0x2E95DCAC, 0x4AF4B165, 0x5D8FA526, 0x640299E3, 0x73798DA0, + 0x82F182A3, 0x958A96E0, 0xAC07AA25, 0xBB7CBE66, 0xDF1DD3AF, 0xC866C7EC, 0xF1EBFB29, 0xE690EF6A, + 0x392920BB, 0x2E5234F8, 0x17DF083D, 0x00A41C7E, 0x64C571B7, 0x73BE65F4, 0x4A335931, 0x5D484D72, + 0x2E31C0D2, 0x394AD491, 0x00C7E854, 0x17BCFC17, 0x73DD91DE, 0x64A6859D, 0x5D2BB958, 0x4A50AD1B, + 0x95E962CA, 0x82927689, 0xBB1F4A4C, 0xAC645E0F, 0xC80533C6, 0xDF7E2785, 0xE6F31B40, 0xF1880F03, + 0xDE920307, 0xC9E91744, 0xF0642B81, 0xE71F3FC2, 0x837E520B, 0x94054648, 0xAD887A8D, 0xBAF36ECE, + 0x654AA11F, 0x7231B55C, 0x4BBC8999, 0x5CC79DDA, 0x38A6F013, 0x2FDDE450, 0x1650D895, 0x012BCCD6, + 0x72524176, 0x65295535, 0x5CA469F0, 0x4BDF7DB3, 0x2FBE107A, 0x38C50439, 0x014838FC, 0x16332CBF, + 0xC98AE36E, 0xDEF1F72D, 0xE77CCBE8, 0xF007DFAB, 0x9466B262, 0x831DA621, 0xBA909AE4, 0xADEB8EA7, + 0x5C6381A4, 0x4B1895E7, 0x7295A922, 0x65EEBD61, 0x018FD0A8, 0x16F4C4EB, 0x2F79F82E, 0x3802EC6D, + 0xE7BB23BC, 0xF0C037FF, 0xC94D0B3A, 0xDE361F79, 0xBA5772B0, 0xAD2C66F3, 0x94A15A36, 0x83DA4E75, + 0xF0A3C3D5, 0xE7D8D796, 0xDE55EB53, 0xC92EFF10, 0xAD4F92D9, 0xBA34869A, 0x83B9BA5F, 0x94C2AE1C, + 0x4B7B61CD, 0x5C00758E, 0x658D494B, 0x72F65D08, 0x169730C1, 0x01EC2482, 0x38611847, 0x2F1A0C04, + 0x6655004F, 0x712E140C, 0x48A328C9, 0x5FD83C8A, 0x3BB95143, 0x2CC24500, 0x154F79C5, 0x02346D86, + 0xDD8DA257, 0xCAF6B614, 0xF37B8AD1, 0xE4009E92, 0x8061F35B, 0x971AE718, 0xAE97DBDD, 0xB9ECCF9E, + 0xCA95423E, 0xDDEE567D, 0xE4636AB8, 0xF3187EFB, 0x97791332, 0x80020771, 0xB98F3BB4, 0xAEF42FF7, + 0x714DE026, 0x6636F465, 0x5FBBC8A0, 0x48C0DCE3, 0x2CA1B12A, 0x3BDAA569, 0x025799AC, 0x152C8DEF, + 0xE4A482EC, 0xF3DF96AF, 0xCA52AA6A, 0xDD29BE29, 0xB948D3E0, 0xAE33C7A3, 0x97BEFB66, 0x80C5EF25, + 0x5F7C20F4, 0x480734B7, 0x718A0872, 0x66F11C31, 0x029071F8, 0x15EB65BB, 0x2C66597E, 0x3B1D4D3D, + 0x4864C09D, 0x5F1FD4DE, 0x6692E81B, 0x71E9FC58, 0x15889191, 0x02F385D2, 0x3B7EB917, 0x2C05AD54, + 0xF3BC6285, 0xE4C776C6, 0xDD4A4A03, 0xCA315E40, 0xAE503389, 0xB92B27CA, 0x80A61B0F, 0x97DD0F4C, + 0xB8C70348, 0xAFBC170B, 0x96312BCE, 0x814A3F8D, 0xE52B5244, 0xF2504607, 0xCBDD7AC2, 0xDCA66E81, + 0x031FA150, 0x1464B513, 0x2DE989D6, 0x3A929D95, 0x5EF3F05C, 0x4988E41F, 0x7005D8DA, 0x677ECC99, + 0x14074139, 0x037C557A, 0x3AF169BF, 0x2D8A7DFC, 0x49EB1035, 0x5E900476, 0x671D38B3, 0x70662CF0, + 0xAFDFE321, 0xB8A4F762, 0x8129CBA7, 0x9652DFE4, 0xF233B22D, 0xE548A66E, 0xDCC59AAB, 0xCBBE8EE8, + 0x3A3681EB, 0x2D4D95A8, 0x14C0A96D, 0x03BBBD2E, 0x67DAD0E7, 0x70A1C4A4, 0x492CF861, 0x5E57EC22, + 0x81EE23F3, 0x969537B0, 0xAF180B75, 0xB8631F36, 0xDC0272FF, 0xCB7966BC, 0xF2F45A79, 0xE58F4E3A, + 0x96F6C39A, 0x818DD7D9, 0xB800EB1C, 0xAF7BFF5F, 0xCB1A9296, 0xDC6186D5, 0xE5ECBA10, 0xF297AE53, + 0x2D2E6182, 0x3A5575C1, 0x03D84904, 0x14A35D47, 0x70C2308E, 0x67B924CD, 0x5E341808, 0x494F0C4B, + }, - { - 0x00000000,0xEFC26B3E,0x04F5D03D,0xEB37BB03,0x09EBA07A,0xE629CB44,0x0D1E7047,0xE2DC1B79, - 0x13D740F4,0xFC152BCA,0x172290C9,0xF8E0FBF7,0x1A3CE08E,0xF5FE8BB0,0x1EC930B3,0xF10B5B8D, - 0x27AE81E8,0xC86CEAD6,0x235B51D5,0xCC993AEB,0x2E452192,0xC1874AAC,0x2AB0F1AF,0xC5729A91, - 0x3479C11C,0xDBBBAA22,0x308C1121,0xDF4E7A1F,0x3D926166,0xD2500A58,0x3967B15B,0xD6A5DA65, - 0x4F5D03D0,0xA09F68EE,0x4BA8D3ED,0xA46AB8D3,0x46B6A3AA,0xA974C894,0x42437397,0xAD8118A9, - 0x5C8A4324,0xB348281A,0x587F9319,0xB7BDF827,0x5561E35E,0xBAA38860,0x51943363,0xBE56585D, - 0x68F38238,0x8731E906,0x6C065205,0x83C4393B,0x61182242,0x8EDA497C,0x65EDF27F,0x8A2F9941, - 0x7B24C2CC,0x94E6A9F2,0x7FD112F1,0x901379CF,0x72CF62B6,0x9D0D0988,0x763AB28B,0x99F8D9B5, - 0x9EBA07A0,0x71786C9E,0x9A4FD79D,0x758DBCA3,0x9751A7DA,0x7893CCE4,0x93A477E7,0x7C661CD9, - 0x8D6D4754,0x62AF2C6A,0x89989769,0x665AFC57,0x8486E72E,0x6B448C10,0x80733713,0x6FB15C2D, - 0xB9148648,0x56D6ED76,0xBDE15675,0x52233D4B,0xB0FF2632,0x5F3D4D0C,0xB40AF60F,0x5BC89D31, - 0xAAC3C6BC,0x4501AD82,0xAE361681,0x41F47DBF,0xA32866C6,0x4CEA0DF8,0xA7DDB6FB,0x481FDDC5, - 0xD1E70470,0x3E256F4E,0xD512D44D,0x3AD0BF73,0xD80CA40A,0x37CECF34,0xDCF97437,0x333B1F09, - 0xC2304484,0x2DF22FBA,0xC6C594B9,0x2907FF87,0xCBDBE4FE,0x24198FC0,0xCF2E34C3,0x20EC5FFD, - 0xF6498598,0x198BEEA6,0xF2BC55A5,0x1D7E3E9B,0xFFA225E2,0x10604EDC,0xFB57F5DF,0x14959EE1, - 0xE59EC56C,0x0A5CAE52,0xE16B1551,0x0EA97E6F,0xEC756516,0x03B70E28,0xE880B52B,0x0742DE15, - 0xE6050901,0x09C7623F,0xE2F0D93C,0x0D32B202,0xEFEEA97B,0x002CC245,0xEB1B7946,0x04D91278, - 0xF5D249F5,0x1A1022CB,0xF12799C8,0x1EE5F2F6,0xFC39E98F,0x13FB82B1,0xF8CC39B2,0x170E528C, - 0xC1AB88E9,0x2E69E3D7,0xC55E58D4,0x2A9C33EA,0xC8402893,0x278243AD,0xCCB5F8AE,0x23779390, - 0xD27CC81D,0x3DBEA323,0xD6891820,0x394B731E,0xDB976867,0x34550359,0xDF62B85A,0x30A0D364, - 0xA9580AD1,0x469A61EF,0xADADDAEC,0x426FB1D2,0xA0B3AAAB,0x4F71C195,0xA4467A96,0x4B8411A8, - 0xBA8F4A25,0x554D211B,0xBE7A9A18,0x51B8F126,0xB364EA5F,0x5CA68161,0xB7913A62,0x5853515C, - 0x8EF68B39,0x6134E007,0x8A035B04,0x65C1303A,0x871D2B43,0x68DF407D,0x83E8FB7E,0x6C2A9040, - 0x9D21CBCD,0x72E3A0F3,0x99D41BF0,0x761670CE,0x94CA6BB7,0x7B080089,0x903FBB8A,0x7FFDD0B4, - 0x78BF0EA1,0x977D659F,0x7C4ADE9C,0x9388B5A2,0x7154AEDB,0x9E96C5E5,0x75A17EE6,0x9A6315D8, - 0x6B684E55,0x84AA256B,0x6F9D9E68,0x805FF556,0x6283EE2F,0x8D418511,0x66763E12,0x89B4552C, - 0x5F118F49,0xB0D3E477,0x5BE45F74,0xB426344A,0x56FA2F33,0xB938440D,0x520FFF0E,0xBDCD9430, - 0x4CC6CFBD,0xA304A483,0x48331F80,0xA7F174BE,0x452D6FC7,0xAAEF04F9,0x41D8BFFA,0xAE1AD4C4, - 0x37E20D71,0xD820664F,0x3317DD4C,0xDCD5B672,0x3E09AD0B,0xD1CBC635,0x3AFC7D36,0xD53E1608, - 0x24354D85,0xCBF726BB,0x20C09DB8,0xCF02F686,0x2DDEEDFF,0xC21C86C1,0x292B3DC2,0xC6E956FC, - 0x104C8C99,0xFF8EE7A7,0x14B95CA4,0xFB7B379A,0x19A72CE3,0xF66547DD,0x1D52FCDE,0xF29097E0, - 0x039BCC6D,0xEC59A753,0x076E1C50,0xE8AC776E,0x0A706C17,0xE5B20729,0x0E85BC2A,0xE147D714, - }, + { + 0x00000000, 0xEFC26B3E, 0x04F5D03D, 0xEB37BB03, 0x09EBA07A, 0xE629CB44, 0x0D1E7047, 0xE2DC1B79, + 0x13D740F4, 0xFC152BCA, 0x172290C9, 0xF8E0FBF7, 0x1A3CE08E, 0xF5FE8BB0, 0x1EC930B3, 0xF10B5B8D, + 0x27AE81E8, 0xC86CEAD6, 0x235B51D5, 0xCC993AEB, 0x2E452192, 0xC1874AAC, 0x2AB0F1AF, 0xC5729A91, + 0x3479C11C, 0xDBBBAA22, 0x308C1121, 0xDF4E7A1F, 0x3D926166, 0xD2500A58, 0x3967B15B, 0xD6A5DA65, + 0x4F5D03D0, 0xA09F68EE, 0x4BA8D3ED, 0xA46AB8D3, 0x46B6A3AA, 0xA974C894, 0x42437397, 0xAD8118A9, + 0x5C8A4324, 0xB348281A, 0x587F9319, 0xB7BDF827, 0x5561E35E, 0xBAA38860, 0x51943363, 0xBE56585D, + 0x68F38238, 0x8731E906, 0x6C065205, 0x83C4393B, 0x61182242, 0x8EDA497C, 0x65EDF27F, 0x8A2F9941, + 0x7B24C2CC, 0x94E6A9F2, 0x7FD112F1, 0x901379CF, 0x72CF62B6, 0x9D0D0988, 0x763AB28B, 0x99F8D9B5, + 0x9EBA07A0, 0x71786C9E, 0x9A4FD79D, 0x758DBCA3, 0x9751A7DA, 0x7893CCE4, 0x93A477E7, 0x7C661CD9, + 0x8D6D4754, 0x62AF2C6A, 0x89989769, 0x665AFC57, 0x8486E72E, 0x6B448C10, 0x80733713, 0x6FB15C2D, + 0xB9148648, 0x56D6ED76, 0xBDE15675, 0x52233D4B, 0xB0FF2632, 0x5F3D4D0C, 0xB40AF60F, 0x5BC89D31, + 0xAAC3C6BC, 0x4501AD82, 0xAE361681, 0x41F47DBF, 0xA32866C6, 0x4CEA0DF8, 0xA7DDB6FB, 0x481FDDC5, + 0xD1E70470, 0x3E256F4E, 0xD512D44D, 0x3AD0BF73, 0xD80CA40A, 0x37CECF34, 0xDCF97437, 0x333B1F09, + 0xC2304484, 0x2DF22FBA, 0xC6C594B9, 0x2907FF87, 0xCBDBE4FE, 0x24198FC0, 0xCF2E34C3, 0x20EC5FFD, + 0xF6498598, 0x198BEEA6, 0xF2BC55A5, 0x1D7E3E9B, 0xFFA225E2, 0x10604EDC, 0xFB57F5DF, 0x14959EE1, + 0xE59EC56C, 0x0A5CAE52, 0xE16B1551, 0x0EA97E6F, 0xEC756516, 0x03B70E28, 0xE880B52B, 0x0742DE15, + 0xE6050901, 0x09C7623F, 0xE2F0D93C, 0x0D32B202, 0xEFEEA97B, 0x002CC245, 0xEB1B7946, 0x04D91278, + 0xF5D249F5, 0x1A1022CB, 0xF12799C8, 0x1EE5F2F6, 0xFC39E98F, 0x13FB82B1, 0xF8CC39B2, 0x170E528C, + 0xC1AB88E9, 0x2E69E3D7, 0xC55E58D4, 0x2A9C33EA, 0xC8402893, 0x278243AD, 0xCCB5F8AE, 0x23779390, + 0xD27CC81D, 0x3DBEA323, 0xD6891820, 0x394B731E, 0xDB976867, 0x34550359, 0xDF62B85A, 0x30A0D364, + 0xA9580AD1, 0x469A61EF, 0xADADDAEC, 0x426FB1D2, 0xA0B3AAAB, 0x4F71C195, 0xA4467A96, 0x4B8411A8, + 0xBA8F4A25, 0x554D211B, 0xBE7A9A18, 0x51B8F126, 0xB364EA5F, 0x5CA68161, 0xB7913A62, 0x5853515C, + 0x8EF68B39, 0x6134E007, 0x8A035B04, 0x65C1303A, 0x871D2B43, 0x68DF407D, 0x83E8FB7E, 0x6C2A9040, + 0x9D21CBCD, 0x72E3A0F3, 0x99D41BF0, 0x761670CE, 0x94CA6BB7, 0x7B080089, 0x903FBB8A, 0x7FFDD0B4, + 0x78BF0EA1, 0x977D659F, 0x7C4ADE9C, 0x9388B5A2, 0x7154AEDB, 0x9E96C5E5, 0x75A17EE6, 0x9A6315D8, + 0x6B684E55, 0x84AA256B, 0x6F9D9E68, 0x805FF556, 0x6283EE2F, 0x8D418511, 0x66763E12, 0x89B4552C, + 0x5F118F49, 0xB0D3E477, 0x5BE45F74, 0xB426344A, 0x56FA2F33, 0xB938440D, 0x520FFF0E, 0xBDCD9430, + 0x4CC6CFBD, 0xA304A483, 0x48331F80, 0xA7F174BE, 0x452D6FC7, 0xAAEF04F9, 0x41D8BFFA, 0xAE1AD4C4, + 0x37E20D71, 0xD820664F, 0x3317DD4C, 0xDCD5B672, 0x3E09AD0B, 0xD1CBC635, 0x3AFC7D36, 0xD53E1608, + 0x24354D85, 0xCBF726BB, 0x20C09DB8, 0xCF02F686, 0x2DDEEDFF, 0xC21C86C1, 0x292B3DC2, 0xC6E956FC, + 0x104C8C99, 0xFF8EE7A7, 0x14B95CA4, 0xFB7B379A, 0x19A72CE3, 0xF66547DD, 0x1D52FCDE, 0xF29097E0, + 0x039BCC6D, 0xEC59A753, 0x076E1C50, 0xE8AC776E, 0x0A706C17, 0xE5B20729, 0x0E85BC2A, 0xE147D714, + }, - { - 0x00000000,0xC18EDFC0,0x586CB9C1,0x99E26601,0xB0D97382,0x7157AC42,0xE8B5CA43,0x293B1583, - 0xBAC3E145,0x7B4D3E85,0xE2AF5884,0x23218744,0x0A1A92C7,0xCB944D07,0x52762B06,0x93F8F4C6, - 0xAEF6C4CB,0x6F781B0B,0xF69A7D0A,0x3714A2CA,0x1E2FB749,0xDFA16889,0x46430E88,0x87CDD148, - 0x1435258E,0xD5BBFA4E,0x4C599C4F,0x8DD7438F,0xA4EC560C,0x656289CC,0xFC80EFCD,0x3D0E300D, - 0x869C8FD7,0x47125017,0xDEF03616,0x1F7EE9D6,0x3645FC55,0xF7CB2395,0x6E294594,0xAFA79A54, - 0x3C5F6E92,0xFDD1B152,0x6433D753,0xA5BD0893,0x8C861D10,0x4D08C2D0,0xD4EAA4D1,0x15647B11, - 0x286A4B1C,0xE9E494DC,0x7006F2DD,0xB1882D1D,0x98B3389E,0x593DE75E,0xC0DF815F,0x01515E9F, - 0x92A9AA59,0x53277599,0xCAC51398,0x0B4BCC58,0x2270D9DB,0xE3FE061B,0x7A1C601A,0xBB92BFDA, - 0xD64819EF,0x17C6C62F,0x8E24A02E,0x4FAA7FEE,0x66916A6D,0xA71FB5AD,0x3EFDD3AC,0xFF730C6C, - 0x6C8BF8AA,0xAD05276A,0x34E7416B,0xF5699EAB,0xDC528B28,0x1DDC54E8,0x843E32E9,0x45B0ED29, - 0x78BEDD24,0xB93002E4,0x20D264E5,0xE15CBB25,0xC867AEA6,0x09E97166,0x900B1767,0x5185C8A7, - 0xC27D3C61,0x03F3E3A1,0x9A1185A0,0x5B9F5A60,0x72A44FE3,0xB32A9023,0x2AC8F622,0xEB4629E2, - 0x50D49638,0x915A49F8,0x08B82FF9,0xC936F039,0xE00DE5BA,0x21833A7A,0xB8615C7B,0x79EF83BB, - 0xEA17777D,0x2B99A8BD,0xB27BCEBC,0x73F5117C,0x5ACE04FF,0x9B40DB3F,0x02A2BD3E,0xC32C62FE, - 0xFE2252F3,0x3FAC8D33,0xA64EEB32,0x67C034F2,0x4EFB2171,0x8F75FEB1,0x169798B0,0xD7194770, - 0x44E1B3B6,0x856F6C76,0x1C8D0A77,0xDD03D5B7,0xF438C034,0x35B61FF4,0xAC5479F5,0x6DDAA635, - 0x77E1359F,0xB66FEA5F,0x2F8D8C5E,0xEE03539E,0xC738461D,0x06B699DD,0x9F54FFDC,0x5EDA201C, - 0xCD22D4DA,0x0CAC0B1A,0x954E6D1B,0x54C0B2DB,0x7DFBA758,0xBC757898,0x25971E99,0xE419C159, - 0xD917F154,0x18992E94,0x817B4895,0x40F59755,0x69CE82D6,0xA8405D16,0x31A23B17,0xF02CE4D7, - 0x63D41011,0xA25ACFD1,0x3BB8A9D0,0xFA367610,0xD30D6393,0x1283BC53,0x8B61DA52,0x4AEF0592, - 0xF17DBA48,0x30F36588,0xA9110389,0x689FDC49,0x41A4C9CA,0x802A160A,0x19C8700B,0xD846AFCB, - 0x4BBE5B0D,0x8A3084CD,0x13D2E2CC,0xD25C3D0C,0xFB67288F,0x3AE9F74F,0xA30B914E,0x62854E8E, - 0x5F8B7E83,0x9E05A143,0x07E7C742,0xC6691882,0xEF520D01,0x2EDCD2C1,0xB73EB4C0,0x76B06B00, - 0xE5489FC6,0x24C64006,0xBD242607,0x7CAAF9C7,0x5591EC44,0x941F3384,0x0DFD5585,0xCC738A45, - 0xA1A92C70,0x6027F3B0,0xF9C595B1,0x384B4A71,0x11705FF2,0xD0FE8032,0x491CE633,0x889239F3, - 0x1B6ACD35,0xDAE412F5,0x430674F4,0x8288AB34,0xABB3BEB7,0x6A3D6177,0xF3DF0776,0x3251D8B6, - 0x0F5FE8BB,0xCED1377B,0x5733517A,0x96BD8EBA,0xBF869B39,0x7E0844F9,0xE7EA22F8,0x2664FD38, - 0xB59C09FE,0x7412D63E,0xEDF0B03F,0x2C7E6FFF,0x05457A7C,0xC4CBA5BC,0x5D29C3BD,0x9CA71C7D, - 0x2735A3A7,0xE6BB7C67,0x7F591A66,0xBED7C5A6,0x97ECD025,0x56620FE5,0xCF8069E4,0x0E0EB624, - 0x9DF642E2,0x5C789D22,0xC59AFB23,0x041424E3,0x2D2F3160,0xECA1EEA0,0x754388A1,0xB4CD5761, - 0x89C3676C,0x484DB8AC,0xD1AFDEAD,0x1021016D,0x391A14EE,0xF894CB2E,0x6176AD2F,0xA0F872EF, - 0x33008629,0xF28E59E9,0x6B6C3FE8,0xAAE2E028,0x83D9F5AB,0x42572A6B,0xDBB54C6A,0x1A3B93AA, - }, + { + 0x00000000, 0xC18EDFC0, 0x586CB9C1, 0x99E26601, 0xB0D97382, 0x7157AC42, 0xE8B5CA43, 0x293B1583, + 0xBAC3E145, 0x7B4D3E85, 0xE2AF5884, 0x23218744, 0x0A1A92C7, 0xCB944D07, 0x52762B06, 0x93F8F4C6, + 0xAEF6C4CB, 0x6F781B0B, 0xF69A7D0A, 0x3714A2CA, 0x1E2FB749, 0xDFA16889, 0x46430E88, 0x87CDD148, + 0x1435258E, 0xD5BBFA4E, 0x4C599C4F, 0x8DD7438F, 0xA4EC560C, 0x656289CC, 0xFC80EFCD, 0x3D0E300D, + 0x869C8FD7, 0x47125017, 0xDEF03616, 0x1F7EE9D6, 0x3645FC55, 0xF7CB2395, 0x6E294594, 0xAFA79A54, + 0x3C5F6E92, 0xFDD1B152, 0x6433D753, 0xA5BD0893, 0x8C861D10, 0x4D08C2D0, 0xD4EAA4D1, 0x15647B11, + 0x286A4B1C, 0xE9E494DC, 0x7006F2DD, 0xB1882D1D, 0x98B3389E, 0x593DE75E, 0xC0DF815F, 0x01515E9F, + 0x92A9AA59, 0x53277599, 0xCAC51398, 0x0B4BCC58, 0x2270D9DB, 0xE3FE061B, 0x7A1C601A, 0xBB92BFDA, + 0xD64819EF, 0x17C6C62F, 0x8E24A02E, 0x4FAA7FEE, 0x66916A6D, 0xA71FB5AD, 0x3EFDD3AC, 0xFF730C6C, + 0x6C8BF8AA, 0xAD05276A, 0x34E7416B, 0xF5699EAB, 0xDC528B28, 0x1DDC54E8, 0x843E32E9, 0x45B0ED29, + 0x78BEDD24, 0xB93002E4, 0x20D264E5, 0xE15CBB25, 0xC867AEA6, 0x09E97166, 0x900B1767, 0x5185C8A7, + 0xC27D3C61, 0x03F3E3A1, 0x9A1185A0, 0x5B9F5A60, 0x72A44FE3, 0xB32A9023, 0x2AC8F622, 0xEB4629E2, + 0x50D49638, 0x915A49F8, 0x08B82FF9, 0xC936F039, 0xE00DE5BA, 0x21833A7A, 0xB8615C7B, 0x79EF83BB, + 0xEA17777D, 0x2B99A8BD, 0xB27BCEBC, 0x73F5117C, 0x5ACE04FF, 0x9B40DB3F, 0x02A2BD3E, 0xC32C62FE, + 0xFE2252F3, 0x3FAC8D33, 0xA64EEB32, 0x67C034F2, 0x4EFB2171, 0x8F75FEB1, 0x169798B0, 0xD7194770, + 0x44E1B3B6, 0x856F6C76, 0x1C8D0A77, 0xDD03D5B7, 0xF438C034, 0x35B61FF4, 0xAC5479F5, 0x6DDAA635, + 0x77E1359F, 0xB66FEA5F, 0x2F8D8C5E, 0xEE03539E, 0xC738461D, 0x06B699DD, 0x9F54FFDC, 0x5EDA201C, + 0xCD22D4DA, 0x0CAC0B1A, 0x954E6D1B, 0x54C0B2DB, 0x7DFBA758, 0xBC757898, 0x25971E99, 0xE419C159, + 0xD917F154, 0x18992E94, 0x817B4895, 0x40F59755, 0x69CE82D6, 0xA8405D16, 0x31A23B17, 0xF02CE4D7, + 0x63D41011, 0xA25ACFD1, 0x3BB8A9D0, 0xFA367610, 0xD30D6393, 0x1283BC53, 0x8B61DA52, 0x4AEF0592, + 0xF17DBA48, 0x30F36588, 0xA9110389, 0x689FDC49, 0x41A4C9CA, 0x802A160A, 0x19C8700B, 0xD846AFCB, + 0x4BBE5B0D, 0x8A3084CD, 0x13D2E2CC, 0xD25C3D0C, 0xFB67288F, 0x3AE9F74F, 0xA30B914E, 0x62854E8E, + 0x5F8B7E83, 0x9E05A143, 0x07E7C742, 0xC6691882, 0xEF520D01, 0x2EDCD2C1, 0xB73EB4C0, 0x76B06B00, + 0xE5489FC6, 0x24C64006, 0xBD242607, 0x7CAAF9C7, 0x5591EC44, 0x941F3384, 0x0DFD5585, 0xCC738A45, + 0xA1A92C70, 0x6027F3B0, 0xF9C595B1, 0x384B4A71, 0x11705FF2, 0xD0FE8032, 0x491CE633, 0x889239F3, + 0x1B6ACD35, 0xDAE412F5, 0x430674F4, 0x8288AB34, 0xABB3BEB7, 0x6A3D6177, 0xF3DF0776, 0x3251D8B6, + 0x0F5FE8BB, 0xCED1377B, 0x5733517A, 0x96BD8EBA, 0xBF869B39, 0x7E0844F9, 0xE7EA22F8, 0x2664FD38, + 0xB59C09FE, 0x7412D63E, 0xEDF0B03F, 0x2C7E6FFF, 0x05457A7C, 0xC4CBA5BC, 0x5D29C3BD, 0x9CA71C7D, + 0x2735A3A7, 0xE6BB7C67, 0x7F591A66, 0xBED7C5A6, 0x97ECD025, 0x56620FE5, 0xCF8069E4, 0x0E0EB624, + 0x9DF642E2, 0x5C789D22, 0xC59AFB23, 0x041424E3, 0x2D2F3160, 0xECA1EEA0, 0x754388A1, 0xB4CD5761, + 0x89C3676C, 0x484DB8AC, 0xD1AFDEAD, 0x1021016D, 0x391A14EE, 0xF894CB2E, 0x6176AD2F, 0xA0F872EF, + 0x33008629, 0xF28E59E9, 0x6B6C3FE8, 0xAAE2E028, 0x83D9F5AB, 0x42572A6B, 0xDBB54C6A, 0x1A3B93AA, + }, - { - 0x00000000,0x9BA54C6F,0xEC3B9E9F,0x779ED2F0,0x03063B7F,0x98A37710,0xEF3DA5E0,0x7498E98F, - 0x060C76FE,0x9DA93A91,0xEA37E861,0x7192A40E,0x050A4D81,0x9EAF01EE,0xE931D31E,0x72949F71, - 0x0C18EDFC,0x97BDA193,0xE0237363,0x7B863F0C,0x0F1ED683,0x94BB9AEC,0xE325481C,0x78800473, - 0x0A149B02,0x91B1D76D,0xE62F059D,0x7D8A49F2,0x0912A07D,0x92B7EC12,0xE5293EE2,0x7E8C728D, - 0x1831DBF8,0x83949797,0xF40A4567,0x6FAF0908,0x1B37E087,0x8092ACE8,0xF70C7E18,0x6CA93277, - 0x1E3DAD06,0x8598E169,0xF2063399,0x69A37FF6,0x1D3B9679,0x869EDA16,0xF10008E6,0x6AA54489, - 0x14293604,0x8F8C7A6B,0xF812A89B,0x63B7E4F4,0x172F0D7B,0x8C8A4114,0xFB1493E4,0x60B1DF8B, - 0x122540FA,0x89800C95,0xFE1EDE65,0x65BB920A,0x11237B85,0x8A8637EA,0xFD18E51A,0x66BDA975, - 0x3063B7F0,0xABC6FB9F,0xDC58296F,0x47FD6500,0x33658C8F,0xA8C0C0E0,0xDF5E1210,0x44FB5E7F, - 0x366FC10E,0xADCA8D61,0xDA545F91,0x41F113FE,0x3569FA71,0xAECCB61E,0xD95264EE,0x42F72881, - 0x3C7B5A0C,0xA7DE1663,0xD040C493,0x4BE588FC,0x3F7D6173,0xA4D82D1C,0xD346FFEC,0x48E3B383, - 0x3A772CF2,0xA1D2609D,0xD64CB26D,0x4DE9FE02,0x3971178D,0xA2D45BE2,0xD54A8912,0x4EEFC57D, - 0x28526C08,0xB3F72067,0xC469F297,0x5FCCBEF8,0x2B545777,0xB0F11B18,0xC76FC9E8,0x5CCA8587, - 0x2E5E1AF6,0xB5FB5699,0xC2658469,0x59C0C806,0x2D582189,0xB6FD6DE6,0xC163BF16,0x5AC6F379, - 0x244A81F4,0xBFEFCD9B,0xC8711F6B,0x53D45304,0x274CBA8B,0xBCE9F6E4,0xCB772414,0x50D2687B, - 0x2246F70A,0xB9E3BB65,0xCE7D6995,0x55D825FA,0x2140CC75,0xBAE5801A,0xCD7B52EA,0x56DE1E85, - 0x60C76FE0,0xFB62238F,0x8CFCF17F,0x1759BD10,0x63C1549F,0xF86418F0,0x8FFACA00,0x145F866F, - 0x66CB191E,0xFD6E5571,0x8AF08781,0x1155CBEE,0x65CD2261,0xFE686E0E,0x89F6BCFE,0x1253F091, - 0x6CDF821C,0xF77ACE73,0x80E41C83,0x1B4150EC,0x6FD9B963,0xF47CF50C,0x83E227FC,0x18476B93, - 0x6AD3F4E2,0xF176B88D,0x86E86A7D,0x1D4D2612,0x69D5CF9D,0xF27083F2,0x85EE5102,0x1E4B1D6D, - 0x78F6B418,0xE353F877,0x94CD2A87,0x0F6866E8,0x7BF08F67,0xE055C308,0x97CB11F8,0x0C6E5D97, - 0x7EFAC2E6,0xE55F8E89,0x92C15C79,0x09641016,0x7DFCF999,0xE659B5F6,0x91C76706,0x0A622B69, - 0x74EE59E4,0xEF4B158B,0x98D5C77B,0x03708B14,0x77E8629B,0xEC4D2EF4,0x9BD3FC04,0x0076B06B, - 0x72E22F1A,0xE9476375,0x9ED9B185,0x057CFDEA,0x71E41465,0xEA41580A,0x9DDF8AFA,0x067AC695, - 0x50A4D810,0xCB01947F,0xBC9F468F,0x273A0AE0,0x53A2E36F,0xC807AF00,0xBF997DF0,0x243C319F, - 0x56A8AEEE,0xCD0DE281,0xBA933071,0x21367C1E,0x55AE9591,0xCE0BD9FE,0xB9950B0E,0x22304761, - 0x5CBC35EC,0xC7197983,0xB087AB73,0x2B22E71C,0x5FBA0E93,0xC41F42FC,0xB381900C,0x2824DC63, - 0x5AB04312,0xC1150F7D,0xB68BDD8D,0x2D2E91E2,0x59B6786D,0xC2133402,0xB58DE6F2,0x2E28AA9D, - 0x489503E8,0xD3304F87,0xA4AE9D77,0x3F0BD118,0x4B933897,0xD03674F8,0xA7A8A608,0x3C0DEA67, - 0x4E997516,0xD53C3979,0xA2A2EB89,0x3907A7E6,0x4D9F4E69,0xD63A0206,0xA1A4D0F6,0x3A019C99, - 0x448DEE14,0xDF28A27B,0xA8B6708B,0x33133CE4,0x478BD56B,0xDC2E9904,0xABB04BF4,0x3015079B, - 0x428198EA,0xD924D485,0xAEBA0675,0x351F4A1A,0x4187A395,0xDA22EFFA,0xADBC3D0A,0x36197165, - }, + { + 0x00000000, 0x9BA54C6F, 0xEC3B9E9F, 0x779ED2F0, 0x03063B7F, 0x98A37710, 0xEF3DA5E0, 0x7498E98F, + 0x060C76FE, 0x9DA93A91, 0xEA37E861, 0x7192A40E, 0x050A4D81, 0x9EAF01EE, 0xE931D31E, 0x72949F71, + 0x0C18EDFC, 0x97BDA193, 0xE0237363, 0x7B863F0C, 0x0F1ED683, 0x94BB9AEC, 0xE325481C, 0x78800473, + 0x0A149B02, 0x91B1D76D, 0xE62F059D, 0x7D8A49F2, 0x0912A07D, 0x92B7EC12, 0xE5293EE2, 0x7E8C728D, + 0x1831DBF8, 0x83949797, 0xF40A4567, 0x6FAF0908, 0x1B37E087, 0x8092ACE8, 0xF70C7E18, 0x6CA93277, + 0x1E3DAD06, 0x8598E169, 0xF2063399, 0x69A37FF6, 0x1D3B9679, 0x869EDA16, 0xF10008E6, 0x6AA54489, + 0x14293604, 0x8F8C7A6B, 0xF812A89B, 0x63B7E4F4, 0x172F0D7B, 0x8C8A4114, 0xFB1493E4, 0x60B1DF8B, + 0x122540FA, 0x89800C95, 0xFE1EDE65, 0x65BB920A, 0x11237B85, 0x8A8637EA, 0xFD18E51A, 0x66BDA975, + 0x3063B7F0, 0xABC6FB9F, 0xDC58296F, 0x47FD6500, 0x33658C8F, 0xA8C0C0E0, 0xDF5E1210, 0x44FB5E7F, + 0x366FC10E, 0xADCA8D61, 0xDA545F91, 0x41F113FE, 0x3569FA71, 0xAECCB61E, 0xD95264EE, 0x42F72881, + 0x3C7B5A0C, 0xA7DE1663, 0xD040C493, 0x4BE588FC, 0x3F7D6173, 0xA4D82D1C, 0xD346FFEC, 0x48E3B383, + 0x3A772CF2, 0xA1D2609D, 0xD64CB26D, 0x4DE9FE02, 0x3971178D, 0xA2D45BE2, 0xD54A8912, 0x4EEFC57D, + 0x28526C08, 0xB3F72067, 0xC469F297, 0x5FCCBEF8, 0x2B545777, 0xB0F11B18, 0xC76FC9E8, 0x5CCA8587, + 0x2E5E1AF6, 0xB5FB5699, 0xC2658469, 0x59C0C806, 0x2D582189, 0xB6FD6DE6, 0xC163BF16, 0x5AC6F379, + 0x244A81F4, 0xBFEFCD9B, 0xC8711F6B, 0x53D45304, 0x274CBA8B, 0xBCE9F6E4, 0xCB772414, 0x50D2687B, + 0x2246F70A, 0xB9E3BB65, 0xCE7D6995, 0x55D825FA, 0x2140CC75, 0xBAE5801A, 0xCD7B52EA, 0x56DE1E85, + 0x60C76FE0, 0xFB62238F, 0x8CFCF17F, 0x1759BD10, 0x63C1549F, 0xF86418F0, 0x8FFACA00, 0x145F866F, + 0x66CB191E, 0xFD6E5571, 0x8AF08781, 0x1155CBEE, 0x65CD2261, 0xFE686E0E, 0x89F6BCFE, 0x1253F091, + 0x6CDF821C, 0xF77ACE73, 0x80E41C83, 0x1B4150EC, 0x6FD9B963, 0xF47CF50C, 0x83E227FC, 0x18476B93, + 0x6AD3F4E2, 0xF176B88D, 0x86E86A7D, 0x1D4D2612, 0x69D5CF9D, 0xF27083F2, 0x85EE5102, 0x1E4B1D6D, + 0x78F6B418, 0xE353F877, 0x94CD2A87, 0x0F6866E8, 0x7BF08F67, 0xE055C308, 0x97CB11F8, 0x0C6E5D97, + 0x7EFAC2E6, 0xE55F8E89, 0x92C15C79, 0x09641016, 0x7DFCF999, 0xE659B5F6, 0x91C76706, 0x0A622B69, + 0x74EE59E4, 0xEF4B158B, 0x98D5C77B, 0x03708B14, 0x77E8629B, 0xEC4D2EF4, 0x9BD3FC04, 0x0076B06B, + 0x72E22F1A, 0xE9476375, 0x9ED9B185, 0x057CFDEA, 0x71E41465, 0xEA41580A, 0x9DDF8AFA, 0x067AC695, + 0x50A4D810, 0xCB01947F, 0xBC9F468F, 0x273A0AE0, 0x53A2E36F, 0xC807AF00, 0xBF997DF0, 0x243C319F, + 0x56A8AEEE, 0xCD0DE281, 0xBA933071, 0x21367C1E, 0x55AE9591, 0xCE0BD9FE, 0xB9950B0E, 0x22304761, + 0x5CBC35EC, 0xC7197983, 0xB087AB73, 0x2B22E71C, 0x5FBA0E93, 0xC41F42FC, 0xB381900C, 0x2824DC63, + 0x5AB04312, 0xC1150F7D, 0xB68BDD8D, 0x2D2E91E2, 0x59B6786D, 0xC2133402, 0xB58DE6F2, 0x2E28AA9D, + 0x489503E8, 0xD3304F87, 0xA4AE9D77, 0x3F0BD118, 0x4B933897, 0xD03674F8, 0xA7A8A608, 0x3C0DEA67, + 0x4E997516, 0xD53C3979, 0xA2A2EB89, 0x3907A7E6, 0x4D9F4E69, 0xD63A0206, 0xA1A4D0F6, 0x3A019C99, + 0x448DEE14, 0xDF28A27B, 0xA8B6708B, 0x33133CE4, 0x478BD56B, 0xDC2E9904, 0xABB04BF4, 0x3015079B, + 0x428198EA, 0xD924D485, 0xAEBA0675, 0x351F4A1A, 0x4187A395, 0xDA22EFFA, 0xADBC3D0A, 0x36197165, + }, - { - 0x00000000,0xDD96D985,0x605CB54B,0xBDCA6CCE,0xC0B96A96,0x1D2FB313,0xA0E5DFDD,0x7D730658, - 0x5A03D36D,0x87950AE8,0x3A5F6626,0xE7C9BFA3,0x9ABAB9FB,0x472C607E,0xFAE60CB0,0x2770D535, - 0xB407A6DA,0x69917F5F,0xD45B1391,0x09CDCA14,0x74BECC4C,0xA92815C9,0x14E27907,0xC974A082, - 0xEE0475B7,0x3392AC32,0x8E58C0FC,0x53CE1979,0x2EBD1F21,0xF32BC6A4,0x4EE1AA6A,0x937773EF, - 0xB37E4BF5,0x6EE89270,0xD322FEBE,0x0EB4273B,0x73C72163,0xAE51F8E6,0x139B9428,0xCE0D4DAD, - 0xE97D9898,0x34EB411D,0x89212DD3,0x54B7F456,0x29C4F20E,0xF4522B8B,0x49984745,0x940E9EC0, - 0x0779ED2F,0xDAEF34AA,0x67255864,0xBAB381E1,0xC7C087B9,0x1A565E3C,0xA79C32F2,0x7A0AEB77, - 0x5D7A3E42,0x80ECE7C7,0x3D268B09,0xE0B0528C,0x9DC354D4,0x40558D51,0xFD9FE19F,0x2009381A, - 0xBD8D91AB,0x601B482E,0xDDD124E0,0x0047FD65,0x7D34FB3D,0xA0A222B8,0x1D684E76,0xC0FE97F3, - 0xE78E42C6,0x3A189B43,0x87D2F78D,0x5A442E08,0x27372850,0xFAA1F1D5,0x476B9D1B,0x9AFD449E, - 0x098A3771,0xD41CEEF4,0x69D6823A,0xB4405BBF,0xC9335DE7,0x14A58462,0xA96FE8AC,0x74F93129, - 0x5389E41C,0x8E1F3D99,0x33D55157,0xEE4388D2,0x93308E8A,0x4EA6570F,0xF36C3BC1,0x2EFAE244, - 0x0EF3DA5E,0xD36503DB,0x6EAF6F15,0xB339B690,0xCE4AB0C8,0x13DC694D,0xAE160583,0x7380DC06, - 0x54F00933,0x8966D0B6,0x34ACBC78,0xE93A65FD,0x944963A5,0x49DFBA20,0xF415D6EE,0x29830F6B, - 0xBAF47C84,0x6762A501,0xDAA8C9CF,0x073E104A,0x7A4D1612,0xA7DBCF97,0x1A11A359,0xC7877ADC, - 0xE0F7AFE9,0x3D61766C,0x80AB1AA2,0x5D3DC327,0x204EC57F,0xFDD81CFA,0x40127034,0x9D84A9B1, - 0xA06A2517,0x7DFCFC92,0xC036905C,0x1DA049D9,0x60D34F81,0xBD459604,0x008FFACA,0xDD19234F, - 0xFA69F67A,0x27FF2FFF,0x9A354331,0x47A39AB4,0x3AD09CEC,0xE7464569,0x5A8C29A7,0x871AF022, - 0x146D83CD,0xC9FB5A48,0x74313686,0xA9A7EF03,0xD4D4E95B,0x094230DE,0xB4885C10,0x691E8595, - 0x4E6E50A0,0x93F88925,0x2E32E5EB,0xF3A43C6E,0x8ED73A36,0x5341E3B3,0xEE8B8F7D,0x331D56F8, - 0x13146EE2,0xCE82B767,0x7348DBA9,0xAEDE022C,0xD3AD0474,0x0E3BDDF1,0xB3F1B13F,0x6E6768BA, - 0x4917BD8F,0x9481640A,0x294B08C4,0xF4DDD141,0x89AED719,0x54380E9C,0xE9F26252,0x3464BBD7, - 0xA713C838,0x7A8511BD,0xC74F7D73,0x1AD9A4F6,0x67AAA2AE,0xBA3C7B2B,0x07F617E5,0xDA60CE60, - 0xFD101B55,0x2086C2D0,0x9D4CAE1E,0x40DA779B,0x3DA971C3,0xE03FA846,0x5DF5C488,0x80631D0D, - 0x1DE7B4BC,0xC0716D39,0x7DBB01F7,0xA02DD872,0xDD5EDE2A,0x00C807AF,0xBD026B61,0x6094B2E4, - 0x47E467D1,0x9A72BE54,0x27B8D29A,0xFA2E0B1F,0x875D0D47,0x5ACBD4C2,0xE701B80C,0x3A976189, - 0xA9E01266,0x7476CBE3,0xC9BCA72D,0x142A7EA8,0x695978F0,0xB4CFA175,0x0905CDBB,0xD493143E, - 0xF3E3C10B,0x2E75188E,0x93BF7440,0x4E29ADC5,0x335AAB9D,0xEECC7218,0x53061ED6,0x8E90C753, - 0xAE99FF49,0x730F26CC,0xCEC54A02,0x13539387,0x6E2095DF,0xB3B64C5A,0x0E7C2094,0xD3EAF911, - 0xF49A2C24,0x290CF5A1,0x94C6996F,0x495040EA,0x342346B2,0xE9B59F37,0x547FF3F9,0x89E92A7C, - 0x1A9E5993,0xC7088016,0x7AC2ECD8,0xA754355D,0xDA273305,0x07B1EA80,0xBA7B864E,0x67ED5FCB, - 0x409D8AFE,0x9D0B537B,0x20C13FB5,0xFD57E630,0x8024E068,0x5DB239ED,0xE0785523,0x3DEE8CA6, - }, + { + 0x00000000, 0xDD96D985, 0x605CB54B, 0xBDCA6CCE, 0xC0B96A96, 0x1D2FB313, 0xA0E5DFDD, 0x7D730658, + 0x5A03D36D, 0x87950AE8, 0x3A5F6626, 0xE7C9BFA3, 0x9ABAB9FB, 0x472C607E, 0xFAE60CB0, 0x2770D535, + 0xB407A6DA, 0x69917F5F, 0xD45B1391, 0x09CDCA14, 0x74BECC4C, 0xA92815C9, 0x14E27907, 0xC974A082, + 0xEE0475B7, 0x3392AC32, 0x8E58C0FC, 0x53CE1979, 0x2EBD1F21, 0xF32BC6A4, 0x4EE1AA6A, 0x937773EF, + 0xB37E4BF5, 0x6EE89270, 0xD322FEBE, 0x0EB4273B, 0x73C72163, 0xAE51F8E6, 0x139B9428, 0xCE0D4DAD, + 0xE97D9898, 0x34EB411D, 0x89212DD3, 0x54B7F456, 0x29C4F20E, 0xF4522B8B, 0x49984745, 0x940E9EC0, + 0x0779ED2F, 0xDAEF34AA, 0x67255864, 0xBAB381E1, 0xC7C087B9, 0x1A565E3C, 0xA79C32F2, 0x7A0AEB77, + 0x5D7A3E42, 0x80ECE7C7, 0x3D268B09, 0xE0B0528C, 0x9DC354D4, 0x40558D51, 0xFD9FE19F, 0x2009381A, + 0xBD8D91AB, 0x601B482E, 0xDDD124E0, 0x0047FD65, 0x7D34FB3D, 0xA0A222B8, 0x1D684E76, 0xC0FE97F3, + 0xE78E42C6, 0x3A189B43, 0x87D2F78D, 0x5A442E08, 0x27372850, 0xFAA1F1D5, 0x476B9D1B, 0x9AFD449E, + 0x098A3771, 0xD41CEEF4, 0x69D6823A, 0xB4405BBF, 0xC9335DE7, 0x14A58462, 0xA96FE8AC, 0x74F93129, + 0x5389E41C, 0x8E1F3D99, 0x33D55157, 0xEE4388D2, 0x93308E8A, 0x4EA6570F, 0xF36C3BC1, 0x2EFAE244, + 0x0EF3DA5E, 0xD36503DB, 0x6EAF6F15, 0xB339B690, 0xCE4AB0C8, 0x13DC694D, 0xAE160583, 0x7380DC06, + 0x54F00933, 0x8966D0B6, 0x34ACBC78, 0xE93A65FD, 0x944963A5, 0x49DFBA20, 0xF415D6EE, 0x29830F6B, + 0xBAF47C84, 0x6762A501, 0xDAA8C9CF, 0x073E104A, 0x7A4D1612, 0xA7DBCF97, 0x1A11A359, 0xC7877ADC, + 0xE0F7AFE9, 0x3D61766C, 0x80AB1AA2, 0x5D3DC327, 0x204EC57F, 0xFDD81CFA, 0x40127034, 0x9D84A9B1, + 0xA06A2517, 0x7DFCFC92, 0xC036905C, 0x1DA049D9, 0x60D34F81, 0xBD459604, 0x008FFACA, 0xDD19234F, + 0xFA69F67A, 0x27FF2FFF, 0x9A354331, 0x47A39AB4, 0x3AD09CEC, 0xE7464569, 0x5A8C29A7, 0x871AF022, + 0x146D83CD, 0xC9FB5A48, 0x74313686, 0xA9A7EF03, 0xD4D4E95B, 0x094230DE, 0xB4885C10, 0x691E8595, + 0x4E6E50A0, 0x93F88925, 0x2E32E5EB, 0xF3A43C6E, 0x8ED73A36, 0x5341E3B3, 0xEE8B8F7D, 0x331D56F8, + 0x13146EE2, 0xCE82B767, 0x7348DBA9, 0xAEDE022C, 0xD3AD0474, 0x0E3BDDF1, 0xB3F1B13F, 0x6E6768BA, + 0x4917BD8F, 0x9481640A, 0x294B08C4, 0xF4DDD141, 0x89AED719, 0x54380E9C, 0xE9F26252, 0x3464BBD7, + 0xA713C838, 0x7A8511BD, 0xC74F7D73, 0x1AD9A4F6, 0x67AAA2AE, 0xBA3C7B2B, 0x07F617E5, 0xDA60CE60, + 0xFD101B55, 0x2086C2D0, 0x9D4CAE1E, 0x40DA779B, 0x3DA971C3, 0xE03FA846, 0x5DF5C488, 0x80631D0D, + 0x1DE7B4BC, 0xC0716D39, 0x7DBB01F7, 0xA02DD872, 0xDD5EDE2A, 0x00C807AF, 0xBD026B61, 0x6094B2E4, + 0x47E467D1, 0x9A72BE54, 0x27B8D29A, 0xFA2E0B1F, 0x875D0D47, 0x5ACBD4C2, 0xE701B80C, 0x3A976189, + 0xA9E01266, 0x7476CBE3, 0xC9BCA72D, 0x142A7EA8, 0x695978F0, 0xB4CFA175, 0x0905CDBB, 0xD493143E, + 0xF3E3C10B, 0x2E75188E, 0x93BF7440, 0x4E29ADC5, 0x335AAB9D, 0xEECC7218, 0x53061ED6, 0x8E90C753, + 0xAE99FF49, 0x730F26CC, 0xCEC54A02, 0x13539387, 0x6E2095DF, 0xB3B64C5A, 0x0E7C2094, 0xD3EAF911, + 0xF49A2C24, 0x290CF5A1, 0x94C6996F, 0x495040EA, 0x342346B2, 0xE9B59F37, 0x547FF3F9, 0x89E92A7C, + 0x1A9E5993, 0xC7088016, 0x7AC2ECD8, 0xA754355D, 0xDA273305, 0x07B1EA80, 0xBA7B864E, 0x67ED5FCB, + 0x409D8AFE, 0x9D0B537B, 0x20C13FB5, 0xFD57E630, 0x8024E068, 0x5DB239ED, 0xE0785523, 0x3DEE8CA6, + }, - { - 0x00000000,0x9D0FE176,0xE16EC4AD,0x7C6125DB,0x19AC8F1B,0x84A36E6D,0xF8C24BB6,0x65CDAAC0, - 0x33591E36,0xAE56FF40,0xD237DA9B,0x4F383BED,0x2AF5912D,0xB7FA705B,0xCB9B5580,0x5694B4F6, - 0x66B23C6C,0xFBBDDD1A,0x87DCF8C1,0x1AD319B7,0x7F1EB377,0xE2115201,0x9E7077DA,0x037F96AC, - 0x55EB225A,0xC8E4C32C,0xB485E6F7,0x298A0781,0x4C47AD41,0xD1484C37,0xAD2969EC,0x3026889A, - 0xCD6478D8,0x506B99AE,0x2C0ABC75,0xB1055D03,0xD4C8F7C3,0x49C716B5,0x35A6336E,0xA8A9D218, - 0xFE3D66EE,0x63328798,0x1F53A243,0x825C4335,0xE791E9F5,0x7A9E0883,0x06FF2D58,0x9BF0CC2E, - 0xABD644B4,0x36D9A5C2,0x4AB88019,0xD7B7616F,0xB27ACBAF,0x2F752AD9,0x53140F02,0xCE1BEE74, - 0x988F5A82,0x0580BBF4,0x79E19E2F,0xE4EE7F59,0x8123D599,0x1C2C34EF,0x604D1134,0xFD42F042, - 0x41B9F7F1,0xDCB61687,0xA0D7335C,0x3DD8D22A,0x581578EA,0xC51A999C,0xB97BBC47,0x24745D31, - 0x72E0E9C7,0xEFEF08B1,0x938E2D6A,0x0E81CC1C,0x6B4C66DC,0xF64387AA,0x8A22A271,0x172D4307, - 0x270BCB9D,0xBA042AEB,0xC6650F30,0x5B6AEE46,0x3EA74486,0xA3A8A5F0,0xDFC9802B,0x42C6615D, - 0x1452D5AB,0x895D34DD,0xF53C1106,0x6833F070,0x0DFE5AB0,0x90F1BBC6,0xEC909E1D,0x719F7F6B, - 0x8CDD8F29,0x11D26E5F,0x6DB34B84,0xF0BCAAF2,0x95710032,0x087EE144,0x741FC49F,0xE91025E9, - 0xBF84911F,0x228B7069,0x5EEA55B2,0xC3E5B4C4,0xA6281E04,0x3B27FF72,0x4746DAA9,0xDA493BDF, - 0xEA6FB345,0x77605233,0x0B0177E8,0x960E969E,0xF3C33C5E,0x6ECCDD28,0x12ADF8F3,0x8FA21985, - 0xD936AD73,0x44394C05,0x385869DE,0xA55788A8,0xC09A2268,0x5D95C31E,0x21F4E6C5,0xBCFB07B3, - 0x8373EFE2,0x1E7C0E94,0x621D2B4F,0xFF12CA39,0x9ADF60F9,0x07D0818F,0x7BB1A454,0xE6BE4522, - 0xB02AF1D4,0x2D2510A2,0x51443579,0xCC4BD40F,0xA9867ECF,0x34899FB9,0x48E8BA62,0xD5E75B14, - 0xE5C1D38E,0x78CE32F8,0x04AF1723,0x99A0F655,0xFC6D5C95,0x6162BDE3,0x1D039838,0x800C794E, - 0xD698CDB8,0x4B972CCE,0x37F60915,0xAAF9E863,0xCF3442A3,0x523BA3D5,0x2E5A860E,0xB3556778, - 0x4E17973A,0xD318764C,0xAF795397,0x3276B2E1,0x57BB1821,0xCAB4F957,0xB6D5DC8C,0x2BDA3DFA, - 0x7D4E890C,0xE041687A,0x9C204DA1,0x012FACD7,0x64E20617,0xF9EDE761,0x858CC2BA,0x188323CC, - 0x28A5AB56,0xB5AA4A20,0xC9CB6FFB,0x54C48E8D,0x3109244D,0xAC06C53B,0xD067E0E0,0x4D680196, - 0x1BFCB560,0x86F35416,0xFA9271CD,0x679D90BB,0x02503A7B,0x9F5FDB0D,0xE33EFED6,0x7E311FA0, - 0xC2CA1813,0x5FC5F965,0x23A4DCBE,0xBEAB3DC8,0xDB669708,0x4669767E,0x3A0853A5,0xA707B2D3, - 0xF1930625,0x6C9CE753,0x10FDC288,0x8DF223FE,0xE83F893E,0x75306848,0x09514D93,0x945EACE5, - 0xA478247F,0x3977C509,0x4516E0D2,0xD81901A4,0xBDD4AB64,0x20DB4A12,0x5CBA6FC9,0xC1B58EBF, - 0x97213A49,0x0A2EDB3F,0x764FFEE4,0xEB401F92,0x8E8DB552,0x13825424,0x6FE371FF,0xF2EC9089, - 0x0FAE60CB,0x92A181BD,0xEEC0A466,0x73CF4510,0x1602EFD0,0x8B0D0EA6,0xF76C2B7D,0x6A63CA0B, - 0x3CF77EFD,0xA1F89F8B,0xDD99BA50,0x40965B26,0x255BF1E6,0xB8541090,0xC435354B,0x593AD43D, - 0x691C5CA7,0xF413BDD1,0x8872980A,0x157D797C,0x70B0D3BC,0xEDBF32CA,0x91DE1711,0x0CD1F667, - 0x5A454291,0xC74AA3E7,0xBB2B863C,0x2624674A,0x43E9CD8A,0xDEE62CFC,0xA2870927,0x3F88E851, - }, + { + 0x00000000, 0x9D0FE176, 0xE16EC4AD, 0x7C6125DB, 0x19AC8F1B, 0x84A36E6D, 0xF8C24BB6, 0x65CDAAC0, + 0x33591E36, 0xAE56FF40, 0xD237DA9B, 0x4F383BED, 0x2AF5912D, 0xB7FA705B, 0xCB9B5580, 0x5694B4F6, + 0x66B23C6C, 0xFBBDDD1A, 0x87DCF8C1, 0x1AD319B7, 0x7F1EB377, 0xE2115201, 0x9E7077DA, 0x037F96AC, + 0x55EB225A, 0xC8E4C32C, 0xB485E6F7, 0x298A0781, 0x4C47AD41, 0xD1484C37, 0xAD2969EC, 0x3026889A, + 0xCD6478D8, 0x506B99AE, 0x2C0ABC75, 0xB1055D03, 0xD4C8F7C3, 0x49C716B5, 0x35A6336E, 0xA8A9D218, + 0xFE3D66EE, 0x63328798, 0x1F53A243, 0x825C4335, 0xE791E9F5, 0x7A9E0883, 0x06FF2D58, 0x9BF0CC2E, + 0xABD644B4, 0x36D9A5C2, 0x4AB88019, 0xD7B7616F, 0xB27ACBAF, 0x2F752AD9, 0x53140F02, 0xCE1BEE74, + 0x988F5A82, 0x0580BBF4, 0x79E19E2F, 0xE4EE7F59, 0x8123D599, 0x1C2C34EF, 0x604D1134, 0xFD42F042, + 0x41B9F7F1, 0xDCB61687, 0xA0D7335C, 0x3DD8D22A, 0x581578EA, 0xC51A999C, 0xB97BBC47, 0x24745D31, + 0x72E0E9C7, 0xEFEF08B1, 0x938E2D6A, 0x0E81CC1C, 0x6B4C66DC, 0xF64387AA, 0x8A22A271, 0x172D4307, + 0x270BCB9D, 0xBA042AEB, 0xC6650F30, 0x5B6AEE46, 0x3EA74486, 0xA3A8A5F0, 0xDFC9802B, 0x42C6615D, + 0x1452D5AB, 0x895D34DD, 0xF53C1106, 0x6833F070, 0x0DFE5AB0, 0x90F1BBC6, 0xEC909E1D, 0x719F7F6B, + 0x8CDD8F29, 0x11D26E5F, 0x6DB34B84, 0xF0BCAAF2, 0x95710032, 0x087EE144, 0x741FC49F, 0xE91025E9, + 0xBF84911F, 0x228B7069, 0x5EEA55B2, 0xC3E5B4C4, 0xA6281E04, 0x3B27FF72, 0x4746DAA9, 0xDA493BDF, + 0xEA6FB345, 0x77605233, 0x0B0177E8, 0x960E969E, 0xF3C33C5E, 0x6ECCDD28, 0x12ADF8F3, 0x8FA21985, + 0xD936AD73, 0x44394C05, 0x385869DE, 0xA55788A8, 0xC09A2268, 0x5D95C31E, 0x21F4E6C5, 0xBCFB07B3, + 0x8373EFE2, 0x1E7C0E94, 0x621D2B4F, 0xFF12CA39, 0x9ADF60F9, 0x07D0818F, 0x7BB1A454, 0xE6BE4522, + 0xB02AF1D4, 0x2D2510A2, 0x51443579, 0xCC4BD40F, 0xA9867ECF, 0x34899FB9, 0x48E8BA62, 0xD5E75B14, + 0xE5C1D38E, 0x78CE32F8, 0x04AF1723, 0x99A0F655, 0xFC6D5C95, 0x6162BDE3, 0x1D039838, 0x800C794E, + 0xD698CDB8, 0x4B972CCE, 0x37F60915, 0xAAF9E863, 0xCF3442A3, 0x523BA3D5, 0x2E5A860E, 0xB3556778, + 0x4E17973A, 0xD318764C, 0xAF795397, 0x3276B2E1, 0x57BB1821, 0xCAB4F957, 0xB6D5DC8C, 0x2BDA3DFA, + 0x7D4E890C, 0xE041687A, 0x9C204DA1, 0x012FACD7, 0x64E20617, 0xF9EDE761, 0x858CC2BA, 0x188323CC, + 0x28A5AB56, 0xB5AA4A20, 0xC9CB6FFB, 0x54C48E8D, 0x3109244D, 0xAC06C53B, 0xD067E0E0, 0x4D680196, + 0x1BFCB560, 0x86F35416, 0xFA9271CD, 0x679D90BB, 0x02503A7B, 0x9F5FDB0D, 0xE33EFED6, 0x7E311FA0, + 0xC2CA1813, 0x5FC5F965, 0x23A4DCBE, 0xBEAB3DC8, 0xDB669708, 0x4669767E, 0x3A0853A5, 0xA707B2D3, + 0xF1930625, 0x6C9CE753, 0x10FDC288, 0x8DF223FE, 0xE83F893E, 0x75306848, 0x09514D93, 0x945EACE5, + 0xA478247F, 0x3977C509, 0x4516E0D2, 0xD81901A4, 0xBDD4AB64, 0x20DB4A12, 0x5CBA6FC9, 0xC1B58EBF, + 0x97213A49, 0x0A2EDB3F, 0x764FFEE4, 0xEB401F92, 0x8E8DB552, 0x13825424, 0x6FE371FF, 0xF2EC9089, + 0x0FAE60CB, 0x92A181BD, 0xEEC0A466, 0x73CF4510, 0x1602EFD0, 0x8B0D0EA6, 0xF76C2B7D, 0x6A63CA0B, + 0x3CF77EFD, 0xA1F89F8B, 0xDD99BA50, 0x40965B26, 0x255BF1E6, 0xB8541090, 0xC435354B, 0x593AD43D, + 0x691C5CA7, 0xF413BDD1, 0x8872980A, 0x157D797C, 0x70B0D3BC, 0xEDBF32CA, 0x91DE1711, 0x0CD1F667, + 0x5A454291, 0xC74AA3E7, 0xBB2B863C, 0x2624674A, 0x43E9CD8A, 0xDEE62CFC, 0xA2870927, 0x3F88E851, + }, - { - 0x00000000,0xB9FBDBE8,0xA886B191,0x117D6A79,0x8A7C6563,0x3387BE8B,0x22FAD4F2,0x9B010F1A, - 0xCF89CC87,0x7672176F,0x670F7D16,0xDEF4A6FE,0x45F5A9E4,0xFC0E720C,0xED731875,0x5488C39D, - 0x44629F4F,0xFD9944A7,0xECE42EDE,0x551FF536,0xCE1EFA2C,0x77E521C4,0x66984BBD,0xDF639055, - 0x8BEB53C8,0x32108820,0x236DE259,0x9A9639B1,0x019736AB,0xB86CED43,0xA911873A,0x10EA5CD2, - 0x88C53E9E,0x313EE576,0x20438F0F,0x99B854E7,0x02B95BFD,0xBB428015,0xAA3FEA6C,0x13C43184, - 0x474CF219,0xFEB729F1,0xEFCA4388,0x56319860,0xCD30977A,0x74CB4C92,0x65B626EB,0xDC4DFD03, - 0xCCA7A1D1,0x755C7A39,0x64211040,0xDDDACBA8,0x46DBC4B2,0xFF201F5A,0xEE5D7523,0x57A6AECB, - 0x032E6D56,0xBAD5B6BE,0xABA8DCC7,0x1253072F,0x89520835,0x30A9D3DD,0x21D4B9A4,0x982F624C, - 0xCAFB7B7D,0x7300A095,0x627DCAEC,0xDB861104,0x40871E1E,0xF97CC5F6,0xE801AF8F,0x51FA7467, - 0x0572B7FA,0xBC896C12,0xADF4066B,0x140FDD83,0x8F0ED299,0x36F50971,0x27886308,0x9E73B8E0, - 0x8E99E432,0x37623FDA,0x261F55A3,0x9FE48E4B,0x04E58151,0xBD1E5AB9,0xAC6330C0,0x1598EB28, - 0x411028B5,0xF8EBF35D,0xE9969924,0x506D42CC,0xCB6C4DD6,0x7297963E,0x63EAFC47,0xDA1127AF, - 0x423E45E3,0xFBC59E0B,0xEAB8F472,0x53432F9A,0xC8422080,0x71B9FB68,0x60C49111,0xD93F4AF9, - 0x8DB78964,0x344C528C,0x253138F5,0x9CCAE31D,0x07CBEC07,0xBE3037EF,0xAF4D5D96,0x16B6867E, - 0x065CDAAC,0xBFA70144,0xAEDA6B3D,0x1721B0D5,0x8C20BFCF,0x35DB6427,0x24A60E5E,0x9D5DD5B6, - 0xC9D5162B,0x702ECDC3,0x6153A7BA,0xD8A87C52,0x43A97348,0xFA52A8A0,0xEB2FC2D9,0x52D41931, - 0x4E87F0BB,0xF77C2B53,0xE601412A,0x5FFA9AC2,0xC4FB95D8,0x7D004E30,0x6C7D2449,0xD586FFA1, - 0x810E3C3C,0x38F5E7D4,0x29888DAD,0x90735645,0x0B72595F,0xB28982B7,0xA3F4E8CE,0x1A0F3326, - 0x0AE56FF4,0xB31EB41C,0xA263DE65,0x1B98058D,0x80990A97,0x3962D17F,0x281FBB06,0x91E460EE, - 0xC56CA373,0x7C97789B,0x6DEA12E2,0xD411C90A,0x4F10C610,0xF6EB1DF8,0xE7967781,0x5E6DAC69, - 0xC642CE25,0x7FB915CD,0x6EC47FB4,0xD73FA45C,0x4C3EAB46,0xF5C570AE,0xE4B81AD7,0x5D43C13F, - 0x09CB02A2,0xB030D94A,0xA14DB333,0x18B668DB,0x83B767C1,0x3A4CBC29,0x2B31D650,0x92CA0DB8, - 0x8220516A,0x3BDB8A82,0x2AA6E0FB,0x935D3B13,0x085C3409,0xB1A7EFE1,0xA0DA8598,0x19215E70, - 0x4DA99DED,0xF4524605,0xE52F2C7C,0x5CD4F794,0xC7D5F88E,0x7E2E2366,0x6F53491F,0xD6A892F7, - 0x847C8BC6,0x3D87502E,0x2CFA3A57,0x9501E1BF,0x0E00EEA5,0xB7FB354D,0xA6865F34,0x1F7D84DC, - 0x4BF54741,0xF20E9CA9,0xE373F6D0,0x5A882D38,0xC1892222,0x7872F9CA,0x690F93B3,0xD0F4485B, - 0xC01E1489,0x79E5CF61,0x6898A518,0xD1637EF0,0x4A6271EA,0xF399AA02,0xE2E4C07B,0x5B1F1B93, - 0x0F97D80E,0xB66C03E6,0xA711699F,0x1EEAB277,0x85EBBD6D,0x3C106685,0x2D6D0CFC,0x9496D714, - 0x0CB9B558,0xB5426EB0,0xA43F04C9,0x1DC4DF21,0x86C5D03B,0x3F3E0BD3,0x2E4361AA,0x97B8BA42, - 0xC33079DF,0x7ACBA237,0x6BB6C84E,0xD24D13A6,0x494C1CBC,0xF0B7C754,0xE1CAAD2D,0x583176C5, - 0x48DB2A17,0xF120F1FF,0xE05D9B86,0x59A6406E,0xC2A74F74,0x7B5C949C,0x6A21FEE5,0xD3DA250D, - 0x8752E690,0x3EA93D78,0x2FD45701,0x962F8CE9,0x0D2E83F3,0xB4D5581B,0xA5A83262,0x1C53E98A, - }, + { + 0x00000000, 0xB9FBDBE8, 0xA886B191, 0x117D6A79, 0x8A7C6563, 0x3387BE8B, 0x22FAD4F2, 0x9B010F1A, + 0xCF89CC87, 0x7672176F, 0x670F7D16, 0xDEF4A6FE, 0x45F5A9E4, 0xFC0E720C, 0xED731875, 0x5488C39D, + 0x44629F4F, 0xFD9944A7, 0xECE42EDE, 0x551FF536, 0xCE1EFA2C, 0x77E521C4, 0x66984BBD, 0xDF639055, + 0x8BEB53C8, 0x32108820, 0x236DE259, 0x9A9639B1, 0x019736AB, 0xB86CED43, 0xA911873A, 0x10EA5CD2, + 0x88C53E9E, 0x313EE576, 0x20438F0F, 0x99B854E7, 0x02B95BFD, 0xBB428015, 0xAA3FEA6C, 0x13C43184, + 0x474CF219, 0xFEB729F1, 0xEFCA4388, 0x56319860, 0xCD30977A, 0x74CB4C92, 0x65B626EB, 0xDC4DFD03, + 0xCCA7A1D1, 0x755C7A39, 0x64211040, 0xDDDACBA8, 0x46DBC4B2, 0xFF201F5A, 0xEE5D7523, 0x57A6AECB, + 0x032E6D56, 0xBAD5B6BE, 0xABA8DCC7, 0x1253072F, 0x89520835, 0x30A9D3DD, 0x21D4B9A4, 0x982F624C, + 0xCAFB7B7D, 0x7300A095, 0x627DCAEC, 0xDB861104, 0x40871E1E, 0xF97CC5F6, 0xE801AF8F, 0x51FA7467, + 0x0572B7FA, 0xBC896C12, 0xADF4066B, 0x140FDD83, 0x8F0ED299, 0x36F50971, 0x27886308, 0x9E73B8E0, + 0x8E99E432, 0x37623FDA, 0x261F55A3, 0x9FE48E4B, 0x04E58151, 0xBD1E5AB9, 0xAC6330C0, 0x1598EB28, + 0x411028B5, 0xF8EBF35D, 0xE9969924, 0x506D42CC, 0xCB6C4DD6, 0x7297963E, 0x63EAFC47, 0xDA1127AF, + 0x423E45E3, 0xFBC59E0B, 0xEAB8F472, 0x53432F9A, 0xC8422080, 0x71B9FB68, 0x60C49111, 0xD93F4AF9, + 0x8DB78964, 0x344C528C, 0x253138F5, 0x9CCAE31D, 0x07CBEC07, 0xBE3037EF, 0xAF4D5D96, 0x16B6867E, + 0x065CDAAC, 0xBFA70144, 0xAEDA6B3D, 0x1721B0D5, 0x8C20BFCF, 0x35DB6427, 0x24A60E5E, 0x9D5DD5B6, + 0xC9D5162B, 0x702ECDC3, 0x6153A7BA, 0xD8A87C52, 0x43A97348, 0xFA52A8A0, 0xEB2FC2D9, 0x52D41931, + 0x4E87F0BB, 0xF77C2B53, 0xE601412A, 0x5FFA9AC2, 0xC4FB95D8, 0x7D004E30, 0x6C7D2449, 0xD586FFA1, + 0x810E3C3C, 0x38F5E7D4, 0x29888DAD, 0x90735645, 0x0B72595F, 0xB28982B7, 0xA3F4E8CE, 0x1A0F3326, + 0x0AE56FF4, 0xB31EB41C, 0xA263DE65, 0x1B98058D, 0x80990A97, 0x3962D17F, 0x281FBB06, 0x91E460EE, + 0xC56CA373, 0x7C97789B, 0x6DEA12E2, 0xD411C90A, 0x4F10C610, 0xF6EB1DF8, 0xE7967781, 0x5E6DAC69, + 0xC642CE25, 0x7FB915CD, 0x6EC47FB4, 0xD73FA45C, 0x4C3EAB46, 0xF5C570AE, 0xE4B81AD7, 0x5D43C13F, + 0x09CB02A2, 0xB030D94A, 0xA14DB333, 0x18B668DB, 0x83B767C1, 0x3A4CBC29, 0x2B31D650, 0x92CA0DB8, + 0x8220516A, 0x3BDB8A82, 0x2AA6E0FB, 0x935D3B13, 0x085C3409, 0xB1A7EFE1, 0xA0DA8598, 0x19215E70, + 0x4DA99DED, 0xF4524605, 0xE52F2C7C, 0x5CD4F794, 0xC7D5F88E, 0x7E2E2366, 0x6F53491F, 0xD6A892F7, + 0x847C8BC6, 0x3D87502E, 0x2CFA3A57, 0x9501E1BF, 0x0E00EEA5, 0xB7FB354D, 0xA6865F34, 0x1F7D84DC, + 0x4BF54741, 0xF20E9CA9, 0xE373F6D0, 0x5A882D38, 0xC1892222, 0x7872F9CA, 0x690F93B3, 0xD0F4485B, + 0xC01E1489, 0x79E5CF61, 0x6898A518, 0xD1637EF0, 0x4A6271EA, 0xF399AA02, 0xE2E4C07B, 0x5B1F1B93, + 0x0F97D80E, 0xB66C03E6, 0xA711699F, 0x1EEAB277, 0x85EBBD6D, 0x3C106685, 0x2D6D0CFC, 0x9496D714, + 0x0CB9B558, 0xB5426EB0, 0xA43F04C9, 0x1DC4DF21, 0x86C5D03B, 0x3F3E0BD3, 0x2E4361AA, 0x97B8BA42, + 0xC33079DF, 0x7ACBA237, 0x6BB6C84E, 0xD24D13A6, 0x494C1CBC, 0xF0B7C754, 0xE1CAAD2D, 0x583176C5, + 0x48DB2A17, 0xF120F1FF, 0xE05D9B86, 0x59A6406E, 0xC2A74F74, 0x7B5C949C, 0x6A21FEE5, 0xD3DA250D, + 0x8752E690, 0x3EA93D78, 0x2FD45701, 0x962F8CE9, 0x0D2E83F3, 0xB4D5581B, 0xA5A83262, 0x1C53E98A, + }, - { - 0x00000000,0xAE689191,0x87A02563,0x29C8B4F2,0xD4314C87,0x7A59DD16,0x539169E4,0xFDF9F875, - 0x73139F4F,0xDD7B0EDE,0xF4B3BA2C,0x5ADB2BBD,0xA722D3C8,0x094A4259,0x2082F6AB,0x8EEA673A, - 0xE6273E9E,0x484FAF0F,0x61871BFD,0xCFEF8A6C,0x32167219,0x9C7EE388,0xB5B6577A,0x1BDEC6EB, - 0x9534A1D1,0x3B5C3040,0x129484B2,0xBCFC1523,0x4105ED56,0xEF6D7CC7,0xC6A5C835,0x68CD59A4, - 0x173F7B7D,0xB957EAEC,0x909F5E1E,0x3EF7CF8F,0xC30E37FA,0x6D66A66B,0x44AE1299,0xEAC68308, - 0x642CE432,0xCA4475A3,0xE38CC151,0x4DE450C0,0xB01DA8B5,0x1E753924,0x37BD8DD6,0x99D51C47, - 0xF11845E3,0x5F70D472,0x76B86080,0xD8D0F111,0x25290964,0x8B4198F5,0xA2892C07,0x0CE1BD96, - 0x820BDAAC,0x2C634B3D,0x05ABFFCF,0xABC36E5E,0x563A962B,0xF85207BA,0xD19AB348,0x7FF222D9, - 0x2E7EF6FA,0x8016676B,0xA9DED399,0x07B64208,0xFA4FBA7D,0x54272BEC,0x7DEF9F1E,0xD3870E8F, - 0x5D6D69B5,0xF305F824,0xDACD4CD6,0x74A5DD47,0x895C2532,0x2734B4A3,0x0EFC0051,0xA09491C0, - 0xC859C864,0x663159F5,0x4FF9ED07,0xE1917C96,0x1C6884E3,0xB2001572,0x9BC8A180,0x35A03011, - 0xBB4A572B,0x1522C6BA,0x3CEA7248,0x9282E3D9,0x6F7B1BAC,0xC1138A3D,0xE8DB3ECF,0x46B3AF5E, - 0x39418D87,0x97291C16,0xBEE1A8E4,0x10893975,0xED70C100,0x43185091,0x6AD0E463,0xC4B875F2, - 0x4A5212C8,0xE43A8359,0xCDF237AB,0x639AA63A,0x9E635E4F,0x300BCFDE,0x19C37B2C,0xB7ABEABD, - 0xDF66B319,0x710E2288,0x58C6967A,0xF6AE07EB,0x0B57FF9E,0xA53F6E0F,0x8CF7DAFD,0x229F4B6C, - 0xAC752C56,0x021DBDC7,0x2BD50935,0x85BD98A4,0x784460D1,0xD62CF140,0xFFE445B2,0x518CD423, - 0x5CFDEDF4,0xF2957C65,0xDB5DC897,0x75355906,0x88CCA173,0x26A430E2,0x0F6C8410,0xA1041581, - 0x2FEE72BB,0x8186E32A,0xA84E57D8,0x0626C649,0xFBDF3E3C,0x55B7AFAD,0x7C7F1B5F,0xD2178ACE, - 0xBADAD36A,0x14B242FB,0x3D7AF609,0x93126798,0x6EEB9FED,0xC0830E7C,0xE94BBA8E,0x47232B1F, - 0xC9C94C25,0x67A1DDB4,0x4E696946,0xE001F8D7,0x1DF800A2,0xB3909133,0x9A5825C1,0x3430B450, - 0x4BC29689,0xE5AA0718,0xCC62B3EA,0x620A227B,0x9FF3DA0E,0x319B4B9F,0x1853FF6D,0xB63B6EFC, - 0x38D109C6,0x96B99857,0xBF712CA5,0x1119BD34,0xECE04541,0x4288D4D0,0x6B406022,0xC528F1B3, - 0xADE5A817,0x038D3986,0x2A458D74,0x842D1CE5,0x79D4E490,0xD7BC7501,0xFE74C1F3,0x501C5062, - 0xDEF63758,0x709EA6C9,0x5956123B,0xF73E83AA,0x0AC77BDF,0xA4AFEA4E,0x8D675EBC,0x230FCF2D, - 0x72831B0E,0xDCEB8A9F,0xF5233E6D,0x5B4BAFFC,0xA6B25789,0x08DAC618,0x211272EA,0x8F7AE37B, - 0x01908441,0xAFF815D0,0x8630A122,0x285830B3,0xD5A1C8C6,0x7BC95957,0x5201EDA5,0xFC697C34, - 0x94A42590,0x3ACCB401,0x130400F3,0xBD6C9162,0x40956917,0xEEFDF886,0xC7354C74,0x695DDDE5, - 0xE7B7BADF,0x49DF2B4E,0x60179FBC,0xCE7F0E2D,0x3386F658,0x9DEE67C9,0xB426D33B,0x1A4E42AA, - 0x65BC6073,0xCBD4F1E2,0xE21C4510,0x4C74D481,0xB18D2CF4,0x1FE5BD65,0x362D0997,0x98459806, - 0x16AFFF3C,0xB8C76EAD,0x910FDA5F,0x3F674BCE,0xC29EB3BB,0x6CF6222A,0x453E96D8,0xEB560749, - 0x839B5EED,0x2DF3CF7C,0x043B7B8E,0xAA53EA1F,0x57AA126A,0xF9C283FB,0xD00A3709,0x7E62A698, - 0xF088C1A2,0x5EE05033,0x7728E4C1,0xD9407550,0x24B98D25,0x8AD11CB4,0xA319A846,0x0D7139D7, - } + { + 0x00000000, 0xAE689191, 0x87A02563, 0x29C8B4F2, 0xD4314C87, 0x7A59DD16, 0x539169E4, 0xFDF9F875, + 0x73139F4F, 0xDD7B0EDE, 0xF4B3BA2C, 0x5ADB2BBD, 0xA722D3C8, 0x094A4259, 0x2082F6AB, 0x8EEA673A, + 0xE6273E9E, 0x484FAF0F, 0x61871BFD, 0xCFEF8A6C, 0x32167219, 0x9C7EE388, 0xB5B6577A, 0x1BDEC6EB, + 0x9534A1D1, 0x3B5C3040, 0x129484B2, 0xBCFC1523, 0x4105ED56, 0xEF6D7CC7, 0xC6A5C835, 0x68CD59A4, + 0x173F7B7D, 0xB957EAEC, 0x909F5E1E, 0x3EF7CF8F, 0xC30E37FA, 0x6D66A66B, 0x44AE1299, 0xEAC68308, + 0x642CE432, 0xCA4475A3, 0xE38CC151, 0x4DE450C0, 0xB01DA8B5, 0x1E753924, 0x37BD8DD6, 0x99D51C47, + 0xF11845E3, 0x5F70D472, 0x76B86080, 0xD8D0F111, 0x25290964, 0x8B4198F5, 0xA2892C07, 0x0CE1BD96, + 0x820BDAAC, 0x2C634B3D, 0x05ABFFCF, 0xABC36E5E, 0x563A962B, 0xF85207BA, 0xD19AB348, 0x7FF222D9, + 0x2E7EF6FA, 0x8016676B, 0xA9DED399, 0x07B64208, 0xFA4FBA7D, 0x54272BEC, 0x7DEF9F1E, 0xD3870E8F, + 0x5D6D69B5, 0xF305F824, 0xDACD4CD6, 0x74A5DD47, 0x895C2532, 0x2734B4A3, 0x0EFC0051, 0xA09491C0, + 0xC859C864, 0x663159F5, 0x4FF9ED07, 0xE1917C96, 0x1C6884E3, 0xB2001572, 0x9BC8A180, 0x35A03011, + 0xBB4A572B, 0x1522C6BA, 0x3CEA7248, 0x9282E3D9, 0x6F7B1BAC, 0xC1138A3D, 0xE8DB3ECF, 0x46B3AF5E, + 0x39418D87, 0x97291C16, 0xBEE1A8E4, 0x10893975, 0xED70C100, 0x43185091, 0x6AD0E463, 0xC4B875F2, + 0x4A5212C8, 0xE43A8359, 0xCDF237AB, 0x639AA63A, 0x9E635E4F, 0x300BCFDE, 0x19C37B2C, 0xB7ABEABD, + 0xDF66B319, 0x710E2288, 0x58C6967A, 0xF6AE07EB, 0x0B57FF9E, 0xA53F6E0F, 0x8CF7DAFD, 0x229F4B6C, + 0xAC752C56, 0x021DBDC7, 0x2BD50935, 0x85BD98A4, 0x784460D1, 0xD62CF140, 0xFFE445B2, 0x518CD423, + 0x5CFDEDF4, 0xF2957C65, 0xDB5DC897, 0x75355906, 0x88CCA173, 0x26A430E2, 0x0F6C8410, 0xA1041581, + 0x2FEE72BB, 0x8186E32A, 0xA84E57D8, 0x0626C649, 0xFBDF3E3C, 0x55B7AFAD, 0x7C7F1B5F, 0xD2178ACE, + 0xBADAD36A, 0x14B242FB, 0x3D7AF609, 0x93126798, 0x6EEB9FED, 0xC0830E7C, 0xE94BBA8E, 0x47232B1F, + 0xC9C94C25, 0x67A1DDB4, 0x4E696946, 0xE001F8D7, 0x1DF800A2, 0xB3909133, 0x9A5825C1, 0x3430B450, + 0x4BC29689, 0xE5AA0718, 0xCC62B3EA, 0x620A227B, 0x9FF3DA0E, 0x319B4B9F, 0x1853FF6D, 0xB63B6EFC, + 0x38D109C6, 0x96B99857, 0xBF712CA5, 0x1119BD34, 0xECE04541, 0x4288D4D0, 0x6B406022, 0xC528F1B3, + 0xADE5A817, 0x038D3986, 0x2A458D74, 0x842D1CE5, 0x79D4E490, 0xD7BC7501, 0xFE74C1F3, 0x501C5062, + 0xDEF63758, 0x709EA6C9, 0x5956123B, 0xF73E83AA, 0x0AC77BDF, 0xA4AFEA4E, 0x8D675EBC, 0x230FCF2D, + 0x72831B0E, 0xDCEB8A9F, 0xF5233E6D, 0x5B4BAFFC, 0xA6B25789, 0x08DAC618, 0x211272EA, 0x8F7AE37B, + 0x01908441, 0xAFF815D0, 0x8630A122, 0x285830B3, 0xD5A1C8C6, 0x7BC95957, 0x5201EDA5, 0xFC697C34, + 0x94A42590, 0x3ACCB401, 0x130400F3, 0xBD6C9162, 0x40956917, 0xEEFDF886, 0xC7354C74, 0x695DDDE5, + 0xE7B7BADF, 0x49DF2B4E, 0x60179FBC, 0xCE7F0E2D, 0x3386F658, 0x9DEE67C9, 0xB426D33B, 0x1A4E42AA, + 0x65BC6073, 0xCBD4F1E2, 0xE21C4510, 0x4C74D481, 0xB18D2CF4, 0x1FE5BD65, 0x362D0997, 0x98459806, + 0x16AFFF3C, 0xB8C76EAD, 0x910FDA5F, 0x3F674BCE, 0xC29EB3BB, 0x6CF6222A, 0x453E96D8, 0xEB560749, + 0x839B5EED, 0x2DF3CF7C, 0x043B7B8E, 0xAA53EA1F, 0x57AA126A, 0xF9C283FB, 0xD00A3709, 0x7E62A698, + 0xF088C1A2, 0x5EE05033, 0x7728E4C1, 0xD9407550, 0x24B98D25, 0x8AD11CB4, 0xA319A846, 0x0D7139D7, + } }; diff --git a/Utilities/CRC32.h b/Utilities/CRC32.h index a3bc813..fe7622e 100644 --- a/Utilities/CRC32.h +++ b/Utilities/CRC32.h @@ -9,4 +9,4 @@ private: public: static uint32_t GetCRC(uint8_t* buffer, std::streamoff length); static uint32_t GetCRC(string filename); -}; \ No newline at end of file +}; diff --git a/Utilities/CamstudioCodec.cpp b/Utilities/CamstudioCodec.cpp index 2ea313e..240dd61 100644 --- a/Utilities/CamstudioCodec.cpp +++ b/Utilities/CamstudioCodec.cpp @@ -19,25 +19,28 @@ bool CamstudioCodec::SetupCompress(int width, int height, uint32_t compressionLe _compressionLevel = compressionLevel; _orgWidth = width; - if(width % 4 != 0) { + if (width % 4 != 0) + { _rowStride = ((int)((width * 24 + 31) / 32 * 4)); - } else { - _rowStride = width*3; + } + else + { + _rowStride = width * 3; } _height = height; - _prevFrame = new uint8_t[_rowStride*_height]; //24-bit RGB - _currentFrame = new uint8_t[_rowStride*_height]; //24-bit RGB - _buffer = new uint8_t[_rowStride*_height]; //24-bit RGB + _prevFrame = new uint8_t[_rowStride * _height]; //24-bit RGB + _currentFrame = new uint8_t[_rowStride * _height]; //24-bit RGB + _buffer = new uint8_t[_rowStride * _height]; //24-bit RGB - _compressBufferLength = compressBound(_rowStride*_height) + 2; + _compressBufferLength = compressBound(_rowStride * _height) + 2; _compressBuffer = new uint8_t[_compressBufferLength]; - + memset(_prevFrame, 0, _rowStride * _height); memset(_currentFrame, 0, _rowStride * _height); memset(_buffer, 0, _rowStride * _height); memset(_compressBuffer, 0, _compressBufferLength); - + deflateInit(&_compressor, compressionLevel); return true; @@ -45,7 +48,8 @@ bool CamstudioCodec::SetupCompress(int width, int height, uint32_t compressionLe void CamstudioCodec::LoadRow(uint8_t* inPointer, uint8_t* outPointer) { - for(int x = 0; x < _orgWidth; x++) { + for (int x = 0; x < _orgWidth; x++) + { outPointer[0] = inPointer[0]; outPointer[1] = inPointer[1]; outPointer[2] = inPointer[2]; @@ -54,7 +58,7 @@ void CamstudioCodec::LoadRow(uint8_t* inPointer, uint8_t* outPointer) } } -int CamstudioCodec::CompressFrame(bool isKeyFrame, uint8_t *frameData, uint8_t** compressedData) +int CamstudioCodec::CompressFrame(bool isKeyFrame, uint8_t* frameData, uint8_t** compressedData) { deflateReset(&_compressor); @@ -65,25 +69,30 @@ int CamstudioCodec::CompressFrame(bool isKeyFrame, uint8_t *frameData, uint8_t** _compressBuffer[1] = 8; //8-bit per color uint8_t* rowBuffer = _currentFrame; - for(int y = 0; y < _height; y++) { + for (int y = 0; y < _height; y++) + { LoadRow(frameData + (_height - y - 1) * _orgWidth * 4, rowBuffer); rowBuffer += _rowStride; } - if(isKeyFrame) { + if (isKeyFrame) + { _compressor.next_in = _currentFrame; - } else { - for(int i = 0, len = _rowStride * _height; i < len; i++) { + } + else + { + for (int i = 0, len = _rowStride * _height; i < len; i++) + { _buffer[i] = _currentFrame[i] - _prevFrame[i]; } _compressor.next_in = _buffer; } - memcpy(_prevFrame, _currentFrame, _rowStride*_height); - + memcpy(_prevFrame, _currentFrame, _rowStride * _height); + _compressor.avail_in = _height * _rowStride; deflate(&_compressor, MZ_FINISH); - + *compressedData = _compressBuffer; return _compressor.total_out + 2; } @@ -91,4 +100,4 @@ int CamstudioCodec::CompressFrame(bool isKeyFrame, uint8_t *frameData, uint8_t** const char* CamstudioCodec::GetFourCC() { return "CSCD"; -} \ No newline at end of file +} diff --git a/Utilities/CamstudioCodec.h b/Utilities/CamstudioCodec.h index 4e5eede..0e108bc 100644 --- a/Utilities/CamstudioCodec.h +++ b/Utilities/CamstudioCodec.h @@ -25,6 +25,6 @@ public: virtual ~CamstudioCodec(); virtual bool SetupCompress(int width, int height, uint32_t compressionLevel) override; - virtual int CompressFrame(bool isKeyFrame, uint8_t *frameData, uint8_t** compressedData) override; + virtual int CompressFrame(bool isKeyFrame, uint8_t* frameData, uint8_t** compressedData) override; virtual const char* GetFourCC() override; -}; \ No newline at end of file +}; diff --git a/Utilities/Equalizer.cpp b/Utilities/Equalizer.cpp index 7189816..c965724 100644 --- a/Utilities/Equalizer.cpp +++ b/Utilities/Equalizer.cpp @@ -2,13 +2,14 @@ #include "Equalizer.h" #include "orfanidis_eq.h" -void Equalizer::ApplyEqualizer(uint32_t sampleCount, int16_t *samples) +void Equalizer::ApplyEqualizer(uint32_t sampleCount, int16_t* samples) { double outL, outR; - for(uint32_t i = 0; i < sampleCount; i++) { + for (uint32_t i = 0; i < sampleCount; i++) + { double inL = samples[i * 2]; double inR = samples[i * 2 + 1]; - + _equalizerLeft->sbs_process(&inL, &outL); _equalizerRight->sbs_process(&inR, &outR); @@ -19,13 +20,18 @@ void Equalizer::ApplyEqualizer(uint32_t sampleCount, int16_t *samples) void Equalizer::UpdateEqualizers(vector bandGains, uint32_t sampleRate) { - if(_prevSampleRate != sampleRate || memcmp(bandGains.data(), _prevEqualizerGains.data(), bandGains.size() * sizeof(double)) != 0) { - vector bands = { 40, 56, 80, 113, 160, 225, 320, 450, 600, 750, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 10000, 12500, 13000 }; + if (_prevSampleRate != sampleRate || memcmp(bandGains.data(), _prevEqualizerGains.data(), + bandGains.size() * sizeof(double)) != 0) + { + vector bands = { + 40, 56, 80, 113, 160, 225, 320, 450, 600, 750, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 10000, 12500, 13000 + }; bands.insert(bands.begin(), bands[0] - (bands[1] - bands[0])); bands.insert(bands.end(), bands[bands.size() - 1] + (bands[bands.size() - 1] - bands[bands.size() - 2])); _eqFrequencyGrid.reset(new orfanidis_eq::freq_grid()); - for(size_t i = 1; i < bands.size() - 1; i++) { + for (size_t i = 1; i < bands.size() - 1; i++) + { _eqFrequencyGrid->add_band((bands[i] + bands[i - 1]) / 2, bands[i], (bands[i + 1] + bands[i]) / 2); } @@ -34,7 +40,8 @@ void Equalizer::UpdateEqualizers(vector bandGains, uint32_t sampleRate) _equalizerLeft->set_sample_rate(sampleRate); _equalizerRight->set_sample_rate(sampleRate); - for(unsigned int i = 0; i < _eqFrequencyGrid->get_number_of_bands(); i++) { + for (unsigned int i = 0; i < _eqFrequencyGrid->get_number_of_bands(); i++) + { _equalizerLeft->change_band_gain_db(i, bandGains[i]); _equalizerRight->change_band_gain_db(i, bandGains[i]); } diff --git a/Utilities/Equalizer.h b/Utilities/Equalizer.h index a354d36..83ebfa5 100644 --- a/Utilities/Equalizer.h +++ b/Utilities/Equalizer.h @@ -13,6 +13,6 @@ private: vector _prevEqualizerGains; public: - void ApplyEqualizer(uint32_t sampleCount, int16_t *samples); + void ApplyEqualizer(uint32_t sampleCount, int16_t* samples); void UpdateEqualizers(vector bandGains, uint32_t sampleRate); -}; \ No newline at end of file +}; diff --git a/Utilities/FastString.h b/Utilities/FastString.h index 2e329f7..b3368fa 100644 --- a/Utilities/FastString.h +++ b/Utilities/FastString.h @@ -8,29 +8,38 @@ private: uint16_t _pos = 0; bool _lowerCase = false; - void WriteAll() {} + void WriteAll() + { + } public: FastString(bool lowerCase = false) { _lowerCase = lowerCase; } FastString(const char* str, int size) { Write(str, size); } - FastString(string &str) { Write(str); } + FastString(string& str) { Write(str); } void Write(char c) { - if(_lowerCase) { + if (_lowerCase) + { _buffer[_pos++] = ::tolower(c); - } else { + } + else + { _buffer[_pos++] = c; } } void Write(const char* str, int size) { - if(_lowerCase) { - for(int i = 0; i < size; i++) { + if (_lowerCase) + { + for (int i = 0; i < size; i++) + { _buffer[_pos + i] = ::tolower(str[i]); } - } else { + } + else + { memcpy(_buffer + _pos, str, size); } _pos += size; @@ -38,7 +47,8 @@ public: void Delimiter(const char* str) { - if(_pos > 0) { + if (_pos > 0) + { Write(str, (uint16_t)strlen(str)); } } @@ -48,19 +58,23 @@ public: Write(str, (uint16_t)strlen(str)); } - void Write(string &str, bool preserveCase = false) + void Write(string& str, bool preserveCase = false) { - if(_lowerCase && !preserveCase) { - for(size_t i = 0; i < str.size(); i++) { + if (_lowerCase && !preserveCase) + { + for (size_t i = 0; i < str.size(); i++) + { _buffer[_pos + i] = ::tolower(str[i]); } - } else { + } + else + { memcpy(_buffer + _pos, str.c_str(), str.size()); } _pos += (uint16_t)str.size(); } - void Write(FastString &str) + void Write(FastString& str) { memcpy(_buffer + _pos, str._buffer, str._pos); _pos += str._pos; @@ -77,8 +91,8 @@ public: return _pos; } - template - void WriteAll(T first, Args... args) + template + void WriteAll(T first, Args ... args) { Write(first); WriteAll(args...); diff --git a/Utilities/FolderUtilities.cpp b/Utilities/FolderUtilities.cpp index aba5cf8..53d2a57 100644 --- a/Utilities/FolderUtilities.cpp +++ b/Utilities/FolderUtilities.cpp @@ -2,8 +2,8 @@ #ifndef LIBRETRO #if __has_include() - #include - namespace fs = std::filesystem; +#include +namespace fs = std::filesystem; #elif __has_include() #include namespace fs = std::experimental::filesystem; @@ -30,7 +30,8 @@ void FolderUtilities::SetHomeFolder(string homeFolder) string FolderUtilities::GetHomeFolder() { - if(_homeFolder.size() == 0) { + if (_homeFolder.size() == 0) + { throw std::runtime_error("Home folder not specified"); } return _homeFolder; @@ -42,15 +43,18 @@ void FolderUtilities::AddKnownGameFolder(string gameFolder) string lowerCaseFolder = gameFolder; std::transform(lowerCaseFolder.begin(), lowerCaseFolder.end(), lowerCaseFolder.begin(), ::tolower); - for(string folder : _gameFolders) { + for (string folder : _gameFolders) + { std::transform(folder.begin(), folder.end(), folder.begin(), ::tolower); - if(folder.compare(lowerCaseFolder) == 0) { + if (folder.compare(lowerCaseFolder) == 0) + { alreadyExists = true; break; } } - if(!alreadyExists) { + if (!alreadyExists) + { _gameFolders.push_back(gameFolder); } } @@ -60,7 +64,8 @@ vector FolderUtilities::GetKnownGameFolders() return _gameFolders; } -void FolderUtilities::SetFolderOverrides(string saveFolder, string saveStateFolder, string screenshotFolder, string firmwareFolder) +void FolderUtilities::SetFolderOverrides(string saveFolder, string saveStateFolder, string screenshotFolder, + string firmwareFolder) { _saveFolderOverride = saveFolder; _saveStateFolderOverride = saveStateFolder; @@ -71,9 +76,12 @@ void FolderUtilities::SetFolderOverrides(string saveFolder, string saveStateFold string FolderUtilities::GetSaveFolder() { string folder; - if(_saveFolderOverride.empty()) { + if (_saveFolderOverride.empty()) + { folder = CombinePath(GetHomeFolder(), "Saves"); - } else { + } + else + { folder = _saveFolderOverride; } CreateFolder(folder); @@ -83,9 +91,12 @@ string FolderUtilities::GetSaveFolder() string FolderUtilities::GetFirmwareFolder() { string folder; - if(_firmwareFolderOverride.empty()) { + if (_firmwareFolderOverride.empty()) + { folder = CombinePath(GetHomeFolder(), "Firmware"); - } else { + } + else + { folder = _firmwareFolderOverride; } CreateFolder(folder); @@ -109,9 +120,12 @@ string FolderUtilities::GetDebuggerFolder() string FolderUtilities::GetSaveStateFolder() { string folder; - if(_saveStateFolderOverride.empty()) { + if (_saveStateFolderOverride.empty()) + { folder = CombinePath(GetHomeFolder(), "SaveStates"); - } else { + } + else + { folder = _saveStateFolderOverride; } CreateFolder(folder); @@ -121,9 +135,12 @@ string FolderUtilities::GetSaveStateFolder() string FolderUtilities::GetScreenshotFolder() { string folder; - if(_screenshotFolderOverride.empty()) { + if (_screenshotFolderOverride.empty()) + { folder = CombinePath(GetHomeFolder(), "Screenshots"); - } else { + } + else + { folder = _screenshotFolderOverride; } CreateFolder(folder); @@ -140,7 +157,8 @@ string FolderUtilities::GetRecentGamesFolder() string FolderUtilities::GetExtension(string filename) { size_t position = filename.find_last_of('.'); - if(position != string::npos) { + if (position != string::npos) + { string ext = filename.substr(position, filename.size() - position); std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower); return ext; @@ -160,16 +178,22 @@ vector FolderUtilities::GetFolders(string rootFolder) vector folders; std::error_code errorCode; - if(!fs::is_directory(fs::u8path(rootFolder), errorCode)) { + if (!fs::is_directory(fs::u8path(rootFolder), errorCode)) + { return folders; - } + } - for(fs::recursive_directory_iterator i(fs::u8path(rootFolder)), end; i != end; i++) { - if(i.depth() > 1) { + for (fs::recursive_directory_iterator i(fs::u8path(rootFolder)), end; i != end; i++) + { + if (i.depth() > 1) + { //Prevent excessive recursion i.disable_recursion_pending(); - } else { - if(fs::is_directory(i->path(), errorCode)) { + } + else + { + if (fs::is_directory(i->path(), errorCode)) + { folders.push_back(i->path().u8string()); } } @@ -178,34 +202,46 @@ vector FolderUtilities::GetFolders(string rootFolder) return folders; } -vector FolderUtilities::GetFilesInFolder(string rootFolder, std::unordered_set extensions, bool recursive) +vector FolderUtilities::GetFilesInFolder(string rootFolder, std::unordered_set extensions, + bool recursive) { vector files; - vector folders = { { rootFolder } }; + vector folders = {{rootFolder}}; std::error_code errorCode; - if(!fs::is_directory(fs::u8path(rootFolder), errorCode)) { + if (!fs::is_directory(fs::u8path(rootFolder), errorCode)) + { return files; } - if(recursive) { - for(fs::recursive_directory_iterator i(fs::u8path(rootFolder)), end; i != end; i++) { - if(i.depth() > 1) { + if (recursive) + { + for (fs::recursive_directory_iterator i(fs::u8path(rootFolder)), end; i != end; i++) + { + if (i.depth() > 1) + { //Prevent excessive recursion i.disable_recursion_pending(); - } else { + } + else + { string extension = i->path().extension().u8string(); std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower); - if(extensions.empty() || extensions.find(extension) != extensions.end()) { + if (extensions.empty() || extensions.find(extension) != extensions.end()) + { files.push_back(i->path().u8string()); } } } - } else { - for(fs::directory_iterator i(fs::u8path(rootFolder)), end; i != end; i++) { + } + else + { + for (fs::directory_iterator i(fs::u8path(rootFolder)), end; i != end; i++) + { string extension = i->path().extension().u8string(); std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower); - if(extensions.empty() || extensions.find(extension) != extensions.end()) { + if (extensions.empty() || extensions.find(extension) != extensions.end()) + { files.push_back(i->path().u8string()); } } @@ -217,7 +253,8 @@ vector FolderUtilities::GetFilesInFolder(string rootFolder, std::unorder string FolderUtilities::GetFilename(string filepath, bool includeExtension) { fs::path filename = fs::u8path(filepath).filename(); - if(!includeExtension) { + if (!includeExtension) + { filename.replace_extension(""); } return filename.u8string(); @@ -231,9 +268,12 @@ string FolderUtilities::GetFolderName(string filepath) string FolderUtilities::CombinePath(string folder, string filename) { //Windows supports forward slashes for paths, too. And fs::u8path is abnormally slow. - if(folder[folder.length() - 1] != '/') { + if (folder[folder.length() - 1] != '/') + { return folder + "/" + filename; - } else { + } + else + { return folder + filename; } } @@ -244,7 +284,7 @@ string FolderUtilities::CombinePath(string folder, string filename) #ifdef _WIN32 static const char* PATHSEPARATOR = "\\"; -#else +#else static const char* PATHSEPARATOR = "/"; #endif @@ -286,4 +326,4 @@ string FolderUtilities::CombinePath(string folder, string filename) return folder + filename; } -#endif \ No newline at end of file +#endif diff --git a/Utilities/FolderUtilities.h b/Utilities/FolderUtilities.h index 2fa9505..3b658b9 100644 --- a/Utilities/FolderUtilities.h +++ b/Utilities/FolderUtilities.h @@ -17,7 +17,8 @@ public: static void SetHomeFolder(string homeFolder); static string GetHomeFolder(); - static void SetFolderOverrides(string saveFolder, string saveStateFolder, string screenshotFolder, string firmwareFolder); + static void SetFolderOverrides(string saveFolder, string saveStateFolder, string screenshotFolder, + string firmwareFolder); static void AddKnownGameFolder(string gameFolder); static vector GetKnownGameFolders(); @@ -40,4 +41,4 @@ public: static void CreateFolder(string folder); static string CombinePath(string folder, string filename); -}; \ No newline at end of file +}; diff --git a/Utilities/GifRecorder.cpp b/Utilities/GifRecorder.cpp index a1978e2..f831eb3 100644 --- a/Utilities/GifRecorder.cpp +++ b/Utilities/GifRecorder.cpp @@ -12,7 +12,8 @@ GifRecorder::~GifRecorder() StopRecording(); } -bool GifRecorder::StartRecording(string filename, uint32_t width, uint32_t height, uint32_t bpp, uint32_t audioSampleRate, double fps) +bool GifRecorder::StartRecording(string filename, uint32_t width, uint32_t height, uint32_t bpp, + uint32_t audioSampleRate, double fps) { _outputFile = filename; _recording = GifBegin(_gif.get(), filename.c_str(), width, height, 2, 8, false); @@ -22,7 +23,8 @@ bool GifRecorder::StartRecording(string filename, uint32_t width, uint32_t heigh void GifRecorder::StopRecording() { - if(_recording) { + if (_recording) + { GifEnd(_gif.get()); } } @@ -30,8 +32,9 @@ void GifRecorder::StopRecording() void GifRecorder::AddFrame(void* frameBuffer, uint32_t width, uint32_t height, double fps) { _frameCounter++; - - if(fps < 55 || (_frameCounter % 6) != 0) { + + if (fps < 55 || (_frameCounter % 6) != 0) + { //At 60 FPS, skip 1 of every 6 frames (max FPS for GIFs is 50fps) GifWriteFrame(_gif.get(), (uint8_t*)frameBuffer, width, height, 2, 8, false); } @@ -49,4 +52,4 @@ bool GifRecorder::IsRecording() string GifRecorder::GetOutputFile() { return _outputFile; -} \ No newline at end of file +} diff --git a/Utilities/GifRecorder.h b/Utilities/GifRecorder.h index 4fbecab..5ede201 100644 --- a/Utilities/GifRecorder.h +++ b/Utilities/GifRecorder.h @@ -16,10 +16,11 @@ public: GifRecorder(); virtual ~GifRecorder(); - bool StartRecording(string filename, uint32_t width, uint32_t height, uint32_t bpp, uint32_t audioSampleRate, double fps) override; + bool StartRecording(string filename, uint32_t width, uint32_t height, uint32_t bpp, uint32_t audioSampleRate, + double fps) override; void StopRecording() override; void AddFrame(void* frameBuffer, uint32_t width, uint32_t height, double fps) override; void AddSound(int16_t* soundBuffer, uint32_t sampleCount, uint32_t sampleRate) override; bool IsRecording() override; string GetOutputFile() override; -}; \ No newline at end of file +}; diff --git a/Utilities/HQX/common.h b/Utilities/HQX/common.h index dbd6c33..7ec2785 100644 --- a/Utilities/HQX/common.h +++ b/Utilities/HQX/common.h @@ -43,100 +43,103 @@ extern uint32_t RGBtoYUV[16777216]; static inline uint32_t rgb_to_yuv(uint32_t c) { - // Mask against MASK_RGB to discard the alpha channel - return RGBtoYUV[MASK_RGB & c]; + // Mask against MASK_RGB to discard the alpha channel + return RGBtoYUV[MASK_RGB & c]; } /* Test if there is difference in color */ -static inline int yuv_diff(uint32_t yuv1, uint32_t yuv2) { - return (( std::abs((int)((yuv1 & Ymask) - (yuv2 & Ymask))) > trY ) || - ( std::abs((int)((yuv1 & Umask) - (yuv2 & Umask))) > trU ) || - ( std::abs((int)((yuv1 & Vmask) - (yuv2 & Vmask))) > trV ) ); +static inline int yuv_diff(uint32_t yuv1, uint32_t yuv2) +{ + return ((std::abs((int)((yuv1 & Ymask) - (yuv2 & Ymask))) > trY) || + (std::abs((int)((yuv1 & Umask) - (yuv2 & Umask))) > trU) || + (std::abs((int)((yuv1 & Vmask) - (yuv2 & Vmask))) > trV)); } static inline int Diff(uint32_t c1, uint32_t c2) { - return yuv_diff(rgb_to_yuv(c1), rgb_to_yuv(c2)); + return yuv_diff(rgb_to_yuv(c1), rgb_to_yuv(c2)); } /* Interpolate functions */ static inline uint32_t Interpolate_2(uint32_t c1, int w1, uint32_t c2, int w2, int s) { - if (c1 == c2) { - return c1; - } - return - (((((c1 & MASK_ALPHA) >> 24) * w1 + ((c2 & MASK_ALPHA) >> 24) * w2) << (24-s)) & MASK_ALPHA) + - ((((c1 & MASK_2) * w1 + (c2 & MASK_2) * w2) >> s) & MASK_2) + - ((((c1 & MASK_13) * w1 + (c2 & MASK_13) * w2) >> s) & MASK_13); + if (c1 == c2) + { + return c1; + } + return + (((((c1 & MASK_ALPHA) >> 24) * w1 + ((c2 & MASK_ALPHA) >> 24) * w2) << (24 - s)) & MASK_ALPHA) + + ((((c1 & MASK_2) * w1 + (c2 & MASK_2) * w2) >> s) & MASK_2) + + ((((c1 & MASK_13) * w1 + (c2 & MASK_13) * w2) >> s) & MASK_13); } static inline uint32_t Interpolate_3(uint32_t c1, int w1, uint32_t c2, int w2, uint32_t c3, int w3, int s) { - return - (((((c1 & MASK_ALPHA) >> 24) * w1 + ((c2 & MASK_ALPHA) >> 24) * w2 + ((c3 & MASK_ALPHA) >> 24) * w3) << (24-s)) & MASK_ALPHA) + - ((((c1 & MASK_2) * w1 + (c2 & MASK_2) * w2 + (c3 & MASK_2) * w3) >> s) & MASK_2) + - ((((c1 & MASK_13) * w1 + (c2 & MASK_13) * w2 + (c3 & MASK_13) * w3) >> s) & MASK_13); + return + (((((c1 & MASK_ALPHA) >> 24) * w1 + ((c2 & MASK_ALPHA) >> 24) * w2 + ((c3 & MASK_ALPHA) >> 24) * w3) << (24 - s)) + & MASK_ALPHA) + + ((((c1 & MASK_2) * w1 + (c2 & MASK_2) * w2 + (c3 & MASK_2) * w3) >> s) & MASK_2) + + ((((c1 & MASK_13) * w1 + (c2 & MASK_13) * w2 + (c3 & MASK_13) * w3) >> s) & MASK_13); } static inline uint32_t Interp1(uint32_t c1, uint32_t c2) { - //(c1*3+c2) >> 2; - return Interpolate_2(c1, 3, c2, 1, 2); + //(c1*3+c2) >> 2; + return Interpolate_2(c1, 3, c2, 1, 2); } static inline uint32_t Interp2(uint32_t c1, uint32_t c2, uint32_t c3) { - //(c1*2+c2+c3) >> 2; - return Interpolate_3(c1, 2, c2, 1, c3, 1, 2); + //(c1*2+c2+c3) >> 2; + return Interpolate_3(c1, 2, c2, 1, c3, 1, 2); } static inline uint32_t Interp3(uint32_t c1, uint32_t c2) { - //(c1*7+c2)/8; - return Interpolate_2(c1, 7, c2, 1, 3); + //(c1*7+c2)/8; + return Interpolate_2(c1, 7, c2, 1, 3); } static inline uint32_t Interp4(uint32_t c1, uint32_t c2, uint32_t c3) { - //(c1*2+(c2+c3)*7)/16; - return Interpolate_3(c1, 2, c2, 7, c3, 7, 4); + //(c1*2+(c2+c3)*7)/16; + return Interpolate_3(c1, 2, c2, 7, c3, 7, 4); } static inline uint32_t Interp5(uint32_t c1, uint32_t c2) { - //(c1+c2) >> 1; - return Interpolate_2(c1, 1, c2, 1, 1); + //(c1+c2) >> 1; + return Interpolate_2(c1, 1, c2, 1, 1); } static inline uint32_t Interp6(uint32_t c1, uint32_t c2, uint32_t c3) { - //(c1*5+c2*2+c3)/8; - return Interpolate_3(c1, 5, c2, 2, c3, 1, 3); + //(c1*5+c2*2+c3)/8; + return Interpolate_3(c1, 5, c2, 2, c3, 1, 3); } static inline uint32_t Interp7(uint32_t c1, uint32_t c2, uint32_t c3) { - //(c1*6+c2+c3)/8; - return Interpolate_3(c1, 6, c2, 1, c3, 1, 3); + //(c1*6+c2+c3)/8; + return Interpolate_3(c1, 6, c2, 1, c3, 1, 3); } static inline uint32_t Interp8(uint32_t c1, uint32_t c2) { - //(c1*5+c2*3)/8; - return Interpolate_2(c1, 5, c2, 3, 3); + //(c1*5+c2*3)/8; + return Interpolate_2(c1, 5, c2, 3, 3); } static inline uint32_t Interp9(uint32_t c1, uint32_t c2, uint32_t c3) { - //(c1*2+(c2+c3)*3)/8; - return Interpolate_3(c1, 2, c2, 3, c3, 3, 3); + //(c1*2+(c2+c3)*3)/8; + return Interpolate_3(c1, 2, c2, 3, c3, 3, 3); } static inline uint32_t Interp10(uint32_t c1, uint32_t c2, uint32_t c3) { - //(c1*14+c2+c3)/16; - return Interpolate_3(c1, 14, c2, 1, c3, 1, 4); + //(c1*14+c2+c3)/16; + return Interpolate_3(c1, 14, c2, 1, c3, 1, 4); } #endif diff --git a/Utilities/HQX/hq2x.cpp b/Utilities/HQX/hq2x.cpp index 0aa7fff..6e1c77d 100644 --- a/Utilities/HQX/hq2x.cpp +++ b/Utilities/HQX/hq2x.cpp @@ -72,2739 +72,2741 @@ #define PIXEL11_90 *(dp+dpL+1) = Interp9(w[5], w[6], w[8]); #define PIXEL11_100 *(dp+dpL+1) = Interp10(w[5], w[6], w[8]); -void HQX_CALLCONV hq2x_32_rb( uint32_t * sp, uint32_t srb, uint32_t * dp, uint32_t drb, int Xres, int Yres ) +void HQX_CALLCONV hq2x_32_rb(uint32_t* sp, uint32_t srb, uint32_t* dp, uint32_t drb, int Xres, int Yres) { - int i, j, k; - int prevline, nextline; - uint32_t w[10]; - int dpL = (drb >> 2); - int spL = (srb >> 2); - uint8_t *sRowP = (uint8_t *) sp; - uint8_t *dRowP = (uint8_t *) dp; - uint32_t yuv1, yuv2; + int i, j, k; + int prevline, nextline; + uint32_t w[10]; + int dpL = (drb >> 2); + int spL = (srb >> 2); + uint8_t* sRowP = (uint8_t*)sp; + uint8_t* dRowP = (uint8_t*)dp; + uint32_t yuv1, yuv2; - // +----+----+----+ - // | | | | - // | w1 | w2 | w3 | - // +----+----+----+ - // | | | | - // | w4 | w5 | w6 | - // +----+----+----+ - // | | | | - // | w7 | w8 | w9 | - // +----+----+----+ + // +----+----+----+ + // | | | | + // | w1 | w2 | w3 | + // +----+----+----+ + // | | | | + // | w4 | w5 | w6 | + // +----+----+----+ + // | | | | + // | w7 | w8 | w9 | + // +----+----+----+ - for (j=0; j0) prevline = -spL; else prevline = 0; - if (j 0) prevline = -spL; + else prevline = 0; + if (j < Yres - 1) nextline = spL; + else nextline = 0; - for (i=0; i0) - { - w[1] = *(sp + prevline - 1); - w[4] = *(sp - 1); - w[7] = *(sp + nextline - 1); - } - else - { - w[1] = w[2]; - w[4] = w[5]; - w[7] = w[8]; - } + if (i > 0) + { + w[1] = *(sp + prevline - 1); + w[4] = *(sp - 1); + w[7] = *(sp + nextline - 1); + } + else + { + w[1] = w[2]; + w[4] = w[5]; + w[7] = w[8]; + } - if (i> 2); - int spL = (srb >> 2); - uint8_t *sRowP = (uint8_t *) sp; - uint8_t *dRowP = (uint8_t *) dp; - uint32_t yuv1, yuv2; + int i, j, k; + int prevline, nextline; + uint32_t w[10]; + int dpL = (drb >> 2); + int spL = (srb >> 2); + uint8_t* sRowP = (uint8_t*)sp; + uint8_t* dRowP = (uint8_t*)dp; + uint32_t yuv1, yuv2; - // +----+----+----+ - // | | | | - // | w1 | w2 | w3 | - // +----+----+----+ - // | | | | - // | w4 | w5 | w6 | - // +----+----+----+ - // | | | | - // | w7 | w8 | w9 | - // +----+----+----+ + // +----+----+----+ + // | | | | + // | w1 | w2 | w3 | + // +----+----+----+ + // | | | | + // | w4 | w5 | w6 | + // +----+----+----+ + // | | | | + // | w7 | w8 | w9 | + // +----+----+----+ - for (j=0; j0) prevline = -spL; else prevline = 0; - if (j 0) prevline = -spL; + else prevline = 0; + if (j < Yres - 1) nextline = spL; + else nextline = 0; - for (i=0; i0) - { - w[1] = *(sp + prevline - 1); - w[4] = *(sp - 1); - w[7] = *(sp + nextline - 1); - } - else - { - w[1] = w[2]; - w[4] = w[5]; - w[7] = w[8]; - } + if (i > 0) + { + w[1] = *(sp + prevline - 1); + w[4] = *(sp - 1); + w[7] = *(sp + nextline - 1); + } + else + { + w[1] = w[2]; + w[4] = w[5]; + w[7] = w[8]; + } - if (i> 2); - int spL = (srb >> 2); - uint8_t *sRowP = (uint8_t *) sp; - uint8_t *dRowP = (uint8_t *) dp; - uint32_t yuv1, yuv2; + int i, j, k; + int prevline, nextline; + uint32_t w[10]; + int dpL = (drb >> 2); + int spL = (srb >> 2); + uint8_t* sRowP = (uint8_t*)sp; + uint8_t* dRowP = (uint8_t*)dp; + uint32_t yuv1, yuv2; - // +----+----+----+ - // | | | | - // | w1 | w2 | w3 | - // +----+----+----+ - // | | | | - // | w4 | w5 | w6 | - // +----+----+----+ - // | | | | - // | w7 | w8 | w9 | - // +----+----+----+ + // +----+----+----+ + // | | | | + // | w1 | w2 | w3 | + // +----+----+----+ + // | | | | + // | w4 | w5 | w6 | + // +----+----+----+ + // | | | | + // | w7 | w8 | w9 | + // +----+----+----+ - for (j=0; j0) prevline = -spL; else prevline = 0; - if (j 0) prevline = -spL; + else prevline = 0; + if (j < Yres - 1) nextline = spL; + else nextline = 0; - for (i=0; i0) - { - w[1] = *(sp + prevline - 1); - w[4] = *(sp - 1); - w[7] = *(sp + nextline - 1); - } - else - { - w[1] = w[2]; - w[4] = w[5]; - w[7] = w[8]; - } + if (i > 0) + { + w[1] = *(sp + prevline - 1); + w[4] = *(sp - 1); + w[7] = *(sp + nextline - 1); + } + else + { + w[1] = w[2]; + w[4] = w[5]; + w[7] = w[8]; + } - if (i #if defined( __GNUC__ ) - #ifdef __MINGW32__ +#ifdef __MINGW32__ #define HQX_CALLCONV __stdcall - #else - #define HQX_CALLCONV - #endif #else - #define HQX_CALLCONV + #define HQX_CALLCONV +#endif +#else +#define HQX_CALLCONV #endif #if defined(_WIN32) - #ifdef DLL_EXPORT +#ifdef DLL_EXPORT #define HQX_API __declspec(dllexport) - #else - #define HQX_API __declspec(dllimport) - #endif +#else +#define HQX_API __declspec(dllimport) +#endif #else #define HQX_API #endif void HQX_CALLCONV hqxInit(void); -void HQX_CALLCONV hqx(uint32_t scale, uint32_t * src, uint32_t * dest, int width, int height); +void HQX_CALLCONV hqx(uint32_t scale, uint32_t* src, uint32_t* dest, int width, int height); -void HQX_CALLCONV hq2x_32( uint32_t * src, uint32_t * dest, int width, int height ); -void HQX_CALLCONV hq3x_32( uint32_t * src, uint32_t * dest, int width, int height ); -void HQX_CALLCONV hq4x_32( uint32_t * src, uint32_t * dest, int width, int height ); +void HQX_CALLCONV hq2x_32(uint32_t* src, uint32_t* dest, int width, int height); +void HQX_CALLCONV hq3x_32(uint32_t* src, uint32_t* dest, int width, int height); +void HQX_CALLCONV hq4x_32(uint32_t* src, uint32_t* dest, int width, int height); -void HQX_CALLCONV hq2x_32_rb( uint32_t * src, uint32_t src_rowBytes, uint32_t * dest, uint32_t dest_rowBytes, int width, int height ); -void HQX_CALLCONV hq3x_32_rb( uint32_t * src, uint32_t src_rowBytes, uint32_t * dest, uint32_t dest_rowBytes, int width, int height ); -void HQX_CALLCONV hq4x_32_rb( uint32_t * src, uint32_t src_rowBytes, uint32_t * dest, uint32_t dest_rowBytes, int width, int height ); +void HQX_CALLCONV hq2x_32_rb(uint32_t* src, uint32_t src_rowBytes, uint32_t* dest, uint32_t dest_rowBytes, int width, + int height); +void HQX_CALLCONV hq3x_32_rb(uint32_t* src, uint32_t src_rowBytes, uint32_t* dest, uint32_t dest_rowBytes, int width, + int height); +void HQX_CALLCONV hq4x_32_rb(uint32_t* src, uint32_t src_rowBytes, uint32_t* dest, uint32_t dest_rowBytes, int width, + int height); #endif diff --git a/Utilities/HQX/init.cpp b/Utilities/HQX/init.cpp index be9de48..65e8046 100644 --- a/Utilities/HQX/init.cpp +++ b/Utilities/HQX/init.cpp @@ -20,29 +20,34 @@ #include #include "hqx.h" -uint32_t RGBtoYUV[16777216]; -uint32_t YUV1, YUV2; +uint32_t RGBtoYUV[16777216]; +uint32_t YUV1, YUV2; void HQX_CALLCONV hqxInit(void) { - /* Initalize RGB to YUV lookup table */ - uint32_t c, r, g, b, y, u, v; - for (c = 0; c < 16777215; c++) { - r = (c & 0xFF0000) >> 16; - g = (c & 0x00FF00) >> 8; - b = c & 0x0000FF; - y = (uint32_t)(0.299*r + 0.587*g + 0.114*b); - u = (uint32_t)(-0.169*r - 0.331*g + 0.5*b) + 128; - v = (uint32_t)(0.5*r - 0.419*g - 0.081*b) + 128; - RGBtoYUV[c] = (y << 16) + (u << 8) + v; - } + /* Initalize RGB to YUV lookup table */ + uint32_t c, r, g, b, y, u, v; + for (c = 0; c < 16777215; c++) + { + r = (c & 0xFF0000) >> 16; + g = (c & 0x00FF00) >> 8; + b = c & 0x0000FF; + y = (uint32_t)(0.299 * r + 0.587 * g + 0.114 * b); + u = (uint32_t)(-0.169 * r - 0.331 * g + 0.5 * b) + 128; + v = (uint32_t)(0.5 * r - 0.419 * g - 0.081 * b) + 128; + RGBtoYUV[c] = (y << 16) + (u << 8) + v; + } } -void HQX_CALLCONV hqx(uint32_t scale, uint32_t * src, uint32_t * dest, int width, int height) +void HQX_CALLCONV hqx(uint32_t scale, uint32_t* src, uint32_t* dest, int width, int height) { - switch(scale) { - case 2: hq2x_32(src, dest, width, height); break; - case 3: hq3x_32(src, dest, width, height); break; - case 4: hq4x_32(src, dest, width, height); break; + switch (scale) + { + case 2: hq2x_32(src, dest, width, height); + break; + case 3: hq3x_32(src, dest, width, height); + break; + case 4: hq4x_32(src, dest, width, height); + break; } -} \ No newline at end of file +} diff --git a/Utilities/HermiteResampler.cpp b/Utilities/HermiteResampler.cpp index db1d2d3..e703721 100644 --- a/Utilities/HermiteResampler.cpp +++ b/Utilities/HermiteResampler.cpp @@ -36,7 +36,8 @@ void HermiteResampler::PushSample(double prevValues[4], int16_t sample) void HermiteResampler::Reset() { - for(int i = 0; i < 4; i++) { + for (int i = 0; i < 4; i++) + { _prevLeft[i] = 0.0; _prevRight[i] = 0.0; } @@ -50,15 +51,18 @@ void HermiteResampler::SetSampleRates(double srcRate, double dstRate) uint32_t HermiteResampler::Resample(int16_t* in, uint32_t inSampleCount, int16_t* out) { - if(_rateRatio == 1.0) { + if (_rateRatio == 1.0) + { memcpy(out, in, inSampleCount * 2 * sizeof(int16_t)); return inSampleCount; } uint32_t outPos = 0; - for(uint32_t i = 0; i < inSampleCount * 2; i += 2) { - while(_fraction <= 1.0) { + for (uint32_t i = 0; i < inSampleCount * 2; i += 2) + { + while (_fraction <= 1.0) + { //Generate interpolated samples until we have enough samples for the current source sample out[outPos] = HermiteInterpolate(_prevLeft, _fraction); out[outPos + 1] = HermiteInterpolate(_prevRight, _fraction); diff --git a/Utilities/HermiteResampler.h b/Utilities/HermiteResampler.h index 5755951..94b6cf1 100644 --- a/Utilities/HermiteResampler.h +++ b/Utilities/HermiteResampler.h @@ -17,4 +17,4 @@ public: void SetSampleRates(double srcRate, double dstRate); uint32_t Resample(int16_t* in, uint32_t inSampleCount, int16_t* out); -}; \ No newline at end of file +}; diff --git a/Utilities/HexUtilities.cpp b/Utilities/HexUtilities.cpp index e370eec..a0d64a8 100644 --- a/Utilities/HexUtilities.cpp +++ b/Utilities/HexUtilities.cpp @@ -1,26 +1,8 @@ #include "stdafx.h" #include "HexUtilities.h" -const vector HexUtilities::_hexCache = { { - "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F", - "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F", - "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F", - "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F", - "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F", - "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F", - "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F", - "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D", "7E", "7F", - "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F", - "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F", - "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF", - "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF", - "C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF", - "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF", - "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF", - "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF" -} }; - -constexpr const char* _hexCharCache[256] = { +const vector HexUtilities::_hexCache = { + { "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F", @@ -37,19 +19,45 @@ constexpr const char* _hexCharCache[256] = { "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF", "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF", "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF" + } +}; + +constexpr const char* _hexCharCache[256] = { + "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F", + "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F", + "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F", + "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F", + "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F", + "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F", + "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F", + "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D", "7E", "7F", + "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F", + "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F", + "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF", + "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF", + "C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF", + "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF", + "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF", + "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF" }; int HexUtilities::FromHex(string hex) { int value = 0; - for(size_t i = 0, len = hex.size(); i < len; i++) { + for (size_t i = 0, len = hex.size(); i < len; i++) + { value <<= 4; - if(hex[i] >= '0' && hex[i] <= '9') { + if (hex[i] >= '0' && hex[i] <= '9') + { value |= hex[i] - '0'; - } else if(hex[i] >= 'A' && hex[i] <= 'F') { + } + else if (hex[i] >= 'A' && hex[i] <= 'F') + { value |= hex[i] - 'A' + 10; - } else if(hex[i] >= 'a' && hex[i] <= 'f') { + } + else if (hex[i] >= 'a' && hex[i] <= 'f') + { value |= hex[i] - 'a' + 10; } } @@ -83,23 +91,32 @@ string HexUtilities::ToHex24(int32_t value) string HexUtilities::ToHex(uint32_t value, bool fullSize) { - if(fullSize || value > 0xFFFFFF) { - return _hexCache[value >> 24] + _hexCache[(value >> 16) & 0xFF] + _hexCache[(value >> 8) & 0xFF] + _hexCache[value & 0xFF]; - } else if(value <= 0xFF) { + if (fullSize || value > 0xFFFFFF) + { + return _hexCache[value >> 24] + _hexCache[(value >> 16) & 0xFF] + _hexCache[(value >> 8) & 0xFF] + _hexCache[value + & 0xFF]; + } + else if (value <= 0xFF) + { return ToHex((uint8_t)value); - } else if(value <= 0xFFFF) { + } + else if (value <= 0xFFFF) + { return ToHex((uint16_t)value); - } else { + } + else + { return _hexCache[(value >> 16) & 0xFF] + _hexCache[(value >> 8) & 0xFF] + _hexCache[value & 0xFF]; } } -string HexUtilities::ToHex(vector &data) +string HexUtilities::ToHex(vector& data) { string result; result.reserve(data.size() * 2); - for(uint8_t value : data) { + for (uint8_t value : data) + { result += HexUtilities::ToHex(value); } return result; -} \ No newline at end of file +} diff --git a/Utilities/HexUtilities.h b/Utilities/HexUtilities.h index 606b55a..87690ef 100644 --- a/Utilities/HexUtilities.h +++ b/Utilities/HexUtilities.h @@ -13,7 +13,7 @@ public: static string ToHex(uint32_t value, bool fullSize = false); static string ToHex(int32_t value, bool fullSize = false); static string ToHex24(int32_t value); - static string ToHex(vector &data); + static string ToHex(vector& data); static int FromHex(string hex); -}; \ No newline at end of file +}; diff --git a/Utilities/ISerializable.h b/Utilities/ISerializable.h index 7d8138e..0727845 100644 --- a/Utilities/ISerializable.h +++ b/Utilities/ISerializable.h @@ -5,6 +5,5 @@ class Serializer; class ISerializable { public: - virtual void Serialize(Serializer &s) = 0; + virtual void Serialize(Serializer& s) = 0; }; - diff --git a/Utilities/IVideoRecorder.h b/Utilities/IVideoRecorder.h index 0d5ccd4..73a2d24 100644 --- a/Utilities/IVideoRecorder.h +++ b/Utilities/IVideoRecorder.h @@ -4,7 +4,8 @@ class IVideoRecorder { public: - virtual bool StartRecording(string filename, uint32_t width, uint32_t height, uint32_t bpp, uint32_t audioSampleRate, double fps) = 0; + virtual bool StartRecording(string filename, uint32_t width, uint32_t height, uint32_t bpp, uint32_t audioSampleRate, + double fps) = 0; virtual void StopRecording() = 0; virtual void AddFrame(void* frameBuffer, uint32_t width, uint32_t height, double fps) = 0; @@ -12,4 +13,4 @@ public: virtual bool IsRecording() = 0; virtual string GetOutputFile() = 0; -}; \ No newline at end of file +}; diff --git a/Utilities/IpsPatcher.cpp b/Utilities/IpsPatcher.cpp index c7a4279..d975d50 100644 --- a/Utilities/IpsPatcher.cpp +++ b/Utilities/IpsPatcher.cpp @@ -15,26 +15,32 @@ public: uint16_t RepeatCount = 0; uint8_t Value = 0; - bool ReadRecord(std::istream &ipsFile) + bool ReadRecord(std::istream& ipsFile) { uint8_t buffer[3]; ipsFile.read((char*)buffer, 3); - if(memcmp(buffer, "EOF", 3) == 0) { + if (memcmp(buffer, "EOF", 3) == 0) + { //EOF reached return false; - } else { + } + else + { Address = buffer[2] | (buffer[1] << 8) | (buffer[0] << 16); ipsFile.read((char*)buffer, 2); Length = buffer[1] | (buffer[0] << 8); - if(Length == 0) { + if (Length == 0) + { //RLE record ipsFile.read((char*)buffer, 3); RepeatCount = buffer[1] | (buffer[0] << 8); Value = buffer[2]; - } else { + } + else + { Replacement.resize(Length); ipsFile.read((char*)Replacement.data(), Length); } @@ -42,7 +48,7 @@ public: } } - void WriteRecord(vector &output) + void WriteRecord(vector& output) { output.push_back((Address >> 16) & 0xFF); output.push_back((Address >> 8) & 0xFF); @@ -51,37 +57,42 @@ public: output.push_back((Length >> 8) & 0xFF); output.push_back(Length & 0xFF); - if(Length == 0) { + if (Length == 0) + { output.push_back((RepeatCount >> 8) & 0xFF); output.push_back(RepeatCount & 0xFF); output.push_back(Value); - } else { + } + else + { output.insert(output.end(), Replacement.data(), Replacement.data() + Replacement.size()); } } }; -bool IpsPatcher::PatchBuffer(string ipsFilepath, vector &input, vector &output) +bool IpsPatcher::PatchBuffer(string ipsFilepath, vector& input, vector& output) { ifstream ipsFile(ipsFilepath, std::ios::in | std::ios::binary); - if(ipsFile) { + if (ipsFile) + { return PatchBuffer(ipsFile, input, output); } return false; } -bool IpsPatcher::PatchBuffer(vector &ipsData, vector &input, vector &output) +bool IpsPatcher::PatchBuffer(vector& ipsData, vector& input, vector& output) { std::stringstream ss; ss.write((char*)ipsData.data(), ipsData.size()); return PatchBuffer(ss, input, output); } -bool IpsPatcher::PatchBuffer(std::istream &ipsFile, vector &input, vector &output) +bool IpsPatcher::PatchBuffer(std::istream& ipsFile, vector& input, vector& output) { char header[5]; ipsFile.read((char*)&header, 5); - if(memcmp((char*)&header, "PATCH", 5) != 0) { + if (memcmp((char*)&header, "PATCH", 5) != 0) + { //Invalid ips file return false; } @@ -89,18 +100,24 @@ bool IpsPatcher::PatchBuffer(std::istream &ipsFile, vector &input, vect vector records; int32_t truncateOffset = -1; size_t maxOutputSize = input.size(); - while(!ipsFile.eof()) { + while (!ipsFile.eof()) + { IpsRecord record; - if(record.ReadRecord(ipsFile)) { - if(record.Address + record.Length + record.RepeatCount > maxOutputSize) { + if (record.ReadRecord(ipsFile)) + { + if (record.Address + record.Length + record.RepeatCount > maxOutputSize) + { maxOutputSize = record.Address + record.Length + record.RepeatCount; } records.push_back(record); - } else { + } + else + { //EOF, try to read truncate offset record if it exists uint8_t buffer[3]; ipsFile.read((char*)buffer, 3); - if(!ipsFile.eof()) { + if (!ipsFile.eof()) + { truncateOffset = buffer[2] | (buffer[1] << 8) | (buffer[0] << 16); } break; @@ -110,15 +127,20 @@ bool IpsPatcher::PatchBuffer(std::istream &ipsFile, vector &input, vect output.resize(maxOutputSize); std::copy(input.begin(), input.end(), output.begin()); - for(IpsRecord record : records) { - if(record.Length == 0) { - std::fill(&output[record.Address], &output[record.Address]+record.RepeatCount, record.Value); - } else { - std::copy(record.Replacement.begin(), record.Replacement.end(), output.begin()+record.Address); + for (IpsRecord record : records) + { + if (record.Length == 0) + { + std::fill(&output[record.Address], &output[record.Address] + record.RepeatCount, record.Value); + } + else + { + std::copy(record.Replacement.begin(), record.Replacement.end(), output.begin() + record.Address); } } - if(truncateOffset != -1 && (int32_t)output.size() > truncateOffset) { + if (truncateOffset != -1 && (int32_t)output.size() > truncateOffset) + { output.resize(truncateOffset); } @@ -128,31 +150,41 @@ bool IpsPatcher::PatchBuffer(std::istream &ipsFile, vector &input, vect vector IpsPatcher::CreatePatch(vector originalData, vector newData) { vector patchFile; - if(originalData.size() != newData.size()) { + if (originalData.size() != newData.size()) + { return patchFile; } - uint8_t header[5] = { 'P', 'A', 'T', 'C', 'H' }; + uint8_t header[5] = {'P', 'A', 'T', 'C', 'H'}; patchFile.insert(patchFile.end(), header, header + sizeof(header)); size_t i = 0, len = originalData.size(); - while(i < len) { - while(i < len && originalData[i] == newData[i]) { + while (i < len) + { + while (i < len && originalData[i] == newData[i]) + { i++; } - if(i < len) { + if (i < len) + { IpsRecord patchRecord; uint8_t rleByte = newData[i]; uint8_t rleCount = 0; bool createRleRecord = false; patchRecord.Address = (uint32_t)i; patchRecord.Length = 0; - while(i < len && patchRecord.Length < 65535 && originalData[i] != newData[i]) { - if(newData[i] == rleByte) { + while (i < len && patchRecord.Length < 65535 && originalData[i] != newData[i]) + { + if (newData[i] == rleByte) + { rleCount++; - } else if(createRleRecord) { + } + else if (createRleRecord) + { break; - } else { + } + else + { rleByte = newData[i]; rleCount = 1; } @@ -160,31 +192,39 @@ vector IpsPatcher::CreatePatch(vector originalData, vector 3) || rleCount > 13) { + if ((patchRecord.Length == rleCount && rleCount > 3) || rleCount > 13) + { //Making a RLE entry would probably save space, so write the current entry and create a RLE entry after it - if(patchRecord.Length == rleCount) { + if (patchRecord.Length == rleCount) + { //Same character since the start of this entry, make the RLE entry now createRleRecord = true; - } else { + } + else + { patchRecord.Length -= rleCount; i -= rleCount; break; } } } - if(createRleRecord) { + if (createRleRecord) + { patchRecord.Length = 0; patchRecord.RepeatCount = rleCount; patchRecord.Value = rleByte; - } else { - patchRecord.Replacement = vector(&newData[patchRecord.Address], &newData[patchRecord.Address + patchRecord.Length]); + } + else + { + patchRecord.Replacement = vector(&newData[patchRecord.Address], + &newData[patchRecord.Address + patchRecord.Length]); } patchRecord.WriteRecord(patchFile); } } - uint8_t endOfFile[3] = { 'E', 'O', 'F' }; + uint8_t endOfFile[3] = {'E', 'O', 'F'}; patchFile.insert(patchFile.end(), endOfFile, endOfFile + sizeof(endOfFile)); return patchFile; -} \ No newline at end of file +} diff --git a/Utilities/IpsPatcher.h b/Utilities/IpsPatcher.h index d88081a..4781833 100644 --- a/Utilities/IpsPatcher.h +++ b/Utilities/IpsPatcher.h @@ -5,8 +5,8 @@ class IpsPatcher { public: - static bool PatchBuffer(string ipsFilepath, vector &input, vector &output); + static bool PatchBuffer(string ipsFilepath, vector& input, vector& output); static bool PatchBuffer(vector& ipsData, vector& input, vector& output); - static bool PatchBuffer(std::istream &ipsFile, vector &input, vector &output); + static bool PatchBuffer(std::istream& ipsFile, vector& input, vector& output); static vector CreatePatch(vector originalData, vector newData); -}; \ No newline at end of file +}; diff --git a/Utilities/KreedSaiEagle/2xSai.cpp b/Utilities/KreedSaiEagle/2xSai.cpp index d35e055..b64459b 100644 --- a/Utilities/KreedSaiEagle/2xSai.cpp +++ b/Utilities/KreedSaiEagle/2xSai.cpp @@ -40,8 +40,7 @@ typename_t colorL = *(in + nextline + nextcolumn2); \ typename_t colorM = *(in + nextline2 - prevcolumn); \ typename_t colorN = *(in + nextline2 + 0); \ - typename_t colorO = *(in + nextline2 + nextcolumn); \ - + typename_t colorO = *(in + nextline2 + nextcolumn); #ifndef twoxsai_function #define twoxsai_function(result_cb, interpolate_cb, interpolate2_cb) \ if (colorA == colorD && colorB != colorC) \ @@ -130,20 +129,23 @@ out += 2 #endif -void twoxsai_generic_xrgb8888(unsigned width, unsigned height, uint32_t *src, unsigned src_stride, uint32_t *dst, unsigned dst_stride) +void twoxsai_generic_xrgb8888(unsigned width, unsigned height, uint32_t* src, unsigned src_stride, uint32_t* dst, + unsigned dst_stride) { - unsigned finish; + unsigned finish; int y = 0; int x = 0; - for(; height; height--) { - uint32_t *in = (uint32_t*)src; - uint32_t *out = (uint32_t*)dst; + for (; height; height--) + { + uint32_t* in = (uint32_t*)src; + uint32_t* out = (uint32_t*)dst; int prevline = (y > 0 ? src_stride : 0); int nextline = (height > 1 ? src_stride : 0); int nextline2 = (height > 2 ? src_stride * 2 : nextline); - for(finish = width; finish; finish -= 1) { + for (finish = width; finish; finish -= 1) + { int prevcolumn = (x > 0 ? 1 : 0); int nextcolumn = (finish > 1 ? 1 : 0); int nextcolumn2 = (finish > 2 ? 2 : nextcolumn); diff --git a/Utilities/KreedSaiEagle/SaiEagle.h b/Utilities/KreedSaiEagle/SaiEagle.h index 129f6b1..5502977 100644 --- a/Utilities/KreedSaiEagle/SaiEagle.h +++ b/Utilities/KreedSaiEagle/SaiEagle.h @@ -1,7 +1,9 @@ #pragma once #include "../stdafx.h" -extern void supertwoxsai_generic_xrgb8888(unsigned width, unsigned height, uint32_t *src, unsigned src_stride, uint32_t *dst, unsigned dst_stride); -extern void twoxsai_generic_xrgb8888(unsigned width, unsigned height, uint32_t *src, unsigned src_stride, uint32_t *dst, unsigned dst_stride); -extern void supereagle_generic_xrgb8888(unsigned width, unsigned height, uint32_t *src, unsigned src_stride, uint32_t *dst, unsigned dst_stride); - +extern void supertwoxsai_generic_xrgb8888(unsigned width, unsigned height, uint32_t* src, unsigned src_stride, + uint32_t* dst, unsigned dst_stride); +extern void twoxsai_generic_xrgb8888(unsigned width, unsigned height, uint32_t* src, unsigned src_stride, uint32_t* dst, + unsigned dst_stride); +extern void supereagle_generic_xrgb8888(unsigned width, unsigned height, uint32_t* src, unsigned src_stride, + uint32_t* dst, unsigned dst_stride); diff --git a/Utilities/KreedSaiEagle/Super2xSai.cpp b/Utilities/KreedSaiEagle/Super2xSai.cpp index ee9d7b2..7ea81b8 100644 --- a/Utilities/KreedSaiEagle/Super2xSai.cpp +++ b/Utilities/KreedSaiEagle/Super2xSai.cpp @@ -108,20 +108,23 @@ out += 2 #endif -void supertwoxsai_generic_xrgb8888(unsigned width, unsigned height, uint32_t *src, unsigned src_stride, uint32_t *dst, unsigned dst_stride) +void supertwoxsai_generic_xrgb8888(unsigned width, unsigned height, uint32_t* src, unsigned src_stride, uint32_t* dst, + unsigned dst_stride) { unsigned finish; int y = 0; int x = 0; - for(; height; height--) { - uint32_t *in = (uint32_t*)src; - uint32_t *out = (uint32_t*)dst; + for (; height; height--) + { + uint32_t* in = (uint32_t*)src; + uint32_t* out = (uint32_t*)dst; int prevline = (y > 0 ? src_stride : 0); int nextline = (height > 1 ? src_stride : 0); int nextline2 = (height > 2 ? src_stride * 2 : nextline); - for(finish = width; finish; finish -= 1) { + for (finish = width; finish; finish -= 1) + { int prevcolumn = (x > 0 ? 1 : 0); int nextcolumn = (finish > 1 ? 1 : 0); int nextcolumn2 = (finish > 2 ? 2 : nextcolumn); @@ -133,7 +136,8 @@ void supertwoxsai_generic_xrgb8888(unsigned width, unsigned height, uint32_t *sr // A1 A2 //-------------------------------------- - supertwoxsai_function(supertwoxsai_result, supertwoxsai_interpolate_xrgb8888, supertwoxsai_interpolate2_xrgb8888); + supertwoxsai_function(supertwoxsai_result, supertwoxsai_interpolate_xrgb8888, + supertwoxsai_interpolate2_xrgb8888); x++; } @@ -142,4 +146,4 @@ void supertwoxsai_generic_xrgb8888(unsigned width, unsigned height, uint32_t *sr y++; x = 0; } -} \ No newline at end of file +} diff --git a/Utilities/KreedSaiEagle/SuperEagle.cpp b/Utilities/KreedSaiEagle/SuperEagle.cpp index 11c15d7..c9d8fdf 100644 --- a/Utilities/KreedSaiEagle/SuperEagle.cpp +++ b/Utilities/KreedSaiEagle/SuperEagle.cpp @@ -125,20 +125,23 @@ out += 2 #endif -void supereagle_generic_xrgb8888(unsigned width, unsigned height, uint32_t *src, unsigned src_stride, uint32_t *dst, unsigned dst_stride) +void supereagle_generic_xrgb8888(unsigned width, unsigned height, uint32_t* src, unsigned src_stride, uint32_t* dst, + unsigned dst_stride) { - unsigned finish; + unsigned finish; int y = 0; int x = 0; - for(; height; height--) { - uint32_t *in = (uint32_t*)src; - uint32_t *out = (uint32_t*)dst; + for (; height; height--) + { + uint32_t* in = (uint32_t*)src; + uint32_t* out = (uint32_t*)dst; int prevline = (y > 0 ? src_stride : 0); int nextline = (height > 1 ? src_stride : 0); int nextline2 = (height > 2 ? src_stride * 2 : nextline); - for(finish = width; finish; finish -= 1) { + for (finish = width; finish; finish -= 1) + { int prevcolumn = (x > 0 ? 1 : 0); int nextcolumn = (finish > 1 ? 1 : 0); int nextcolumn2 = (finish > 2 ? 2 : nextcolumn); @@ -153,4 +156,4 @@ void supereagle_generic_xrgb8888(unsigned width, unsigned height, uint32_t *src, y++; x = 0; } -} \ No newline at end of file +} diff --git a/Utilities/LowPassFilter.h b/Utilities/LowPassFilter.h index 4550ecb..f8b7938 100644 --- a/Utilities/LowPassFilter.h +++ b/Utilities/LowPassFilter.h @@ -7,31 +7,36 @@ class LowPassFilter { private: uint8_t _prevSampleCounter = 0; - int16_t _prevSamplesLeft[10] = { 0,0,0,0,0,0,0,0,0,0 }; - int16_t _prevSamplesRight[10] = { 0,0,0,0,0,0,0,0,0,0 }; + int16_t _prevSamplesLeft[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + int16_t _prevSamplesRight[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - void UpdateSample(int16_t *buffer, size_t index, int strength, double volume, int16_t *_prevSamples) + void UpdateSample(int16_t* buffer, size_t index, int strength, double volume, int16_t* _prevSamples) { - if(strength > 0) { + if (strength > 0) + { int32_t sum = std::accumulate(_prevSamples, _prevSamples + strength, 0); buffer[index] = (int16_t)((sum + buffer[index]) / (strength + 1) * volume); _prevSamples[_prevSampleCounter] = buffer[index]; - } else { + } + else + { buffer[index] = (int16_t)(buffer[index] * volume); } } public: - void ApplyFilter(int16_t *buffer, size_t sampleCount, int strength, double volume = 1.0f) + void ApplyFilter(int16_t* buffer, size_t sampleCount, int strength, double volume = 1.0f) { assert(strength <= 10); - for(size_t i = 0; i < sampleCount*2; i+=2) { + for (size_t i = 0; i < sampleCount * 2; i += 2) + { UpdateSample(buffer, i, strength, volume, _prevSamplesLeft); - UpdateSample(buffer, i+1, strength, volume, _prevSamplesRight); - if(strength > 0) { + UpdateSample(buffer, i + 1, strength, volume, _prevSamplesRight); + if (strength > 0) + { _prevSampleCounter = (_prevSampleCounter + 1) % strength; } } } -}; \ No newline at end of file +}; diff --git a/Utilities/PNGHelper.cpp b/Utilities/PNGHelper.cpp index 75fb41d..45cb870 100644 --- a/Utilities/PNGHelper.cpp +++ b/Utilities/PNGHelper.cpp @@ -3,24 +3,30 @@ #include "PNGHelper.h" #include "miniz.h" -bool PNGHelper::WritePNG(std::stringstream &stream, uint32_t* buffer, uint32_t xSize, uint32_t ySize, uint32_t bitsPerPixel) +bool PNGHelper::WritePNG(std::stringstream& stream, uint32_t* buffer, uint32_t xSize, uint32_t ySize, + uint32_t bitsPerPixel) { size_t pngSize = 0; //ARGB -> BGR uint32_t size = xSize * ySize * bitsPerPixel / 8 / 4; vector convertedData(size * 3, 0); - for(uint32_t i = 0; i < size; i++) { + for (uint32_t i = 0; i < size; i++) + { convertedData[i * 3] = (buffer[i] & 0xFF0000) >> 16; convertedData[i * 3 + 1] = (buffer[i] & 0xFF00) >> 8; convertedData[i * 3 + 2] = (buffer[i] & 0xFF); } - void* pngData = tdefl_write_image_to_png_file_in_memory_ex(convertedData.data(), xSize, ySize, 3, &pngSize, MZ_DEFAULT_LEVEL, MZ_FALSE); - if(!pngData) { + void* pngData = tdefl_write_image_to_png_file_in_memory_ex(convertedData.data(), xSize, ySize, 3, &pngSize, + MZ_DEFAULT_LEVEL, MZ_FALSE); + if (!pngData) + { std::cout << "tdefl_write_image_to_png_file_in_memory_ex() failed!" << std::endl; return false; - } else { + } + else + { stream.write((char*)pngData, pngSize); mz_free(pngData); return true; @@ -30,9 +36,11 @@ bool PNGHelper::WritePNG(std::stringstream &stream, uint32_t* buffer, uint32_t x bool PNGHelper::WritePNG(string filename, uint32_t* buffer, uint32_t xSize, uint32_t ySize, uint32_t bitsPerPixel) { std::stringstream stream; - if(WritePNG(stream, buffer, xSize, ySize, bitsPerPixel)) { + if (WritePNG(stream, buffer, xSize, ySize, bitsPerPixel)) + { ofstream file(filename, std::ios::out | std::ios::binary); - if(file.good()) { + if (file.good()) + { file << stream.rdbuf(); } file.close(); @@ -41,7 +49,7 @@ bool PNGHelper::WritePNG(string filename, uint32_t* buffer, uint32_t xSize, uint return false; } -bool PNGHelper::ReadPNG(vector input, vector &output, uint32_t &pngWidth, uint32_t &pngHeight) +bool PNGHelper::ReadPNG(vector input, vector& output, uint32_t& pngWidth, uint32_t& pngHeight) { unsigned long width = 0; unsigned long height = 0; @@ -49,28 +57,34 @@ bool PNGHelper::ReadPNG(vector input, vector &output, uint32_t pngWidth = 0; pngHeight = 0; - if(DecodePNG(output, width, height, input.data(), input.size()) == 0) { - uint32_t *pngDataPtr = (uint32_t*)output.data(); - for(size_t i = 0, len = output.size() / 4; i < len; i++) { + if (DecodePNG(output, width, height, input.data(), input.size()) == 0) + { + uint32_t* pngDataPtr = (uint32_t*)output.data(); + for (size_t i = 0, len = output.size() / 4; i < len; i++) + { //ABGR to ARGB - pngDataPtr[i] = (pngDataPtr[i] & 0xFF00FF00) | ((pngDataPtr[i] & 0xFF0000) >> 16) | ((pngDataPtr[i] & 0xFF) << 16); + pngDataPtr[i] = (pngDataPtr[i] & 0xFF00FF00) | ((pngDataPtr[i] & 0xFF0000) >> 16) | ((pngDataPtr[i] & 0xFF) << + 16); } pngWidth = width; pngHeight = height; return true; - } else { + } + else + { return false; } -} +} -bool PNGHelper::ReadPNG(string filename, vector &pngData, uint32_t &pngWidth, uint32_t &pngHeight) +bool PNGHelper::ReadPNG(string filename, vector& pngData, uint32_t& pngWidth, uint32_t& pngHeight) { pngWidth = 0; pngHeight = 0; ifstream pngFile(filename, std::ios::in | std::ios::binary); - if(pngFile) { + if (pngFile) + { pngFile.seekg(0, std::ios::end); size_t fileSize = (size_t)pngFile.tellg(); pngFile.seekg(0, std::ios::beg); @@ -104,512 +118,846 @@ convert_to_rgba32: optional parameter, true by default. works for trusted PNG files. Use LodePNG instead of picoPNG if you need this information. return: 0 if success, not 0 if some error occured. */ -int PNGHelper::DecodePNG(vector& out_image, unsigned long& image_width, unsigned long& image_height, const unsigned char* in_png, size_t in_size, bool convert_to_rgba32) +int PNGHelper::DecodePNG(vector& out_image, unsigned long& image_width, unsigned long& image_height, + const unsigned char* in_png, size_t in_size, bool convert_to_rgba32) { - // picoPNG version 20101224 - // Copyright (c) 2005-2010 Lode Vandevenne - // - // This software is provided 'as-is', without any express or implied - // warranty. In no event will the authors be held liable for any damages - // arising from the use of this software. - // - // Permission is granted to anyone to use this software for any purpose, - // including commercial applications, and to alter it and redistribute it - // freely, subject to the following restrictions: - // - // 1. The origin of this software must not be misrepresented; you must not - // claim that you wrote the original software. If you use this software - // in a product, an acknowledgment in the product documentation would be - // appreciated but is not required. - // 2. Altered source versions must be plainly marked as such, and must not be - // misrepresented as being the original software. - // 3. This notice may not be removed or altered from any source distribution. - - // picoPNG is a PNG decoder in one C++ function of around 500 lines. Use picoPNG for - // programs that need only 1 .cpp file. Since it's a single function, it's very limited, - // it can convert a PNG to raw pixel data either converted to 32-bit RGBA color or - // with no color conversion at all. For anything more complex, another tiny library - // is available: LodePNG (lodepng.c(pp)), which is a single source and header file. - // Apologies for the compact code style, it's to make this tiny. - - static const unsigned long LENBASE[29] = {3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258}; - static const unsigned long LENEXTRA[29] = {0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0}; - static const unsigned long DISTBASE[30] = {1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577}; - static const unsigned long DISTEXTRA[30] = {0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; - static const unsigned long CLCL[19] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; //code length code lengths - struct Zlib //nested functions for zlib decompression - { - static unsigned long readBitFromStream(size_t& bitp, const unsigned char* bits) { unsigned long result = (bits[bitp >> 3] >> (bitp & 0x7)) & 1; bitp++; return result;} - static unsigned long readBitsFromStream(size_t& bitp, const unsigned char* bits, size_t nbits) - { - unsigned long result = 0; - for(size_t i = 0; i < nbits; i++) result += (readBitFromStream(bitp, bits)) << i; - return result; - } - struct HuffmanTree - { - int makeFromLengths(const std::vector& bitlen, unsigned long maxbitlen) - { //make tree given the lengths - unsigned long numcodes = (unsigned long)(bitlen.size()), treepos = 0, nodefilled = 0; - std::vector tree1d(numcodes), blcount(maxbitlen + 1, 0), nextcode(maxbitlen + 1, 0); - for(unsigned long bits = 0; bits < numcodes; bits++) blcount[bitlen[bits]]++; //count number of instances of each code length - for(unsigned long bits = 1; bits <= maxbitlen; bits++) nextcode[bits] = (nextcode[bits - 1] + blcount[bits - 1]) << 1; - for(unsigned long n = 0; n < numcodes; n++) if(bitlen[n] != 0) tree1d[n] = nextcode[bitlen[n]]++; //generate all the codes - tree2d.clear(); tree2d.resize(numcodes * 2, 32767); //32767 here means the tree2d isn't filled there yet - for(unsigned long n = 0; n < numcodes; n++) //the codes - for(unsigned long i = 0; i < bitlen[n]; i++) //the bits for this code - { - unsigned long bit = (tree1d[n] >> (bitlen[n] - i - 1)) & 1; - if(treepos > numcodes - 2) return 55; - if(tree2d[2 * treepos + bit] == 32767) //not yet filled in - { - if(i + 1 == bitlen[n]) { tree2d[2 * treepos + bit] = n; treepos = 0; } //last bit - else { tree2d[2 * treepos + bit] = ++nodefilled + numcodes; treepos = nodefilled; } //addresses are encoded as values > numcodes - } - else treepos = tree2d[2 * treepos + bit] - numcodes; //subtract numcodes from address to get address value - } - return 0; - } - int decode(bool& decoded, unsigned long& result, size_t& treepos, unsigned long bit) const - { //Decodes a symbol from the tree - unsigned long numcodes = (unsigned long)tree2d.size() / 2; - if(treepos >= numcodes) return 11; //error: you appeared outside the codetree - result = tree2d[2 * treepos + bit]; - decoded = (result < numcodes); - treepos = decoded ? 0 : result - numcodes; - return 0; - } - std::vector tree2d; //2D representation of a huffman tree: The one dimension is "0" or "1", the other contains all nodes and leaves of the tree. - }; - struct Inflator - { - int error; - void inflate(std::vector& out, const std::vector& in, size_t inpos = 0) - { - size_t bp = 0, pos = 0; //bit pointer and byte pointer - error = 0; - unsigned long BFINAL = 0; - while(!BFINAL && !error) - { - if(bp >> 3 >= in.size()) { error = 52; return; } //error, bit pointer will jump past memory - BFINAL = readBitFromStream(bp, &in[inpos]); - unsigned long BTYPE = readBitFromStream(bp, &in[inpos]); BTYPE += 2 * readBitFromStream(bp, &in[inpos]); - if(BTYPE == 3) { error = 20; return; } //error: invalid BTYPE - else if(BTYPE == 0) inflateNoCompression(out, &in[inpos], bp, pos, in.size()); - else inflateHuffmanBlock(out, &in[inpos], bp, pos, in.size(), BTYPE); - } - if(!error) out.resize(pos); //Only now we know the true size of out, resize it to that - } - void generateFixedTrees(HuffmanTree& tree, HuffmanTree& treeD) //get the tree of a deflated block with fixed tree - { - std::vector bitlen(288, 8), bitlenD(32, 5);; - for(size_t i = 144; i <= 255; i++) bitlen[i] = 9; - for(size_t i = 256; i <= 279; i++) bitlen[i] = 7; - tree.makeFromLengths(bitlen, 15); - treeD.makeFromLengths(bitlenD, 15); - } - HuffmanTree codetree, codetreeD, codelengthcodetree; //the code tree for Huffman codes, dist codes, and code length codes - unsigned long huffmanDecodeSymbol(const unsigned char* in, size_t& bp, const HuffmanTree& codetree, size_t inlength) - { //decode a single symbol from given list of bits with given code tree. return value is the symbol - bool decoded; unsigned long ct; - for(size_t treepos = 0;;) - { - if((bp & 0x07) == 0 && (bp >> 3) > inlength) { error = 10; return 0; } //error: end reached without endcode - error = codetree.decode(decoded, ct, treepos, readBitFromStream(bp, in)); if(error) return 0; //stop, an error happened - if(decoded) return ct; - } - } - void getTreeInflateDynamic(HuffmanTree& tree, HuffmanTree& treeD, const unsigned char* in, size_t& bp, size_t inlength) - { //get the tree of a deflated block with dynamic tree, the tree itself is also Huffman compressed with a known tree - std::vector bitlen(288, 0), bitlenD(32, 0); - if(bp >> 3 >= inlength - 2) { error = 49; return; } //the bit pointer is or will go past the memory - size_t HLIT = readBitsFromStream(bp, in, 5) + 257; //number of literal/length codes + 257 - size_t HDIST = readBitsFromStream(bp, in, 5) + 1; //number of dist codes + 1 - size_t HCLEN = readBitsFromStream(bp, in, 4) + 4; //number of code length codes + 4 - std::vector codelengthcode(19); //lengths of tree to decode the lengths of the dynamic tree - for(size_t i = 0; i < 19; i++) codelengthcode[CLCL[i]] = (i < HCLEN) ? readBitsFromStream(bp, in, 3) : 0; - error = codelengthcodetree.makeFromLengths(codelengthcode, 7); if(error) return; - size_t i = 0, replength; - while(i < HLIT + HDIST) - { - unsigned long code = huffmanDecodeSymbol(in, bp, codelengthcodetree, inlength); if(error) return; - if(code <= 15) { if(i < HLIT) bitlen[i++] = code; else bitlenD[i++ - HLIT] = code; } //a length code - else if(code == 16) //repeat previous - { - if(bp >> 3 >= inlength) { error = 50; return; } //error, bit pointer jumps past memory - replength = 3 + readBitsFromStream(bp, in, 2); - unsigned long value; //set value to the previous code - if((i - 1) < HLIT) value = bitlen[i - 1]; - else value = bitlenD[i - HLIT - 1]; - for(size_t n = 0; n < replength; n++) //repeat this value in the next lengths - { - if(i >= HLIT + HDIST) { error = 13; return; } //error: i is larger than the amount of codes - if(i < HLIT) bitlen[i++] = value; else bitlenD[i++ - HLIT] = value; - } - } - else if(code == 17) //repeat "0" 3-10 times - { - if(bp >> 3 >= inlength) { error = 50; return; } //error, bit pointer jumps past memory - replength = 3 + readBitsFromStream(bp, in, 3); - for(size_t n = 0; n < replength; n++) //repeat this value in the next lengths - { - if(i >= HLIT + HDIST) { error = 14; return; } //error: i is larger than the amount of codes - if(i < HLIT) bitlen[i++] = 0; else bitlenD[i++ - HLIT] = 0; - } - } - else if(code == 18) //repeat "0" 11-138 times - { - if(bp >> 3 >= inlength) { error = 50; return; } //error, bit pointer jumps past memory - replength = 11 + readBitsFromStream(bp, in, 7); - for(size_t n = 0; n < replength; n++) //repeat this value in the next lengths - { - if(i >= HLIT + HDIST) { error = 15; return; } //error: i is larger than the amount of codes - if(i < HLIT) bitlen[i++] = 0; else bitlenD[i++ - HLIT] = 0; - } - } - else { error = 16; return; } //error: somehow an unexisting code appeared. This can never happen. - } - if(bitlen[256] == 0) { error = 64; return; } //the length of the end code 256 must be larger than 0 - error = tree.makeFromLengths(bitlen, 15); if(error) return; //now we've finally got HLIT and HDIST, so generate the code trees, and the function is done - error = treeD.makeFromLengths(bitlenD, 15); if(error) return; - } - void inflateHuffmanBlock(std::vector& out, const unsigned char* in, size_t& bp, size_t& pos, size_t inlength, unsigned long btype) - { - if(btype == 1) { generateFixedTrees(codetree, codetreeD); } - else if(btype == 2) { getTreeInflateDynamic(codetree, codetreeD, in, bp, inlength); if(error) return; } - for(;;) - { - unsigned long code = huffmanDecodeSymbol(in, bp, codetree, inlength); if(error) return; - if(code == 256) return; //end code - else if(code <= 255) //literal symbol - { - if(pos >= out.size()) out.resize((pos + 1) * 2); //reserve more room - out[pos++] = (unsigned char)(code); - } - else if(code >= 257 && code <= 285) //length code - { - size_t length = LENBASE[code - 257], numextrabits = LENEXTRA[code - 257]; - if((bp >> 3) >= inlength) { error = 51; return; } //error, bit pointer will jump past memory - length += readBitsFromStream(bp, in, numextrabits); - unsigned long codeD = huffmanDecodeSymbol(in, bp, codetreeD, inlength); if(error) return; - if(codeD > 29) { error = 18; return; } //error: invalid dist code (30-31 are never used) - unsigned long dist = DISTBASE[codeD], numextrabitsD = DISTEXTRA[codeD]; - if((bp >> 3) >= inlength) { error = 51; return; } //error, bit pointer will jump past memory - dist += readBitsFromStream(bp, in, numextrabitsD); - size_t start = pos, back = start - dist; //backwards - if(pos + length >= out.size()) out.resize((pos + length) * 2); //reserve more room - for(size_t i = 0; i < length; i++) { out[pos++] = out[back++]; if(back >= start) back = start - dist; } - } - } - } - void inflateNoCompression(std::vector& out, const unsigned char* in, size_t& bp, size_t& pos, size_t inlength) - { - while((bp & 0x7) != 0) bp++; //go to first boundary of byte - size_t p = bp / 8; - if(p >= inlength - 4) { error = 52; return; } //error, bit pointer will jump past memory - unsigned long LEN = in[p] + 256 * in[p + 1], NLEN = in[p + 2] + 256 * in[p + 3]; p += 4; - if(LEN + NLEN != 65535) { error = 21; return; } //error: NLEN is not one's complement of LEN - if(pos + LEN >= out.size()) out.resize(pos + LEN); - if(p + LEN > inlength) { error = 23; return; } //error: reading outside of in buffer - for(unsigned long n = 0; n < LEN; n++) out[pos++] = in[p++]; //read LEN bytes of literal data - bp = p * 8; - } - }; - int decompress(std::vector& out, const std::vector& in) //returns error value - { - Inflator inflator; - if(in.size() < 2) { return 53; } //error, size of zlib data too small - if((in[0] * 256 + in[1]) % 31 != 0) { return 24; } //error: 256 * in[0] + in[1] must be a multiple of 31, the FCHECK value is supposed to be made that way - unsigned long CM = in[0] & 15, CINFO = (in[0] >> 4) & 15, FDICT = (in[1] >> 5) & 1; - if(CM != 8 || CINFO > 7) { return 25; } //error: only compression method 8: inflate with sliding window of 32k is supported by the PNG spec - if(FDICT != 0) { return 26; } //error: the specification of PNG says about the zlib stream: "The additional flags shall not specify a preset dictionary." - inflator.inflate(out, in, 2); - return inflator.error; //note: adler32 checksum was skipped and ignored - } - }; - struct PNG //nested functions for PNG decoding - { - struct Info - { - unsigned long width, height, colorType, bitDepth, compressionMethod, filterMethod, interlaceMethod, key_r, key_g, key_b; - bool key_defined; //is a transparent color key given? - std::vector palette; - } info; - int error; - void decode(std::vector& out, const unsigned char* in, size_t size, bool convert_to_rgba32) - { - error = 0; - if(size == 0 || in == 0) { error = 48; return; } //the given data is empty - readPngHeader(&in[0], size); if(error) return; - size_t pos = 33; //first byte of the first chunk after the header - std::vector idat; //the data from idat chunks - bool IEND = false; - info.key_defined = false; - while(!IEND) //loop through the chunks, ignoring unknown chunks and stopping at IEND chunk. IDAT data is put at the start of the in buffer - { - if(pos + 8 >= size) { error = 30; return; } //error: size of the in buffer too small to contain next chunk - size_t chunkLength = read32bitInt(&in[pos]); pos += 4; - if(chunkLength > 2147483647) { error = 63; return; } - if(pos + chunkLength >= size) { error = 35; return; } //error: size of the in buffer too small to contain next chunk - if(in[pos + 0] == 'I' && in[pos + 1] == 'D' && in[pos + 2] == 'A' && in[pos + 3] == 'T') //IDAT chunk, containing compressed image data - { - idat.insert(idat.end(), &in[pos + 4], &in[pos + 4 + chunkLength]); - pos += (4 + chunkLength); - } - else if(in[pos + 0] == 'I' && in[pos + 1] == 'E' && in[pos + 2] == 'N' && in[pos + 3] == 'D') { pos += 4; IEND = true; } - else if(in[pos + 0] == 'P' && in[pos + 1] == 'L' && in[pos + 2] == 'T' && in[pos + 3] == 'E') //palette chunk (PLTE) - { - pos += 4; //go after the 4 letters - info.palette.resize(4 * (chunkLength / 3)); - if(info.palette.size() > (4 * 256)) { error = 38; return; } //error: palette too big - for(size_t i = 0; i < info.palette.size(); i += 4) - { - for(size_t j = 0; j < 3; j++) info.palette[i + j] = in[pos++]; //RGB - info.palette[i + 3] = 255; //alpha - } - } - else if(in[pos + 0] == 't' && in[pos + 1] == 'R' && in[pos + 2] == 'N' && in[pos + 3] == 'S') //palette transparency chunk (tRNS) - { - pos += 4; //go after the 4 letters - if(info.colorType == 3) - { - if(4 * chunkLength > info.palette.size()) { error = 39; return; } //error: more alpha values given than there are palette entries - for(size_t i = 0; i < chunkLength; i++) info.palette[4 * i + 3] = in[pos++]; - } - else if(info.colorType == 0) - { - if(chunkLength != 2) { error = 40; return; } //error: this chunk must be 2 bytes for greyscale image - info.key_defined = 1; info.key_r = info.key_g = info.key_b = 256 * in[pos] + in[pos + 1]; pos += 2; - } - else if(info.colorType == 2) - { - if(chunkLength != 6) { error = 41; return; } //error: this chunk must be 6 bytes for RGB image - info.key_defined = 1; - info.key_r = 256 * in[pos] + in[pos + 1]; pos += 2; - info.key_g = 256 * in[pos] + in[pos + 1]; pos += 2; - info.key_b = 256 * in[pos] + in[pos + 1]; pos += 2; - } - else { error = 42; return; } //error: tRNS chunk not allowed for other color models - } - else //it's not an implemented chunk type, so ignore it: skip over the data - { - if(!(in[pos + 0] & 32)) { error = 69; return; } //error: unknown critical chunk (5th bit of first byte of chunk type is 0) - pos += (chunkLength + 4); //skip 4 letters and uninterpreted data of unimplemented chunk - } - pos += 4; //step over CRC (which is ignored) - } - unsigned long bpp = getBpp(info); - std::vector scanlines(((info.width * (info.height * bpp + 7)) / 8) + info.height); //now the out buffer will be filled - Zlib zlib; //decompress with the Zlib decompressor - error = zlib.decompress(scanlines, idat); if(error) return; //stop if the zlib decompressor returned an error - size_t bytewidth = (bpp + 7) / 8, outlength = (info.height * info.width * bpp + 7) / 8; - out.resize(outlength); //time to fill the out buffer - unsigned char* out_ = outlength ? &out[0] : 0; //use a regular pointer to the std::vector for faster code if compiled without optimization - if(info.interlaceMethod == 0) //no interlace, just filter - { - size_t linestart = 0, linelength = (info.width * bpp + 7) / 8; //length in bytes of a scanline, excluding the filtertype byte - if(bpp >= 8) //byte per byte - for(unsigned long y = 0; y < info.height; y++) - { - unsigned long filterType = scanlines[linestart]; - const unsigned char* prevline = (y == 0) ? 0 : &out_[(y - 1) * info.width * bytewidth]; - unFilterScanline(&out_[linestart - y], &scanlines[linestart + 1], prevline, bytewidth, filterType, linelength); if(error) return; - linestart += (1 + linelength); //go to start of next scanline - } - else //less than 8 bits per pixel, so fill it up bit per bit - { - std::vector templine((info.width * bpp + 7) >> 3); //only used if bpp < 8 - for(size_t y = 0, obp = 0; y < info.height; y++) - { - unsigned long filterType = scanlines[linestart]; - const unsigned char* prevline = (y == 0) ? 0 : &out_[(y - 1) * info.width * bytewidth]; - unFilterScanline(&templine[0], &scanlines[linestart + 1], prevline, bytewidth, filterType, linelength); if(error) return; - for(size_t bp = 0; bp < info.width * bpp;) setBitOfReversedStream(obp, out_, readBitFromReversedStream(bp, &templine[0])); - linestart += (1 + linelength); //go to start of next scanline - } - } - } - else //interlaceMethod is 1 (Adam7) - { - size_t passw[7] = { (info.width + 7) / 8, (info.width + 3) / 8, (info.width + 3) / 4, (info.width + 1) / 4, (info.width + 1) / 2, (info.width + 0) / 2, (info.width + 0) / 1 }; - size_t passh[7] = { (info.height + 7) / 8, (info.height + 7) / 8, (info.height + 3) / 8, (info.height + 3) / 4, (info.height + 1) / 4, (info.height + 1) / 2, (info.height + 0) / 2 }; - size_t passstart[7] = {0}; - size_t pattern[28] = {0,4,0,2,0,1,0,0,0,4,0,2,0,1,8,8,4,4,2,2,1,8,8,8,4,4,2,2}; //values for the adam7 passes - for(int i = 0; i < 6; i++) passstart[i + 1] = passstart[i] + passh[i] * ((passw[i] ? 1 : 0) + (passw[i] * bpp + 7) / 8); - std::vector scanlineo((info.width * bpp + 7) / 8), scanlinen((info.width * bpp + 7) / 8); //"old" and "new" scanline - for(int i = 0; i < 7; i++) - adam7Pass(&out_[0], &scanlinen[0], &scanlineo[0], &scanlines[passstart[i]], info.width, pattern[i], pattern[i + 7], pattern[i + 14], pattern[i + 21], passw[i], passh[i], bpp); - } - if(convert_to_rgba32 && (info.colorType != 6 || info.bitDepth != 8)) //conversion needed - { - std::vector data = out; - error = convert(out, &data[0], info, info.width, info.height); - } - } - void readPngHeader(const unsigned char* in, size_t inlength) //read the information from the header and store it in the Info - { - if(inlength < 29) { error = 27; return; } //error: the data length is smaller than the length of the header - if(in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71 || in[4] != 13 || in[5] != 10 || in[6] != 26 || in[7] != 10) { error = 28; return; } //no PNG signature - if(in[12] != 'I' || in[13] != 'H' || in[14] != 'D' || in[15] != 'R') { error = 29; return; } //error: it doesn't start with a IHDR chunk! - info.width = read32bitInt(&in[16]); info.height = read32bitInt(&in[20]); - info.bitDepth = in[24]; info.colorType = in[25]; - info.compressionMethod = in[26]; if(in[26] != 0) { error = 32; return; } //error: only compression method 0 is allowed in the specification - info.filterMethod = in[27]; if(in[27] != 0) { error = 33; return; } //error: only filter method 0 is allowed in the specification - info.interlaceMethod = in[28]; if(in[28] > 1) { error = 34; return; } //error: only interlace methods 0 and 1 exist in the specification - error = checkColorValidity(info.colorType, info.bitDepth); - } - void unFilterScanline(unsigned char* recon, const unsigned char* scanline, const unsigned char* precon, size_t bytewidth, unsigned long filterType, size_t length) - { - switch(filterType) - { - case 0: for(size_t i = 0; i < length; i++) recon[i] = scanline[i]; break; - case 1: - for(size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i]; - for(size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth]; - break; - case 2: - if(precon) for(size_t i = 0; i < length; i++) recon[i] = scanline[i] + precon[i]; - else for(size_t i = 0; i < length; i++) recon[i] = scanline[i]; - break; - case 3: - if(precon) - { - for(size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i] + precon[i] / 2; - for(size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) / 2); - } - else - { - for(size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i]; - for(size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth] / 2; - } - break; - case 4: - if(precon) - { - for(size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i] + paethPredictor(0, precon[i], 0); - for(size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth]); - } - else - { - for(size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i]; - for(size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + paethPredictor(recon[i - bytewidth], 0, 0); - } - break; - default: error = 36; return; //error: unexisting filter type given - } - } - void adam7Pass(unsigned char* out, unsigned char* linen, unsigned char* lineo, const unsigned char* in, unsigned long w, size_t passleft, size_t passtop, size_t spacex, size_t spacey, size_t passw, size_t passh, unsigned long bpp) - { //filter and reposition the pixels into the output when the image is Adam7 interlaced. This function can only do it after the full image is already decoded. The out buffer must have the correct allocated memory size already. - if(passw == 0) return; - size_t bytewidth = (bpp + 7) / 8, linelength = 1 + ((bpp * passw + 7) / 8); - for(unsigned long y = 0; y < passh; y++) - { - unsigned char filterType = in[y * linelength], *prevline = (y == 0) ? 0 : lineo; - unFilterScanline(linen, &in[y * linelength + 1], prevline, bytewidth, filterType, (w * bpp + 7) / 8); if(error) return; - if(bpp >= 8) for(size_t i = 0; i < passw; i++) for(size_t b = 0; b < bytewidth; b++) //b = current byte of this pixel - out[bytewidth * w * (passtop + spacey * y) + bytewidth * (passleft + spacex * i) + b] = linen[bytewidth * i + b]; - else for(size_t i = 0; i < passw; i++) - { - size_t obp = bpp * w * (passtop + spacey * y) + bpp * (passleft + spacex * i), bp = i * bpp; - for(size_t b = 0; b < bpp; b++) setBitOfReversedStream(obp, out, readBitFromReversedStream(bp, &linen[0])); - } - unsigned char* temp = linen; linen = lineo; lineo = temp; //swap the two buffer pointers "line old" and "line new" - } - } - static unsigned long readBitFromReversedStream(size_t& bitp, const unsigned char* bits) { unsigned long result = (bits[bitp >> 3] >> (7 - (bitp & 0x7))) & 1; bitp++; return result;} - static unsigned long readBitsFromReversedStream(size_t& bitp, const unsigned char* bits, unsigned long nbits) - { - unsigned long result = 0; - for(size_t i = nbits - 1; i < nbits; i--) result += ((readBitFromReversedStream(bitp, bits)) << i); - return result; - } - void setBitOfReversedStream(size_t& bitp, unsigned char* bits, unsigned long bit) { bits[bitp >> 3] |= (bit << (7 - (bitp & 0x7))); bitp++; } - unsigned long read32bitInt(const unsigned char* buffer) { return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; } - int checkColorValidity(unsigned long colorType, unsigned long bd) //return type is a LodePNG error code - { - if((colorType == 2 || colorType == 4 || colorType == 6)) { if(!(bd == 8 || bd == 16)) return 37; else return 0; } - else if(colorType == 0) { if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) return 37; else return 0; } - else if(colorType == 3) { if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 )) return 37; else return 0; } - else return 31; //unexisting color type - } - unsigned long getBpp(const Info& info) - { - if(info.colorType == 2) return (3 * info.bitDepth); - else if(info.colorType >= 4) return (info.colorType - 2) * info.bitDepth; - else return info.bitDepth; - } - int convert(std::vector& out, const unsigned char* in, Info& infoIn, unsigned long w, unsigned long h) - { //converts from any color type to 32-bit. return value = LodePNG error code - size_t numpixels = w * h, bp = 0; - out.resize(numpixels * 4); - unsigned char* out_ = out.empty() ? 0 : &out[0]; //faster if compiled without optimization - if(infoIn.bitDepth == 8 && infoIn.colorType == 0) //greyscale - for(size_t i = 0; i < numpixels; i++) - { - out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[i]; - out_[4 * i + 3] = (infoIn.key_defined && in[i] == infoIn.key_r) ? 0 : 255; - } - else if(infoIn.bitDepth == 8 && infoIn.colorType == 2) //RGB color - for(size_t i = 0; i < numpixels; i++) - { - for(size_t c = 0; c < 3; c++) out_[4 * i + c] = in[3 * i + c]; - out_[4 * i + 3] = (infoIn.key_defined == 1 && in[3 * i + 0] == infoIn.key_r && in[3 * i + 1] == infoIn.key_g && in[3 * i + 2] == infoIn.key_b) ? 0 : 255; - } - else if(infoIn.bitDepth == 8 && infoIn.colorType == 3) //indexed color (palette) - for(size_t i = 0; i < numpixels; i++) - { - if(4U * in[i] >= infoIn.palette.size()) return 46; - for(size_t c = 0; c < 4; c++) out_[4 * i + c] = infoIn.palette[4 * in[i] + c]; //get rgb colors from the palette - } - else if(infoIn.bitDepth == 8 && infoIn.colorType == 4) //greyscale with alpha - for(size_t i = 0; i < numpixels; i++) - { - out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[2 * i + 0]; - out_[4 * i + 3] = in[2 * i + 1]; - } - else if(infoIn.bitDepth == 8 && infoIn.colorType == 6) for(size_t i = 0; i < numpixels; i++) for(size_t c = 0; c < 4; c++) out_[4 * i + c] = in[4 * i + c]; //RGB with alpha - else if(infoIn.bitDepth == 16 && infoIn.colorType == 0) //greyscale - for(size_t i = 0; i < numpixels; i++) - { - out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[2 * i]; - out_[4 * i + 3] = (infoIn.key_defined && 256U * in[i] + in[i + 1] == infoIn.key_r) ? 0 : 255; - } - else if(infoIn.bitDepth == 16 && infoIn.colorType == 2) //RGB color - for(size_t i = 0; i < numpixels; i++) - { - for(size_t c = 0; c < 3; c++) out_[4 * i + c] = in[6 * i + 2 * c]; - out_[4 * i + 3] = (infoIn.key_defined && 256U*in[6*i+0]+in[6*i+1] == infoIn.key_r && 256U*in[6*i+2]+in[6*i+3] == infoIn.key_g && 256U*in[6*i+4]+in[6*i+5] == infoIn.key_b) ? 0 : 255; - } - else if(infoIn.bitDepth == 16 && infoIn.colorType == 4) //greyscale with alpha - for(size_t i = 0; i < numpixels; i++) - { - out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[4 * i]; //most significant byte - out_[4 * i + 3] = in[4 * i + 2]; - } - else if(infoIn.bitDepth == 16 && infoIn.colorType == 6) for(size_t i = 0; i < numpixels; i++) for(size_t c = 0; c < 4; c++) out_[4 * i + c] = in[8 * i + 2 * c]; //RGB with alpha - else if(infoIn.bitDepth < 8 && infoIn.colorType == 0) //greyscale - for(size_t i = 0; i < numpixels; i++) - { - unsigned long value = (readBitsFromReversedStream(bp, in, infoIn.bitDepth) * 255) / ((1 << infoIn.bitDepth) - 1); //scale value from 0 to 255 - out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = (unsigned char)(value); - out_[4 * i + 3] = (infoIn.key_defined && value && ((1U << infoIn.bitDepth) - 1U) == infoIn.key_r && ((1U << infoIn.bitDepth) - 1U)) ? 0 : 255; - } - else if(infoIn.bitDepth < 8 && infoIn.colorType == 3) //palette - for(size_t i = 0; i < numpixels; i++) - { - unsigned long value = readBitsFromReversedStream(bp, in, infoIn.bitDepth); - if(4 * value >= infoIn.palette.size()) return 47; - for(size_t c = 0; c < 4; c++) out_[4 * i + c] = infoIn.palette[4 * value + c]; //get rgb colors from the palette - } - return 0; - } - unsigned char paethPredictor(short a, short b, short c) //Paeth predicter, used by PNG filter type 4 - { - short p = a + b - c, pa = p > a ? (p - a) : (a - p), pb = p > b ? (p - b) : (b - p), pc = p > c ? (p - c) : (c - p); - return (unsigned char)((pa <= pb && pa <= pc) ? a : pb <= pc ? b : c); - } - }; - PNG decoder = { }; decoder.decode(out_image, in_png, in_size, convert_to_rgba32); - image_width = decoder.info.width; image_height = decoder.info.height; - return decoder.error; -} \ No newline at end of file + // picoPNG version 20101224 + // Copyright (c) 2005-2010 Lode Vandevenne + // + // This software is provided 'as-is', without any express or implied + // warranty. In no event will the authors be held liable for any damages + // arising from the use of this software. + // + // Permission is granted to anyone to use this software for any purpose, + // including commercial applications, and to alter it and redistribute it + // freely, subject to the following restrictions: + // + // 1. The origin of this software must not be misrepresented; you must not + // claim that you wrote the original software. If you use this software + // in a product, an acknowledgment in the product documentation would be + // appreciated but is not required. + // 2. Altered source versions must be plainly marked as such, and must not be + // misrepresented as being the original software. + // 3. This notice may not be removed or altered from any source distribution. + + // picoPNG is a PNG decoder in one C++ function of around 500 lines. Use picoPNG for + // programs that need only 1 .cpp file. Since it's a single function, it's very limited, + // it can convert a PNG to raw pixel data either converted to 32-bit RGBA color or + // with no color conversion at all. For anything more complex, another tiny library + // is available: LodePNG (lodepng.c(pp)), which is a single source and header file. + // Apologies for the compact code style, it's to make this tiny. + + static const unsigned long LENBASE[29] = { + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258 + }; + static const unsigned long LENEXTRA[29] = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 + }; + static const unsigned long DISTBASE[30] = { + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577 + }; + static const unsigned long DISTEXTRA[30] = { + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 + }; + static const unsigned long CLCL[19] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + //code length code lengths + struct Zlib //nested functions for zlib decompression + { + static unsigned long readBitFromStream(size_t& bitp, const unsigned char* bits) + { + unsigned long result = (bits[bitp >> 3] >> (bitp & 0x7)) & 1; + bitp++; + return result; + } + + static unsigned long readBitsFromStream(size_t& bitp, const unsigned char* bits, size_t nbits) + { + unsigned long result = 0; + for (size_t i = 0; i < nbits; i++) result += (readBitFromStream(bitp, bits)) << i; + return result; + } + + struct HuffmanTree + { + int makeFromLengths(const std::vector& bitlen, unsigned long maxbitlen) + { + //make tree given the lengths + unsigned long numcodes = (unsigned long)(bitlen.size()), treepos = 0, nodefilled = 0; + std::vector tree1d(numcodes), blcount(maxbitlen + 1, 0), nextcode(maxbitlen + 1, 0); + for (unsigned long bits = 0; bits < numcodes; bits++) blcount[bitlen[bits]]++; + //count number of instances of each code length + for (unsigned long bits = 1; bits <= maxbitlen; bits++) nextcode[bits] = (nextcode[bits - 1] + blcount[bits + - 1]) << 1; + for (unsigned long n = 0; n < numcodes; n++) if (bitlen[n] != 0) tree1d[n] = nextcode[bitlen[n]]++; + //generate all the codes + tree2d.clear(); + tree2d.resize(numcodes * 2, 32767); //32767 here means the tree2d isn't filled there yet + for (unsigned long n = 0; n < numcodes; n++) //the codes + for (unsigned long i = 0; i < bitlen[n]; i++) //the bits for this code + { + unsigned long bit = (tree1d[n] >> (bitlen[n] - i - 1)) & 1; + if (treepos > numcodes - 2) return 55; + if (tree2d[2 * treepos + bit] == 32767) //not yet filled in + { + if (i + 1 == bitlen[n]) + { + tree2d[2 * treepos + bit] = n; + treepos = 0; + } //last bit + else + { + tree2d[2 * treepos + bit] = ++nodefilled + numcodes; + treepos = nodefilled; + } //addresses are encoded as values > numcodes + } + else treepos = tree2d[2 * treepos + bit] - numcodes; + //subtract numcodes from address to get address value + } + return 0; + } + + int decode(bool& decoded, unsigned long& result, size_t& treepos, unsigned long bit) const + { + //Decodes a symbol from the tree + unsigned long numcodes = (unsigned long)tree2d.size() / 2; + if (treepos >= numcodes) return 11; //error: you appeared outside the codetree + result = tree2d[2 * treepos + bit]; + decoded = (result < numcodes); + treepos = decoded ? 0 : result - numcodes; + return 0; + } + + std::vector tree2d; + //2D representation of a huffman tree: The one dimension is "0" or "1", the other contains all nodes and leaves of the tree. + }; + + struct Inflator + { + int error; + + void inflate(std::vector& out, const std::vector& in, size_t inpos = 0) + { + size_t bp = 0, pos = 0; //bit pointer and byte pointer + error = 0; + unsigned long BFINAL = 0; + while (!BFINAL && !error) + { + if (bp >> 3 >= in.size()) + { + error = 52; + return; + } //error, bit pointer will jump past memory + BFINAL = readBitFromStream(bp, &in[inpos]); + unsigned long BTYPE = readBitFromStream(bp, &in[inpos]); + BTYPE += 2 * readBitFromStream(bp, &in[inpos]); + if (BTYPE == 3) + { + error = 20; + return; + } //error: invalid BTYPE + else if (BTYPE == 0) inflateNoCompression(out, &in[inpos], bp, pos, in.size()); + else inflateHuffmanBlock(out, &in[inpos], bp, pos, in.size(), BTYPE); + } + if (!error) out.resize(pos); //Only now we know the true size of out, resize it to that + } + + void generateFixedTrees(HuffmanTree& tree, HuffmanTree& treeD) + //get the tree of a deflated block with fixed tree + { + std::vector bitlen(288, 8), bitlenD(32, 5);; + for (size_t i = 144; i <= 255; i++) bitlen[i] = 9; + for (size_t i = 256; i <= 279; i++) bitlen[i] = 7; + tree.makeFromLengths(bitlen, 15); + treeD.makeFromLengths(bitlenD, 15); + } + + HuffmanTree codetree, codetreeD, codelengthcodetree; + //the code tree for Huffman codes, dist codes, and code length codes + unsigned long huffmanDecodeSymbol(const unsigned char* in, size_t& bp, const HuffmanTree& codetree, + size_t inlength) + { + //decode a single symbol from given list of bits with given code tree. return value is the symbol + bool decoded; + unsigned long ct; + for (size_t treepos = 0;;) + { + if ((bp & 0x07) == 0 && (bp >> 3) > inlength) + { + error = 10; + return 0; + } //error: end reached without endcode + error = codetree.decode(decoded, ct, treepos, readBitFromStream(bp, in)); + if (error) return 0; //stop, an error happened + if (decoded) return ct; + } + } + + void getTreeInflateDynamic(HuffmanTree& tree, HuffmanTree& treeD, const unsigned char* in, size_t& bp, + size_t inlength) + { + //get the tree of a deflated block with dynamic tree, the tree itself is also Huffman compressed with a known tree + std::vector bitlen(288, 0), bitlenD(32, 0); + if (bp >> 3 >= inlength - 2) + { + error = 49; + return; + } //the bit pointer is or will go past the memory + size_t HLIT = readBitsFromStream(bp, in, 5) + 257; //number of literal/length codes + 257 + size_t HDIST = readBitsFromStream(bp, in, 5) + 1; //number of dist codes + 1 + size_t HCLEN = readBitsFromStream(bp, in, 4) + 4; //number of code length codes + 4 + std::vector codelengthcode(19); //lengths of tree to decode the lengths of the dynamic tree + for (size_t i = 0; i < 19; i++) codelengthcode[CLCL[i]] = (i < HCLEN) ? readBitsFromStream(bp, in, 3) : 0; + error = codelengthcodetree.makeFromLengths(codelengthcode, 7); + if (error) return; + size_t i = 0, replength; + while (i < HLIT + HDIST) + { + unsigned long code = huffmanDecodeSymbol(in, bp, codelengthcodetree, inlength); + if (error) return; + if (code <= 15) + { + if (i < HLIT) bitlen[i++] = code; + else bitlenD[i++ - HLIT] = code; + } //a length code + else if (code == 16) //repeat previous + { + if (bp >> 3 >= inlength) + { + error = 50; + return; + } //error, bit pointer jumps past memory + replength = 3 + readBitsFromStream(bp, in, 2); + unsigned long value; //set value to the previous code + if ((i - 1) < HLIT) value = bitlen[i - 1]; + else value = bitlenD[i - HLIT - 1]; + for (size_t n = 0; n < replength; n++) //repeat this value in the next lengths + { + if (i >= HLIT + HDIST) + { + error = 13; + return; + } //error: i is larger than the amount of codes + if (i < HLIT) bitlen[i++] = value; + else bitlenD[i++ - HLIT] = value; + } + } + else if (code == 17) //repeat "0" 3-10 times + { + if (bp >> 3 >= inlength) + { + error = 50; + return; + } //error, bit pointer jumps past memory + replength = 3 + readBitsFromStream(bp, in, 3); + for (size_t n = 0; n < replength; n++) //repeat this value in the next lengths + { + if (i >= HLIT + HDIST) + { + error = 14; + return; + } //error: i is larger than the amount of codes + if (i < HLIT) bitlen[i++] = 0; + else bitlenD[i++ - HLIT] = 0; + } + } + else if (code == 18) //repeat "0" 11-138 times + { + if (bp >> 3 >= inlength) + { + error = 50; + return; + } //error, bit pointer jumps past memory + replength = 11 + readBitsFromStream(bp, in, 7); + for (size_t n = 0; n < replength; n++) //repeat this value in the next lengths + { + if (i >= HLIT + HDIST) + { + error = 15; + return; + } //error: i is larger than the amount of codes + if (i < HLIT) bitlen[i++] = 0; + else bitlenD[i++ - HLIT] = 0; + } + } + else + { + error = 16; + return; + } //error: somehow an unexisting code appeared. This can never happen. + } + if (bitlen[256] == 0) + { + error = 64; + return; + } //the length of the end code 256 must be larger than 0 + error = tree.makeFromLengths(bitlen, 15); + if (error) return; + //now we've finally got HLIT and HDIST, so generate the code trees, and the function is done + error = treeD.makeFromLengths(bitlenD, 15); + if (error) return; + } + + void inflateHuffmanBlock(std::vector& out, const unsigned char* in, size_t& bp, size_t& pos, + size_t inlength, unsigned long btype) + { + if (btype == 1) { generateFixedTrees(codetree, codetreeD); } + else if (btype == 2) + { + getTreeInflateDynamic(codetree, codetreeD, in, bp, inlength); + if (error) return; + } + for (;;) + { + unsigned long code = huffmanDecodeSymbol(in, bp, codetree, inlength); + if (error) return; + if (code == 256) return; //end code + else if (code <= 255) //literal symbol + { + if (pos >= out.size()) out.resize((pos + 1) * 2); //reserve more room + out[pos++] = (unsigned char)(code); + } + else if (code >= 257 && code <= 285) //length code + { + size_t length = LENBASE[code - 257], numextrabits = LENEXTRA[code - 257]; + if ((bp >> 3) >= inlength) + { + error = 51; + return; + } //error, bit pointer will jump past memory + length += readBitsFromStream(bp, in, numextrabits); + unsigned long codeD = huffmanDecodeSymbol(in, bp, codetreeD, inlength); + if (error) return; + if (codeD > 29) + { + error = 18; + return; + } //error: invalid dist code (30-31 are never used) + unsigned long dist = DISTBASE[codeD], numextrabitsD = DISTEXTRA[codeD]; + if ((bp >> 3) >= inlength) + { + error = 51; + return; + } //error, bit pointer will jump past memory + dist += readBitsFromStream(bp, in, numextrabitsD); + size_t start = pos, back = start - dist; //backwards + if (pos + length >= out.size()) out.resize((pos + length) * 2); //reserve more room + for (size_t i = 0; i < length; i++) + { + out[pos++] = out[back++]; + if (back >= start) back = start - dist; + } + } + } + } + + void inflateNoCompression(std::vector& out, const unsigned char* in, size_t& bp, size_t& pos, + size_t inlength) + { + while ((bp & 0x7) != 0) bp++; //go to first boundary of byte + size_t p = bp / 8; + if (p >= inlength - 4) + { + error = 52; + return; + } //error, bit pointer will jump past memory + unsigned long LEN = in[p] + 256 * in[p + 1], NLEN = in[p + 2] + 256 * in[p + 3]; + p += 4; + if (LEN + NLEN != 65535) + { + error = 21; + return; + } //error: NLEN is not one's complement of LEN + if (pos + LEN >= out.size()) out.resize(pos + LEN); + if (p + LEN > inlength) + { + error = 23; + return; + } //error: reading outside of in buffer + for (unsigned long n = 0; n < LEN; n++) out[pos++] = in[p++]; //read LEN bytes of literal data + bp = p * 8; + } + }; + + int decompress(std::vector& out, const std::vector& in) //returns error value + { + Inflator inflator; + if (in.size() < 2) { return 53; } //error, size of zlib data too small + if ((in[0] * 256 + in[1]) % 31 != 0) { return 24; } + //error: 256 * in[0] + in[1] must be a multiple of 31, the FCHECK value is supposed to be made that way + unsigned long CM = in[0] & 15, CINFO = (in[0] >> 4) & 15, FDICT = (in[1] >> 5) & 1; + if (CM != 8 || CINFO > 7) { return 25; } + //error: only compression method 8: inflate with sliding window of 32k is supported by the PNG spec + if (FDICT != 0) { return 26; } + //error: the specification of PNG says about the zlib stream: "The additional flags shall not specify a preset dictionary." + inflator.inflate(out, in, 2); + return inflator.error; //note: adler32 checksum was skipped and ignored + } + }; + struct PNG //nested functions for PNG decoding + { + struct Info + { + unsigned long width, height, colorType, bitDepth, compressionMethod, filterMethod, interlaceMethod, key_r, + key_g, key_b; + bool key_defined; //is a transparent color key given? + std::vector palette; + } info; + + int error; + + void decode(std::vector& out, const unsigned char* in, size_t size, bool convert_to_rgba32) + { + error = 0; + if (size == 0 || in == 0) + { + error = 48; + return; + } //the given data is empty + readPngHeader(&in[0], size); + if (error) return; + size_t pos = 33; //first byte of the first chunk after the header + std::vector idat; //the data from idat chunks + bool IEND = false; + info.key_defined = false; + while (!IEND) + //loop through the chunks, ignoring unknown chunks and stopping at IEND chunk. IDAT data is put at the start of the in buffer + { + if (pos + 8 >= size) + { + error = 30; + return; + } //error: size of the in buffer too small to contain next chunk + size_t chunkLength = read32bitInt(&in[pos]); + pos += 4; + if (chunkLength > 2147483647) + { + error = 63; + return; + } + if (pos + chunkLength >= size) + { + error = 35; + return; + } //error: size of the in buffer too small to contain next chunk + if (in[pos + 0] == 'I' && in[pos + 1] == 'D' && in[pos + 2] == 'A' && in[pos + 3] == 'T') + //IDAT chunk, containing compressed image data + { + idat.insert(idat.end(), &in[pos + 4], &in[pos + 4 + chunkLength]); + pos += (4 + chunkLength); + } + else if (in[pos + 0] == 'I' && in[pos + 1] == 'E' && in[pos + 2] == 'N' && in[pos + 3] == 'D') + { + pos += 4; + IEND = true; + } + else if (in[pos + 0] == 'P' && in[pos + 1] == 'L' && in[pos + 2] == 'T' && in[pos + 3] == 'E') + //palette chunk (PLTE) + { + pos += 4; //go after the 4 letters + info.palette.resize(4 * (chunkLength / 3)); + if (info.palette.size() > (4 * 256)) + { + error = 38; + return; + } //error: palette too big + for (size_t i = 0; i < info.palette.size(); i += 4) + { + for (size_t j = 0; j < 3; j++) info.palette[i + j] = in[pos++]; //RGB + info.palette[i + 3] = 255; //alpha + } + } + else if (in[pos + 0] == 't' && in[pos + 1] == 'R' && in[pos + 2] == 'N' && in[pos + 3] == 'S') + //palette transparency chunk (tRNS) + { + pos += 4; //go after the 4 letters + if (info.colorType == 3) + { + if (4 * chunkLength > info.palette.size()) + { + error = 39; + return; + } //error: more alpha values given than there are palette entries + for (size_t i = 0; i < chunkLength; i++) info.palette[4 * i + 3] = in[pos++]; + } + else if (info.colorType == 0) + { + if (chunkLength != 2) + { + error = 40; + return; + } //error: this chunk must be 2 bytes for greyscale image + info.key_defined = 1; + info.key_r = info.key_g = info.key_b = 256 * in[pos] + in[pos + 1]; + pos += 2; + } + else if (info.colorType == 2) + { + if (chunkLength != 6) + { + error = 41; + return; + } //error: this chunk must be 6 bytes for RGB image + info.key_defined = 1; + info.key_r = 256 * in[pos] + in[pos + 1]; + pos += 2; + info.key_g = 256 * in[pos] + in[pos + 1]; + pos += 2; + info.key_b = 256 * in[pos] + in[pos + 1]; + pos += 2; + } + else + { + error = 42; + return; + } //error: tRNS chunk not allowed for other color models + } + else //it's not an implemented chunk type, so ignore it: skip over the data + { + if (!(in[pos + 0] & 32)) + { + error = 69; + return; + } //error: unknown critical chunk (5th bit of first byte of chunk type is 0) + pos += (chunkLength + 4); //skip 4 letters and uninterpreted data of unimplemented chunk + } + pos += 4; //step over CRC (which is ignored) + } + unsigned long bpp = getBpp(info); + std::vector scanlines(((info.width * (info.height * bpp + 7)) / 8) + info.height); + //now the out buffer will be filled + Zlib zlib; //decompress with the Zlib decompressor + error = zlib.decompress(scanlines, idat); + if (error) return; //stop if the zlib decompressor returned an error + size_t bytewidth = (bpp + 7) / 8, outlength = (info.height * info.width * bpp + 7) / 8; + out.resize(outlength); //time to fill the out buffer + unsigned char* out_ = outlength ? &out[0] : 0; + //use a regular pointer to the std::vector for faster code if compiled without optimization + if (info.interlaceMethod == 0) //no interlace, just filter + { + size_t linestart = 0, linelength = (info.width * bpp + 7) / 8; + //length in bytes of a scanline, excluding the filtertype byte + if (bpp >= 8) //byte per byte + for (unsigned long y = 0; y < info.height; y++) + { + unsigned long filterType = scanlines[linestart]; + const unsigned char* prevline = (y == 0) ? 0 : &out_[(y - 1) * info.width * bytewidth]; + unFilterScanline(&out_[linestart - y], &scanlines[linestart + 1], prevline, bytewidth, filterType, + linelength); + if (error) return; + linestart += (1 + linelength); //go to start of next scanline + } + else //less than 8 bits per pixel, so fill it up bit per bit + { + std::vector templine((info.width * bpp + 7) >> 3); //only used if bpp < 8 + for (size_t y = 0, obp = 0; y < info.height; y++) + { + unsigned long filterType = scanlines[linestart]; + const unsigned char* prevline = (y == 0) ? 0 : &out_[(y - 1) * info.width * bytewidth]; + unFilterScanline(&templine[0], &scanlines[linestart + 1], prevline, bytewidth, filterType, + linelength); + if (error) return; + for (size_t bp = 0; bp < info.width * bpp;) setBitOfReversedStream( + obp, out_, readBitFromReversedStream(bp, &templine[0])); + linestart += (1 + linelength); //go to start of next scanline + } + } + } + else //interlaceMethod is 1 (Adam7) + { + size_t passw[7] = { + (info.width + 7) / 8, (info.width + 3) / 8, (info.width + 3) / 4, (info.width + 1) / 4, + (info.width + 1) / 2, (info.width + 0) / 2, (info.width + 0) / 1 + }; + size_t passh[7] = { + (info.height + 7) / 8, (info.height + 7) / 8, (info.height + 3) / 8, (info.height + 3) / 4, + (info.height + 1) / 4, (info.height + 1) / 2, (info.height + 0) / 2 + }; + size_t passstart[7] = {0}; + size_t pattern[28] = { + 0, 4, 0, 2, 0, 1, 0, 0, 0, 4, 0, 2, 0, 1, 8, 8, 4, 4, 2, 2, 1, 8, 8, 8, 4, 4, 2, 2 + }; //values for the adam7 passes + for (int i = 0; i < 6; i++) passstart[i + 1] = passstart[i] + passh[i] * ((passw[i] ? 1 : 0) + (passw[i] * + bpp + 7) / 8); + std::vector scanlineo((info.width * bpp + 7) / 8), scanlinen((info.width * bpp + 7) / 8); + //"old" and "new" scanline + for (int i = 0; i < 7; i++) + adam7Pass(&out_[0], &scanlinen[0], &scanlineo[0], &scanlines[passstart[i]], info.width, pattern[i], + pattern[i + 7], pattern[i + 14], pattern[i + 21], passw[i], passh[i], bpp); + } + if (convert_to_rgba32 && (info.colorType != 6 || info.bitDepth != 8)) //conversion needed + { + std::vector data = out; + error = convert(out, &data[0], info, info.width, info.height); + } + } + + void readPngHeader(const unsigned char* in, size_t inlength) + //read the information from the header and store it in the Info + { + if (inlength < 29) + { + error = 27; + return; + } //error: the data length is smaller than the length of the header + if (in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71 || in[4] != 13 || in[5] != 10 || in[6] != 26 || + in[7] != 10) + { + error = 28; + return; + } //no PNG signature + if (in[12] != 'I' || in[13] != 'H' || in[14] != 'D' || in[15] != 'R') + { + error = 29; + return; + } //error: it doesn't start with a IHDR chunk! + info.width = read32bitInt(&in[16]); + info.height = read32bitInt(&in[20]); + info.bitDepth = in[24]; + info.colorType = in[25]; + info.compressionMethod = in[26]; + if (in[26] != 0) + { + error = 32; + return; + } //error: only compression method 0 is allowed in the specification + info.filterMethod = in[27]; + if (in[27] != 0) + { + error = 33; + return; + } //error: only filter method 0 is allowed in the specification + info.interlaceMethod = in[28]; + if (in[28] > 1) + { + error = 34; + return; + } //error: only interlace methods 0 and 1 exist in the specification + error = checkColorValidity(info.colorType, info.bitDepth); + } + + void unFilterScanline(unsigned char* recon, const unsigned char* scanline, const unsigned char* precon, + size_t bytewidth, unsigned long filterType, size_t length) + { + switch (filterType) + { + case 0: for (size_t i = 0; i < length; i++) recon[i] = scanline[i]; + break; + case 1: + for (size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i]; + for (size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth]; + break; + case 2: + if (precon) for (size_t i = 0; i < length; i++) recon[i] = scanline[i] + precon[i]; + else for (size_t i = 0; i < length; i++) recon[i] = scanline[i]; + break; + case 3: + if (precon) + { + for (size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i] + precon[i] / 2; + for (size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) + / 2); + } + else + { + for (size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i]; + for (size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth] / 2; + } + break; + case 4: + if (precon) + { + for (size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i] + paethPredictor(0, precon[i], 0); + for (size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + paethPredictor( + recon[i - bytewidth], precon[i], precon[i - bytewidth]); + } + else + { + for (size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i]; + for (size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + paethPredictor( + recon[i - bytewidth], 0, 0); + } + break; + default: error = 36; + return; //error: unexisting filter type given + } + } + + void adam7Pass(unsigned char* out, unsigned char* linen, unsigned char* lineo, const unsigned char* in, + unsigned long w, size_t passleft, size_t passtop, size_t spacex, size_t spacey, size_t passw, + size_t passh, unsigned long bpp) + { + //filter and reposition the pixels into the output when the image is Adam7 interlaced. This function can only do it after the full image is already decoded. The out buffer must have the correct allocated memory size already. + if (passw == 0) return; + size_t bytewidth = (bpp + 7) / 8, linelength = 1 + ((bpp * passw + 7) / 8); + for (unsigned long y = 0; y < passh; y++) + { + unsigned char filterType = in[y * linelength], *prevline = (y == 0) ? 0 : lineo; + unFilterScanline(linen, &in[y * linelength + 1], prevline, bytewidth, filterType, (w * bpp + 7) / 8); + if (error) return; + if (bpp >= 8) + for (size_t i = 0; i < passw; i++) + for (size_t b = 0; b < bytewidth; b++) //b = current byte of this pixel + out[bytewidth * w * (passtop + spacey * y) + bytewidth * (passleft + spacex * i) + b] = linen[ + bytewidth * i + b]; + else + for (size_t i = 0; i < passw; i++) + { + size_t obp = bpp * w * (passtop + spacey * y) + bpp * (passleft + spacex * i), bp = i * bpp; + for (size_t b = 0; b < bpp; b++) setBitOfReversedStream( + obp, out, readBitFromReversedStream(bp, &linen[0])); + } + unsigned char* temp = linen; + linen = lineo; + lineo = temp; //swap the two buffer pointers "line old" and "line new" + } + } + + static unsigned long readBitFromReversedStream(size_t& bitp, const unsigned char* bits) + { + unsigned long result = (bits[bitp >> 3] >> (7 - (bitp & 0x7))) & 1; + bitp++; + return result; + } + + static unsigned long readBitsFromReversedStream(size_t& bitp, const unsigned char* bits, unsigned long nbits) + { + unsigned long result = 0; + for (size_t i = nbits - 1; i < nbits; i--) result += ((readBitFromReversedStream(bitp, bits)) << i); + return result; + } + + void setBitOfReversedStream(size_t& bitp, unsigned char* bits, unsigned long bit) + { + bits[bitp >> 3] |= (bit << (7 - (bitp & 0x7))); + bitp++; + } + + unsigned long read32bitInt(const unsigned char* buffer) + { + return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; + } + + int checkColorValidity(unsigned long colorType, unsigned long bd) //return type is a LodePNG error code + { + if ((colorType == 2 || colorType == 4 || colorType == 6)) + { + if (!(bd == 8 || bd == 16)) return 37; + else return 0; + } + else if (colorType == 0) + { + if (!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) return 37; + else return 0; + } + else if (colorType == 3) + { + if (!(bd == 1 || bd == 2 || bd == 4 || bd == 8)) return 37; + else return 0; + } + else return 31; //unexisting color type + } + + unsigned long getBpp(const Info& info) + { + if (info.colorType == 2) return (3 * info.bitDepth); + else if (info.colorType >= 4) return (info.colorType - 2) * info.bitDepth; + else return info.bitDepth; + } + + int convert(std::vector& out, const unsigned char* in, Info& infoIn, unsigned long w, + unsigned long h) + { + //converts from any color type to 32-bit. return value = LodePNG error code + size_t numpixels = w * h, bp = 0; + out.resize(numpixels * 4); + unsigned char* out_ = out.empty() ? 0 : &out[0]; //faster if compiled without optimization + if (infoIn.bitDepth == 8 && infoIn.colorType == 0) //greyscale + for (size_t i = 0; i < numpixels; i++) + { + out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[i]; + out_[4 * i + 3] = (infoIn.key_defined && in[i] == infoIn.key_r) ? 0 : 255; + } + else if (infoIn.bitDepth == 8 && infoIn.colorType == 2) //RGB color + for (size_t i = 0; i < numpixels; i++) + { + for (size_t c = 0; c < 3; c++) out_[4 * i + c] = in[3 * i + c]; + out_[4 * i + 3] = (infoIn.key_defined == 1 && in[3 * i + 0] == infoIn.key_r && in[3 * i + 1] == infoIn. + key_g && in[3 * i + 2] == infoIn.key_b) + ? 0 + : 255; + } + else if (infoIn.bitDepth == 8 && infoIn.colorType == 3) //indexed color (palette) + for (size_t i = 0; i < numpixels; i++) + { + if (4U * in[i] >= infoIn.palette.size()) return 46; + for (size_t c = 0; c < 4; c++) out_[4 * i + c] = infoIn.palette[4 * in[i] + c]; + //get rgb colors from the palette + } + else if (infoIn.bitDepth == 8 && infoIn.colorType == 4) //greyscale with alpha + for (size_t i = 0; i < numpixels; i++) + { + out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[2 * i + 0]; + out_[4 * i + 3] = in[2 * i + 1]; + } + else if (infoIn.bitDepth == 8 && infoIn.colorType == 6) for (size_t i = 0; i < numpixels; i++) for ( + size_t c = 0; c < 4; c++) out_[4 * i + c] = in[4 * i + c]; //RGB with alpha + else if (infoIn.bitDepth == 16 && infoIn.colorType == 0) //greyscale + for (size_t i = 0; i < numpixels; i++) + { + out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[2 * i]; + out_[4 * i + 3] = (infoIn.key_defined && 256U * in[i] + in[i + 1] == infoIn.key_r) ? 0 : 255; + } + else if (infoIn.bitDepth == 16 && infoIn.colorType == 2) //RGB color + for (size_t i = 0; i < numpixels; i++) + { + for (size_t c = 0; c < 3; c++) out_[4 * i + c] = in[6 * i + 2 * c]; + out_[4 * i + 3] = (infoIn.key_defined && 256U * in[6 * i + 0] + in[6 * i + 1] == infoIn.key_r && 256U * + in[6 * i + 2] + in[6 * i + 3] == infoIn.key_g && 256U * in[6 * i + 4] + in[6 * i + 5 + ] == infoIn.key_b) + ? 0 + : 255; + } + else if (infoIn.bitDepth == 16 && infoIn.colorType == 4) //greyscale with alpha + for (size_t i = 0; i < numpixels; i++) + { + out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[4 * i]; //most significant byte + out_[4 * i + 3] = in[4 * i + 2]; + } + else if (infoIn.bitDepth == 16 && infoIn.colorType == 6) for (size_t i = 0; i < numpixels; i++) for ( + size_t c = 0; c < 4; c++) out_[4 * i + c] = in[8 * i + 2 * c]; //RGB with alpha + else if (infoIn.bitDepth < 8 && infoIn.colorType == 0) //greyscale + for (size_t i = 0; i < numpixels; i++) + { + unsigned long value = (readBitsFromReversedStream(bp, in, infoIn.bitDepth) * 255) / ((1 << infoIn. + bitDepth) - 1); //scale value from 0 to 255 + out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = (unsigned char)(value); + out_[4 * i + 3] = (infoIn.key_defined && value && ((1U << infoIn.bitDepth) - 1U) == infoIn.key_r && ((1U + << infoIn.bitDepth) - 1U)) + ? 0 + : 255; + } + else if (infoIn.bitDepth < 8 && infoIn.colorType == 3) //palette + for (size_t i = 0; i < numpixels; i++) + { + unsigned long value = readBitsFromReversedStream(bp, in, infoIn.bitDepth); + if (4 * value >= infoIn.palette.size()) return 47; + for (size_t c = 0; c < 4; c++) out_[4 * i + c] = infoIn.palette[4 * value + c]; + //get rgb colors from the palette + } + return 0; + } + + unsigned char paethPredictor(short a, short b, short c) //Paeth predicter, used by PNG filter type 4 + { + short p = a + b - c, pa = p > a ? (p - a) : (a - p), pb = p > b ? (p - b) : (b - p), pc = + p > c ? (p - c) : (c - p); + return (unsigned char)((pa <= pb && pa <= pc) ? a : pb <= pc ? b : c); + } + }; + PNG decoder = {}; + decoder.decode(out_image, in_png, in_size, convert_to_rgba32); + image_width = decoder.info.width; + image_height = decoder.info.height; + return decoder.error; +} diff --git a/Utilities/PNGHelper.h b/Utilities/PNGHelper.h index 531a709..96d936f 100644 --- a/Utilities/PNGHelper.h +++ b/Utilities/PNGHelper.h @@ -4,11 +4,13 @@ class PNGHelper { private: - static int DecodePNG(vector& out_image, unsigned long& image_width, unsigned long& image_height, const unsigned char* in_png, size_t in_size, bool convert_to_rgba32 = true); + static int DecodePNG(vector& out_image, unsigned long& image_width, unsigned long& image_height, + const unsigned char* in_png, size_t in_size, bool convert_to_rgba32 = true); public: - static bool WritePNG(std::stringstream &stream, uint32_t* buffer, uint32_t xSize, uint32_t ySize, uint32_t bitsPerPixel = 32); + static bool WritePNG(std::stringstream& stream, uint32_t* buffer, uint32_t xSize, uint32_t ySize, + uint32_t bitsPerPixel = 32); static bool WritePNG(string filename, uint32_t* buffer, uint32_t xSize, uint32_t ySize, uint32_t bitsPerPixel = 32); - static bool ReadPNG(string filename, vector &pngData, uint32_t &pngWidth, uint32_t &pngHeight); - static bool ReadPNG(vector input, vector &output, uint32_t &pngWidth, uint32_t &pngHeight); -}; \ No newline at end of file + static bool ReadPNG(string filename, vector& pngData, uint32_t& pngWidth, uint32_t& pngHeight); + static bool ReadPNG(vector input, vector& output, uint32_t& pngWidth, uint32_t& pngHeight); +}; diff --git a/Utilities/PlatformUtilities.cpp b/Utilities/PlatformUtilities.cpp index d129c07..bef9e4d 100644 --- a/Utilities/PlatformUtilities.cpp +++ b/Utilities/PlatformUtilities.cpp @@ -11,35 +11,37 @@ void PlatformUtilities::DisableScreensaver() { //Prevent screensaver/etc from starting while using the emulator //DirectInput devices apparently do not always count as user input - #if !defined(LIBRETRO) && defined(_WIN32) +#if !defined(LIBRETRO) && defined(_WIN32) SetThreadExecutionState(ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED | ES_CONTINUOUS); - #endif +#endif } void PlatformUtilities::EnableScreensaver() { - #if !defined(LIBRETRO) && defined(_WIN32) +#if !defined(LIBRETRO) && defined(_WIN32) SetThreadExecutionState(ES_CONTINUOUS); - #endif +#endif } void PlatformUtilities::EnableHighResolutionTimer() { #if !defined(LIBRETRO) && defined(_WIN32) //Request a 1ms timer resolution on Windows while a game is running - if(!_highResTimerEnabled) { + if (!_highResTimerEnabled) + { timeBeginPeriod(1); _highResTimerEnabled = true; } - #endif +#endif } void PlatformUtilities::RestoreTimerResolution() { - #if !defined(LIBRETRO) && defined(_WIN32) - if(_highResTimerEnabled) { +#if !defined(LIBRETRO) && defined(_WIN32) + if (_highResTimerEnabled) + { timeEndPeriod(1); _highResTimerEnabled = false; } - #endif -} \ No newline at end of file +#endif +} diff --git a/Utilities/PlatformUtilities.h b/Utilities/PlatformUtilities.h index e5a0fd1..774ee1f 100644 --- a/Utilities/PlatformUtilities.h +++ b/Utilities/PlatformUtilities.h @@ -12,4 +12,4 @@ public: static void EnableHighResolutionTimer(); static void RestoreTimerResolution(); -}; \ No newline at end of file +}; diff --git a/Utilities/RawCodec.h b/Utilities/RawCodec.h index ea32899..5fa64c5 100644 --- a/Utilities/RawCodec.h +++ b/Utilities/RawCodec.h @@ -24,15 +24,17 @@ public: return true; } - virtual int CompressFrame(bool isKeyFrame, uint8_t *frameData, uint8_t** compressedData) override + virtual int CompressFrame(bool isKeyFrame, uint8_t* frameData, uint8_t** compressedData) override { *compressedData = _buffer; //Convert raw frame to BMP/DIB format (row order is reversed) uint8_t* buffer = _buffer; frameData += (_height - 1) * _width * 4; - for(int y = 0; y < _height; y++) { - for(int x = 0; x < _width; x++) { + for (int y = 0; y < _height; y++) + { + for (int x = 0; x < _width; x++) + { buffer[0] = frameData[0]; buffer[1] = frameData[1]; buffer[2] = frameData[2]; @@ -48,4 +50,4 @@ public: { return "\0\0\0\0"; } -}; \ No newline at end of file +}; diff --git a/Utilities/SZReader.cpp b/Utilities/SZReader.cpp index 71daade..1e28d4d 100644 --- a/Utilities/SZReader.cpp +++ b/Utilities/SZReader.cpp @@ -16,13 +16,14 @@ SZReader::~SZReader() bool SZReader::InternalLoadArchive(void* buffer, size_t size) { - if(_initialized) { + if (_initialized) + { SzArEx_Free(&_archive, &_allocImp); _initialized = false; } - ISzAlloc allocImp{ SzAlloc, SzFree }; - ISzAlloc allocTempImp{ SzAllocTemp, SzFreeTemp }; + ISzAlloc allocImp{SzAlloc, SzFree}; + ISzAlloc allocTempImp{SzAllocTemp, SzFreeTemp}; MemBufferInit(&_memBufferStream, &_lookStream, buffer, size); CrcGenerateTable(); @@ -31,30 +32,36 @@ bool SZReader::InternalLoadArchive(void* buffer, size_t size) return !SzArEx_Open(&_archive, &_lookStream.s, &allocImp, &allocTempImp); } -bool SZReader::ExtractFile(string filename, vector &output) +bool SZReader::ExtractFile(string filename, vector& output) { bool result = false; - if(_initialized) { - char16_t *utf16Filename = (char16_t*)SzAlloc(nullptr, 2000); + if (_initialized) + { + char16_t* utf16Filename = (char16_t*)SzAlloc(nullptr, 2000); uint32_t blockIndex = 0xFFFFFFFF; - uint8_t *outBuffer = 0; + uint8_t* outBuffer = 0; size_t outBufferSize = 0; - for(uint32_t i = 0; i < _archive.NumFiles; i++) { + for (uint32_t i = 0; i < _archive.NumFiles; i++) + { size_t offset = 0; size_t outSizeProcessed = 0; unsigned isDir = SzArEx_IsDir(&_archive, i); - if(isDir) { + if (isDir) + { continue; } SzArEx_GetFileNameUtf16(&_archive, i, (uint16_t*)utf16Filename); string entryName = utf8::utf8::encode(std::u16string(utf16Filename)); - if(filename == entryName) { - WRes res = SzArEx_Extract(&_archive, &_lookStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &_allocImp, &_allocTempImp); - if(res == SZ_OK) { - output = vector(outBuffer+offset, outBuffer+offset+outSizeProcessed); + if (filename == entryName) + { + WRes res = SzArEx_Extract(&_archive, &_lookStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset, + &outSizeProcessed, &_allocImp, &_allocTempImp); + if (res == SZ_OK) + { + output = vector(outBuffer + offset, outBuffer + offset + outSizeProcessed); result = true; } IAlloc_Free(&_allocImp, outBuffer); @@ -70,12 +77,15 @@ bool SZReader::ExtractFile(string filename, vector &output) vector SZReader::InternalGetFileList() { vector filenames; - char16_t *utf16Filename = (char16_t*)SzAlloc(nullptr, 2000); + char16_t* utf16Filename = (char16_t*)SzAlloc(nullptr, 2000); - if(_initialized) { - for(uint32_t i = 0; i < _archive.NumFiles; i++) { + if (_initialized) + { + for (uint32_t i = 0; i < _archive.NumFiles; i++) + { unsigned isDir = SzArEx_IsDir(&_archive, i); - if(isDir) { + if (isDir) + { continue; } @@ -87,4 +97,4 @@ vector SZReader::InternalGetFileList() SzFree(nullptr, utf16Filename); return filenames; -} \ No newline at end of file +} diff --git a/Utilities/SZReader.h b/Utilities/SZReader.h index 9c3634f..91bb825 100644 --- a/Utilities/SZReader.h +++ b/Utilities/SZReader.h @@ -13,8 +13,8 @@ private: CMemBufferInStream _memBufferStream; CLookToRead _lookStream; CSzArEx _archive; - ISzAlloc _allocImp{ SzAlloc, SzFree }; - ISzAlloc _allocTempImp{ SzAllocTemp, SzFreeTemp }; + ISzAlloc _allocImp{SzAlloc, SzFree}; + ISzAlloc _allocTempImp{SzAllocTemp, SzFreeTemp}; protected: bool InternalLoadArchive(void* buffer, size_t size); @@ -24,5 +24,5 @@ public: SZReader(); virtual ~SZReader(); - bool ExtractFile(string filename, vector &output); -}; \ No newline at end of file + bool ExtractFile(string filename, vector& output); +}; diff --git a/Utilities/Scale2x/scale2x.cpp b/Utilities/Scale2x/scale2x.cpp index 43f31b1..94989de 100644 --- a/Utilities/Scale2x/scale2x.cpp +++ b/Utilities/Scale2x/scale2x.cpp @@ -44,15 +44,19 @@ */ /* #define USE_SCALE_RANDOMWRITE */ -static inline void scale2x_8_def_border(scale2x_uint8* dst, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) +static inline void scale2x_8_def_border(scale2x_uint8* dst, const scale2x_uint8* src0, const scale2x_uint8* src1, + const scale2x_uint8* src2, unsigned count) { assert(count >= 2); /* first pixel */ - if (src0[0] != src2[0] && src1[0] != src1[1]) { + if (src0[0] != src2[0] && src1[0] != src1[1]) + { dst[0] = src1[0] == src0[0] ? src0[0] : src1[0]; dst[1] = src1[1] == src0[0] ? src0[0] : src1[0]; - } else { + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; } @@ -63,11 +67,15 @@ static inline void scale2x_8_def_border(scale2x_uint8* dst, const scale2x_uint8* /* central pixels */ count -= 2; - while (count) { - if (src0[0] != src2[0] && src1[-1] != src1[1]) { + while (count) + { + if (src0[0] != src2[0] && src1[-1] != src1[1]) + { dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0]; dst[1] = src1[1] == src0[0] ? src0[0] : src1[0]; - } else { + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; } @@ -80,24 +88,33 @@ static inline void scale2x_8_def_border(scale2x_uint8* dst, const scale2x_uint8* } /* last pixel */ - if (src0[0] != src2[0] && src1[-1] != src1[0]) { + if (src0[0] != src2[0] && src1[-1] != src1[0]) + { dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0]; dst[1] = src1[0] == src0[0] ? src0[0] : src1[0]; - } else { + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; } } -static inline void scale2x_8_def_center(scale2x_uint8* dst, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) +static inline void scale2x_8_def_center(scale2x_uint8* dst, const scale2x_uint8* src0, const scale2x_uint8* src1, + const scale2x_uint8* src2, unsigned count) { assert(count >= 2); /* first pixel */ - if (src0[0] != src2[0] && src1[0] != src1[1]) { + if (src0[0] != src2[0] && src1[0] != src1[1]) + { dst[0] = src1[0]; - dst[1] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; - } else { + dst[1] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) + ? src1[1] + : src1[0]; + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; } @@ -108,11 +125,19 @@ static inline void scale2x_8_def_center(scale2x_uint8* dst, const scale2x_uint8* /* central pixels */ count -= 2; - while (count) { - if (src0[0] != src2[0] && src1[-1] != src1[1]) { - dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; - dst[1] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; - } else { + while (count) + { + if (src0[0] != src2[0] && src1[-1] != src1[1]) + { + dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) + ? src1[-1] + : src1[0]; + dst[1] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) + ? src1[1] + : src1[0]; + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; } @@ -125,24 +150,33 @@ static inline void scale2x_8_def_center(scale2x_uint8* dst, const scale2x_uint8* } /* last pixel */ - if (src0[0] != src2[0] && src1[-1] != src1[0]) { - dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; + if (src0[0] != src2[0] && src1[-1] != src1[0]) + { + dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) + ? src1[-1] + : src1[0]; dst[1] = src1[0]; - } else { + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; } } -static inline void scale2x_16_def_border(scale2x_uint16* dst, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) +static inline void scale2x_16_def_border(scale2x_uint16* dst, const scale2x_uint16* src0, const scale2x_uint16* src1, + const scale2x_uint16* src2, unsigned count) { assert(count >= 2); /* first pixel */ - if (src0[0] != src2[0] && src1[0] != src1[1]) { + if (src0[0] != src2[0] && src1[0] != src1[1]) + { dst[0] = src1[0] == src0[0] ? src0[0] : src1[0]; dst[1] = src1[1] == src0[0] ? src0[0] : src1[0]; - } else { + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; } @@ -153,11 +187,15 @@ static inline void scale2x_16_def_border(scale2x_uint16* dst, const scale2x_uint /* central pixels */ count -= 2; - while (count) { - if (src0[0] != src2[0] && src1[-1] != src1[1]) { + while (count) + { + if (src0[0] != src2[0] && src1[-1] != src1[1]) + { dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0]; dst[1] = src1[1] == src0[0] ? src0[0] : src1[0]; - } else { + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; } @@ -170,24 +208,33 @@ static inline void scale2x_16_def_border(scale2x_uint16* dst, const scale2x_uint } /* last pixel */ - if (src0[0] != src2[0] && src1[-1] != src1[0]) { + if (src0[0] != src2[0] && src1[-1] != src1[0]) + { dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0]; dst[1] = src1[0] == src0[0] ? src0[0] : src1[0]; - } else { + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; } } -static inline void scale2x_16_def_center(scale2x_uint16* dst, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) +static inline void scale2x_16_def_center(scale2x_uint16* dst, const scale2x_uint16* src0, const scale2x_uint16* src1, + const scale2x_uint16* src2, unsigned count) { assert(count >= 2); /* first pixel */ - if (src0[0] != src2[0] && src1[0] != src1[1]) { + if (src0[0] != src2[0] && src1[0] != src1[1]) + { dst[0] = src1[0]; - dst[1] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; - } else { + dst[1] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) + ? src1[1] + : src1[0]; + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; } @@ -198,11 +245,19 @@ static inline void scale2x_16_def_center(scale2x_uint16* dst, const scale2x_uint /* central pixels */ count -= 2; - while (count) { - if (src0[0] != src2[0] && src1[-1] != src1[1]) { - dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; - dst[1] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; - } else { + while (count) + { + if (src0[0] != src2[0] && src1[-1] != src1[1]) + { + dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) + ? src1[-1] + : src1[0]; + dst[1] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) + ? src1[1] + : src1[0]; + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; } @@ -215,24 +270,33 @@ static inline void scale2x_16_def_center(scale2x_uint16* dst, const scale2x_uint } /* last pixel */ - if (src0[0] != src2[0] && src1[-1] != src1[0]) { - dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; + if (src0[0] != src2[0] && src1[-1] != src1[0]) + { + dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) + ? src1[-1] + : src1[0]; dst[1] = src1[0]; - } else { + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; } } -static inline void scale2x_32_def_border(scale2x_uint32* dst, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) +static inline void scale2x_32_def_border(scale2x_uint32* dst, const scale2x_uint32* src0, const scale2x_uint32* src1, + const scale2x_uint32* src2, unsigned count) { assert(count >= 2); /* first pixel */ - if (src0[0] != src2[0] && src1[0] != src1[1]) { + if (src0[0] != src2[0] && src1[0] != src1[1]) + { dst[0] = src1[0] == src0[0] ? src0[0] : src1[0]; dst[1] = src1[1] == src0[0] ? src0[0] : src1[0]; - } else { + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; } @@ -243,11 +307,15 @@ static inline void scale2x_32_def_border(scale2x_uint32* dst, const scale2x_uint /* central pixels */ count -= 2; - while (count) { - if (src0[0] != src2[0] && src1[-1] != src1[1]) { + while (count) + { + if (src0[0] != src2[0] && src1[-1] != src1[1]) + { dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0]; dst[1] = src1[1] == src0[0] ? src0[0] : src1[0]; - } else { + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; } @@ -260,24 +328,33 @@ static inline void scale2x_32_def_border(scale2x_uint32* dst, const scale2x_uint } /* last pixel */ - if (src0[0] != src2[0] && src1[-1] != src1[0]) { + if (src0[0] != src2[0] && src1[-1] != src1[0]) + { dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0]; dst[1] = src1[0] == src0[0] ? src0[0] : src1[0]; - } else { + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; } } -static inline void scale2x_32_def_center(scale2x_uint32* dst, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) +static inline void scale2x_32_def_center(scale2x_uint32* dst, const scale2x_uint32* src0, const scale2x_uint32* src1, + const scale2x_uint32* src2, unsigned count) { assert(count >= 2); /* first pixel */ - if (src0[0] != src2[0] && src1[0] != src1[1]) { + if (src0[0] != src2[0] && src1[0] != src1[1]) + { dst[0] = src1[0]; - dst[1] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; - } else { + dst[1] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) + ? src1[1] + : src1[0]; + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; } @@ -288,11 +365,19 @@ static inline void scale2x_32_def_center(scale2x_uint32* dst, const scale2x_uint /* central pixels */ count -= 2; - while (count) { - if (src0[0] != src2[0] && src1[-1] != src1[1]) { - dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; - dst[1] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; - } else { + while (count) + { + if (src0[0] != src2[0] && src1[-1] != src1[1]) + { + dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) + ? src1[-1] + : src1[0]; + dst[1] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) + ? src1[1] + : src1[0]; + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; } @@ -305,10 +390,15 @@ static inline void scale2x_32_def_center(scale2x_uint32* dst, const scale2x_uint } /* last pixel */ - if (src0[0] != src2[0] && src1[-1] != src1[0]) { - dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; + if (src0[0] != src2[0] && src1[-1] != src1[0]) + { + dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) + ? src1[-1] + : src1[0]; dst[1] = src1[0]; - } else { + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; } @@ -329,7 +419,8 @@ static inline void scale2x_32_def_center(scale2x_uint32* dst, const scale2x_uint * \param dst0 First destination row, double length in pixels. * \param dst1 Second destination row, double length in pixels. */ -void scale2x_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) +void scale2x_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, + const scale2x_uint8* src2, unsigned count) { #ifdef USE_SCALE_RANDOMWRITE scale2x_8_def_whole(dst0, dst1, src0, src1, src2, count); @@ -350,7 +441,8 @@ void scale2x_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8 * \param dst0 First destination row, double length in pixels. * \param dst1 Second destination row, double length in pixels. */ -void scale2x_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) +void scale2x_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, + const scale2x_uint16* src2, unsigned count) { #ifdef USE_SCALE_RANDOMWRITE scale2x_16_def_whole(dst0, dst1, src0, src1, src2, count); @@ -371,7 +463,8 @@ void scale2x_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_ui * \param dst0 First destination row, double length in pixels. * \param dst1 Second destination row, double length in pixels. */ -void scale2x_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) +void scale2x_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, + const scale2x_uint32* src2, unsigned count) { #ifdef USE_SCALE_RANDOMWRITE scale2x_32_def_whole(dst0, dst1, src0, src1, src2, count); @@ -385,7 +478,8 @@ void scale2x_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_ui * Scale by a factor of 2x3 a row of pixels of 8 bits. * \note Like scale2x_8_def(); */ -void scale2x3_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, scale2x_uint8* dst2, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) +void scale2x3_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, scale2x_uint8* dst2, const scale2x_uint8* src0, + const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) { #ifdef USE_SCALE_RANDOMWRITE scale2x_8_def_whole(dst0, dst2, src0, src1, src2, count); @@ -401,7 +495,8 @@ void scale2x3_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, scale2x_uint8* dst * Scale by a factor of 2x3 a row of pixels of 16 bits. * \note Like scale2x_16_def(); */ -void scale2x3_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, scale2x_uint16* dst2, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) +void scale2x3_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, scale2x_uint16* dst2, const scale2x_uint16* src0, + const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) { #ifdef USE_SCALE_RANDOMWRITE scale2x_16_def_whole(dst0, dst2, src0, src1, src2, count); @@ -417,7 +512,8 @@ void scale2x3_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, scale2x_uint16* * Scale by a factor of 2x3 a row of pixels of 32 bits. * \note Like scale2x_32_def(); */ -void scale2x3_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, scale2x_uint32* dst2, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) +void scale2x3_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, scale2x_uint32* dst2, const scale2x_uint32* src0, + const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) { #ifdef USE_SCALE_RANDOMWRITE scale2x_32_def_whole(dst0, dst2, src0, src1, src2, count); @@ -433,7 +529,8 @@ void scale2x3_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, scale2x_uint32* * Scale by a factor of 2x4 a row of pixels of 8 bits. * \note Like scale2x_8_def(); */ -void scale2x4_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, scale2x_uint8* dst2, scale2x_uint8* dst3, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) +void scale2x4_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, scale2x_uint8* dst2, scale2x_uint8* dst3, + const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) { #ifdef USE_SCALE_RANDOMWRITE scale2x_8_def_whole(dst0, dst3, src0, src1, src2, count); @@ -451,7 +548,8 @@ void scale2x4_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, scale2x_uint8* dst * Scale by a factor of 2x4 a row of pixels of 16 bits. * \note Like scale2x_16_def(); */ -void scale2x4_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, scale2x_uint16* dst2, scale2x_uint16* dst3, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) +void scale2x4_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, scale2x_uint16* dst2, scale2x_uint16* dst3, + const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) { #ifdef USE_SCALE_RANDOMWRITE scale2x_16_def_whole(dst0, dst3, src0, src1, src2, count); @@ -469,7 +567,8 @@ void scale2x4_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, scale2x_uint16* * Scale by a factor of 2x4 a row of pixels of 32 bits. * \note Like scale2x_32_def(); */ -void scale2x4_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, scale2x_uint32* dst2, scale2x_uint32* dst3, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) +void scale2x4_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, scale2x_uint32* dst2, scale2x_uint32* dst3, + const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) { #ifdef USE_SCALE_RANDOMWRITE scale2x_32_def_whole(dst0, dst3, src0, src1, src2, count); diff --git a/Utilities/Scale2x/scale2x.h b/Utilities/Scale2x/scale2x.h index e1431c4..5801469 100644 --- a/Utilities/Scale2x/scale2x.h +++ b/Utilities/Scale2x/scale2x.h @@ -21,17 +21,27 @@ typedef unsigned char scale2x_uint8; typedef unsigned short scale2x_uint16; typedef unsigned scale2x_uint32; -void scale2x_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count); -void scale2x_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count); -void scale2x_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count); +void scale2x_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, + const scale2x_uint8* src2, unsigned count); +void scale2x_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, + const scale2x_uint16* src2, unsigned count); +void scale2x_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, + const scale2x_uint32* src2, unsigned count); -void scale2x3_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, scale2x_uint8* dst2, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count); -void scale2x3_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, scale2x_uint16* dst2, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count); -void scale2x3_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, scale2x_uint32* dst2, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count); +void scale2x3_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, scale2x_uint8* dst2, const scale2x_uint8* src0, + const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count); +void scale2x3_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, scale2x_uint16* dst2, const scale2x_uint16* src0, + const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count); +void scale2x3_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, scale2x_uint32* dst2, const scale2x_uint32* src0, + const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count); -void scale2x4_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, scale2x_uint8* dst2, scale2x_uint8* dst3, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count); -void scale2x4_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, scale2x_uint16* dst2, scale2x_uint16* dst3, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count); -void scale2x4_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, scale2x_uint32* dst2, scale2x_uint32* dst3, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count); +void scale2x4_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, scale2x_uint8* dst2, scale2x_uint8* dst3, + const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count); +void scale2x4_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, scale2x_uint16* dst2, scale2x_uint16* dst3, + const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, + unsigned count); +void scale2x4_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, scale2x_uint32* dst2, scale2x_uint32* dst3, + const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, + unsigned count); #endif - diff --git a/Utilities/Scale2x/scale3x.cpp b/Utilities/Scale2x/scale3x.cpp index 8bfe328..11d7bae 100644 --- a/Utilities/Scale2x/scale3x.cpp +++ b/Utilities/Scale2x/scale3x.cpp @@ -44,16 +44,22 @@ */ /* #define USE_SCALE_RANDOMWRITE */ -static inline void scale3x_8_def_border(scale3x_uint8* dst, const scale3x_uint8* src0, const scale3x_uint8* src1, const scale3x_uint8* src2, unsigned count) +static inline void scale3x_8_def_border(scale3x_uint8* dst, const scale3x_uint8* src0, const scale3x_uint8* src1, + const scale3x_uint8* src2, unsigned count) { assert(count >= 2); /* first pixel */ - if (src0[0] != src2[0] && src1[0] != src1[1]) { + if (src0[0] != src2[0] && src1[0] != src1[1]) + { dst[0] = src1[0]; - dst[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0]; + dst[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) + ? src0[0] + : src1[0]; dst[2] = src1[1] == src0[0] ? src1[1] : src1[0]; - } else { + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; @@ -65,12 +71,18 @@ static inline void scale3x_8_def_border(scale3x_uint8* dst, const scale3x_uint8* /* central pixels */ count -= 2; - while (count) { - if (src0[0] != src2[0] && src1[-1] != src1[1]) { + while (count) + { + if (src0[0] != src2[0] && src1[-1] != src1[1]) + { dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0]; - dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0]; + dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) + ? src0[0] + : src1[0]; dst[2] = src1[1] == src0[0] ? src1[1] : src1[0]; - } else { + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; @@ -84,27 +96,40 @@ static inline void scale3x_8_def_border(scale3x_uint8* dst, const scale3x_uint8* } /* last pixel */ - if (src0[0] != src2[0] && src1[-1] != src1[0]) { + if (src0[0] != src2[0] && src1[-1] != src1[0]) + { dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0]; - dst[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0]; + dst[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) + ? src0[0] + : src1[0]; dst[2] = src1[0]; - } else { + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; } } -static inline void scale3x_8_def_center(scale3x_uint8* dst, const scale3x_uint8* src0, const scale3x_uint8* src1, const scale3x_uint8* src2, unsigned count) +static inline void scale3x_8_def_center(scale3x_uint8* dst, const scale3x_uint8* src0, const scale3x_uint8* src1, + const scale3x_uint8* src2, unsigned count) { assert(count >= 2); /* first pixel */ - if (src0[0] != src2[0] && src1[0] != src1[1]) { - dst[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0]; + if (src0[0] != src2[0] && src1[0] != src1[1]) + { + dst[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) + ? src1[0] + : src1[0]; dst[1] = src1[0]; - dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; - } else { + dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) + ? src1[1] + : src1[0]; + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; @@ -116,12 +141,20 @@ static inline void scale3x_8_def_center(scale3x_uint8* dst, const scale3x_uint8* /* central pixels */ count -= 2; - while (count) { - if (src0[0] != src2[0] && src1[-1] != src1[1]) { - dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; + while (count) + { + if (src0[0] != src2[0] && src1[-1] != src1[1]) + { + dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) + ? src1[-1] + : src1[0]; dst[1] = src1[0]; - dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; - } else { + dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) + ? src1[1] + : src1[0]; + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; @@ -135,27 +168,40 @@ static inline void scale3x_8_def_center(scale3x_uint8* dst, const scale3x_uint8* } /* last pixel */ - if (src0[0] != src2[0] && src1[-1] != src1[0]) { - dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; + if (src0[0] != src2[0] && src1[-1] != src1[0]) + { + dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) + ? src1[-1] + : src1[0]; dst[1] = src1[0]; - dst[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0]; - } else { + dst[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) + ? src1[0] + : src1[0]; + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; } } -static inline void scale3x_16_def_border(scale3x_uint16* dst, const scale3x_uint16* src0, const scale3x_uint16* src1, const scale3x_uint16* src2, unsigned count) +static inline void scale3x_16_def_border(scale3x_uint16* dst, const scale3x_uint16* src0, const scale3x_uint16* src1, + const scale3x_uint16* src2, unsigned count) { assert(count >= 2); /* first pixel */ - if (src0[0] != src2[0] && src1[0] != src1[1]) { + if (src0[0] != src2[0] && src1[0] != src1[1]) + { dst[0] = src1[0]; - dst[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0]; + dst[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) + ? src0[0] + : src1[0]; dst[2] = src1[1] == src0[0] ? src1[1] : src1[0]; - } else { + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; @@ -167,12 +213,18 @@ static inline void scale3x_16_def_border(scale3x_uint16* dst, const scale3x_uint /* central pixels */ count -= 2; - while (count) { - if (src0[0] != src2[0] && src1[-1] != src1[1]) { + while (count) + { + if (src0[0] != src2[0] && src1[-1] != src1[1]) + { dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0]; - dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0]; + dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) + ? src0[0] + : src1[0]; dst[2] = src1[1] == src0[0] ? src1[1] : src1[0]; - } else { + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; @@ -186,27 +238,40 @@ static inline void scale3x_16_def_border(scale3x_uint16* dst, const scale3x_uint } /* last pixel */ - if (src0[0] != src2[0] && src1[-1] != src1[0]) { + if (src0[0] != src2[0] && src1[-1] != src1[0]) + { dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0]; - dst[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0]; + dst[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) + ? src0[0] + : src1[0]; dst[2] = src1[0]; - } else { + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; } } -static inline void scale3x_16_def_center(scale3x_uint16* dst, const scale3x_uint16* src0, const scale3x_uint16* src1, const scale3x_uint16* src2, unsigned count) +static inline void scale3x_16_def_center(scale3x_uint16* dst, const scale3x_uint16* src0, const scale3x_uint16* src1, + const scale3x_uint16* src2, unsigned count) { assert(count >= 2); /* first pixel */ - if (src0[0] != src2[0] && src1[0] != src1[1]) { - dst[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0]; + if (src0[0] != src2[0] && src1[0] != src1[1]) + { + dst[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) + ? src1[0] + : src1[0]; dst[1] = src1[0]; - dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; - } else { + dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) + ? src1[1] + : src1[0]; + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; @@ -218,12 +283,20 @@ static inline void scale3x_16_def_center(scale3x_uint16* dst, const scale3x_uint /* central pixels */ count -= 2; - while (count) { - if (src0[0] != src2[0] && src1[-1] != src1[1]) { - dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; + while (count) + { + if (src0[0] != src2[0] && src1[-1] != src1[1]) + { + dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) + ? src1[-1] + : src1[0]; dst[1] = src1[0]; - dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; - } else { + dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) + ? src1[1] + : src1[0]; + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; @@ -237,27 +310,40 @@ static inline void scale3x_16_def_center(scale3x_uint16* dst, const scale3x_uint } /* last pixel */ - if (src0[0] != src2[0] && src1[-1] != src1[0]) { - dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; + if (src0[0] != src2[0] && src1[-1] != src1[0]) + { + dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) + ? src1[-1] + : src1[0]; dst[1] = src1[0]; - dst[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0]; - } else { + dst[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) + ? src1[0] + : src1[0]; + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; } } -static inline void scale3x_32_def_border(scale3x_uint32* dst, const scale3x_uint32* src0, const scale3x_uint32* src1, const scale3x_uint32* src2, unsigned count) +static inline void scale3x_32_def_border(scale3x_uint32* dst, const scale3x_uint32* src0, const scale3x_uint32* src1, + const scale3x_uint32* src2, unsigned count) { assert(count >= 2); /* first pixel */ - if (src0[0] != src2[0] && src1[0] != src1[1]) { + if (src0[0] != src2[0] && src1[0] != src1[1]) + { dst[0] = src1[0]; - dst[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0]; + dst[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) + ? src0[0] + : src1[0]; dst[2] = src1[1] == src0[0] ? src1[1] : src1[0]; - } else { + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; @@ -269,12 +355,18 @@ static inline void scale3x_32_def_border(scale3x_uint32* dst, const scale3x_uint /* central pixels */ count -= 2; - while (count) { - if (src0[0] != src2[0] && src1[-1] != src1[1]) { + while (count) + { + if (src0[0] != src2[0] && src1[-1] != src1[1]) + { dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0]; - dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0]; + dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) + ? src0[0] + : src1[0]; dst[2] = src1[1] == src0[0] ? src1[1] : src1[0]; - } else { + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; @@ -288,27 +380,40 @@ static inline void scale3x_32_def_border(scale3x_uint32* dst, const scale3x_uint } /* last pixel */ - if (src0[0] != src2[0] && src1[-1] != src1[0]) { + if (src0[0] != src2[0] && src1[-1] != src1[0]) + { dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0]; - dst[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0]; + dst[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) + ? src0[0] + : src1[0]; dst[2] = src1[0]; - } else { + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; } } -static inline void scale3x_32_def_center(scale3x_uint32* dst, const scale3x_uint32* src0, const scale3x_uint32* src1, const scale3x_uint32* src2, unsigned count) +static inline void scale3x_32_def_center(scale3x_uint32* dst, const scale3x_uint32* src0, const scale3x_uint32* src1, + const scale3x_uint32* src2, unsigned count) { assert(count >= 2); /* first pixel */ - if (src0[0] != src2[0] && src1[0] != src1[1]) { - dst[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0]; + if (src0[0] != src2[0] && src1[0] != src1[1]) + { + dst[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) + ? src1[0] + : src1[0]; dst[1] = src1[0]; - dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; - } else { + dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) + ? src1[1] + : src1[0]; + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; @@ -320,12 +425,20 @@ static inline void scale3x_32_def_center(scale3x_uint32* dst, const scale3x_uint /* central pixels */ count -= 2; - while (count) { - if (src0[0] != src2[0] && src1[-1] != src1[1]) { - dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; + while (count) + { + if (src0[0] != src2[0] && src1[-1] != src1[1]) + { + dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) + ? src1[-1] + : src1[0]; dst[1] = src1[0]; - dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; - } else { + dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) + ? src1[1] + : src1[0]; + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; @@ -339,11 +452,18 @@ static inline void scale3x_32_def_center(scale3x_uint32* dst, const scale3x_uint } /* last pixel */ - if (src0[0] != src2[0] && src1[-1] != src1[0]) { - dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; + if (src0[0] != src2[0] && src1[-1] != src1[0]) + { + dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) + ? src1[-1] + : src1[0]; dst[1] = src1[0]; - dst[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0]; - } else { + dst[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) + ? src1[0] + : src1[0]; + } + else + { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; @@ -364,7 +484,8 @@ static inline void scale3x_32_def_center(scale3x_uint32* dst, const scale3x_uint * \param dst1 Second destination row, triple length in pixels. * \param dst2 Third destination row, triple length in pixels. */ -void scale3x_8_def(scale3x_uint8* dst0, scale3x_uint8* dst1, scale3x_uint8* dst2, const scale3x_uint8* src0, const scale3x_uint8* src1, const scale3x_uint8* src2, unsigned count) +void scale3x_8_def(scale3x_uint8* dst0, scale3x_uint8* dst1, scale3x_uint8* dst2, const scale3x_uint8* src0, + const scale3x_uint8* src1, const scale3x_uint8* src2, unsigned count) { #ifdef USE_SCALE_RANDOMWRITE scale3x_8_def_whole(dst0, dst1, dst2, src0, src1, src2, count); @@ -387,7 +508,8 @@ void scale3x_8_def(scale3x_uint8* dst0, scale3x_uint8* dst1, scale3x_uint8* dst2 * \param dst1 Second destination row, triple length in pixels. * \param dst2 Third destination row, triple length in pixels. */ -void scale3x_16_def(scale3x_uint16* dst0, scale3x_uint16* dst1, scale3x_uint16* dst2, const scale3x_uint16* src0, const scale3x_uint16* src1, const scale3x_uint16* src2, unsigned count) +void scale3x_16_def(scale3x_uint16* dst0, scale3x_uint16* dst1, scale3x_uint16* dst2, const scale3x_uint16* src0, + const scale3x_uint16* src1, const scale3x_uint16* src2, unsigned count) { #ifdef USE_SCALE_RANDOMWRITE scale3x_16_def_whole(dst0, dst1, dst2, src0, src1, src2, count); @@ -410,7 +532,8 @@ void scale3x_16_def(scale3x_uint16* dst0, scale3x_uint16* dst1, scale3x_uint16* * \param dst1 Second destination row, triple length in pixels. * \param dst2 Third destination row, triple length in pixels. */ -void scale3x_32_def(scale3x_uint32* dst0, scale3x_uint32* dst1, scale3x_uint32* dst2, const scale3x_uint32* src0, const scale3x_uint32* src1, const scale3x_uint32* src2, unsigned count) +void scale3x_32_def(scale3x_uint32* dst0, scale3x_uint32* dst1, scale3x_uint32* dst2, const scale3x_uint32* src0, + const scale3x_uint32* src1, const scale3x_uint32* src2, unsigned count) { #ifdef USE_SCALE_RANDOMWRITE scale3x_32_def_whole(dst0, dst1, dst2, src0, src1, src2, count); @@ -420,4 +543,3 @@ void scale3x_32_def(scale3x_uint32* dst0, scale3x_uint32* dst1, scale3x_uint32* scale3x_32_def_border(dst2, src2, src1, src0, count); #endif } - diff --git a/Utilities/Scale2x/scale3x.h b/Utilities/Scale2x/scale3x.h index 895752a..d4e8972 100644 --- a/Utilities/Scale2x/scale3x.h +++ b/Utilities/Scale2x/scale3x.h @@ -21,9 +21,11 @@ typedef unsigned char scale3x_uint8; typedef unsigned short scale3x_uint16; typedef unsigned scale3x_uint32; -void scale3x_8_def(scale3x_uint8* dst0, scale3x_uint8* dst1, scale3x_uint8* dst2, const scale3x_uint8* src0, const scale3x_uint8* src1, const scale3x_uint8* src2, unsigned count); -void scale3x_16_def(scale3x_uint16* dst0, scale3x_uint16* dst1, scale3x_uint16* dst2, const scale3x_uint16* src0, const scale3x_uint16* src1, const scale3x_uint16* src2, unsigned count); -void scale3x_32_def(scale3x_uint32* dst0, scale3x_uint32* dst1, scale3x_uint32* dst2, const scale3x_uint32* src0, const scale3x_uint32* src1, const scale3x_uint32* src2, unsigned count); +void scale3x_8_def(scale3x_uint8* dst0, scale3x_uint8* dst1, scale3x_uint8* dst2, const scale3x_uint8* src0, + const scale3x_uint8* src1, const scale3x_uint8* src2, unsigned count); +void scale3x_16_def(scale3x_uint16* dst0, scale3x_uint16* dst1, scale3x_uint16* dst2, const scale3x_uint16* src0, + const scale3x_uint16* src1, const scale3x_uint16* src2, unsigned count); +void scale3x_32_def(scale3x_uint32* dst0, scale3x_uint32* dst1, scale3x_uint32* dst2, const scale3x_uint32* src0, + const scale3x_uint32* src1, const scale3x_uint32* src2, unsigned count); #endif - diff --git a/Utilities/Scale2x/scalebit.cpp b/Utilities/Scale2x/scalebit.cpp index d4ab4c3..f19f82e 100644 --- a/Utilities/Scale2x/scalebit.cpp +++ b/Utilities/Scale2x/scalebit.cpp @@ -49,55 +49,83 @@ /** * Apply the Scale2x effect on a group of rows. Used internally. */ -static inline void stage_scale2x(void* dst0, void* dst1, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row) +static inline void stage_scale2x(void* dst0, void* dst1, const void* src0, const void* src1, const void* src2, + unsigned pixel, unsigned pixel_per_row) { - switch (pixel) { - case 1 : scale2x_8_def(SSDST(8,0), SSDST(8,1), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break; - case 2 : scale2x_16_def(SSDST(16,0), SSDST(16,1), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break; - case 4 : scale2x_32_def(SSDST(32,0), SSDST(32,1), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break; + switch (pixel) + { + case 1: scale2x_8_def(SSDST(8, 0), SSDST(8, 1), SSSRC(8, 0), SSSRC(8, 1), SSSRC(8, 2), pixel_per_row); + break; + case 2: scale2x_16_def(SSDST(16, 0), SSDST(16, 1), SSSRC(16, 0), SSSRC(16, 1), SSSRC(16, 2), pixel_per_row); + break; + case 4: scale2x_32_def(SSDST(32, 0), SSDST(32, 1), SSSRC(32, 0), SSSRC(32, 1), SSSRC(32, 2), pixel_per_row); + break; } } /** * Apply the Scale2x3 effect on a group of rows. Used internally. */ -static inline void stage_scale2x3(void* dst0, void* dst1, void* dst2, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row) +static inline void stage_scale2x3(void* dst0, void* dst1, void* dst2, const void* src0, const void* src1, + const void* src2, unsigned pixel, unsigned pixel_per_row) { - switch (pixel) { - case 1 : scale2x3_8_def(SSDST(8,0), SSDST(8,1), SSDST(8,2), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break; - case 2 : scale2x3_16_def(SSDST(16,0), SSDST(16,1), SSDST(16,2), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break; - case 4 : scale2x3_32_def(SSDST(32,0), SSDST(32,1), SSDST(32,2), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break; + switch (pixel) + { + case 1: scale2x3_8_def(SSDST(8, 0), SSDST(8, 1), SSDST(8, 2), SSSRC(8, 0), SSSRC(8, 1), SSSRC(8, 2), pixel_per_row); + break; + case 2: scale2x3_16_def(SSDST(16, 0), SSDST(16, 1), SSDST(16, 2), SSSRC(16, 0), SSSRC(16, 1), SSSRC(16, 2), + pixel_per_row); + break; + case 4: scale2x3_32_def(SSDST(32, 0), SSDST(32, 1), SSDST(32, 2), SSSRC(32, 0), SSSRC(32, 1), SSSRC(32, 2), + pixel_per_row); + break; } } /** * Apply the Scale2x4 effect on a group of rows. Used internally. */ -static inline void stage_scale2x4(void* dst0, void* dst1, void* dst2, void* dst3, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row) +static inline void stage_scale2x4(void* dst0, void* dst1, void* dst2, void* dst3, const void* src0, const void* src1, + const void* src2, unsigned pixel, unsigned pixel_per_row) { - switch (pixel) { - case 1 : scale2x4_8_def(SSDST(8,0), SSDST(8,1), SSDST(8,2), SSDST(8,3), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break; - case 2 : scale2x4_16_def(SSDST(16,0), SSDST(16,1), SSDST(16,2), SSDST(16,3), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break; - case 4 : scale2x4_32_def(SSDST(32,0), SSDST(32,1), SSDST(32,2), SSDST(32,3), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break; + switch (pixel) + { + case 1: scale2x4_8_def(SSDST(8, 0), SSDST(8, 1), SSDST(8, 2), SSDST(8, 3), SSSRC(8, 0), SSSRC(8, 1), SSSRC(8, 2), + pixel_per_row); + break; + case 2: scale2x4_16_def(SSDST(16, 0), SSDST(16, 1), SSDST(16, 2), SSDST(16, 3), SSSRC(16, 0), SSSRC(16, 1), + SSSRC(16, 2), pixel_per_row); + break; + case 4: scale2x4_32_def(SSDST(32, 0), SSDST(32, 1), SSDST(32, 2), SSDST(32, 3), SSSRC(32, 0), SSSRC(32, 1), + SSSRC(32, 2), pixel_per_row); + break; } } /** * Apply the Scale3x effect on a group of rows. Used internally. */ -static inline void stage_scale3x(void* dst0, void* dst1, void* dst2, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row) +static inline void stage_scale3x(void* dst0, void* dst1, void* dst2, const void* src0, const void* src1, + const void* src2, unsigned pixel, unsigned pixel_per_row) { - switch (pixel) { - case 1 : scale3x_8_def(SSDST(8,0), SSDST(8,1), SSDST(8,2), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break; - case 2 : scale3x_16_def(SSDST(16,0), SSDST(16,1), SSDST(16,2), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break; - case 4 : scale3x_32_def(SSDST(32,0), SSDST(32,1), SSDST(32,2), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break; + switch (pixel) + { + case 1: scale3x_8_def(SSDST(8, 0), SSDST(8, 1), SSDST(8, 2), SSSRC(8, 0), SSSRC(8, 1), SSSRC(8, 2), pixel_per_row); + break; + case 2: scale3x_16_def(SSDST(16, 0), SSDST(16, 1), SSDST(16, 2), SSSRC(16, 0), SSSRC(16, 1), SSSRC(16, 2), + pixel_per_row); + break; + case 4: scale3x_32_def(SSDST(32, 0), SSDST(32, 1), SSDST(32, 2), SSSRC(32, 0), SSSRC(32, 1), SSSRC(32, 2), + pixel_per_row); + break; } } /** * Apply the Scale4x effect on a group of rows. Used internally. */ -static inline void stage_scale4x(void* dst0, void* dst1, void* dst2, void* dst3, const void* src0, const void* src1, const void* src2, const void* src3, unsigned pixel, unsigned pixel_per_row) +static inline void stage_scale4x(void* dst0, void* dst1, void* dst2, void* dst3, const void* src0, const void* src1, + const void* src2, const void* src3, unsigned pixel, unsigned pixel_per_row) { stage_scale2x(dst0, dst1, src0, src1, src2, pixel, 2 * pixel_per_row); stage_scale2x(dst2, dst3, src1, src2, src3, pixel, 2 * pixel_per_row); @@ -121,7 +149,8 @@ static inline void stage_scale4x(void* dst0, void* dst1, void* dst2, void* dst3, * \param width Horizontal size in pixels of the source bitmap. * \param height Vertical size in pixels of the source bitmap. */ -static void scale2x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) +static void scale2x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, + unsigned width, unsigned height) { unsigned char* dst = (unsigned char*)void_dst; const unsigned char* src = (const unsigned char*)void_src; @@ -136,7 +165,8 @@ static void scale2x(void* void_dst, unsigned dst_slice, const void* void_src, un dst = SCDST(2); count -= 2; - while (count) { + while (count) + { stage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width); dst = SCDST(2); @@ -162,7 +192,8 @@ static void scale2x(void* void_dst, unsigned dst_slice, const void* void_src, un * \param width Horizontal size in pixels of the source bitmap. * \param height Vertical size in pixels of the source bitmap. */ -static void scale2x3(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) +static void scale2x3(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, + unsigned width, unsigned height) { unsigned char* dst = (unsigned char*)void_dst; const unsigned char* src = (const unsigned char*)void_src; @@ -177,7 +208,8 @@ static void scale2x3(void* void_dst, unsigned dst_slice, const void* void_src, u dst = SCDST(3); count -= 2; - while (count) { + while (count) + { stage_scale2x3(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width); dst = SCDST(3); @@ -203,7 +235,8 @@ static void scale2x3(void* void_dst, unsigned dst_slice, const void* void_src, u * \param width Horizontal size in pixels of the source bitmap. * \param height Vertical size in pixels of the source bitmap. */ -static void scale2x4(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) +static void scale2x4(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, + unsigned width, unsigned height) { unsigned char* dst = (unsigned char*)void_dst; const unsigned char* src = (const unsigned char*)void_src; @@ -218,7 +251,8 @@ static void scale2x4(void* void_dst, unsigned dst_slice, const void* void_src, u dst = SCDST(4); count -= 2; - while (count) { + while (count) + { stage_scale2x4(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width); dst = SCDST(4); @@ -244,7 +278,8 @@ static void scale2x4(void* void_dst, unsigned dst_slice, const void* void_src, u * \param width Horizontal size in pixels of the source bitmap. * \param height Vertical size in pixels of the source bitmap. */ -static void scale3x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) +static void scale3x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, + unsigned width, unsigned height) { unsigned char* dst = (unsigned char*)void_dst; const unsigned char* src = (const unsigned char*)void_src; @@ -259,7 +294,8 @@ static void scale3x(void* void_dst, unsigned dst_slice, const void* void_src, un dst = SCDST(3); count -= 2; - while (count) { + while (count) + { stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width); dst = SCDST(3); @@ -292,7 +328,8 @@ static void scale3x(void* void_dst, unsigned dst_slice, const void* void_src, un * \param width Horizontal size in pixels of the source bitmap. * \param height Vertical size in pixels of the source bitmap. */ -static void scale4x_buf(void* void_dst, unsigned dst_slice, void* void_mid, unsigned mid_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) +static void scale4x_buf(void* void_dst, unsigned dst_slice, void* void_mid, unsigned mid_slice, const void* void_src, + unsigned src_slice, unsigned pixel, unsigned width, unsigned height) { unsigned char* dst = (unsigned char*)void_dst; const unsigned char* src = (const unsigned char*)void_src; @@ -323,7 +360,8 @@ static void scale4x_buf(void* void_dst, unsigned dst_slice, void* void_mid, unsi dst = SCDST(4); count -= 4; - while (count) { + while (count) + { unsigned char* tmp; stage_scale2x(SCMID(4), SCMID(5), SCSRC(2), SCSRC(3), SCSRC(4), pixel, width); @@ -368,7 +406,8 @@ static void scale4x_buf(void* void_dst, unsigned dst_slice, void* void_mid, unsi * \param width Horizontal size in pixels of the source bitmap. * \param height Vertical size in pixels of the source bitmap. */ -static void scale4x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) +static void scale4x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, + unsigned width, unsigned height) { unsigned mid_slice; void* mid; @@ -410,18 +449,19 @@ int scale_precondition(unsigned scale, unsigned pixel, unsigned width, unsigned if (pixel != 1 && pixel != 2 && pixel != 4) return -1; - switch (scale) { - case 202 : - case 203 : - case 204 : - case 2 : - case 303 : - case 3 : + switch (scale) + { + case 202: + case 203: + case 204: + case 2: + case 303: + case 3: if (height < 2) return -1; break; - case 404 : - case 4 : + case 404: + case 4: if (height < 4) return -1; break; @@ -447,27 +487,28 @@ int scale_precondition(unsigned scale, unsigned pixel, unsigned width, unsigned * \param width Horizontal size in pixels of the source bitmap. * \param height Vertical size in pixels of the source bitmap. */ -void scale(unsigned scale, void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) +void scale(unsigned scale, void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, + unsigned width, unsigned height) { - switch (scale) { - case 202 : - case 2 : + switch (scale) + { + case 202: + case 2: scale2x(void_dst, dst_slice, void_src, src_slice, pixel, width, height); break; - case 203 : + case 203: scale2x3(void_dst, dst_slice, void_src, src_slice, pixel, width, height); break; - case 204 : + case 204: scale2x4(void_dst, dst_slice, void_src, src_slice, pixel, width, height); break; - case 303 : - case 3 : + case 303: + case 3: scale3x(void_dst, dst_slice, void_src, src_slice, pixel, width, height); break; - case 404 : - case 4 : + case 404: + case 4: scale4x(void_dst, dst_slice, void_src, src_slice, pixel, width, height); break; } } - diff --git a/Utilities/Scale2x/scalebit.h b/Utilities/Scale2x/scalebit.h index 29dd5f5..bf1b0a2 100644 --- a/Utilities/Scale2x/scalebit.h +++ b/Utilities/Scale2x/scalebit.h @@ -27,7 +27,7 @@ #define __SCALEBIT_H int scale_precondition(unsigned scale, unsigned pixel, unsigned width, unsigned height); -void scale(unsigned scale, void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height); +void scale(unsigned scale, void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, + unsigned width, unsigned height); #endif - diff --git a/Utilities/Serializer.cpp b/Utilities/Serializer.cpp index 0a20fe3..478e4a5 100644 --- a/Utilities/Serializer.cpp +++ b/Utilities/Serializer.cpp @@ -14,7 +14,7 @@ Serializer::Serializer(uint32_t version) _saving = true; } -Serializer::Serializer(istream &file, uint32_t version, bool compressed) +Serializer::Serializer(istream& file, uint32_t version, bool compressed) { _version = version; @@ -22,7 +22,8 @@ Serializer::Serializer(istream &file, uint32_t version, bool compressed) _block->Position = 0; _saving = false; - if(compressed) { + if (compressed) + { uint32_t decompressedSize; file.read((char*)&decompressedSize, sizeof(decompressedSize)); @@ -36,7 +37,9 @@ Serializer::Serializer(istream &file, uint32_t version, bool compressed) unsigned long decompSize = decompressedSize; uncompress(_block->Data.data(), &decompSize, compressedData.data(), (unsigned long)compressedData.size()); - } else { + } + else + { file.seekg(0, std::ios::end); uint32_t size = (uint32_t)file.tellg(); file.seekg(0, std::ios::beg); @@ -50,14 +53,16 @@ void Serializer::EnsureCapacity(uint32_t typeSize) { //Make sure the current block/stream is large enough to fit the next write uint32_t oldSize = (uint32_t)_block->Data.size(); - if(oldSize == 0) { + if (oldSize == 0) + { oldSize = typeSize * 2; } uint32_t sizeRequired = _block->Position + typeSize; - + uint32_t newSize = oldSize; - while(newSize < sizeRequired) { + while (newSize < sizeRequired) + { newSize *= 2; } @@ -73,10 +78,13 @@ void Serializer::StreamStartBlock() unique_ptr block(new BlockData()); block->Position = 0; - if(!_saving) { - VectorInfo vectorInfo = { &block->Data }; + if (!_saving) + { + VectorInfo vectorInfo = {&block->Data}; InternalStream(vectorInfo); - } else { + } + else + { block->Data = vector(0x100); } @@ -86,7 +94,8 @@ void Serializer::StreamStartBlock() void Serializer::StreamEndBlock() { - if(_blocks.empty()) { + if (_blocks.empty()) + { throw std::runtime_error("Invalid call to end block"); } @@ -95,20 +104,25 @@ void Serializer::StreamEndBlock() _block = std::move(_blocks.back()); _blocks.pop_back(); - if(_saving) { - ArrayInfo arrayInfo { block->Data.data(), block->Position }; + if (_saving) + { + ArrayInfo arrayInfo{block->Data.data(), block->Position}; InternalStream(arrayInfo); } } void Serializer::Save(ostream& file, int compressionLevel) { - if(compressionLevel == 0) { + if (compressionLevel == 0) + { file.write((char*)_block->Data.data(), _block->Position); - } else { + } + else + { unsigned long compressedSize = compressBound((unsigned long)_block->Position); uint8_t* compressedData = new uint8_t[compressedSize]; - compress2(compressedData, &compressedSize, (unsigned char*)_block->Data.data(), (unsigned long)_block->Position, compressionLevel); + compress2(compressedData, &compressedSize, (unsigned char*)_block->Data.data(), (unsigned long)_block->Position, + compressionLevel); uint32_t size = (uint32_t)compressedSize; file.write((char*)&_block->Position, sizeof(uint32_t)); @@ -131,27 +145,31 @@ void Serializer::SkipBlock(istream* file) file->seekg(blockSize, std::ios::cur); } -void Serializer::Stream(ISerializable &obj) +void Serializer::Stream(ISerializable& obj) { StreamStartBlock(); obj.Serialize(*this); StreamEndBlock(); } -void Serializer::Stream(ISerializable *obj) + +void Serializer::Stream(ISerializable* obj) { StreamStartBlock(); obj->Serialize(*this); StreamEndBlock(); } -void Serializer::InternalStream(string &str) +void Serializer::InternalStream(string& str) { - if(_saving) { + if (_saving) + { vector stringData; stringData.resize(str.size()); memcpy(stringData.data(), str.data(), str.size()); StreamVector(stringData); - } else { + } + else + { vector stringData; StreamVector(stringData); str = string(stringData.begin(), stringData.end()); diff --git a/Utilities/Serializer.h b/Utilities/Serializer.h index 07cd518..10145b9 100644 --- a/Utilities/Serializer.h +++ b/Utilities/Serializer.h @@ -5,20 +5,20 @@ class Serializer; class ISerializable; -template +template struct ArrayInfo { T* Array; uint32_t ElementCount; }; -template +template struct VectorInfo { vector* Vector; }; -template +template struct ValueInfo { T* Value; @@ -34,7 +34,7 @@ struct BlockData class Serializer { private: - vector> _blocks; + vector> _blocks; unique_ptr _block; uint32_t _version = 0; @@ -43,69 +43,86 @@ private: private: void EnsureCapacity(uint32_t typeSize); - template void StreamElement(T &value, T defaultValue = T()); - - template void InternalStream(ArrayInfo &info); - template void InternalStream(VectorInfo &info); - template void InternalStream(ValueInfo &info); - template void InternalStream(T &value); - void InternalStream(string &str); + template + void StreamElement(T& value, T defaultValue = T()); + + template + void InternalStream(ArrayInfo& info); + template + void InternalStream(VectorInfo& info); + template + void InternalStream(ValueInfo& info); + template + void InternalStream(T& value); + void InternalStream(string& str); void RecursiveStream(); - template void RecursiveStream(T &value, T2&... args); + template + void RecursiveStream(T& value, T2&... args); void StreamStartBlock(); void StreamEndBlock(); public: Serializer(uint32_t version); - Serializer(istream &file, uint32_t version, bool compressed = true); + Serializer(istream& file, uint32_t version, bool compressed = true); uint32_t GetVersion() { return _version; } bool IsSaving() { return _saving; } - template void Stream(T&... args); - template void StreamArray(T *array, uint32_t size); - template void StreamVector(vector &list); + template + void Stream(T&... args); + template + void StreamArray(T* array, uint32_t size); + template + void StreamVector(vector& list); - void Save(ostream &file, int compressionLevel = 1); + void Save(ostream& file, int compressionLevel = 1); - void Stream(ISerializable &obj); - void Stream(ISerializable *obj); + void Stream(ISerializable& obj); + void Stream(ISerializable* obj); void WriteEmptyBlock(ostream* file); void SkipBlock(istream* file); }; -template -void Serializer::StreamElement(T &value, T defaultValue) +template +void Serializer::StreamElement(T& value, T defaultValue) { - if(_saving) { + if (_saving) + { uint8_t* bytes = (uint8_t*)&value; int typeSize = sizeof(T); EnsureCapacity(typeSize); - for(int i = 0; i < typeSize; i++) { + for (int i = 0; i < typeSize; i++) + { _block->Data[_block->Position++] = bytes[i]; } - } else { - if(_block->Position + sizeof(T) <= _block->Data.size()) { + } + else + { + if (_block->Position + sizeof(T) <= _block->Data.size()) + { memcpy(&value, _block->Data.data() + _block->Position, sizeof(T)); _block->Position += sizeof(T); - } else { + } + else + { value = defaultValue; _block->Position = (uint32_t)_block->Data.size(); } } } -template -void Serializer::InternalStream(ArrayInfo &info) +template +void Serializer::InternalStream(ArrayInfo& info) { uint32_t count = info.ElementCount; StreamElement(count); - if(!_saving) { + if (!_saving) + { //Reset array to 0 before loading from file memset(info.Array, 0, info.ElementCount * sizeof(T)); } @@ -113,58 +130,64 @@ void Serializer::InternalStream(ArrayInfo &info) //Load the number of elements requested, or the maximum possible (based on what is present in the save state) EnsureCapacity(info.ElementCount * sizeof(T)); - if(_saving) { + if (_saving) + { memcpy(_block->Data.data() + _block->Position, info.Array, info.ElementCount * sizeof(T)); - } else { + } + else + { memcpy(info.Array, _block->Data.data() + _block->Position, info.ElementCount * sizeof(T)); } _block->Position += info.ElementCount * sizeof(T); } -template -void Serializer::InternalStream(VectorInfo &info) +template +void Serializer::InternalStream(VectorInfo& info) { - vector *vector = info.Vector; + vector* vector = info.Vector; uint32_t count = (uint32_t)vector->size(); StreamElement(count); - if(!_saving) { - if(count > 0xFFFFFF) { + if (!_saving) + { + if (count > 0xFFFFFF) + { throw std::runtime_error("Invalid save state"); } vector->resize(count); - memset(vector->data(), 0, sizeof(T)*count); + memset(vector->data(), 0, sizeof(T) * count); } //Load the number of elements requested T* pointer = vector->data(); - for(uint32_t i = 0; i < count; i++) { + for (uint32_t i = 0; i < count; i++) + { StreamElement(*pointer); pointer++; } } -template -void Serializer::InternalStream(ValueInfo &info) +template +void Serializer::InternalStream(ValueInfo& info) { StreamElement(*info.Value, info.DefaultValue); } -template -void Serializer::InternalStream(T &value) +template +void Serializer::InternalStream(T& value) { StreamElement(value); } -template -void Serializer::RecursiveStream(T &value, T2&... args) +template +void Serializer::RecursiveStream(T& value, T2&... args) { InternalStream(value); RecursiveStream(args...); } -template +template void Serializer::Stream(T&... args) { StreamStartBlock(); @@ -172,8 +195,8 @@ void Serializer::Stream(T&... args) StreamEndBlock(); } -template -void Serializer::StreamArray(T *array, uint32_t size) +template +void Serializer::StreamArray(T* array, uint32_t size) { ArrayInfo info; info.Array = array; @@ -181,10 +204,10 @@ void Serializer::StreamArray(T *array, uint32_t size) InternalStream(info); } -template -void Serializer::StreamVector(vector &list) +template +void Serializer::StreamVector(vector& list) { VectorInfo info; info.Vector = &list; InternalStream(info); -} \ No newline at end of file +} diff --git a/Utilities/SimpleLock.cpp b/Utilities/SimpleLock.cpp index b3f6946..c87abb5 100644 --- a/Utilities/SimpleLock.cpp +++ b/Utilities/SimpleLock.cpp @@ -22,11 +22,14 @@ LockHandler SimpleLock::AcquireSafe() void SimpleLock::Acquire() { - if(_lockCount == 0 || _holderThreadID != _threadID) { - while(_lock.test_and_set()); + if (_lockCount == 0 || _holderThreadID != _threadID) + { + while (_lock.test_and_set()); _holderThreadID = _threadID; _lockCount = 1; - } else { + } + else + { //Same thread can acquire the same lock multiple times _lockCount++; } @@ -46,19 +49,23 @@ void SimpleLock::WaitForRelease() void SimpleLock::Release() { - if(_lockCount > 0 && _holderThreadID == _threadID) { + if (_lockCount > 0 && _holderThreadID == _threadID) + { _lockCount--; - if(_lockCount == 0) { + if (_lockCount == 0) + { _holderThreadID = std::thread::id(); _lock.clear(); } - } else { + } + else + { assert(false); } } -LockHandler::LockHandler(SimpleLock *lock) +LockHandler::LockHandler(SimpleLock* lock) { _lock = lock; _lock->Acquire(); @@ -67,4 +74,4 @@ LockHandler::LockHandler(SimpleLock *lock) LockHandler::~LockHandler() { _lock->Release(); -} \ No newline at end of file +} diff --git a/Utilities/SimpleLock.h b/Utilities/SimpleLock.h index 630a3ab..6ecf7d5 100644 --- a/Utilities/SimpleLock.h +++ b/Utilities/SimpleLock.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include "stdafx.h" #include @@ -7,9 +7,9 @@ class SimpleLock; class LockHandler { private: - SimpleLock *_lock; + SimpleLock* _lock; public: - LockHandler(SimpleLock *lock); + LockHandler(SimpleLock* lock); ~LockHandler(); }; @@ -33,4 +33,3 @@ public: void WaitForRelease(); void Release(); }; - diff --git a/Utilities/Socket.cpp b/Utilities/Socket.cpp index 4b3bb50..1e94322 100644 --- a/Utilities/Socket.cpp +++ b/Utilities/Socket.cpp @@ -8,11 +8,11 @@ using namespace std; #ifdef _WIN32 - #pragma comment(lib,"ws2_32.lib") //Winsock Library - #define WIN32_LEAN_AND_MEAN - #include - #include - #include +#pragma comment(lib,"ws2_32.lib") //Winsock Library +#define WIN32_LEAN_AND_MEAN +#include +#include +#include #else #include #include @@ -38,51 +38,61 @@ using namespace std; Socket::Socket() { - #ifdef _WIN32 - WSADATA wsaDat; - if(WSAStartup(MAKEWORD(2, 2), &wsaDat) != 0) { - std::cout << "WSAStartup failed." << std::endl; - SetConnectionErrorFlag(); - return; - } - _cleanupWSA = true; - #endif +#ifdef _WIN32 + WSADATA wsaDat; + if (WSAStartup(MAKEWORD(2, 2), &wsaDat) != 0) + { + std::cout << "WSAStartup failed." << std::endl; + SetConnectionErrorFlag(); + return; + } + _cleanupWSA = true; +#endif _socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if(_socket == INVALID_SOCKET) { + if (_socket == INVALID_SOCKET) + { std::cout << "Socket creation failed." << std::endl; SetConnectionErrorFlag(); - } else { + } + else + { SetSocketOptions(); } } -Socket::Socket(uintptr_t socket) +Socket::Socket(uintptr_t socket) { _socket = socket; - if(socket == INVALID_SOCKET) { + if (socket == INVALID_SOCKET) + { SetConnectionErrorFlag(); - } else { + } + else + { SetSocketOptions(); } } Socket::~Socket() { - if(_UPnPPort != -1) { + if (_UPnPPort != -1) + { UPnPPortMapper::RemoveNATPortMapping(_UPnPPort, IPProtocol::TCP); } - if(_socket != INVALID_SOCKET) { + if (_socket != INVALID_SOCKET) + { Close(); } - #ifdef _WIN32 - if(_cleanupWSA) { - WSACleanup(); - } - #endif +#ifdef _WIN32 + if (_cleanupWSA) + { + WSACleanup(); + } +#endif } void Socket::SetSocketOptions() @@ -90,7 +100,7 @@ void Socket::SetSocketOptions() //Non-blocking mode u_long iMode = 1; ioctlsocket(_socket, FIONBIO, &iMode); - + //Set send/recv buffers to 256k int bufferSize = 0x40000; setsockopt(_socket, SOL_SOCKET, SO_RCVBUF, (char*)&bufferSize, sizeof(int)); @@ -98,7 +108,7 @@ void Socket::SetSocketOptions() //Disable nagle's algorithm to improve latency u_long value = 1; - setsockopt(_socket, IPPROTO_TCP, TCP_NODELAY, (char*)&value, sizeof(value)); + setsockopt(_socket, IPPROTO_TCP, TCP_NODELAY, (char*)&value, sizeof(value)); } void Socket::SetConnectionErrorFlag() @@ -126,11 +136,13 @@ void Socket::Bind(uint16_t port) serverInf.sin_addr.s_addr = INADDR_ANY; serverInf.sin_port = htons(port); - if(UPnPPortMapper::AddNATPortMapping(port, port, IPProtocol::TCP)) { + if (UPnPPortMapper::AddNATPortMapping(port, port, IPProtocol::TCP)) + { _UPnPPort = port; } - if(::bind(_socket, (SOCKADDR*)(&serverInf), sizeof(serverInf)) == SOCKET_ERROR) { + if (::bind(_socket, (SOCKADDR*)(&serverInf), sizeof(serverInf)) == SOCKET_ERROR) + { std::cout << "Unable to bind socket." << std::endl; SetConnectionErrorFlag(); } @@ -145,12 +157,15 @@ bool Socket::Connect(const char* hostname, uint16_t port) hint.ai_family = AF_INET; hint.ai_protocol = IPPROTO_TCP; hint.ai_socktype = SOCK_STREAM; - addrinfo *addrInfo; + addrinfo* addrInfo; - if(getaddrinfo(hostname, std::to_string(port).c_str(), &hint, &addrInfo) != 0) { + if (getaddrinfo(hostname, std::to_string(port).c_str(), &hint, &addrInfo) != 0) + { std::cout << "Failed to resolve hostname." << std::endl; SetConnectionErrorFlag(); - } else { + } + else + { //Set socket in non-blocking mode u_long iMode = 1; ioctlsocket(_socket, FIONBIO, &iMode); @@ -159,13 +174,13 @@ bool Socket::Connect(const char* hostname, uint16_t port) connect(_socket, addrInfo->ai_addr, (int)addrInfo->ai_addrlen); fd_set writeSockets; - #ifdef _WIN32 - writeSockets.fd_count = 1; - writeSockets.fd_array[0] = _socket; - #else +#ifdef _WIN32 + writeSockets.fd_count = 1; + writeSockets.fd_array[0] = _socket; +#else FD_ZERO(&writeSockets); FD_SET(_socket, &writeSockets); - #endif +#endif //Timeout after 3 seconds TIMEVAL timeout; @@ -173,18 +188,22 @@ bool Socket::Connect(const char* hostname, uint16_t port) timeout.tv_usec = 0; // check if the socket is ready - int returnVal = select((int)_socket+1, nullptr, &writeSockets, nullptr, &timeout); - if(returnVal > 0) { + int returnVal = select((int)_socket + 1, nullptr, &writeSockets, nullptr, &timeout); + if (returnVal > 0) + { result = true; - } else { + } + else + { //Could not connect - if(returnVal == SOCKET_ERROR) { + if (returnVal == SOCKET_ERROR) + { //int nError = WSAGetLastError(); //std::cout << "select failed: nError " << std::to_string(nError) << " returnVal" << std::to_string(returnVal) << std::endl; } SetConnectionErrorFlag(); } - + freeaddrinfo(addrInfo); } @@ -193,7 +212,8 @@ bool Socket::Connect(const char* hostname, uint16_t port) void Socket::Listen(int backlog) { - if(listen(_socket, backlog) == SOCKET_ERROR) { + if (listen(_socket, backlog) == SOCKET_ERROR) + { std::cout << "listen failed." << std::endl; SetConnectionErrorFlag(); } @@ -210,53 +230,68 @@ bool WouldBlock(int nError) return nError == WSAEWOULDBLOCK || nError == EAGAIN; } -int Socket::Send(char *buf, int len, int flags) +int Socket::Send(char* buf, int len, int flags) { int retryCount = 15; int nError = 0; int returnVal; - do { + do + { //Loop until everything has been sent (shouldn't loop at all in the vast majority of cases) returnVal = send(_socket, buf, len, flags); - if(returnVal > 0) { + if (returnVal > 0) + { //Sent partial data, adjust pointer & length buf += returnVal; len -= returnVal; - } else if(returnVal == SOCKET_ERROR) { + } + else if (returnVal == SOCKET_ERROR) + { nError = WSAGetLastError(); - if(nError != 0) { - if(!WouldBlock(nError)) { + if (nError != 0) + { + if (!WouldBlock(nError)) + { SetConnectionErrorFlag(); - } else { + } + else + { retryCount--; - if(retryCount == 0) { + if (retryCount == 0) + { //Connection seems dead, close it. std::cout << "Unable to send data, closing socket." << std::endl; Close(); return 0; } - + std::this_thread::sleep_for(std::chrono::duration(10)); } } } - } while(WouldBlock(nError) && len > 0); - + } + while (WouldBlock(nError) && len > 0); + return returnVal; } -int Socket::Recv(char *buf, int len, int flags) +int Socket::Recv(char* buf, int len, int flags) { int returnVal = recv(_socket, buf, len, flags); - - if(returnVal == SOCKET_ERROR) { + + if (returnVal == SOCKET_ERROR) + { int nError = WSAGetLastError(); - if(nError && !WouldBlock(nError)) { - std::cout << "recv failed: nError " << std::to_string(nError) << " returnVal" << std::to_string(returnVal) << std::endl; + if (nError && !WouldBlock(nError)) + { + std::cout << "recv failed: nError " << std::to_string(nError) << " returnVal" << std::to_string(returnVal) << + std::endl; SetConnectionErrorFlag(); } - } else if(returnVal == 0) { + } + else if (returnVal == 0) + { //Socket closed std::cout << "Socket closed by peer." << std::endl; Close(); diff --git a/Utilities/Socket.h b/Utilities/Socket.h index 841491a..9b930fb 100644 --- a/Utilities/Socket.h +++ b/Utilities/Socket.h @@ -6,10 +6,10 @@ class Socket { private: #ifndef LIBRETRO - #ifdef _WIN32 +#ifdef _WIN32 bool _cleanupWSA = false; - #endif - +#endif + uintptr_t _socket = ~0; bool _connectionError = false; int32_t _UPnPPort = -1; @@ -31,8 +31,8 @@ public: void Listen(int backlog); shared_ptr Accept(); - int Send(char *buf, int len, int flags); - void BufferedSend(char *buf, int len); + int Send(char* buf, int len, int flags); + void BufferedSend(char* buf, int len); void SendBuffer(); - int Recv(char *buf, int len, int flags); + int Recv(char* buf, int len, int flags); }; diff --git a/Utilities/StringUtilities.h b/Utilities/StringUtilities.h index 22658be..6257aa0 100644 --- a/Utilities/StringUtilities.h +++ b/Utilities/StringUtilities.h @@ -9,7 +9,8 @@ public: vector result; size_t index = 0; size_t lastIndex = 0; - while((index = input.find(delimiter, index)) != string::npos) { + while ((index = input.find(delimiter, index)) != string::npos) + { result.push_back(input.substr(lastIndex, index - lastIndex)); index++; lastIndex = index; diff --git a/Utilities/Timer.cpp b/Utilities/Timer.cpp index a26c653..b2f5162 100644 --- a/Utilities/Timer.cpp +++ b/Utilities/Timer.cpp @@ -6,7 +6,7 @@ using namespace std::chrono; -Timer::Timer() +Timer::Timer() { Reset(); } @@ -25,9 +25,11 @@ double Timer::GetElapsedMS() void Timer::WaitUntil(double targetMillisecond) { - if(targetMillisecond > 0) { + if (targetMillisecond > 0) + { double elapsedTime = GetElapsedMS(); - if(targetMillisecond - elapsedTime > 1) { + if (targetMillisecond - elapsedTime > 1) + { std::this_thread::sleep_for(std::chrono::duration((int)(targetMillisecond - elapsedTime))); } } diff --git a/Utilities/Timer.h b/Utilities/Timer.h index 743ac7f..d679ddc 100644 --- a/Utilities/Timer.h +++ b/Utilities/Timer.h @@ -5,12 +5,12 @@ using namespace std::chrono; class Timer { - private: - high_resolution_clock::time_point _start; +private: + high_resolution_clock::time_point _start; public: - Timer(); - void Reset(); - double GetElapsedMS(); - void WaitUntil(double targetMillisecond); -}; \ No newline at end of file + Timer(); + void Reset(); + double GetElapsedMS(); + void WaitUntil(double targetMillisecond); +}; diff --git a/Utilities/UPnPPortMapper.cpp b/Utilities/UPnPPortMapper.cpp index 2b5bc8e..4af4dd7 100644 --- a/Utilities/UPnPPortMapper.cpp +++ b/Utilities/UPnPPortMapper.cpp @@ -6,58 +6,72 @@ #include #include -bool UPnPPortMapper::AddNATPortMapping(uint16_t internalPort, uint16_t externalPort, IPProtocol protocol) +bool UPnPPortMapper::AddNATPortMapping(uint16_t internalPort, uint16_t externalPort, IPProtocol protocol) { bool result = false; - + CoInitializeEx(nullptr, COINIT_MULTITHREADED); - IUPnPNAT *nat = nullptr; + IUPnPNAT* nat = nullptr; HRESULT hResult = CoCreateInstance(__uuidof(UPnPNAT), nullptr, CLSCTX_ALL, __uuidof(IUPnPNAT), (void**)&nat); BSTR proto = SysAllocString((protocol == IPProtocol::TCP) ? L"TCP" : L"UDP"); - if(SUCCEEDED(hResult) && nat) { - IStaticPortMappingCollection *spmc = nullptr; + if (SUCCEEDED(hResult) && nat) + { + IStaticPortMappingCollection* spmc = nullptr; hResult = nat->get_StaticPortMappingCollection(&spmc); - if(SUCCEEDED(hResult) && spmc) { - IStaticPortMapping *spm = nullptr; + if (SUCCEEDED(hResult) && spmc) + { + IStaticPortMapping* spm = nullptr; hResult = spmc->get_Item(externalPort, proto, &spm); - if(spm != nullptr) { + if (spm != nullptr) + { //An identical mapping already exists, remove it - if(RemoveNATPortMapping(externalPort, protocol)) { + if (RemoveNATPortMapping(externalPort, protocol)) + { std::cout << "Removed existing UPnP mapping." << std::endl; spm->Release(); spm = nullptr; } } - if(!SUCCEEDED(hResult) || spm == nullptr) { + if (!SUCCEEDED(hResult) || spm == nullptr) + { std::cout << "Attempting to automatically forward port via UPnP..." << std::endl; vector localIPs = GetLocalIPs(); BSTR desc = SysAllocString(L"Mesen NetPlay"); spm = nullptr; - for(size_t i = 0, len = localIPs.size(); i < len; i++) { + for (size_t i = 0, len = localIPs.size(); i < len; i++) + { BSTR clientStr = SysAllocString(localIPs[i].c_str()); hResult = spmc->Add(externalPort, proto, internalPort, clientStr, true, desc, &spm); SysFreeString(clientStr); SysFreeString(desc); - if(SUCCEEDED(hResult) && spm) { + if (SUCCEEDED(hResult) && spm) + { //Successfully added a new port mapping - std::cout << std::dec << "Forwarded port " << externalPort << " to IP " << utf8::utf8::encode(localIPs[i]) << std::endl; + std::cout << std::dec << "Forwarded port " << externalPort << " to IP " << + utf8::utf8::encode(localIPs[i]) << std::endl; result = true; - } else { - std::cout << "Unable to add UPnP port mapping. IP: " << utf8::utf8::encode(localIPs[i]) << " HRESULT: 0x" << std::hex << hResult << std::endl; + } + else + { + std::cout << "Unable to add UPnP port mapping. IP: " << utf8::utf8::encode(localIPs[i]) << + " HRESULT: 0x" << std::hex << hResult << std::endl; } - if(spm) { + if (spm) + { spm->Release(); } } - } else { + } + else + { std::cout << "Unable to add UPnP port mapping." << std::endl; } spmc->Release(); @@ -66,16 +80,16 @@ bool UPnPPortMapper::AddNATPortMapping(uint16_t internalPort, uint16_t externalP } SysFreeString(proto); - + CoUninitialize(); return result; } -bool UPnPPortMapper::RemoveNATPortMapping(uint16_t externalPort, IPProtocol protocol) +bool UPnPPortMapper::RemoveNATPortMapping(uint16_t externalPort, IPProtocol protocol) { - IUPnPNAT *nat = nullptr; - IStaticPortMappingCollection *spmc; + IUPnPNAT* nat = nullptr; + IStaticPortMappingCollection* spmc; bool result = false; CoInitializeEx(nullptr, COINIT_MULTITHREADED); @@ -84,9 +98,11 @@ bool UPnPPortMapper::RemoveNATPortMapping(uint16_t externalPort, IPProtocol prot BSTR proto = SysAllocString((protocol == IPProtocol::TCP) ? L"TCP" : L"UDP"); - if(SUCCEEDED(hResult) && nat) { + if (SUCCEEDED(hResult) && nat) + { hResult = nat->get_StaticPortMappingCollection(&spmc); - if(SUCCEEDED(hResult) && spmc) { + if (SUCCEEDED(hResult) && spmc) + { spmc->Remove(externalPort, proto); spmc->Release(); result = true; @@ -104,8 +120,8 @@ bool UPnPPortMapper::RemoveNATPortMapping(uint16_t externalPort, IPProtocol prot vector UPnPPortMapper::GetLocalIPs() { vector localIPs; - ADDRINFOW *result = nullptr; - ADDRINFOW *current = nullptr; + ADDRINFOW* result = nullptr; + ADDRINFOW* current = nullptr; ADDRINFOW hints; ZeroMemory(&hints, sizeof(hints)); @@ -117,14 +133,18 @@ vector UPnPPortMapper::GetLocalIPs() DWORD hostSize = 255; GetComputerName(hostName, &hostSize); - if(GetAddrInfoW(hostName, nullptr, &hints, &result) == 0) { + if (GetAddrInfoW(hostName, nullptr, &hints, &result) == 0) + { current = result; - while(current != nullptr) { + while (current != nullptr) + { wchar_t ipAddr[255]; DWORD ipSize = 255; - if(WSAAddressToString(current->ai_addr, (DWORD)current->ai_addrlen, nullptr, ipAddr, &ipSize) == 0) { - if(std::find(localIPs.begin(), localIPs.end(), ipAddr) == localIPs.end()) { + if (WSAAddressToString(current->ai_addr, (DWORD)current->ai_addrlen, nullptr, ipAddr, &ipSize) == 0) + { + if (std::find(localIPs.begin(), localIPs.end(), ipAddr) == localIPs.end()) + { localIPs.push_back(ipAddr); } } @@ -153,4 +173,4 @@ vector UPnPPortMapper::GetLocalIPs() return vector(); } -#endif \ No newline at end of file +#endif diff --git a/Utilities/UPnPPortMapper.h b/Utilities/UPnPPortMapper.h index 82f1301..17109ec 100644 --- a/Utilities/UPnPPortMapper.h +++ b/Utilities/UPnPPortMapper.h @@ -18,4 +18,4 @@ private: public: static bool AddNATPortMapping(uint16_t internalPort, uint16_t externalPort, IPProtocol protocol); static bool RemoveNATPortMapping(uint16_t externalPort, IPProtocol protocol); -}; \ No newline at end of file +}; diff --git a/Utilities/UTF8Util.cpp b/Utilities/UTF8Util.cpp index 0a99fea..11c54b3 100644 --- a/Utilities/UTF8Util.cpp +++ b/Utilities/UTF8Util.cpp @@ -3,29 +3,29 @@ #include #include -namespace utf8 +namespace utf8 { - std::wstring utf8::decode(const std::string &str) + std::wstring utf8::decode(const std::string& str) { std::wstring_convert> conv; return conv.from_bytes(str); } - std::string utf8::encode(const std::wstring &wstr) + std::string utf8::encode(const std::wstring& wstr) { std::wstring_convert> conv; - return conv.to_bytes(wstr); + return conv.to_bytes(wstr); } - std::string utf8::encode(const std::u16string &wstr) + std::string utf8::encode(const std::u16string& wstr) { - #ifdef _MSC_VER - std::wstring_convert, int16_t> conv; - auto p = reinterpret_cast(wstr.data()); - return conv.to_bytes(p, p + wstr.size()); - #else +#ifdef _MSC_VER + std::wstring_convert, int16_t> conv; + auto p = reinterpret_cast(wstr.data()); + return conv.to_bytes(p, p + wstr.size()); +#else std::wstring_convert, char16_t> conv; return conv.to_bytes(wstr); - #endif - } -} \ No newline at end of file +#endif + } +} diff --git a/Utilities/UTF8Util.h b/Utilities/UTF8Util.h index c60c966..3925cee 100644 --- a/Utilities/UTF8Util.h +++ b/Utilities/UTF8Util.h @@ -2,33 +2,54 @@ #include -namespace utf8 { +namespace utf8 +{ class utf8 { public: - static std::wstring decode(const std::string &str); - static std::string encode(const std::wstring &wstr); - static std::string encode(const std::u16string &wstr); + static std::wstring decode(const std::string& str); + static std::string encode(const std::wstring& wstr); + static std::string encode(const std::u16string& wstr); }; - + #if defined(_WIN32) && !defined(LIBRETRO) class ifstream : public std::ifstream { public: - ifstream(const std::string& _Str, ios_base::openmode _Mode = ios_base::in, int _Prot = (int)ios_base::_Openprot) : std::ifstream(utf8::decode(_Str), _Mode, _Prot) { } - ifstream() : std::ifstream() { } - void open(const std::string& _Str, ios_base::openmode _Mode = ios_base::in, int _Prot = (int)ios_base::_Openprot) { std::ifstream::open(utf8::decode(_Str), _Mode, _Prot); } + ifstream(const std::string& _Str, ios_base::openmode _Mode = ios_base::in, + int _Prot = (int)ios_base::_Openprot) : std::ifstream(utf8::decode(_Str), _Mode, _Prot) + { + } + + ifstream() : std::ifstream() + { + } + + void open(const std::string& _Str, ios_base::openmode _Mode = ios_base::in, int _Prot = (int)ios_base::_Openprot) + { + std::ifstream::open(utf8::decode(_Str), _Mode, _Prot); + } }; class ofstream : public std::ofstream { public: - ofstream(const std::string& _Str, ios_base::openmode _Mode = ios_base::in, int _Prot = (int)ios_base::_Openprot) : std::ofstream(utf8::decode(_Str), _Mode, _Prot) { } - ofstream() : std::ofstream() { } - void open(const std::string& _Str, ios_base::openmode _Mode = ios_base::in, int _Prot = (int)ios_base::_Openprot) { std::ofstream::open(utf8::decode(_Str), _Mode, _Prot); } + ofstream(const std::string& _Str, ios_base::openmode _Mode = ios_base::in, + int _Prot = (int)ios_base::_Openprot) : std::ofstream(utf8::decode(_Str), _Mode, _Prot) + { + } + + ofstream() : std::ofstream() + { + } + + void open(const std::string& _Str, ios_base::openmode _Mode = ios_base::in, int _Prot = (int)ios_base::_Openprot) + { + std::ofstream::open(utf8::decode(_Str), _Mode, _Prot); + } }; #else using std::ifstream; using std::ofstream; #endif -} \ No newline at end of file +} diff --git a/Utilities/UpsPatcher.cpp b/Utilities/UpsPatcher.cpp index 1c3a72b..c02f412 100644 --- a/Utilities/UpsPatcher.cpp +++ b/Utilities/UpsPatcher.cpp @@ -4,19 +4,22 @@ #include "UpsPatcher.h" #include "CRC32.h" -int64_t UpsPatcher::ReadBase128Number(std::istream &file) +int64_t UpsPatcher::ReadBase128Number(std::istream& file) { int64_t result = 0; int shift = 0; uint8_t buffer; - while(true) { + while (true) + { file.read((char*)&buffer, 1); - if(file.eof()) { + if (file.eof()) + { return -1; } result += (buffer & 0x7F) << shift; shift += 7; - if(buffer & 0x80) { + if (buffer & 0x80) + { break; } result += (int64_t)1 << shift; @@ -25,16 +28,17 @@ int64_t UpsPatcher::ReadBase128Number(std::istream &file) return result; } -bool UpsPatcher::PatchBuffer(string upsFilepath, vector &input, vector &output) +bool UpsPatcher::PatchBuffer(string upsFilepath, vector& input, vector& output) { ifstream upsFile(upsFilepath, std::ios::in | std::ios::binary); - if(upsFile) { + if (upsFile) + { return PatchBuffer(upsFile, input, output); } return false; } -bool UpsPatcher::PatchBuffer(std::istream &upsFile, vector &input, vector &output) +bool UpsPatcher::PatchBuffer(std::istream& upsFile, vector& input, vector& output) { upsFile.seekg(0, std::ios::end); size_t fileSize = (size_t)upsFile.tellg(); @@ -42,14 +46,16 @@ bool UpsPatcher::PatchBuffer(std::istream &upsFile, vector &input, vect char header[4]; upsFile.read((char*)&header, 4); - if(memcmp((char*)&header, "UPS1", 4) != 0) { + if (memcmp((char*)&header, "UPS1", 4) != 0) + { //Invalid UPS file return false; } int64_t inputFileSize = ReadBase128Number(upsFile); int64_t outputFileSize = ReadBase128Number(upsFile); - if(inputFileSize == -1 || outputFileSize == -1) { + if (inputFileSize == -1 || outputFileSize == -1) + { //Invalid file return false; } @@ -58,19 +64,23 @@ bool UpsPatcher::PatchBuffer(std::istream &upsFile, vector &input, vect std::copy(input.begin(), input.end(), output.begin()); uint32_t pos = 0; - while((size_t)upsFile.tellg() < fileSize - 12) { + while ((size_t)upsFile.tellg() < fileSize - 12) + { int32_t offset = (int32_t)ReadBase128Number(upsFile); - if(offset == -1) { + if (offset == -1) + { //Invalid file return false; } pos += offset; - while(true) { + while (true) + { uint8_t xorValue = 0; upsFile.read((char*)&xorValue, 1); - if((size_t)upsFile.tellg() > fileSize - 12) { + if ((size_t)upsFile.tellg() > fileSize - 12) + { //Invalid file return false; } @@ -78,7 +88,8 @@ bool UpsPatcher::PatchBuffer(std::istream &upsFile, vector &input, vect output[pos] ^= xorValue; pos++; - if(!xorValue) { + if (!xorValue) + { break; } } @@ -88,12 +99,15 @@ bool UpsPatcher::PatchBuffer(std::istream &upsFile, vector &input, vect uint8_t outputChecksum[4]; upsFile.read((char*)inputChecksum, 4); upsFile.read((char*)outputChecksum, 4); - uint32_t patchInputCrc = inputChecksum[0] | (inputChecksum[1] << 8) | (inputChecksum[2] << 16) | (inputChecksum[3] << 24); - uint32_t patchOutputCrc = outputChecksum[0] | (outputChecksum[1] << 8) | (outputChecksum[2] << 16) | (outputChecksum[3] << 24); + uint32_t patchInputCrc = inputChecksum[0] | (inputChecksum[1] << 8) | (inputChecksum[2] << 16) | (inputChecksum[3] << + 24); + uint32_t patchOutputCrc = outputChecksum[0] | (outputChecksum[1] << 8) | (outputChecksum[2] << 16) | (outputChecksum[ + 3] << 24); uint32_t inputCrc = CRC32::GetCRC(input.data(), input.size()); uint32_t outputCrc = CRC32::GetCRC(output.data(), output.size()); - if(patchInputCrc != inputCrc || patchOutputCrc != outputCrc) { + if (patchInputCrc != inputCrc || patchOutputCrc != outputCrc) + { return false; } return true; diff --git a/Utilities/UpsPatcher.h b/Utilities/UpsPatcher.h index bf75b1e..7a3c2c2 100644 --- a/Utilities/UpsPatcher.h +++ b/Utilities/UpsPatcher.h @@ -5,9 +5,9 @@ class UpsPatcher { private: - static int64_t ReadBase128Number(std::istream &file); + static int64_t ReadBase128Number(std::istream& file); public: - static bool PatchBuffer(std::istream &upsFile, vector &input, vector &output); - static bool PatchBuffer(string upsFilepath, vector &input, vector &output); -}; \ No newline at end of file + static bool PatchBuffer(std::istream& upsFile, vector& input, vector& output); + static bool PatchBuffer(string upsFilepath, vector& input, vector& output); +}; diff --git a/Utilities/VirtualFile.cpp b/Utilities/VirtualFile.cpp index 3144e42..d41a3ef 100644 --- a/Utilities/VirtualFile.cpp +++ b/Utilities/VirtualFile.cpp @@ -10,7 +10,7 @@ #include "../Utilities/IpsPatcher.h" #include "../Utilities/UpsPatcher.h" -const std::initializer_list VirtualFile::RomExtensions = { ".sfc", ".smc", ".swc", ".fig", ".bs", ".gb", ".gbc" }; +const std::initializer_list VirtualFile::RomExtensions = {".sfc", ".smc", ".swc", ".fig", ".bs", ".gb", ".gbc"}; VirtualFile::VirtualFile() { @@ -26,12 +26,18 @@ VirtualFile::VirtualFile(const string& file) { vector tokens = StringUtilities::Split(file, '\x1'); _path = tokens[0]; - if(tokens.size() > 1) { + if (tokens.size() > 1) + { _innerFile = tokens[1]; - if(tokens.size() > 2) { - try { + if (tokens.size() > 2) + { + try + { _innerFileIndex = std::stoi(tokens[2]); - } catch(std::exception&) {} + } + catch (std::exception&) + { + } } } } @@ -52,14 +58,22 @@ VirtualFile::VirtualFile(std::istream& input, string filePath) VirtualFile::operator std::string() const { - if(_innerFile.empty()) { + if (_innerFile.empty()) + { return _path; - } else if(_path.empty()) { + } + else if (_path.empty()) + { throw std::runtime_error("Cannot convert to string"); - } else { - if(_innerFileIndex >= 0) { + } + else + { + if (_innerFileIndex >= 0) + { return _path + "\x1" + _innerFile + "\x1" + std::to_string(_innerFileIndex); - } else { + } + else + { return _path + "\x1" + _innerFile; } } @@ -77,22 +91,32 @@ void VirtualFile::FromStream(std::istream& input, vector& output) void VirtualFile::LoadFile() { - if(_data.size() == 0) { - if(!_innerFile.empty()) { + if (_data.size() == 0) + { + if (!_innerFile.empty()) + { shared_ptr reader = ArchiveReader::GetReader(_path); - if(reader) { - if(_innerFileIndex >= 0) { + if (reader) + { + if (_innerFileIndex >= 0) + { vector filelist = reader->GetFileList(VirtualFile::RomExtensions); - if((int32_t)filelist.size() > _innerFileIndex) { + if ((int32_t)filelist.size() > _innerFileIndex) + { reader->ExtractFile(filelist[_innerFileIndex], _data); } - } else { + } + else + { reader->ExtractFile(_innerFile, _data); } } - } else { + } + else + { ifstream input(_path, std::ios::in | std::ios::binary); - if(input.good()) { + if (input.good()) + { FromStream(input, _data); } } @@ -101,25 +125,35 @@ void VirtualFile::LoadFile() bool VirtualFile::IsValid() { - if(_data.size() > 0) { + if (_data.size() > 0) + { return true; } - if(!_innerFile.empty()) { + if (!_innerFile.empty()) + { shared_ptr reader = ArchiveReader::GetReader(_path); - if(reader) { + if (reader) + { vector filelist = reader->GetFileList(); - if(_innerFileIndex >= 0) { - if((int32_t)filelist.size() > _innerFileIndex) { + if (_innerFileIndex >= 0) + { + if ((int32_t)filelist.size() > _innerFileIndex) + { return true; } - } else { + } + else + { return std::find(filelist.begin(), filelist.end(), _innerFile) != filelist.end(); } } - } else { + } + else + { ifstream input(_path, std::ios::in | std::ios::binary); - if(input) { + if (input) + { return true; } } @@ -156,7 +190,8 @@ size_t VirtualFile::GetSize() bool VirtualFile::ReadFile(vector& out) { LoadFile(); - if(_data.size() > 0) { + if (_data.size() > 0) + { out.resize(_data.size(), 0); std::copy(_data.begin(), _data.end(), out.begin()); return true; @@ -167,7 +202,8 @@ bool VirtualFile::ReadFile(vector& out) bool VirtualFile::ReadFile(std::stringstream& out) { LoadFile(); - if(_data.size() > 0) { + if (_data.size() > 0) + { out.write((char*)_data.data(), _data.size()); return true; } @@ -177,7 +213,8 @@ bool VirtualFile::ReadFile(std::stringstream& out) bool VirtualFile::ReadFile(uint8_t* out, uint32_t expectedSize) { LoadFile(); - if(_data.size() == expectedSize) { + if (_data.size() == expectedSize) + { memcpy(out, _data.data(), _data.size()); return true; } @@ -188,25 +225,33 @@ bool VirtualFile::ApplyPatch(VirtualFile& patch) { //Apply patch file bool result = false; - if(IsValid() && patch.IsValid()) { + if (IsValid() && patch.IsValid()) + { patch.LoadFile(); LoadFile(); - if(patch._data.size() >= 5) { + if (patch._data.size() >= 5) + { vector patchedData; std::stringstream ss; patch.ReadFile(ss); - if(memcmp(patch._data.data(), "PATCH", 5) == 0) { + if (memcmp(patch._data.data(), "PATCH", 5) == 0) + { result = IpsPatcher::PatchBuffer(ss, _data, patchedData); - } else if(memcmp(patch._data.data(), "UPS1", 4) == 0) { + } + else if (memcmp(patch._data.data(), "UPS1", 4) == 0) + { result = UpsPatcher::PatchBuffer(ss, _data, patchedData); - } else if(memcmp(patch._data.data(), "BPS1", 4) == 0) { + } + else if (memcmp(patch._data.data(), "BPS1", 4) == 0) + { result = BpsPatcher::PatchBuffer(ss, _data, patchedData); } - if(result) { + if (result) + { _data = patchedData; } } } return result; -} \ No newline at end of file +} diff --git a/Utilities/VirtualFile.h b/Utilities/VirtualFile.h index 6e59c09..e2a232e 100644 --- a/Utilities/VirtualFile.h +++ b/Utilities/VirtualFile.h @@ -10,7 +10,7 @@ private: int32_t _innerFileIndex = -1; vector _data; - void FromStream(std::istream &input, vector &output); + void FromStream(std::istream& input, vector& output); void LoadFile(); @@ -18,13 +18,13 @@ public: static const std::initializer_list RomExtensions; VirtualFile(); - VirtualFile(const string &archivePath, const string innerFile); - VirtualFile(const string &file); - VirtualFile(const void *buffer, size_t bufferSize, string fileName = "noname"); - VirtualFile(std::istream &input, string filePath); + VirtualFile(const string& archivePath, const string innerFile); + VirtualFile(const string& file); + VirtualFile(const void* buffer, size_t bufferSize, string fileName = "noname"); + VirtualFile(std::istream& input, string filePath); operator std::string() const; - + bool IsValid(); string GetFilePath(); string GetFolderPath(); @@ -33,9 +33,9 @@ public: size_t GetSize(); - bool ReadFile(vector &out); - bool ReadFile(std::stringstream &out); + bool ReadFile(vector& out); + bool ReadFile(std::stringstream& out); bool ReadFile(uint8_t* out, uint32_t expectedSize); - bool ApplyPatch(VirtualFile &patch); -}; \ No newline at end of file + bool ApplyPatch(VirtualFile& patch); +}; diff --git a/Utilities/ZipReader.cpp b/Utilities/ZipReader.cpp index 9023eb1..a0bde83 100644 --- a/Utilities/ZipReader.cpp +++ b/Utilities/ZipReader.cpp @@ -10,14 +10,16 @@ ZipReader::ZipReader() ZipReader::~ZipReader() { - if(_initialized) { + if (_initialized) + { mz_zip_reader_end(&_zipArchive); } } bool ZipReader::InternalLoadArchive(void* buffer, size_t size) { - if(_initialized) { + if (_initialized) + { mz_zip_reader_end(&_zipArchive); memset(&_zipArchive, 0, sizeof(mz_zip_archive)); _initialized = false; @@ -29,10 +31,13 @@ bool ZipReader::InternalLoadArchive(void* buffer, size_t size) vector ZipReader::InternalGetFileList() { vector fileList; - if(_initialized) { - for(int i = 0, len = (int)mz_zip_reader_get_num_files(&_zipArchive); i < len; i++) { + if (_initialized) + { + for (int i = 0, len = (int)mz_zip_reader_get_num_files(&_zipArchive); i < len; i++) + { mz_zip_archive_file_stat file_stat; - if(!mz_zip_reader_file_stat(&_zipArchive, i, &file_stat)) { + if (!mz_zip_reader_file_stat(&_zipArchive, i, &file_stat)) + { std::cout << "mz_zip_reader_file_stat() failed!" << std::endl; } @@ -42,12 +47,14 @@ vector ZipReader::InternalGetFileList() return fileList; } -bool ZipReader::ExtractFile(string filename, vector &output) +bool ZipReader::ExtractFile(string filename, vector& output) { - if(_initialized) { + if (_initialized) + { size_t uncompSize; - void *p = mz_zip_reader_extract_file_to_heap(&_zipArchive, filename.c_str(), &uncompSize, 0); - if(!p) { + void* p = mz_zip_reader_extract_file_to_heap(&_zipArchive, filename.c_str(), &uncompSize, 0); + if (!p) + { #ifdef _DEBUG std::cout << "mz_zip_reader_extract_file_to_heap() failed!" << std::endl; #endif @@ -63,4 +70,4 @@ bool ZipReader::ExtractFile(string filename, vector &output) } return false; -} \ No newline at end of file +} diff --git a/Utilities/ZipReader.h b/Utilities/ZipReader.h index 4d4573e..61e817e 100644 --- a/Utilities/ZipReader.h +++ b/Utilities/ZipReader.h @@ -16,5 +16,5 @@ public: ZipReader(); virtual ~ZipReader(); - bool ExtractFile(string filename, vector &output); -}; \ No newline at end of file + bool ExtractFile(string filename, vector& output); +}; diff --git a/Utilities/ZipWriter.cpp b/Utilities/ZipWriter.cpp index 37ef6b9..966c568 100644 --- a/Utilities/ZipWriter.cpp +++ b/Utilities/ZipWriter.cpp @@ -29,19 +29,21 @@ bool ZipWriter::Save() void ZipWriter::AddFile(string filepath, string zipFilename) { - if(!mz_zip_writer_add_file(&_zipArchive, zipFilename.c_str(), filepath.c_str(), "", 0, MZ_BEST_COMPRESSION)) { + if (!mz_zip_writer_add_file(&_zipArchive, zipFilename.c_str(), filepath.c_str(), "", 0, MZ_BEST_COMPRESSION)) + { std::cout << "mz_zip_writer_add_file() failed!" << std::endl; } } -void ZipWriter::AddFile(vector &fileData, string zipFilename) +void ZipWriter::AddFile(vector& fileData, string zipFilename) { - if(!mz_zip_writer_add_mem(&_zipArchive, zipFilename.c_str(), fileData.data(), fileData.size(), MZ_BEST_COMPRESSION)) { + if (!mz_zip_writer_add_mem(&_zipArchive, zipFilename.c_str(), fileData.data(), fileData.size(), MZ_BEST_COMPRESSION)) + { std::cout << "mz_zip_writer_add_file() failed!" << std::endl; } } -void ZipWriter::AddFile(std::stringstream &filestream, string zipFilename) +void ZipWriter::AddFile(std::stringstream& filestream, string zipFilename) { filestream.seekg(0, std::ios::end); size_t bufferSize = (size_t)filestream.tellg(); diff --git a/Utilities/ZipWriter.h b/Utilities/ZipWriter.h index 45b111c..3d8af5b 100644 --- a/Utilities/ZipWriter.h +++ b/Utilities/ZipWriter.h @@ -16,6 +16,6 @@ public: bool Save(); void AddFile(string filepath, string zipFilename); - void AddFile(vector &fileData, string zipFilename); - void AddFile(std::stringstream &filestream, string zipFilename); -}; \ No newline at end of file + void AddFile(vector& fileData, string zipFilename); + void AddFile(std::stringstream& filestream, string zipFilename); +}; diff --git a/Utilities/ZmbvCodec.cpp b/Utilities/ZmbvCodec.cpp index f6fadca..4fb07bc 100644 --- a/Utilities/ZmbvCodec.cpp +++ b/Utilities/ZmbvCodec.cpp @@ -39,24 +39,32 @@ #define Mask_KeyFrame 0x01 #define Mask_DeltaPalette 0x02 -int ZmbvCodec::NeededSize( int _width, int _height, zmbv_format_t _format) { +int ZmbvCodec::NeededSize(int _width, int _height, zmbv_format_t _format) +{ int f; - switch (_format) { - case ZMBV_FORMAT_8BPP:f = 1;break; - case ZMBV_FORMAT_15BPP:f = 2;break; - case ZMBV_FORMAT_16BPP:f = 2;break; - case ZMBV_FORMAT_32BPP:f = 4;break; + switch (_format) + { + case ZMBV_FORMAT_8BPP: f = 1; + break; + case ZMBV_FORMAT_15BPP: f = 2; + break; + case ZMBV_FORMAT_16BPP: f = 2; + break; + case ZMBV_FORMAT_32BPP: f = 4; + break; default: return -1; } - f = f*_width*_height + 2*(1+(_width/8)) * (1+(_height/8))+1024; - return f + f/1000; + f = f * _width * _height + 2 * (1 + (_width / 8)) * (1 + (_height / 8)) + 1024; + return f + f / 1000; } -bool ZmbvCodec::SetupBuffers(zmbv_format_t _format, int blockwidth, int blockheight) { +bool ZmbvCodec::SetupBuffers(zmbv_format_t _format, int blockwidth, int blockheight) +{ FreeBuffers(); palsize = 0; - switch (_format) { + switch (_format) + { case ZMBV_FORMAT_8BPP: pixelsize = 1; palsize = 256; @@ -73,50 +81,59 @@ bool ZmbvCodec::SetupBuffers(zmbv_format_t _format, int blockwidth, int blockhei default: return false; }; - bufsize = (height+2*MAX_VECTOR)*pitch*pixelsize+2048; + bufsize = (height + 2 * MAX_VECTOR) * pitch * pixelsize + 2048; buf1 = new unsigned char[bufsize]; buf2 = new unsigned char[bufsize]; work = new unsigned char[bufsize]; - int xblocks = (width/blockwidth); + int xblocks = (width / blockwidth); int xleft = width % blockwidth; if (xleft) xblocks++; - int yblocks = (height/blockheight); + int yblocks = (height / blockheight); int yleft = height % blockheight; if (yleft) yblocks++; - blockcount=yblocks*xblocks; - blocks=new FrameBlock[blockcount]; + blockcount = yblocks * xblocks; + blocks = new FrameBlock[blockcount]; - if (!buf1 || !buf2 || !work || !blocks) { + if (!buf1 || !buf2 || !work || !blocks) + { FreeBuffers(); return false; } - int y,x,i; - i=0; - for (y=0;y -INLINE int ZmbvCodec::PossibleBlock(int vx,int vy,FrameBlock * block) { - int ret=0; - P * pold=((P*)oldframe)+block->start+(vy*pitch)+vx; - P * pnew=((P*)newframe)+block->start;; - for (int y=0;ydy;y+=4) { - for (int x=0;xdx;x+=4) { - int test=0-((pold[x]-pnew[x])&0x00ffffff); - ret-=(test>>31); +template +INLINE int ZmbvCodec::PossibleBlock(int vx, int vy, FrameBlock* block) +{ + int ret = 0; + P* pold = ((P*)oldframe) + block->start + (vy * pitch) + vx; + P* pnew = ((P*)newframe) + block->start;; + for (int y = 0; y < block->dy; y += 4) + { + for (int x = 0; x < block->dx; x += 4) + { + int test = 0 - ((pold[x] - pnew[x]) & 0x00ffffff); + ret -= (test >> 31); } - pold+=pitch*4; - pnew+=pitch*4; + pold += pitch * 4; + pnew += pitch * 4; } return ret; } -template -INLINE int ZmbvCodec::CompareBlock(int vx,int vy,FrameBlock * block) { - int ret=0; - P * pold=((P*)oldframe)+block->start+(vy*pitch)+vx; - P * pnew=((P*)newframe)+block->start;; - for (int y=0;ydy;y++) { - for (int x=0;xdx;x++) { - int test=0-((pold[x]-pnew[x])&0x00ffffff); - ret-=(test>>31); +template +INLINE int ZmbvCodec::CompareBlock(int vx, int vy, FrameBlock* block) +{ + int ret = 0; + P* pold = ((P*)oldframe) + block->start + (vy * pitch) + vx; + P* pnew = ((P*)newframe) + block->start;; + for (int y = 0; y < block->dy; y++) + { + for (int x = 0; x < block->dx; x++) + { + int test = 0 - ((pold[x] - pnew[x]) & 0x00ffffff); + ret -= (test >> 31); } - pold+=pitch; - pnew+=pitch; + pold += pitch; + pnew += pitch; } return ret; } -template -INLINE void ZmbvCodec::AddXorBlock(int vx,int vy,FrameBlock * block) { - P * pold=((P*)oldframe)+block->start+(vy*pitch)+vx; - P * pnew=((P*)newframe)+block->start; - for (int y=0;ydy;y++) { - for (int x=0;xdx;x++) { - *((P*)&work[workUsed])=pnew[x] ^ pold[x]; - workUsed+=sizeof(P); +template +INLINE void ZmbvCodec::AddXorBlock(int vx, int vy, FrameBlock* block) +{ + P* pold = ((P*)oldframe) + block->start + (vy * pitch) + vx; + P* pnew = ((P*)newframe) + block->start; + for (int y = 0; y < block->dy; y++) + { + for (int x = 0; x < block->dx; x++) + { + *((P*)&work[workUsed]) = pnew[x] ^ pold[x]; + workUsed += sizeof(P); } - pold+=pitch; - pnew+=pitch; + pold += pitch; + pnew += pitch; } } -template -void ZmbvCodec::AddXorFrame(void) { - signed char * vectors=(signed char*)&work[workUsed]; +template +void ZmbvCodec::AddXorFrame(void) +{ + signed char* vectors = (signed char*)&work[workUsed]; /* Align the following xor data on 4 byte boundary*/ - workUsed=(workUsed + blockcount*2 +3) & ~3; - for (int b=0;b(0,0, block); - int possibles=64; - for (int v=0;v(0, 0, block); + int possibles = 64; + for (int v = 0; v < VectorCount && possibles; v++) + { + if (bestchange < 4) break; int vx = VectorTable[v].x; int vy = VectorTable[v].y; - if (PossibleBlock

(vx, vy, block) < 4) { + if (PossibleBlock

(vx, vy, block) < 4) + { possibles--; - int testchange=CompareBlock

(vx,vy, block); - if (testchange(vx, vy, block); + if (testchange < bestchange) + { + bestchange = testchange; bestvx = vx; bestvy = vy; } } } - vectors[b*2+0]=(bestvx << 1); - vectors[b*2+1]=(bestvy << 1); - if (bestchange) { - vectors[b*2+0]|=1; + vectors[b * 2 + 0] = (bestvx << 1); + vectors[b * 2 + 1] = (bestvy << 1); + if (bestchange) + { + vectors[b * 2 + 0] |= 1; AddXorBlock

(bestvx, bestvy, block); } } } -bool ZmbvCodec::SetupCompress( int _width, int _height, uint32_t compressionLevel ) { +bool ZmbvCodec::SetupCompress(int _width, int _height, uint32_t compressionLevel) +{ width = _width; height = _height; - pitch = _width + 2*MAX_VECTOR; + pitch = _width + 2 * MAX_VECTOR; format = ZMBV_FORMAT_NONE; - if (deflateInit (&zstream, compressionLevel) != Z_OK) + if (deflateInit(&zstream, compressionLevel) != Z_OK) return false; return true; } -bool ZmbvCodec::PrepareCompressFrame(int flags, zmbv_format_t _format, char * pal) +bool ZmbvCodec::PrepareCompressFrame(int flags, zmbv_format_t _format, char* pal) { int i; - unsigned char *firstByte; + unsigned char* firstByte; - if (_format != format) { - if (!SetupBuffers( _format, 16, 16)) + if (_format != format) + { + if (!SetupBuffers(_format, 16, 16)) return false; - flags|=1; //Force a keyframe + flags |= 1; //Force a keyframe } /* replace oldframe with new frame */ - unsigned char *copyFrame = newframe; + unsigned char* copyFrame = newframe; newframe = oldframe; oldframe = copyFrame; compressInfo.linesDone = 0; compressInfo.writeSize = _bufSize; compressInfo.writeDone = 1; - compressInfo.writeBuf = (unsigned char *)_buf; + compressInfo.writeBuf = (unsigned char*)_buf; /* Set a pointer to the first byte which will contain info about this frame */ firstByte = compressInfo.writeBuf; *firstByte = 0; //Reset the work buffer - workUsed = 0;workPos = 0; - if (flags & 1) { + workUsed = 0; + workPos = 0; + if (flags & 1) + { /* Make a keyframe */ *firstByte |= Mask_KeyFrame; - KeyframeHeader * header = (KeyframeHeader *)(compressInfo.writeBuf + compressInfo.writeDone); + KeyframeHeader* header = (KeyframeHeader*)(compressInfo.writeBuf + compressInfo.writeDone); header->high_version = DBZV_VERSION_HIGH; header->low_version = DBZV_VERSION_LOW; header->compression = COMPRESSION_ZLIB; @@ -268,85 +309,98 @@ bool ZmbvCodec::PrepareCompressFrame(int flags, zmbv_format_t _format, char * pa header->blockheight = 16; compressInfo.writeDone += sizeof(KeyframeHeader); /* Copy the new frame directly over */ - if (palsize) { + if (palsize) + { if (pal) memcpy(&palette, pal, sizeof(palette)); - else - memset(&palette,0, sizeof(palette)); + else + memset(&palette, 0, sizeof(palette)); /* keyframes get the full palette */ - for (i=0;i(); - break; - case ZMBV_FORMAT_15BPP: - case ZMBV_FORMAT_16BPP: - AddXorFrame(); - break; + switch (format) + { + case ZMBV_FORMAT_8BPP: + AddXorFrame(); + break; + case ZMBV_FORMAT_15BPP: + case ZMBV_FORMAT_16BPP: + AddXorFrame(); + break; - default: - case ZMBV_FORMAT_32BPP: - AddXorFrame(); - break; + default: + case ZMBV_FORMAT_32BPP: + AddXorFrame(); + break; } } /* Create the actual frame with compression */ - zstream.next_in = (Bytef *)work; + zstream.next_in = (Bytef*)work; zstream.avail_in = workUsed; zstream.total_in = 0; - zstream.next_out = (Bytef *)(compressInfo.writeBuf + compressInfo.writeDone); + zstream.next_out = (Bytef*)(compressInfo.writeBuf + compressInfo.writeDone); zstream.avail_out = compressInfo.writeSize - compressInfo.writeDone; zstream.total_out = 0; - + deflate(&zstream, Z_SYNC_FLUSH); *compressedData = _buf; @@ -368,24 +422,26 @@ void ZmbvCodec::FreeBuffers() _buf = nullptr; } -ZmbvCodec::ZmbvCodec() +ZmbvCodec::ZmbvCodec() { CreateVectorTable(); blocks = nullptr; buf1 = nullptr; buf2 = nullptr; work = nullptr; - memset( &zstream, 0, sizeof(zstream)); + memset(&zstream, 0, sizeof(zstream)); } -int ZmbvCodec::CompressFrame(bool isKeyFrame, uint8_t *frameData, uint8_t** compressedData) +int ZmbvCodec::CompressFrame(bool isKeyFrame, uint8_t* frameData, uint8_t** compressedData) { - if(!PrepareCompressFrame(isKeyFrame ? 1 : 0, ZMBV_FORMAT_32BPP, nullptr)) { + if (!PrepareCompressFrame(isKeyFrame ? 1 : 0, ZMBV_FORMAT_32BPP, nullptr)) + { return -1; } - for(int i = 0; i < height; i++) { - void * rowPointer = frameData + i*width*4; + for (int i = 0; i < height; i++) + { + void* rowPointer = frameData + i * width * 4; CompressLines(1, &rowPointer); } @@ -395,4 +451,4 @@ int ZmbvCodec::CompressFrame(bool isKeyFrame, uint8_t *frameData, uint8_t** comp const char* ZmbvCodec::GetFourCC() { return "ZMBV"; -} \ No newline at end of file +} diff --git a/Utilities/ZmbvCodec.h b/Utilities/ZmbvCodec.h index 5e3c285..f0d56ea 100644 --- a/Utilities/ZmbvCodec.h +++ b/Utilities/ZmbvCodec.h @@ -30,58 +30,65 @@ #define INLINE inline #endif -typedef enum { - ZMBV_FORMAT_NONE = 0x00, - ZMBV_FORMAT_1BPP = 0x01, - ZMBV_FORMAT_2BPP = 0x02, - ZMBV_FORMAT_4BPP = 0x03, - ZMBV_FORMAT_8BPP = 0x04, - ZMBV_FORMAT_15BPP = 0x05, - ZMBV_FORMAT_16BPP = 0x06, - ZMBV_FORMAT_24BPP = 0x07, - ZMBV_FORMAT_32BPP = 0x08 +typedef enum +{ + ZMBV_FORMAT_NONE = 0x00, + ZMBV_FORMAT_1BPP = 0x01, + ZMBV_FORMAT_2BPP = 0x02, + ZMBV_FORMAT_4BPP = 0x03, + ZMBV_FORMAT_8BPP = 0x04, + ZMBV_FORMAT_15BPP = 0x05, + ZMBV_FORMAT_16BPP = 0x06, + ZMBV_FORMAT_24BPP = 0x07, + ZMBV_FORMAT_32BPP = 0x08 } zmbv_format_t; class ZmbvCodec : public BaseCodec { private: - struct FrameBlock { + struct FrameBlock + { int start = 0; - int dx = 0,dy = 0; + int dx = 0, dy = 0; }; - struct CodecVector { - int x = 0,y = 0; + + struct CodecVector + { + int x = 0, y = 0; int slot = 0; }; - struct KeyframeHeader { + + struct KeyframeHeader + { unsigned char high_version = 0; unsigned char low_version = 0; unsigned char compression = 0; unsigned char format = 0; - unsigned char blockwidth = 0,blockheight = 0; + unsigned char blockwidth = 0, blockheight = 0; }; - struct { - int linesDone = 0; - int writeSize = 0; - int writeDone = 0; - unsigned char *writeBuf = nullptr; + struct + { + int linesDone = 0; + int writeSize = 0; + int writeDone = 0; + unsigned char* writeBuf = nullptr; } compressInfo; CodecVector VectorTable[512] = {}; int VectorCount = 0; - unsigned char *oldframe=nullptr, *newframe=nullptr; - unsigned char *buf1=nullptr, *buf2=nullptr, *work=nullptr; + unsigned char *oldframe = nullptr, *newframe = nullptr; + unsigned char *buf1 = nullptr, *buf2 = nullptr, *work = nullptr; int bufsize = 0; - int blockcount = 0; - FrameBlock * blocks = nullptr; + int blockcount = 0; + FrameBlock* blocks = nullptr; int workUsed = 0, workPos = 0; int palsize = 0; - char palette[256*4] = {}; + char palette[256 * 4] = {}; int height = 0, width = 0, pitch = 0; zmbv_format_t format = zmbv_format_t::ZMBV_FORMAT_NONE; int pixelsize = 0; @@ -96,20 +103,24 @@ private: void CreateVectorTable(void); bool SetupBuffers(zmbv_format_t format, int blockwidth, int blockheight); - template void AddXorFrame(void); - template INLINE int PossibleBlock(int vx,int vy,FrameBlock * block); - template INLINE int CompareBlock(int vx,int vy,FrameBlock * block); - template INLINE void AddXorBlock(int vx,int vy,FrameBlock * block); + template + void AddXorFrame(void); + template + INLINE int PossibleBlock(int vx, int vy, FrameBlock* block); + template + INLINE int CompareBlock(int vx, int vy, FrameBlock* block); + template + INLINE void AddXorBlock(int vx, int vy, FrameBlock* block); int NeededSize(int _width, int _height, zmbv_format_t _format); - void CompressLines(int lineCount, void *lineData[]); - bool PrepareCompressFrame(int flags, zmbv_format_t _format, char * pal); + void CompressLines(int lineCount, void* lineData[]); + bool PrepareCompressFrame(int flags, zmbv_format_t _format, char* pal); int FinishCompressFrame(uint8_t** compressedData); public: ZmbvCodec(); bool SetupCompress(int _width, int _height, uint32_t compressionLevel) override; - int CompressFrame(bool isKeyFrame, uint8_t *frameData, uint8_t** compressedData) override; + int CompressFrame(bool isKeyFrame, uint8_t* frameData, uint8_t** compressedData) override; const char* GetFourCC() override; }; diff --git a/Utilities/blip_buf.cpp b/Utilities/blip_buf.cpp index ad42438..e8e959c 100644 --- a/Utilities/blip_buf.cpp +++ b/Utilities/blip_buf.cpp @@ -30,8 +30,9 @@ Avoids constants that don't fit in 32 bits. */ enum { pre_shift = 32 }; #elif defined(ULLONG_MAX) - typedef unsigned long long fixed_t; - enum { pre_shift = 32 }; +typedef unsigned long long fixed_t; + +enum { pre_shift = 32 }; #else typedef unsigned fixed_t; @@ -41,17 +42,23 @@ Avoids constants that don't fit in 32 bits. */ enum { time_bits = pre_shift + 20 }; -static fixed_t const time_unit = (fixed_t) 1 << time_bits; +static fixed_t const time_unit = (fixed_t)1 << time_bits; -enum { bass_shift = 9 }; /* affects high-pass filter breakpoint frequency */ +enum { bass_shift = 9 }; /* affects high-pass filter breakpoint frequency */ enum { end_frame_extra = 2 }; /* allows deltas slightly after frame length */ -enum { half_width = 8 }; -enum { buf_extra = half_width*2 + end_frame_extra }; -enum { phase_bits = 5 }; +enum { half_width = 8 }; + +enum { buf_extra = half_width * 2 + end_frame_extra }; + +enum { phase_bits = 5 }; + enum { phase_count = 1 << phase_bits }; -enum { delta_bits = 15 }; -enum { delta_unit = 1 << delta_bits }; + +enum { delta_bits = 15 }; + +enum { delta_unit = 1 << delta_bits }; + enum { frac_bits = time_bits - pre_shift }; /* We could eliminate avail and encode whole samples in offset, but that would @@ -80,6 +87,7 @@ typedef int buf_t; ((n) >> (shift)) enum { max_sample = +32767 }; + enum { min_sample = -32768 }; #define CLAMP( n ) \ @@ -88,158 +96,158 @@ enum { min_sample = -32768 }; n = ARITH_SHIFT( n, 16 ) ^ max_sample;\ } -static void check_assumptions( void ) +static void check_assumptions(void) { int n; - - #if INT_MAX < 0x7FFFFFFF || UINT_MAX < 0xFFFFFFFF + +#if INT_MAX < 0x7FFFFFFF || UINT_MAX < 0xFFFFFFFF #error "int must be at least 32 bits" - #endif - - assert( (-3 >> 1) == -2 ); /* right shift must preserve sign */ - +#endif + + assert((-3 >> 1) == -2); /* right shift must preserve sign */ + n = max_sample * 2; - CLAMP( n ); - assert( n == max_sample ); - + CLAMP(n); + assert(n == max_sample); + n = min_sample * 2; - CLAMP( n ); - assert( n == min_sample ); - - assert( blip_max_ratio <= time_unit ); - assert( blip_max_frame <= (fixed_t) -1 >> time_bits ); + CLAMP(n); + assert(n == min_sample); + + assert(blip_max_ratio <= time_unit); + assert(blip_max_frame <= (fixed_t) -1 >> time_bits); } -blip_t* blip_new( int size ) +blip_t* blip_new(int size) { blip_t* m; - assert( size >= 0 ); - - m = (blip_t*) malloc( sizeof *m + (size + buf_extra) * sizeof (buf_t) ); - if ( m ) + assert(size >= 0); + + m = (blip_t*)malloc(sizeof *m + (size + buf_extra) * sizeof(buf_t)); + if (m) { m->factor = time_unit / blip_max_ratio; - m->size = size; - blip_clear( m ); + m->size = size; + blip_clear(m); check_assumptions(); } return m; } -void blip_delete( blip_t* m ) +void blip_delete(blip_t* m) { - if ( m != NULL ) + if (m != NULL) { /* Clear fields in case user tries to use after freeing */ - memset( m, 0, sizeof *m ); - free( m ); + memset(m, 0, sizeof *m); + free(m); } } -void blip_set_rates( blip_t* m, double clock_rate, double sample_rate ) +void blip_set_rates(blip_t* m, double clock_rate, double sample_rate) { double factor = time_unit * sample_rate / clock_rate; - m->factor = (fixed_t) factor; - + m->factor = (fixed_t)factor; + /* Fails if clock_rate exceeds maximum, relative to sample_rate */ - assert( 0 <= factor - m->factor && factor - m->factor < 1 ); - + assert(0 <= factor - m->factor && factor - m->factor < 1); + /* Avoid requiring math.h. Equivalent to m->factor = (int) ceil( factor ) */ - if ( m->factor < factor ) + if (m->factor < factor) m->factor++; - + /* At this point, factor is most likely rounded up, but could still have been rounded down in the floating-point calculation. */ } -void blip_clear( blip_t* m ) +void blip_clear(blip_t* m) { /* We could set offset to 0, factor/2, or factor-1. 0 is suitable if factor is rounded up. factor-1 is suitable if factor is rounded down. Since we don't know rounding direction, factor/2 accommodates either, with the slight loss of showing an error in half the time. Since for a 64-bit factor this is years, the halving isn't a problem. */ - - m->offset = m->factor / 2; - m->avail = 0; + + m->offset = m->factor / 2; + m->avail = 0; m->integrator = 0; - memset( SAMPLES( m ), 0, (m->size + buf_extra) * sizeof (buf_t) ); + memset(SAMPLES(m), 0, (m->size + buf_extra) * sizeof(buf_t)); } -int blip_clocks_needed( const blip_t* m, int samples ) +int blip_clocks_needed(const blip_t* m, int samples) { fixed_t needed; - + /* Fails if buffer can't hold that many more samples */ - assert( samples >= 0 && m->avail + samples <= m->size ); - - needed = (fixed_t) samples * time_unit; - if ( needed < m->offset ) + assert(samples >= 0 && m->avail + samples <= m->size); + + needed = (fixed_t)samples * time_unit; + if (needed < m->offset) return 0; - + return (int)((needed - m->offset + m->factor - 1) / m->factor); } -void blip_end_frame( blip_t* m, unsigned t ) +void blip_end_frame(blip_t* m, unsigned t) { fixed_t off = t * m->factor + m->offset; m->avail += off >> time_bits; m->offset = off & (time_unit - 1); - + /* Fails if buffer size was exceeded */ - assert( m->avail <= m->size ); + assert(m->avail <= m->size); } -int blip_samples_avail( const blip_t* m ) +int blip_samples_avail(const blip_t* m) { return m->avail; } -static void remove_samples( blip_t* m, int count ) +static void remove_samples(blip_t* m, int count) { - buf_t* buf = SAMPLES( m ); + buf_t* buf = SAMPLES(m); int remain = m->avail + buf_extra - count; m->avail -= count; - - memmove( &buf [0], &buf [count], remain * sizeof buf [0] ); - memset( &buf [remain], 0, count * sizeof buf [0] ); + + memmove(&buf[0], &buf[count], remain * sizeof buf[0]); + memset(&buf[remain], 0, count * sizeof buf[0]); } -int blip_read_samples( blip_t* m, short out [], int count, int stereo ) +int blip_read_samples(blip_t* m, short out[], int count, int stereo) { - assert( count >= 0 ); - - if ( count > m->avail ) + assert(count >= 0); + + if (count > m->avail) count = m->avail; - - if ( count ) + + if (count) { int const step = stereo ? 2 : 1; - buf_t const* in = SAMPLES( m ); + buf_t const* in = SAMPLES(m); buf_t const* end = in + count; int sum = m->integrator; do { /* Eliminate fraction */ - int s = ARITH_SHIFT( sum, delta_bits ); - + int s = ARITH_SHIFT(sum, delta_bits); + sum += *in++; - - CLAMP( s ); - + + CLAMP(s); + *out = s; out += step; - + /* High-pass filter */ sum -= s << (delta_bits - bass_shift); } - while ( in != end ); + while (in != end); m->integrator = sum; - - remove_samples( m, count ); + + remove_samples(m, count); } - + return count; } @@ -250,41 +258,41 @@ int blip_read_samples( blip_t* m, short out [], int count, int stereo ) */ /* Sinc_Generator( 0.9, 0.55, 4.5 ) */ -static short const bl_step [phase_count + 1] [half_width] = +static short const bl_step[phase_count + 1][half_width] = { -{ 43, -115, 350, -488, 1136, -914, 5861,21022}, -{ 44, -118, 348, -473, 1076, -799, 5274,21001}, -{ 45, -121, 344, -454, 1011, -677, 4706,20936}, -{ 46, -122, 336, -431, 942, -549, 4156,20829}, -{ 47, -123, 327, -404, 868, -418, 3629,20679}, -{ 47, -122, 316, -375, 792, -285, 3124,20488}, -{ 47, -120, 303, -344, 714, -151, 2644,20256}, -{ 46, -117, 289, -310, 634, -17, 2188,19985}, -{ 46, -114, 273, -275, 553, 117, 1758,19675}, -{ 44, -108, 255, -237, 471, 247, 1356,19327}, -{ 43, -103, 237, -199, 390, 373, 981,18944}, -{ 42, -98, 218, -160, 310, 495, 633,18527}, -{ 40, -91, 198, -121, 231, 611, 314,18078}, -{ 38, -84, 178, -81, 153, 722, 22,17599}, -{ 36, -76, 157, -43, 80, 824, -241,17092}, -{ 34, -68, 135, -3, 8, 919, -476,16558}, -{ 32, -61, 115, 34, -60, 1006, -683,16001}, -{ 29, -52, 94, 70, -123, 1083, -862,15422}, -{ 27, -44, 73, 106, -184, 1152,-1015,14824}, -{ 25, -36, 53, 139, -239, 1211,-1142,14210}, -{ 22, -27, 34, 170, -290, 1261,-1244,13582}, -{ 20, -20, 16, 199, -335, 1301,-1322,12942}, -{ 18, -12, -3, 226, -375, 1331,-1376,12293}, -{ 15, -4, -19, 250, -410, 1351,-1408,11638}, -{ 13, 3, -35, 272, -439, 1361,-1419,10979}, -{ 11, 9, -49, 292, -464, 1362,-1410,10319}, -{ 9, 16, -63, 309, -483, 1354,-1383, 9660}, -{ 7, 22, -75, 322, -496, 1337,-1339, 9005}, -{ 6, 26, -85, 333, -504, 1312,-1280, 8355}, -{ 4, 31, -94, 341, -507, 1278,-1205, 7713}, -{ 3, 35, -102, 347, -506, 1238,-1119, 7082}, -{ 1, 40, -110, 350, -499, 1190,-1021, 6464}, -{ 0, 43, -115, 350, -488, 1136, -914, 5861} + {43, -115, 350, -488, 1136, -914, 5861, 21022}, + {44, -118, 348, -473, 1076, -799, 5274, 21001}, + {45, -121, 344, -454, 1011, -677, 4706, 20936}, + {46, -122, 336, -431, 942, -549, 4156, 20829}, + {47, -123, 327, -404, 868, -418, 3629, 20679}, + {47, -122, 316, -375, 792, -285, 3124, 20488}, + {47, -120, 303, -344, 714, -151, 2644, 20256}, + {46, -117, 289, -310, 634, -17, 2188, 19985}, + {46, -114, 273, -275, 553, 117, 1758, 19675}, + {44, -108, 255, -237, 471, 247, 1356, 19327}, + {43, -103, 237, -199, 390, 373, 981, 18944}, + {42, -98, 218, -160, 310, 495, 633, 18527}, + {40, -91, 198, -121, 231, 611, 314, 18078}, + {38, -84, 178, -81, 153, 722, 22, 17599}, + {36, -76, 157, -43, 80, 824, -241, 17092}, + {34, -68, 135, -3, 8, 919, -476, 16558}, + {32, -61, 115, 34, -60, 1006, -683, 16001}, + {29, -52, 94, 70, -123, 1083, -862, 15422}, + {27, -44, 73, 106, -184, 1152, -1015, 14824}, + {25, -36, 53, 139, -239, 1211, -1142, 14210}, + {22, -27, 34, 170, -290, 1261, -1244, 13582}, + {20, -20, 16, 199, -335, 1301, -1322, 12942}, + {18, -12, -3, 226, -375, 1331, -1376, 12293}, + {15, -4, -19, 250, -410, 1351, -1408, 11638}, + {13, 3, -35, 272, -439, 1361, -1419, 10979}, + {11, 9, -49, 292, -464, 1362, -1410, 10319}, + {9, 16, -63, 309, -483, 1354, -1383, 9660}, + {7, 22, -75, 322, -496, 1337, -1339, 9005}, + {6, 26, -85, 333, -504, 1312, -1280, 8355}, + {4, 31, -94, 341, -507, 1278, -1205, 7713}, + {3, 35, -102, 347, -506, 1238, -1119, 7082}, + {1, 40, -110, 350, -499, 1190, -1021, 6464}, + {0, 43, -115, 350, -488, 1136, -914, 5861} }; /* Shifting by pre_shift allows calculation using unsigned int rather than @@ -292,54 +300,54 @@ possibly-wider fixed_t. On 32-bit platforms, this is likely more efficient. And by having pre_shift 32, a 32-bit platform can easily do the shift by simply ignoring the low half. */ -void blip_add_delta( blip_t* m, unsigned time, int delta ) +void blip_add_delta(blip_t* m, unsigned time, int delta) { - unsigned fixed = (unsigned) ((time * m->factor + m->offset) >> pre_shift); - buf_t* out = SAMPLES( m ) + m->avail + (fixed >> frac_bits); - + unsigned fixed = (unsigned)((time * m->factor + m->offset) >> pre_shift); + buf_t* out = SAMPLES(m) + m->avail + (fixed >> frac_bits); + int const phase_shift = frac_bits - phase_bits; int phase = fixed >> phase_shift & (phase_count - 1); - short const* in = bl_step [phase]; - short const* rev = bl_step [phase_count - phase]; - + short const* in = bl_step[phase]; + short const* rev = bl_step[phase_count - phase]; + int interp = fixed >> (phase_shift - delta_bits) & (delta_unit - 1); int delta2 = (delta * interp) >> delta_bits; delta -= delta2; - + /* Fails if buffer size was exceeded */ - assert( out <= &SAMPLES( m ) [m->size + end_frame_extra] ); - - out [0] += in[0]*delta + in[half_width+0]*delta2; - out [1] += in[1]*delta + in[half_width+1]*delta2; - out [2] += in[2]*delta + in[half_width+2]*delta2; - out [3] += in[3]*delta + in[half_width+3]*delta2; - out [4] += in[4]*delta + in[half_width+4]*delta2; - out [5] += in[5]*delta + in[half_width+5]*delta2; - out [6] += in[6]*delta + in[half_width+6]*delta2; - out [7] += in[7]*delta + in[half_width+7]*delta2; - + assert(out <= &SAMPLES( m ) [m->size + end_frame_extra]); + + out[0] += in[0] * delta + in[half_width + 0] * delta2; + out[1] += in[1] * delta + in[half_width + 1] * delta2; + out[2] += in[2] * delta + in[half_width + 2] * delta2; + out[3] += in[3] * delta + in[half_width + 3] * delta2; + out[4] += in[4] * delta + in[half_width + 4] * delta2; + out[5] += in[5] * delta + in[half_width + 5] * delta2; + out[6] += in[6] * delta + in[half_width + 6] * delta2; + out[7] += in[7] * delta + in[half_width + 7] * delta2; + in = rev; - out [ 8] += in[7]*delta + in[7-half_width]*delta2; - out [ 9] += in[6]*delta + in[6-half_width]*delta2; - out [10] += in[5]*delta + in[5-half_width]*delta2; - out [11] += in[4]*delta + in[4-half_width]*delta2; - out [12] += in[3]*delta + in[3-half_width]*delta2; - out [13] += in[2]*delta + in[2-half_width]*delta2; - out [14] += in[1]*delta + in[1-half_width]*delta2; - out [15] += in[0]*delta + in[0-half_width]*delta2; + out[8] += in[7] * delta + in[7 - half_width] * delta2; + out[9] += in[6] * delta + in[6 - half_width] * delta2; + out[10] += in[5] * delta + in[5 - half_width] * delta2; + out[11] += in[4] * delta + in[4 - half_width] * delta2; + out[12] += in[3] * delta + in[3 - half_width] * delta2; + out[13] += in[2] * delta + in[2 - half_width] * delta2; + out[14] += in[1] * delta + in[1 - half_width] * delta2; + out[15] += in[0] * delta + in[0 - half_width] * delta2; } -void blip_add_delta_fast( blip_t* m, unsigned time, int delta ) +void blip_add_delta_fast(blip_t* m, unsigned time, int delta) { - unsigned fixed = (unsigned) ((time * m->factor + m->offset) >> pre_shift); - buf_t* out = SAMPLES( m ) + m->avail + (fixed >> frac_bits); - + unsigned fixed = (unsigned)((time * m->factor + m->offset) >> pre_shift); + buf_t* out = SAMPLES(m) + m->avail + (fixed >> frac_bits); + int interp = fixed >> (frac_bits - delta_bits) & (delta_unit - 1); int delta2 = delta * interp; - + /* Fails if buffer size was exceeded */ - assert( out <= &SAMPLES( m ) [m->size + end_frame_extra] ); - - out [7] += delta * delta_unit - delta2; - out [8] += delta2; + assert(out <= &SAMPLES( m ) [m->size + end_frame_extra]); + + out[7] += delta * delta_unit - delta2; + out[8] += delta2; } diff --git a/Utilities/blip_buf.h b/Utilities/blip_buf.h index a50ff96..8983d4b 100644 --- a/Utilities/blip_buf.h +++ b/Utilities/blip_buf.h @@ -5,17 +5,17 @@ Sample buffer that resamples from input clock rate to output sample rate */ /* blip_buf 1.1.0 */ -#ifndef BLIP_BUF_H +#ifndef BLIP_BUF_H #define BLIP_BUF_H #if defined(_MSC_VER) - #define EXPORT __declspec(dllexport) +#define EXPORT __declspec(dllexport) #else #define EXPORT -#endif +#endif #ifdef __cplusplus - extern "C" { +extern "C" { #endif /** First parameter of most functions is blip_t*, or const blip_t* if nothing @@ -25,57 +25,63 @@ typedef struct blip_t blip_t; /** Creates new buffer that can hold at most sample_count samples. Sets rates so that there are blip_max_ratio clocks per sample. Returns pointer to new buffer, or NULL if insufficient memory. */ -EXPORT blip_t* blip_new( int sample_count ); +EXPORT blip_t* blip_new(int sample_count); /** Sets approximate input clock rate and output sample rate. For every clock_rate input clocks, approximately sample_rate samples are generated. */ -EXPORT void blip_set_rates( blip_t*, double clock_rate, double sample_rate ); +EXPORT void blip_set_rates(blip_t*, double clock_rate, double sample_rate); -enum { /** Maximum clock_rate/sample_rate ratio. For a given sample_rate, -clock_rate must not be greater than sample_rate*blip_max_ratio. */ -blip_max_ratio = 1 << 20 }; +enum +{ + /** Maximum clock_rate/sample_rate ratio. For a given sample_rate, + clock_rate must not be greater than sample_rate*blip_max_ratio. */ + blip_max_ratio = 1 << 20 +}; /** Clears entire buffer. Afterwards, blip_samples_avail() == 0. */ -EXPORT void blip_clear( blip_t* ); +EXPORT void blip_clear(blip_t*); /** Adds positive/negative delta into buffer at specified clock time. */ -EXPORT void blip_add_delta( blip_t*, unsigned int clock_time, int delta ); +EXPORT void blip_add_delta(blip_t*, unsigned int clock_time, int delta); /** Same as blip_add_delta(), but uses faster, lower-quality synthesis. */ -void blip_add_delta_fast( blip_t*, unsigned int clock_time, int delta ); +void blip_add_delta_fast(blip_t*, unsigned int clock_time, int delta); /** Length of time frame, in clocks, needed to make sample_count additional samples available. */ -int blip_clocks_needed( const blip_t*, int sample_count ); +int blip_clocks_needed(const blip_t*, int sample_count); -enum { /** Maximum number of samples that can be generated from one time frame. */ -blip_max_frame = 4000 }; +enum +{ + /** Maximum number of samples that can be generated from one time frame. */ + blip_max_frame = 4000 +}; /** Makes input clocks before clock_duration available for reading as output samples. Also begins new time frame at clock_duration, so that clock time 0 in the new time frame specifies the same clock as clock_duration in the old time frame specified. Deltas can have been added slightly past clock_duration (up to however many clocks there are in two output samples). */ -EXPORT void blip_end_frame( blip_t*, unsigned int clock_duration ); +EXPORT void blip_end_frame(blip_t*, unsigned int clock_duration); /** Number of buffered samples available for reading. */ -int blip_samples_avail( const blip_t* ); +int blip_samples_avail(const blip_t*); /** Reads and removes at most 'count' samples and writes them to 'out'. If 'stereo' is true, writes output to every other element of 'out', allowing easy interleaving of two buffers into a stereo sample stream. Outputs 16-bit signed samples. Returns number of samples actually read. */ -EXPORT int blip_read_samples( blip_t*, short out [], int count, int stereo ); +EXPORT int blip_read_samples(blip_t*, short out[], int count, int stereo); /** Frees buffer. No effect if NULL is passed. */ -EXPORT void blip_delete( blip_t* ); +EXPORT void blip_delete(blip_t*); /* Deprecated */ typedef blip_t blip_buffer_t; #ifdef __cplusplus - } +} #endif #endif diff --git a/Utilities/gif.h b/Utilities/gif.h index 7d9615e..a67d4c4 100644 --- a/Utilities/gif.h +++ b/Utilities/gif.h @@ -63,23 +63,23 @@ const int kGifTransIndex = 0; struct GifPalette { - int bitDepth; + int bitDepth; - uint8_t r[256]; - uint8_t g[256]; - uint8_t b[256]; + uint8_t r[256]; + uint8_t g[256]; + uint8_t b[256]; - // k-d tree over RGB space, organized in heap fashion - // i.e. left child of node i is node i*2, right child is node i*2+1 - // nodes 256-511 are implicitly the leaves, containing a color - uint8_t treeSplitElt[255]; - uint8_t treeSplit[255]; + // k-d tree over RGB space, organized in heap fashion + // i.e. left child of node i is node i*2, right child is node i*2+1 + // nodes 256-511 are implicitly the leaves, containing a color + uint8_t treeSplitElt[255]; + uint8_t treeSplit[255]; }; // max, min, and abs functions -int GifIMax(int l, int r) { return l>r?l:r; } -int GifIMin(int l, int r) { return l r ? l : r; } +int GifIMin(int l, int r) { return l < r ? l : r; } +int GifIAbs(int i) { return i < 0 ? -i : i; } // walks the k-d tree to pick the palette entry for a desired color. // Takes as in/out parameters the current best color and its error - @@ -87,750 +87,763 @@ int GifIAbs(int i) { return i<0?-i:i; } // this is the major hotspot in the code at the moment. void GifGetClosestPaletteColor(GifPalette* pPal, int r, int g, int b, int& bestInd, int& bestDiff, int treeRoot = 1) { - // base case, reached the bottom of the tree - if(treeRoot > (1<bitDepth)-1) - { - int ind = treeRoot-(1<bitDepth); - if(ind == kGifTransIndex) return; + // base case, reached the bottom of the tree + if (treeRoot > (1 << pPal->bitDepth) - 1) + { + int ind = treeRoot - (1 << pPal->bitDepth); + if (ind == kGifTransIndex) return; - // check whether this color is better than the current winner - int r_err = r - ((int32_t)pPal->r[ind]); - int g_err = g - ((int32_t)pPal->g[ind]); - int b_err = b - ((int32_t)pPal->b[ind]); - int diff = GifIAbs(r_err)+GifIAbs(g_err)+GifIAbs(b_err); + // check whether this color is better than the current winner + int r_err = r - ((int32_t)pPal->r[ind]); + int g_err = g - ((int32_t)pPal->g[ind]); + int b_err = b - ((int32_t)pPal->b[ind]); + int diff = GifIAbs(r_err) + GifIAbs(g_err) + GifIAbs(b_err); - if(diff < bestDiff) - { - bestInd = ind; - bestDiff = diff; - } + if (diff < bestDiff) + { + bestInd = ind; + bestDiff = diff; + } - return; - } + return; + } - // take the appropriate color (r, g, or b) for this node of the k-d tree - int comps[3]; comps[0] = r; comps[1] = g; comps[2] = b; - int splitComp = comps[pPal->treeSplitElt[treeRoot]]; + // take the appropriate color (r, g, or b) for this node of the k-d tree + int comps[3]; + comps[0] = r; + comps[1] = g; + comps[2] = b; + int splitComp = comps[pPal->treeSplitElt[treeRoot]]; - int splitPos = pPal->treeSplit[treeRoot]; - if(splitPos > splitComp) - { - // check the left subtree - GifGetClosestPaletteColor(pPal, r, g, b, bestInd, bestDiff, treeRoot*2); - if( bestDiff > splitPos - splitComp ) - { - // cannot prove there's not a better value in the right subtree, check that too - GifGetClosestPaletteColor(pPal, r, g, b, bestInd, bestDiff, treeRoot*2+1); - } - } - else - { - GifGetClosestPaletteColor(pPal, r, g, b, bestInd, bestDiff, treeRoot*2+1); - if( bestDiff > splitComp - splitPos ) - { - GifGetClosestPaletteColor(pPal, r, g, b, bestInd, bestDiff, treeRoot*2); - } - } + int splitPos = pPal->treeSplit[treeRoot]; + if (splitPos > splitComp) + { + // check the left subtree + GifGetClosestPaletteColor(pPal, r, g, b, bestInd, bestDiff, treeRoot * 2); + if (bestDiff > splitPos - splitComp) + { + // cannot prove there's not a better value in the right subtree, check that too + GifGetClosestPaletteColor(pPal, r, g, b, bestInd, bestDiff, treeRoot * 2 + 1); + } + } + else + { + GifGetClosestPaletteColor(pPal, r, g, b, bestInd, bestDiff, treeRoot * 2 + 1); + if (bestDiff > splitComp - splitPos) + { + GifGetClosestPaletteColor(pPal, r, g, b, bestInd, bestDiff, treeRoot * 2); + } + } } void GifSwapPixels(uint8_t* image, int pixA, int pixB) { - uint8_t rA = image[pixA*4]; - uint8_t gA = image[pixA*4+1]; - uint8_t bA = image[pixA*4+2]; - uint8_t aA = image[pixA*4+3]; + uint8_t rA = image[pixA * 4]; + uint8_t gA = image[pixA * 4 + 1]; + uint8_t bA = image[pixA * 4 + 2]; + uint8_t aA = image[pixA * 4 + 3]; - uint8_t rB = image[pixB*4]; - uint8_t gB = image[pixB*4+1]; - uint8_t bB = image[pixB*4+2]; - uint8_t aB = image[pixA*4+3]; + uint8_t rB = image[pixB * 4]; + uint8_t gB = image[pixB * 4 + 1]; + uint8_t bB = image[pixB * 4 + 2]; + uint8_t aB = image[pixA * 4 + 3]; - image[pixA*4] = rB; - image[pixA*4+1] = gB; - image[pixA*4+2] = bB; - image[pixA*4+3] = aB; + image[pixA * 4] = rB; + image[pixA * 4 + 1] = gB; + image[pixA * 4 + 2] = bB; + image[pixA * 4 + 3] = aB; - image[pixB*4] = rA; - image[pixB*4+1] = gA; - image[pixB*4+2] = bA; - image[pixB*4+3] = aA; + image[pixB * 4] = rA; + image[pixB * 4 + 1] = gA; + image[pixB * 4 + 2] = bA; + image[pixB * 4 + 3] = aA; } // just the partition operation from quicksort int GifPartition(uint8_t* image, const int left, const int right, const int elt, int pivotIndex) { - const int pivotValue = image[(pivotIndex)*4+elt]; - GifSwapPixels(image, pivotIndex, right-1); - int storeIndex = left; - bool split = 0; - for(int ii=left; ii neededCenter) - GifPartitionByMedian(image, left, pivotIndex, com, neededCenter); + // Only "sort" the section of the array that contains the median + if (pivotIndex > neededCenter) + GifPartitionByMedian(image, left, pivotIndex, com, neededCenter); - if(pivotIndex < neededCenter) - GifPartitionByMedian(image, pivotIndex+1, right, com, neededCenter); - } + if (pivotIndex < neededCenter) + GifPartitionByMedian(image, pivotIndex + 1, right, com, neededCenter); + } } // Builds a palette by creating a balanced k-d tree of all pixels in the image -void GifSplitPalette(uint8_t* image, int numPixels, int firstElt, int lastElt, int splitElt, int splitDist, int treeNode, bool buildForDither, GifPalette* pal) +void GifSplitPalette(uint8_t* image, int numPixels, int firstElt, int lastElt, int splitElt, int splitDist, + int treeNode, bool buildForDither, GifPalette* pal) { - if(lastElt <= firstElt || numPixels == 0) - return; + if (lastElt <= firstElt || numPixels == 0) + return; - // base case, bottom of the tree - if(lastElt == firstElt+1) - { - if(buildForDither) - { - // Dithering needs at least one color as dark as anything - // in the image and at least one brightest color - - // otherwise it builds up error and produces strange artifacts - if( firstElt == 1 ) - { - // special case: the darkest color in the image - uint32_t r=255, g=255, b=255; - for(int ii=0; iir[firstElt] = (uint8_t)r; - pal->g[firstElt] = (uint8_t)g; - pal->b[firstElt] = (uint8_t)b; + pal->r[firstElt] = (uint8_t)r; + pal->g[firstElt] = (uint8_t)g; + pal->b[firstElt] = (uint8_t)b; - return; - } + return; + } - if( firstElt == (1 << pal->bitDepth)-1 ) - { - // special case: the lightest color in the image - uint32_t r=0, g=0, b=0; - for(int ii=0; iibitDepth) - 1) + { + // special case: the lightest color in the image + uint32_t r = 0, g = 0, b = 0; + for (int ii = 0; ii < numPixels; ++ii) + { + r = (uint32_t)GifIMax((int32_t)r, image[ii * 4 + 0]); + g = (uint32_t)GifIMax((int32_t)g, image[ii * 4 + 1]); + b = (uint32_t)GifIMax((int32_t)b, image[ii * 4 + 2]); + } - pal->r[firstElt] = (uint8_t)r; - pal->g[firstElt] = (uint8_t)g; - pal->b[firstElt] = (uint8_t)b; + pal->r[firstElt] = (uint8_t)r; + pal->g[firstElt] = (uint8_t)g; + pal->b[firstElt] = (uint8_t)b; - return; - } - } + return; + } + } - // otherwise, take the average of all colors in this subcube - uint64_t r=0, g=0, b=0; - for(int ii=0; iir[firstElt] = (uint8_t)r; - pal->g[firstElt] = (uint8_t)g; - pal->b[firstElt] = (uint8_t)b; + pal->r[firstElt] = (uint8_t)r; + pal->g[firstElt] = (uint8_t)g; + pal->b[firstElt] = (uint8_t)b; - return; - } + return; + } - // Find the axis with the largest range - int minR = 255, maxR = 0; - int minG = 255, maxG = 0; - int minB = 255, maxB = 0; - for(int ii=0; ii maxR) maxR = r; - if(r < minR) minR = r; + if (r > maxR) maxR = r; + if (r < minR) minR = r; - if(g > maxG) maxG = g; - if(g < minG) minG = g; + if (g > maxG) maxG = g; + if (g < minG) minG = g; - if(b > maxB) maxB = b; - if(b < minB) minB = b; - } + if (b > maxB) maxB = b; + if (b < minB) minB = b; + } - int rRange = maxR - minR; - int gRange = maxG - minG; - int bRange = maxB - minB; + int rRange = maxR - minR; + int gRange = maxG - minG; + int bRange = maxB - minB; - // and split along that axis. (incidentally, this means this isn't a "proper" k-d tree but I don't know what else to call it) - int splitCom = 1; - if(bRange > gRange) splitCom = 2; - if(rRange > bRange && rRange > gRange) splitCom = 0; + // and split along that axis. (incidentally, this means this isn't a "proper" k-d tree but I don't know what else to call it) + int splitCom = 1; + if (bRange > gRange) splitCom = 2; + if (rRange > bRange && rRange > gRange) splitCom = 0; - int subPixelsA = numPixels * (splitElt - firstElt) / (lastElt - firstElt); - int subPixelsB = numPixels-subPixelsA; + int subPixelsA = numPixels * (splitElt - firstElt) / (lastElt - firstElt); + int subPixelsB = numPixels - subPixelsA; - GifPartitionByMedian(image, 0, numPixels, splitCom, subPixelsA); + GifPartitionByMedian(image, 0, numPixels, splitCom, subPixelsA); - pal->treeSplitElt[treeNode] = (uint8_t)splitCom; - pal->treeSplit[treeNode] = image[subPixelsA*4+splitCom]; + pal->treeSplitElt[treeNode] = (uint8_t)splitCom; + pal->treeSplit[treeNode] = image[subPixelsA * 4 + splitCom]; - GifSplitPalette(image, subPixelsA, firstElt, splitElt, splitElt-splitDist, splitDist/2, treeNode*2, buildForDither, pal); - GifSplitPalette(image+subPixelsA*4, subPixelsB, splitElt, lastElt, splitElt+splitDist, splitDist/2, treeNode*2+1, buildForDither, pal); + GifSplitPalette(image, subPixelsA, firstElt, splitElt, splitElt - splitDist, splitDist / 2, treeNode * 2, + buildForDither, pal); + GifSplitPalette(image + subPixelsA * 4, subPixelsB, splitElt, lastElt, splitElt + splitDist, splitDist / 2, + treeNode * 2 + 1, buildForDither, pal); } // Finds all pixels that have changed from the previous image and // moves them to the fromt of th buffer. // This allows us to build a palette optimized for the colors of the // changed pixels only. -int GifPickChangedPixels( const uint8_t* lastFrame, uint8_t* frame, int numPixels ) +int GifPickChangedPixels(const uint8_t* lastFrame, uint8_t* frame, int numPixels) { - int numChanged = 0; - uint8_t* writeIter = frame; + int numChanged = 0; + uint8_t* writeIter = frame; - for (int ii=0; iibitDepth = bitDepth; + pPal->bitDepth = bitDepth; - // SplitPalette is destructive (it sorts the pixels by color) so - // we must create a copy of the image for it to destroy - size_t imageSize = (size_t)(width * height * 4 * sizeof(uint8_t)); - uint8_t* destroyableImage = (uint8_t*)GIF_TEMP_MALLOC(imageSize); - memcpy(destroyableImage, nextFrame, imageSize); + // SplitPalette is destructive (it sorts the pixels by color) so + // we must create a copy of the image for it to destroy + size_t imageSize = (size_t)(width * height * 4 * sizeof(uint8_t)); + uint8_t* destroyableImage = (uint8_t*)GIF_TEMP_MALLOC(imageSize); + memcpy(destroyableImage, nextFrame, imageSize); - int numPixels = (int)(width * height); - if(lastFrame) - numPixels = GifPickChangedPixels(lastFrame, destroyableImage, numPixels); + int numPixels = (int)(width * height); + if (lastFrame) + numPixels = GifPickChangedPixels(lastFrame, destroyableImage, numPixels); - const int lastElt = 1 << bitDepth; - const int splitElt = lastElt/2; - const int splitDist = splitElt/2; + const int lastElt = 1 << bitDepth; + const int splitElt = lastElt / 2; + const int splitDist = splitElt / 2; - GifSplitPalette(destroyableImage, numPixels, 1, lastElt, splitElt, splitDist, 1, buildForDither, pPal); + GifSplitPalette(destroyableImage, numPixels, 1, lastElt, splitElt, splitDist, 1, buildForDither, pPal); - GIF_TEMP_FREE(destroyableImage); + GIF_TEMP_FREE(destroyableImage); - // add the bottom node for the transparency index - int index = 1 << (bitDepth - 1); - pPal->treeSplit[index] = 0; - pPal->treeSplitElt[index] = 0; - - pPal->r[0] = pPal->g[0] = pPal->b[0] = 0; + // add the bottom node for the transparency index + int index = 1 << (bitDepth - 1); + pPal->treeSplit[index] = 0; + pPal->treeSplitElt[index] = 0; + + pPal->r[0] = pPal->g[0] = pPal->b[0] = 0; } // Implements Floyd-Steinberg dithering, writes palette value to alpha -void GifDitherImage( const uint8_t* lastFrame, const uint8_t* nextFrame, uint8_t* outFrame, uint32_t width, uint32_t height, GifPalette* pPal ) +void GifDitherImage(const uint8_t* lastFrame, const uint8_t* nextFrame, uint8_t* outFrame, uint32_t width, + uint32_t height, GifPalette* pPal) { - int numPixels = (int)(width * height); + int numPixels = (int)(width * height); - // quantPixels initially holds color*256 for all pixels - // The extra 8 bits of precision allow for sub-single-color error values - // to be propagated - int32_t *quantPixels = (int32_t *)GIF_TEMP_MALLOC(sizeof(int32_t) * (size_t)numPixels * 4); + // quantPixels initially holds color*256 for all pixels + // The extra 8 bits of precision allow for sub-single-color error values + // to be propagated + int32_t* quantPixels = (int32_t*)GIF_TEMP_MALLOC(sizeof(int32_t) * (size_t)numPixels * 4); - for( int ii=0; iir[bestInd]) * 256; - int32_t g_err = nextPix[1] - int32_t(pPal->g[bestInd]) * 256; - int32_t b_err = nextPix[2] - int32_t(pPal->b[bestInd]) * 256; + // Write the result to the temp buffer + int32_t r_err = nextPix[0] - int32_t(pPal->r[bestInd]) * 256; + int32_t g_err = nextPix[1] - int32_t(pPal->g[bestInd]) * 256; + int32_t b_err = nextPix[2] - int32_t(pPal->b[bestInd]) * 256; - nextPix[0] = pPal->r[bestInd]; - nextPix[1] = pPal->g[bestInd]; - nextPix[2] = pPal->b[bestInd]; - nextPix[3] = bestInd; + nextPix[0] = pPal->r[bestInd]; + nextPix[1] = pPal->g[bestInd]; + nextPix[2] = pPal->b[bestInd]; + nextPix[3] = bestInd; - // Propagate the error to the four adjacent locations - // that we haven't touched yet - int quantloc_7 = (int)(yy * width + xx + 1); - int quantloc_3 = (int)(yy * width + width + xx - 1); - int quantloc_5 = (int)(yy * width + width + xx); - int quantloc_1 = (int)(yy * width + width + xx + 1); + // Propagate the error to the four adjacent locations + // that we haven't touched yet + int quantloc_7 = (int)(yy * width + xx + 1); + int quantloc_3 = (int)(yy * width + width + xx - 1); + int quantloc_5 = (int)(yy * width + width + xx); + int quantloc_1 = (int)(yy * width + width + xx + 1); - if(quantloc_7 < numPixels) - { - int32_t* pix7 = quantPixels+4*quantloc_7; - pix7[0] += GifIMax( -pix7[0], r_err * 7 / 16 ); - pix7[1] += GifIMax( -pix7[1], g_err * 7 / 16 ); - pix7[2] += GifIMax( -pix7[2], b_err * 7 / 16 ); - } + if (quantloc_7 < numPixels) + { + int32_t* pix7 = quantPixels + 4 * quantloc_7; + pix7[0] += GifIMax(-pix7[0], r_err * 7 / 16); + pix7[1] += GifIMax(-pix7[1], g_err * 7 / 16); + pix7[2] += GifIMax(-pix7[2], b_err * 7 / 16); + } - if(quantloc_3 < numPixels) - { - int32_t* pix3 = quantPixels+4*quantloc_3; - pix3[0] += GifIMax( -pix3[0], r_err * 3 / 16 ); - pix3[1] += GifIMax( -pix3[1], g_err * 3 / 16 ); - pix3[2] += GifIMax( -pix3[2], b_err * 3 / 16 ); - } + if (quantloc_3 < numPixels) + { + int32_t* pix3 = quantPixels + 4 * quantloc_3; + pix3[0] += GifIMax(-pix3[0], r_err * 3 / 16); + pix3[1] += GifIMax(-pix3[1], g_err * 3 / 16); + pix3[2] += GifIMax(-pix3[2], b_err * 3 / 16); + } - if(quantloc_5 < numPixels) - { - int32_t* pix5 = quantPixels+4*quantloc_5; - pix5[0] += GifIMax( -pix5[0], r_err * 5 / 16 ); - pix5[1] += GifIMax( -pix5[1], g_err * 5 / 16 ); - pix5[2] += GifIMax( -pix5[2], b_err * 5 / 16 ); - } + if (quantloc_5 < numPixels) + { + int32_t* pix5 = quantPixels + 4 * quantloc_5; + pix5[0] += GifIMax(-pix5[0], r_err * 5 / 16); + pix5[1] += GifIMax(-pix5[1], g_err * 5 / 16); + pix5[2] += GifIMax(-pix5[2], b_err * 5 / 16); + } - if(quantloc_1 < numPixels) - { - int32_t* pix1 = quantPixels+4*quantloc_1; - pix1[0] += GifIMax( -pix1[0], r_err / 16 ); - pix1[1] += GifIMax( -pix1[1], g_err / 16 ); - pix1[2] += GifIMax( -pix1[2], b_err / 16 ); - } - } - } + if (quantloc_1 < numPixels) + { + int32_t* pix1 = quantPixels + 4 * quantloc_1; + pix1[0] += GifIMax(-pix1[0], r_err / 16); + pix1[1] += GifIMax(-pix1[1], g_err / 16); + pix1[2] += GifIMax(-pix1[2], b_err / 16); + } + } + } - // Copy the palettized result to the output buffer - for( int ii=0; iir[bestInd]; - outFrame[1] = pPal->g[bestInd]; - outFrame[2] = pPal->b[bestInd]; - outFrame[3] = (uint8_t)bestInd; - } + // Write the resulting color to the output buffer + outFrame[0] = pPal->r[bestInd]; + outFrame[1] = pPal->g[bestInd]; + outFrame[2] = pPal->b[bestInd]; + outFrame[3] = (uint8_t)bestInd; + } - if(lastFrame) lastFrame += 4; - outFrame += 4; - nextFrame += 4; - } + if (lastFrame) lastFrame += 4; + outFrame += 4; + nextFrame += 4; + } } // Simple structure to write out the LZW-compressed portion of the image // one bit at a time struct GifBitStatus { - uint8_t bitIndex; // how many bits in the partial byte written so far - uint8_t byte; // current partial byte + uint8_t bitIndex; // how many bits in the partial byte written so far + uint8_t byte; // current partial byte - uint32_t chunkIndex; - uint8_t chunk[256]; // bytes are written in here until we have 256 of them, then written to the file + uint32_t chunkIndex; + uint8_t chunk[256]; // bytes are written in here until we have 256 of them, then written to the file }; // insert a single bit -void GifWriteBit( GifBitStatus& stat, uint32_t bit ) +void GifWriteBit(GifBitStatus& stat, uint32_t bit) { - bit = bit & 1; - bit = bit << stat.bitIndex; - stat.byte |= bit; + bit = bit & 1; + bit = bit << stat.bitIndex; + stat.byte |= bit; - ++stat.bitIndex; - if( stat.bitIndex > 7 ) - { - // move the newly-finished byte to the chunk buffer - stat.chunk[stat.chunkIndex++] = stat.byte; - // and start a new byte - stat.bitIndex = 0; - stat.byte = 0; - } + ++stat.bitIndex; + if (stat.bitIndex > 7) + { + // move the newly-finished byte to the chunk buffer + stat.chunk[stat.chunkIndex++] = stat.byte; + // and start a new byte + stat.bitIndex = 0; + stat.byte = 0; + } } // write all bytes so far to the file -void GifWriteChunk( FILE* f, GifBitStatus& stat ) +void GifWriteChunk(FILE* f, GifBitStatus& stat) { - fputc((int)stat.chunkIndex, f); - fwrite(stat.chunk, 1, stat.chunkIndex, f); + fputc((int)stat.chunkIndex, f); + fwrite(stat.chunk, 1, stat.chunkIndex, f); - stat.bitIndex = 0; - stat.byte = 0; - stat.chunkIndex = 0; + stat.bitIndex = 0; + stat.byte = 0; + stat.chunkIndex = 0; } -void GifWriteCode( FILE* f, GifBitStatus& stat, uint32_t code, uint32_t length ) +void GifWriteCode(FILE* f, GifBitStatus& stat, uint32_t code, uint32_t length) { - for( uint32_t ii=0; ii> 1; + for (uint32_t ii = 0; ii < length; ++ii) + { + GifWriteBit(stat, code); + code = code >> 1; - if( stat.chunkIndex == 255 ) - { - GifWriteChunk(f, stat); - } - } + if (stat.chunkIndex == 255) + { + GifWriteChunk(f, stat); + } + } } // The LZW dictionary is a 256-ary tree constructed as the file is encoded, // this is one node struct GifLzwNode { - uint16_t m_next[256]; + uint16_t m_next[256]; }; // write a 256-color (8-bit) image palette to the file -void GifWritePalette( const GifPalette* pPal, FILE* f ) +void GifWritePalette(const GifPalette* pPal, FILE* f) { - fputc(0, f); // first color: transparency - fputc(0, f); - fputc(0, f); + fputc(0, f); // first color: transparency + fputc(0, f); + fputc(0, f); - for(int ii=1; ii<(1 << pPal->bitDepth); ++ii) - { - uint32_t r = pPal->r[ii]; - uint32_t g = pPal->g[ii]; - uint32_t b = pPal->b[ii]; + for (int ii = 1; ii < (1 << pPal->bitDepth); ++ii) + { + uint32_t r = pPal->r[ii]; + uint32_t g = pPal->g[ii]; + uint32_t b = pPal->b[ii]; - fputc((int)b, f); - fputc((int)g, f); - fputc((int)r, f); - } + fputc((int)b, f); + fputc((int)g, f); + fputc((int)r, f); + } } // write the image header, LZW-compress and write out the image -void GifWriteLzwImage(FILE* f, uint8_t* image, uint32_t left, uint32_t top, uint32_t width, uint32_t height, uint32_t delay, GifPalette* pPal) +void GifWriteLzwImage(FILE* f, uint8_t* image, uint32_t left, uint32_t top, uint32_t width, uint32_t height, + uint32_t delay, GifPalette* pPal) { - // graphics control extension - fputc(0x21, f); - fputc(0xf9, f); - fputc(0x04, f); - fputc(0x05, f); // leave prev frame in place, this frame has transparency - fputc(delay & 0xff, f); - fputc((delay >> 8) & 0xff, f); - fputc(kGifTransIndex, f); // transparent color index - fputc(0, f); + // graphics control extension + fputc(0x21, f); + fputc(0xf9, f); + fputc(0x04, f); + fputc(0x05, f); // leave prev frame in place, this frame has transparency + fputc(delay & 0xff, f); + fputc((delay >> 8) & 0xff, f); + fputc(kGifTransIndex, f); // transparent color index + fputc(0, f); - fputc(0x2c, f); // image descriptor block + fputc(0x2c, f); // image descriptor block - fputc(left & 0xff, f); // corner of image in canvas space - fputc((left >> 8) & 0xff, f); - fputc(top & 0xff, f); - fputc((top >> 8) & 0xff, f); + fputc(left & 0xff, f); // corner of image in canvas space + fputc((left >> 8) & 0xff, f); + fputc(top & 0xff, f); + fputc((top >> 8) & 0xff, f); - fputc(width & 0xff, f); // width and height of image - fputc((width >> 8) & 0xff, f); - fputc(height & 0xff, f); - fputc((height >> 8) & 0xff, f); + fputc(width & 0xff, f); // width and height of image + fputc((width >> 8) & 0xff, f); + fputc(height & 0xff, f); + fputc((height >> 8) & 0xff, f); - //fputc(0, f); // no local color table, no transparency - //fputc(0x80, f); // no local color table, but transparency + //fputc(0, f); // no local color table, no transparency + //fputc(0x80, f); // no local color table, but transparency - fputc(0x80 + pPal->bitDepth-1, f); // local color table present, 2 ^ bitDepth entries - GifWritePalette(pPal, f); + fputc(0x80 + pPal->bitDepth - 1, f); // local color table present, 2 ^ bitDepth entries + GifWritePalette(pPal, f); - const int minCodeSize = pPal->bitDepth; - const uint32_t clearCode = 1 << pPal->bitDepth; + const int minCodeSize = pPal->bitDepth; + const uint32_t clearCode = 1 << pPal->bitDepth; - fputc(minCodeSize, f); // min code size 8 bits + fputc(minCodeSize, f); // min code size 8 bits - GifLzwNode* codetree = (GifLzwNode*)GIF_TEMP_MALLOC(sizeof(GifLzwNode)*4096); + GifLzwNode* codetree = (GifLzwNode*)GIF_TEMP_MALLOC(sizeof(GifLzwNode) * 4096); - memset(codetree, 0, sizeof(GifLzwNode)*4096); - int32_t curCode = -1; - uint32_t codeSize = (uint32_t)minCodeSize + 1; - uint32_t maxCode = clearCode+1; + memset(codetree, 0, sizeof(GifLzwNode) * 4096); + int32_t curCode = -1; + uint32_t codeSize = (uint32_t)minCodeSize + 1; + uint32_t maxCode = clearCode + 1; - GifBitStatus stat; - stat.byte = 0; - stat.bitIndex = 0; - stat.chunkIndex = 0; + GifBitStatus stat; + stat.byte = 0; + stat.bitIndex = 0; + stat.chunkIndex = 0; - GifWriteCode(f, stat, clearCode, codeSize); // start with a fresh LZW dictionary + GifWriteCode(f, stat, clearCode, codeSize); // start with a fresh LZW dictionary - for(uint32_t yy=0; yy= (1ul << codeSize) ) - { - // dictionary entry count has broken a size barrier, - // we need more bits for codes - codeSize++; - } - if( maxCode == 4095 ) - { - // the dictionary is full, clear it out and begin anew - GifWriteCode(f, stat, clearCode, codeSize); // clear tree + if (maxCode >= (1ul << codeSize)) + { + // dictionary entry count has broken a size barrier, + // we need more bits for codes + codeSize++; + } + if (maxCode == 4095) + { + // the dictionary is full, clear it out and begin anew + GifWriteCode(f, stat, clearCode, codeSize); // clear tree - memset(codetree, 0, sizeof(GifLzwNode)*4096); - codeSize = (uint32_t)(minCodeSize + 1); - maxCode = clearCode+1; - } + memset(codetree, 0, sizeof(GifLzwNode) * 4096); + codeSize = (uint32_t)(minCodeSize + 1); + maxCode = clearCode + 1; + } - curCode = nextValue; - } - } - } + curCode = nextValue; + } + } + } - // compression footer - GifWriteCode(f, stat, (uint32_t)curCode, codeSize); - GifWriteCode(f, stat, clearCode, codeSize); - GifWriteCode(f, stat, clearCode + 1, (uint32_t)minCodeSize + 1); + // compression footer + GifWriteCode(f, stat, (uint32_t)curCode, codeSize); + GifWriteCode(f, stat, clearCode, codeSize); + GifWriteCode(f, stat, clearCode + 1, (uint32_t)minCodeSize + 1); - // write out the last partial chunk - while( stat.bitIndex ) GifWriteBit(stat, 0); - if( stat.chunkIndex ) GifWriteChunk(f, stat); + // write out the last partial chunk + while (stat.bitIndex) GifWriteBit(stat, 0); + if (stat.chunkIndex) GifWriteChunk(f, stat); - fputc(0, f); // image block terminator + fputc(0, f); // image block terminator - GIF_TEMP_FREE(codetree); + GIF_TEMP_FREE(codetree); } struct GifWriter { - FILE* f; - uint8_t* oldImage; - bool firstFrame; + FILE* f; + uint8_t* oldImage; + bool firstFrame; }; // Creates a gif file. // The input GIFWriter is assumed to be uninitialized. // The delay value is the time between frames in hundredths of a second - note that not all viewers pay much attention to this value. -bool GifBegin( GifWriter* writer, const char* filename, uint32_t width, uint32_t height, uint32_t delay, int32_t bitDepth = 8, bool dither = false ) +bool GifBegin(GifWriter* writer, const char* filename, uint32_t width, uint32_t height, uint32_t delay, + int32_t bitDepth = 8, bool dither = false) { - (void)bitDepth; (void)dither; // Mute "Unused argument" warnings + (void)bitDepth; + (void)dither; // Mute "Unused argument" warnings #if defined(_MSC_VER) && (_MSC_VER >= 1400) writer->f = 0; - fopen_s(&writer->f, filename, "wb"); + fopen_s(&writer->f, filename, "wb"); #else writer->f = fopen(filename, "wb"); #endif - if(!writer->f) return false; + if (!writer->f) return false; - writer->firstFrame = true; + writer->firstFrame = true; - // allocate - writer->oldImage = (uint8_t*)GIF_MALLOC(width*height*4); + // allocate + writer->oldImage = (uint8_t*)GIF_MALLOC(width * height * 4); - fputs("GIF89a", writer->f); + fputs("GIF89a", writer->f); - // screen descriptor - fputc(width & 0xff, writer->f); - fputc((width >> 8) & 0xff, writer->f); - fputc(height & 0xff, writer->f); - fputc((height >> 8) & 0xff, writer->f); + // screen descriptor + fputc(width & 0xff, writer->f); + fputc((width >> 8) & 0xff, writer->f); + fputc(height & 0xff, writer->f); + fputc((height >> 8) & 0xff, writer->f); - fputc(0xf0, writer->f); // there is an unsorted global color table of 2 entries - fputc(0, writer->f); // background color - fputc(0, writer->f); // pixels are square (we need to specify this because it's 1989) + fputc(0xf0, writer->f); // there is an unsorted global color table of 2 entries + fputc(0, writer->f); // background color + fputc(0, writer->f); // pixels are square (we need to specify this because it's 1989) - // now the "global" palette (really just a dummy palette) - // color 0: black - fputc(0, writer->f); - fputc(0, writer->f); - fputc(0, writer->f); - // color 1: also black - fputc(0, writer->f); - fputc(0, writer->f); - fputc(0, writer->f); + // now the "global" palette (really just a dummy palette) + // color 0: black + fputc(0, writer->f); + fputc(0, writer->f); + fputc(0, writer->f); + // color 1: also black + fputc(0, writer->f); + fputc(0, writer->f); + fputc(0, writer->f); - if( delay != 0 ) - { - // animation header - fputc(0x21, writer->f); // extension - fputc(0xff, writer->f); // application specific - fputc(11, writer->f); // length 11 - fputs("NETSCAPE2.0", writer->f); // yes, really - fputc(3, writer->f); // 3 bytes of NETSCAPE2.0 data + if (delay != 0) + { + // animation header + fputc(0x21, writer->f); // extension + fputc(0xff, writer->f); // application specific + fputc(11, writer->f); // length 11 + fputs("NETSCAPE2.0", writer->f); // yes, really + fputc(3, writer->f); // 3 bytes of NETSCAPE2.0 data - fputc(1, writer->f); // JUST BECAUSE - fputc(0, writer->f); // loop infinitely (byte 0) - fputc(0, writer->f); // loop infinitely (byte 1) + fputc(1, writer->f); // JUST BECAUSE + fputc(0, writer->f); // loop infinitely (byte 0) + fputc(0, writer->f); // loop infinitely (byte 1) - fputc(0, writer->f); // block terminator - } + fputc(0, writer->f); // block terminator + } - return true; + return true; } // Writes out a new frame to a GIF in progress. // The GIFWriter should have been created by GIFBegin. // AFAIK, it is legal to use different bit depths for different frames of an image - // this may be handy to save bits in animations that don't change much. -bool GifWriteFrame( GifWriter* writer, const uint8_t* image, uint32_t width, uint32_t height, uint32_t delay, int bitDepth = 8, bool dither = false ) +bool GifWriteFrame(GifWriter* writer, const uint8_t* image, uint32_t width, uint32_t height, uint32_t delay, + int bitDepth = 8, bool dither = false) { - if(!writer->f) return false; + if (!writer->f) return false; - const uint8_t* oldImage = writer->firstFrame? NULL : writer->oldImage; - writer->firstFrame = false; + const uint8_t* oldImage = writer->firstFrame ? NULL : writer->oldImage; + writer->firstFrame = false; - GifPalette pal; - GifMakePalette((dither? NULL : oldImage), image, width, height, bitDepth, dither, &pal); + GifPalette pal; + GifMakePalette((dither ? NULL : oldImage), image, width, height, bitDepth, dither, &pal); - if(dither) - GifDitherImage(oldImage, image, writer->oldImage, width, height, &pal); - else - GifThresholdImage(oldImage, image, writer->oldImage, width, height, &pal); + if (dither) + GifDitherImage(oldImage, image, writer->oldImage, width, height, &pal); + else + GifThresholdImage(oldImage, image, writer->oldImage, width, height, &pal); - GifWriteLzwImage(writer->f, writer->oldImage, 0, 0, width, height, delay, &pal); + GifWriteLzwImage(writer->f, writer->oldImage, 0, 0, width, height, delay, &pal); - return true; + return true; } // Writes the EOF code, closes the file handle, and frees temp memory used by a GIF. // Many if not most viewers will still display a GIF properly if the EOF code is missing, // but it's still a good idea to write it out. -bool GifEnd( GifWriter* writer ) +bool GifEnd(GifWriter* writer) { - if(!writer->f) return false; + if (!writer->f) return false; - fputc(0x3b, writer->f); // end of file - fclose(writer->f); - GIF_FREE(writer->oldImage); + fputc(0x3b, writer->f); // end of file + fclose(writer->f); + GIF_FREE(writer->oldImage); - writer->f = NULL; - writer->oldImage = NULL; + writer->f = NULL; + writer->oldImage = NULL; - return true; + return true; } #endif diff --git a/Utilities/md5.cpp b/Utilities/md5.cpp index f7c1f7c..9ab38b3 100644 --- a/Utilities/md5.cpp +++ b/Utilities/md5.cpp @@ -90,26 +90,27 @@ * This processes one or more 64-byte data blocks, but does NOT update * the bit counters. There are no alignment requirements. */ -static const void *body(MD5_CTX *ctx, const void *data, unsigned long size) +static const void* body(MD5_CTX* ctx, const void* data, unsigned long size) { - const unsigned char *ptr; + const unsigned char* ptr; MD5_u32plus a, b, c, d; MD5_u32plus saved_a, saved_b, saved_c, saved_d; - ptr = (const unsigned char *)data; + ptr = (const unsigned char*)data; a = ctx->a; b = ctx->b; c = ctx->c; d = ctx->d; - do { + do + { saved_a = a; saved_b = b; saved_c = c; saved_d = d; -/* Round 1 */ + /* Round 1 */ STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7) STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12) STEP(F, c, d, a, b, SET(2), 0x242070db, 17) @@ -127,7 +128,7 @@ static const void *body(MD5_CTX *ctx, const void *data, unsigned long size) STEP(F, c, d, a, b, SET(14), 0xa679438e, 17) STEP(F, b, c, d, a, SET(15), 0x49b40821, 22) -/* Round 2 */ + /* Round 2 */ STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5) STEP(G, d, a, b, c, GET(6), 0xc040b340, 9) STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14) @@ -145,7 +146,7 @@ static const void *body(MD5_CTX *ctx, const void *data, unsigned long size) STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14) STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20) -/* Round 3 */ + /* Round 3 */ STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4) STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11) STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16) @@ -163,7 +164,7 @@ static const void *body(MD5_CTX *ctx, const void *data, unsigned long size) STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16) STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23) -/* Round 4 */ + /* Round 4 */ STEP(I, a, b, c, d, GET(0), 0xf4292244, 6) STEP(I, d, a, b, c, GET(7), 0x432aff97, 10) STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15) @@ -187,7 +188,8 @@ static const void *body(MD5_CTX *ctx, const void *data, unsigned long size) d += saved_d; ptr += 64; - } while (size -= 64); + } + while (size -= 64); ctx->a = a; ctx->b = b; @@ -197,7 +199,7 @@ static const void *body(MD5_CTX *ctx, const void *data, unsigned long size) return ptr; } -void MD5_Init(MD5_CTX *ctx) +void MD5_Init(MD5_CTX* ctx) { ctx->a = 0x67452301; ctx->b = 0xefcdab89; @@ -208,7 +210,7 @@ void MD5_Init(MD5_CTX *ctx) ctx->hi = 0; } -void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size) +void MD5_Update(MD5_CTX* ctx, const void* data, unsigned long size) { MD5_u32plus saved_lo; unsigned long used, available; @@ -220,21 +222,24 @@ void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size) used = saved_lo & 0x3f; - if (used) { + if (used) + { available = 64 - used; - if (size < available) { + if (size < available) + { memcpy(&ctx->buffer[used], data, size); return; } memcpy(&ctx->buffer[used], data, available); - data = (const unsigned char *)data + available; + data = (const unsigned char*)data + available; size -= available; body(ctx, ctx->buffer, 64); } - if (size >= 64) { + if (size >= 64) + { data = body(ctx, data, size & ~(unsigned long)0x3f); size &= 0x3f; } @@ -242,7 +247,7 @@ void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size) memcpy(ctx->buffer, data, size); } -void MD5_Final(unsigned char *result, MD5_CTX *ctx) +void MD5_Final(unsigned char* result, MD5_CTX* ctx) { unsigned long used, available; @@ -252,7 +257,8 @@ void MD5_Final(unsigned char *result, MD5_CTX *ctx) available = 64 - used; - if (available < 8) { + if (available < 8) + { memset(&ctx->buffer[used], 0, available); body(ctx, ctx->buffer, 64); used = 0; @@ -308,8 +314,9 @@ string GetMd5Sum(void* buffer, size_t size) std::stringstream ss; ss << std::hex << std::uppercase << std::setfill('0'); - for(int i = 0; i < 16; i++) { + for (int i = 0; i < 16; i++) + { ss << std::setw(2) << (int)result[i]; } return ss.str(); -} \ No newline at end of file +} diff --git a/Utilities/md5.h b/Utilities/md5.h index ed006ed..2456a6e 100644 --- a/Utilities/md5.h +++ b/Utilities/md5.h @@ -23,20 +23,21 @@ * See md5.c for more information. */ -#pragma once +#pragma once /* Any 32-bit or wider unsigned integer data type will do */ typedef unsigned int MD5_u32plus; -typedef struct { +typedef struct +{ MD5_u32plus lo, hi; MD5_u32plus a, b, c, d; unsigned char buffer[64]; MD5_u32plus block[16]; } MD5_CTX; -extern void MD5_Init(MD5_CTX *ctx); -extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size); -extern void MD5_Final(unsigned char *result, MD5_CTX *ctx); -extern void GetMd5Sum(unsigned char *result, void* buffer, unsigned long size); +extern void MD5_Init(MD5_CTX* ctx); +extern void MD5_Update(MD5_CTX* ctx, const void* data, unsigned long size); +extern void MD5_Final(unsigned char* result, MD5_CTX* ctx); +extern void GetMd5Sum(unsigned char* result, void* buffer, unsigned long size); extern string GetMd5Sum(void* buffer, size_t size); diff --git a/Utilities/miniz.cpp b/Utilities/miniz.cpp index 84ac43e..c43a70a 100644 --- a/Utilities/miniz.cpp +++ b/Utilities/miniz.cpp @@ -159,9 +159,9 @@ #include "stdafx.h" #include "miniz.h" -typedef unsigned char mz_validate_uint16[sizeof(mz_uint16)==2 ? 1 : -1]; -typedef unsigned char mz_validate_uint32[sizeof(mz_uint32)==4 ? 1 : -1]; -typedef unsigned char mz_validate_uint64[sizeof(mz_uint64)==8 ? 1 : -1]; +typedef unsigned char mz_validate_uint16[sizeof(mz_uint16) == 2 ? 1 : -1]; +typedef unsigned char mz_validate_uint32[sizeof(mz_uint32) == 4 ? 1 : -1]; +typedef unsigned char mz_validate_uint64[sizeof(mz_uint64) == 8 ? 1 : -1]; #include #include @@ -173,9 +173,9 @@ typedef unsigned char mz_validate_uint64[sizeof(mz_uint64)==8 ? 1 : -1]; #define MZ_FREE(x) (void)x, ((void)0) #define MZ_REALLOC(p, x) NULL #else - #define MZ_MALLOC(x) malloc(x) - #define MZ_FREE(x) free(x) - #define MZ_REALLOC(p, x) realloc(p, x) +#define MZ_MALLOC(x) malloc(x) +#define MZ_FREE(x) free(x) +#define MZ_REALLOC(p, x) realloc(p, x) #endif #define MZ_MAX(a,b) (((a)>(b))?(a):(b)) @@ -183,15 +183,15 @@ typedef unsigned char mz_validate_uint64[sizeof(mz_uint64)==8 ? 1 : -1]; #define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj)) #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN - #define MZ_READ_LE16(p) *((const mz_uint16 *)(p)) - #define MZ_READ_LE32(p) *((const mz_uint32 *)(p)) +#define MZ_READ_LE16(p) *((const mz_uint16 *)(p)) +#define MZ_READ_LE32(p) *((const mz_uint32 *)(p)) #else #define MZ_READ_LE16(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U)) #define MZ_READ_LE32(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) | ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) | ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U)) #endif #ifdef _MSC_VER - #define MZ_FORCEINLINE __forceinline +#define MZ_FORCEINLINE __forceinline #elif defined(__GNUC__) #define MZ_FORCEINLINE inline __attribute__((__always_inline__)) #else @@ -199,388 +199,457 @@ typedef unsigned char mz_validate_uint64[sizeof(mz_uint64)==8 ? 1 : -1]; #endif #ifdef __cplusplus - extern "C" { +extern "C" { #endif // ------------------- zlib-style API's -mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len) +mz_ulong mz_adler32(mz_ulong adler, const unsigned char* ptr, size_t buf_len) { - mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16); size_t block_len = buf_len % 5552; - if (!ptr) return MZ_ADLER32_INIT; - while (buf_len) { - for (i = 0; i + 7 < block_len; i += 8, ptr += 8) { - s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1; - s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1; - } - for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1; - s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552; - } - return (s2 << 16) + s1; + mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16); + size_t block_len = buf_len % 5552; + if (!ptr) return MZ_ADLER32_INIT; + while (buf_len) + { + for (i = 0; i + 7 < block_len; i += 8, ptr += 8) + { + s1 += ptr[0], s2 += s1; + s1 += ptr[1], s2 += s1; + s1 += ptr[2], s2 += s1; + s1 += ptr[3], s2 += s1; + s1 += ptr[4], s2 += s1; + s1 += ptr[5], s2 += s1; + s1 += ptr[6], s2 += s1; + s1 += ptr[7], s2 += s1; + } + for (; i < block_len; ++i) s1 += *ptr++, s2 += s1; + s1 %= 65521U, s2 %= 65521U; + buf_len -= block_len; + block_len = 5552; + } + return (s2 << 16) + s1; } // Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/ -mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len) +mz_ulong mz_crc32(mz_ulong crc, const mz_uint8* ptr, size_t buf_len) { - static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, - 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c }; - mz_uint32 crcu32 = (mz_uint32)crc; - if (!ptr) return MZ_CRC32_INIT; - crcu32 = ~crcu32; while (buf_len--) { mz_uint8 b = *ptr++; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)]; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)]; } - return ~crcu32; + static const mz_uint32 s_crc32[16] = { + 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, + 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c + }; + mz_uint32 crcu32 = (mz_uint32)crc; + if (!ptr) return MZ_CRC32_INIT; + crcu32 = ~crcu32; + while (buf_len--) + { + mz_uint8 b = *ptr++; + crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)]; + crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)]; + } + return ~crcu32; } -void mz_free(void *p) +void mz_free(void* p) { - MZ_FREE(p); + MZ_FREE(p); } #ifndef MINIZ_NO_ZLIB_APIS -static void *def_alloc_func(void *opaque, size_t items, size_t size) { (void)opaque, (void)items, (void)size; return MZ_MALLOC(items * size); } -static void def_free_func(void *opaque, void *address) { (void)opaque, (void)address; MZ_FREE(address); } -static void *def_realloc_func(void *opaque, void *address, size_t items, size_t size) { (void)opaque, (void)address, (void)items, (void)size; return MZ_REALLOC(address, items * size); } - -const char *mz_version(void) +static void* def_alloc_func(void* opaque, size_t items, size_t size) { - return MZ_VERSION; + (void)opaque, (void)items, (void)size; + return MZ_MALLOC(items * size); +} + +static void def_free_func(void* opaque, void* address) +{ + (void)opaque, (void)address; + MZ_FREE(address); +} + +static void* def_realloc_func(void* opaque, void* address, size_t items, size_t size) +{ + (void)opaque, (void)address, (void)items, (void)size; + return MZ_REALLOC(address, items * size); +} + +const char* mz_version(void) +{ + return MZ_VERSION; } int mz_deflateInit(mz_streamp pStream, int level) { - return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY); + return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY); } int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy) { - tdefl_compressor *pComp; - mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy); + tdefl_compressor* pComp; + mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy); - if (!pStream) return MZ_STREAM_ERROR; - if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))) return MZ_PARAM_ERROR; + if (!pStream) return MZ_STREAM_ERROR; + if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (- + window_bits != MZ_DEFAULT_WINDOW_BITS))) return MZ_PARAM_ERROR; - pStream->data_type = 0; - pStream->adler = MZ_ADLER32_INIT; - pStream->msg = NULL; - pStream->reserved = 0; - pStream->total_in = 0; - pStream->total_out = 0; - if (!pStream->zalloc) pStream->zalloc = def_alloc_func; - if (!pStream->zfree) pStream->zfree = def_free_func; + pStream->data_type = 0; + pStream->adler = MZ_ADLER32_INIT; + pStream->msg = NULL; + pStream->reserved = 0; + pStream->total_in = 0; + pStream->total_out = 0; + if (!pStream->zalloc) pStream->zalloc = def_alloc_func; + if (!pStream->zfree) pStream->zfree = def_free_func; - pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor)); - if (!pComp) - return MZ_MEM_ERROR; + pComp = (tdefl_compressor*)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor)); + if (!pComp) + return MZ_MEM_ERROR; - pStream->state = (struct mz_internal_state *)pComp; + pStream->state = (struct mz_internal_state*)pComp; - if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY) - { - mz_deflateEnd(pStream); - return MZ_PARAM_ERROR; - } + if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY) + { + mz_deflateEnd(pStream); + return MZ_PARAM_ERROR; + } - return MZ_OK; + return MZ_OK; } int mz_deflateReset(mz_streamp pStream) { - if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree)) return MZ_STREAM_ERROR; - pStream->total_in = pStream->total_out = 0; - tdefl_init((tdefl_compressor*)pStream->state, NULL, NULL, ((tdefl_compressor*)pStream->state)->m_flags); - return MZ_OK; + if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree)) return MZ_STREAM_ERROR; + pStream->total_in = pStream->total_out = 0; + tdefl_init((tdefl_compressor*)pStream->state, NULL, NULL, ((tdefl_compressor*)pStream->state)->m_flags); + return MZ_OK; } int mz_deflate(mz_streamp pStream, int flush) { - size_t in_bytes, out_bytes; - mz_ulong orig_total_in, orig_total_out; - int mz_status = MZ_OK; + size_t in_bytes, out_bytes; + mz_ulong orig_total_in, orig_total_out; + int mz_status = MZ_OK; - if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out)) return MZ_STREAM_ERROR; - if (!pStream->avail_out) return MZ_BUF_ERROR; + if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out)) return + MZ_STREAM_ERROR; + if (!pStream->avail_out) return MZ_BUF_ERROR; - if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH; + if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH; - if (((tdefl_compressor*)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE) - return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR; + if (((tdefl_compressor*)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE) + return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR; - orig_total_in = pStream->total_in; orig_total_out = pStream->total_out; - for ( ; ; ) - { - tdefl_status defl_status; - in_bytes = pStream->avail_in; out_bytes = pStream->avail_out; + orig_total_in = pStream->total_in; + orig_total_out = pStream->total_out; + for (; ;) + { + tdefl_status defl_status; + in_bytes = pStream->avail_in; + out_bytes = pStream->avail_out; - defl_status = tdefl_compress((tdefl_compressor*)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush); - pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; - pStream->total_in += (mz_uint)in_bytes; pStream->adler = tdefl_get_adler32((tdefl_compressor*)pStream->state); + defl_status = tdefl_compress((tdefl_compressor*)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, + &out_bytes, (tdefl_flush)flush); + pStream->next_in += (mz_uint)in_bytes; + pStream->avail_in -= (mz_uint)in_bytes; + pStream->total_in += (mz_uint)in_bytes; + pStream->adler = tdefl_get_adler32((tdefl_compressor*)pStream->state); - pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes; - pStream->total_out += (mz_uint)out_bytes; + pStream->next_out += (mz_uint)out_bytes; + pStream->avail_out -= (mz_uint)out_bytes; + pStream->total_out += (mz_uint)out_bytes; - if (defl_status < 0) - { - mz_status = MZ_STREAM_ERROR; - break; - } - else if (defl_status == TDEFL_STATUS_DONE) - { - mz_status = MZ_STREAM_END; - break; - } - else if (!pStream->avail_out) - break; - else if ((!pStream->avail_in) && (flush != MZ_FINISH)) - { - if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out)) - break; - return MZ_BUF_ERROR; // Can't make forward progress without some input. - } - } - return mz_status; + if (defl_status < 0) + { + mz_status = MZ_STREAM_ERROR; + break; + } + else if (defl_status == TDEFL_STATUS_DONE) + { + mz_status = MZ_STREAM_END; + break; + } + else if (!pStream->avail_out) + break; + else if ((!pStream->avail_in) && (flush != MZ_FINISH)) + { + if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out)) + break; + return MZ_BUF_ERROR; // Can't make forward progress without some input. + } + } + return mz_status; } int mz_deflateEnd(mz_streamp pStream) { - if (!pStream) return MZ_STREAM_ERROR; - if (pStream->state) - { - pStream->zfree(pStream->opaque, pStream->state); - pStream->state = NULL; - } - return MZ_OK; + if (!pStream) return MZ_STREAM_ERROR; + if (pStream->state) + { + pStream->zfree(pStream->opaque, pStream->state); + pStream->state = NULL; + } + return MZ_OK; } mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len) { - (void)pStream; - // This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.) - return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5); + (void)pStream; + // This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.) + return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5); } -int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level) +int mz_compress2(unsigned char* pDest, mz_ulong* pDest_len, const unsigned char* pSource, mz_ulong source_len, + int level) { - int status; - mz_stream stream; - memset(&stream, 0, sizeof(stream)); + int status; + mz_stream stream; + memset(&stream, 0, sizeof(stream)); - // In case mz_ulong is 64-bits (argh I hate longs). - if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR; + // In case mz_ulong is 64-bits (argh I hate longs). + if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR; - stream.next_in = pSource; - stream.avail_in = (mz_uint32)source_len; - stream.next_out = pDest; - stream.avail_out = (mz_uint32)*pDest_len; + stream.next_in = pSource; + stream.avail_in = (mz_uint32)source_len; + stream.next_out = pDest; + stream.avail_out = (mz_uint32)*pDest_len; - status = mz_deflateInit(&stream, level); - if (status != MZ_OK) return status; + status = mz_deflateInit(&stream, level); + if (status != MZ_OK) return status; - status = mz_deflate(&stream, MZ_FINISH); - if (status != MZ_STREAM_END) - { - mz_deflateEnd(&stream); - return (status == MZ_OK) ? MZ_BUF_ERROR : status; - } + status = mz_deflate(&stream, MZ_FINISH); + if (status != MZ_STREAM_END) + { + mz_deflateEnd(&stream); + return (status == MZ_OK) ? MZ_BUF_ERROR : status; + } - *pDest_len = stream.total_out; - return mz_deflateEnd(&stream); + *pDest_len = stream.total_out; + return mz_deflateEnd(&stream); } -int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len) +int mz_compress(unsigned char* pDest, mz_ulong* pDest_len, const unsigned char* pSource, mz_ulong source_len) { - return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION); + return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION); } mz_ulong mz_compressBound(mz_ulong source_len) { - return mz_deflateBound(NULL, source_len); + return mz_deflateBound(NULL, source_len); } typedef struct { - tinfl_decompressor m_decomp; - mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed; int m_window_bits; - mz_uint8 m_dict[TINFL_LZ_DICT_SIZE]; - tinfl_status m_last_status; + tinfl_decompressor m_decomp; + mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed; + int m_window_bits; + mz_uint8 m_dict[TINFL_LZ_DICT_SIZE]; + tinfl_status m_last_status; } inflate_state; int mz_inflateInit2(mz_streamp pStream, int window_bits) { - inflate_state *pDecomp; - if (!pStream) return MZ_STREAM_ERROR; - if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)) return MZ_PARAM_ERROR; + inflate_state* pDecomp; + if (!pStream) return MZ_STREAM_ERROR; + if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)) return MZ_PARAM_ERROR; - pStream->data_type = 0; - pStream->adler = 0; - pStream->msg = NULL; - pStream->total_in = 0; - pStream->total_out = 0; - pStream->reserved = 0; - if (!pStream->zalloc) pStream->zalloc = def_alloc_func; - if (!pStream->zfree) pStream->zfree = def_free_func; + pStream->data_type = 0; + pStream->adler = 0; + pStream->msg = NULL; + pStream->total_in = 0; + pStream->total_out = 0; + pStream->reserved = 0; + if (!pStream->zalloc) pStream->zalloc = def_alloc_func; + if (!pStream->zfree) pStream->zfree = def_free_func; - pDecomp = (inflate_state*)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state)); - if (!pDecomp) return MZ_MEM_ERROR; + pDecomp = (inflate_state*)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state)); + if (!pDecomp) return MZ_MEM_ERROR; - pStream->state = (struct mz_internal_state *)pDecomp; + pStream->state = (struct mz_internal_state*)pDecomp; - tinfl_init(&pDecomp->m_decomp); - pDecomp->m_dict_ofs = 0; - pDecomp->m_dict_avail = 0; - pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT; - pDecomp->m_first_call = 1; - pDecomp->m_has_flushed = 0; - pDecomp->m_window_bits = window_bits; + tinfl_init(&pDecomp->m_decomp); + pDecomp->m_dict_ofs = 0; + pDecomp->m_dict_avail = 0; + pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT; + pDecomp->m_first_call = 1; + pDecomp->m_has_flushed = 0; + pDecomp->m_window_bits = window_bits; - return MZ_OK; + return MZ_OK; } int mz_inflateInit(mz_streamp pStream) { - return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS); + return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS); } int mz_inflate(mz_streamp pStream, int flush) { - inflate_state* pState; - mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32; - size_t in_bytes, out_bytes, orig_avail_in; - tinfl_status status; + inflate_state* pState; + mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32; + size_t in_bytes, out_bytes, orig_avail_in; + tinfl_status status; - if ((!pStream) || (!pStream->state)) return MZ_STREAM_ERROR; - if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH; - if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH)) return MZ_STREAM_ERROR; + if ((!pStream) || (!pStream->state)) return MZ_STREAM_ERROR; + if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH; + if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH)) return MZ_STREAM_ERROR; - pState = (inflate_state*)pStream->state; - if (pState->m_window_bits > 0) decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER; - orig_avail_in = pStream->avail_in; + pState = (inflate_state*)pStream->state; + if (pState->m_window_bits > 0) decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER; + orig_avail_in = pStream->avail_in; - first_call = pState->m_first_call; pState->m_first_call = 0; - if (pState->m_last_status < 0) return MZ_DATA_ERROR; + first_call = pState->m_first_call; + pState->m_first_call = 0; + if (pState->m_last_status < 0) return MZ_DATA_ERROR; - if (pState->m_has_flushed && (flush != MZ_FINISH)) return MZ_STREAM_ERROR; - pState->m_has_flushed |= (flush == MZ_FINISH); + if (pState->m_has_flushed && (flush != MZ_FINISH)) return MZ_STREAM_ERROR; + pState->m_has_flushed |= (flush == MZ_FINISH); - if ((flush == MZ_FINISH) && (first_call)) - { - // MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file. - decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF; - in_bytes = pStream->avail_in; out_bytes = pStream->avail_out; - status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags); - pState->m_last_status = status; - pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; pStream->total_in += (mz_uint)in_bytes; - pStream->adler = tinfl_get_adler32(&pState->m_decomp); - pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes; pStream->total_out += (mz_uint)out_bytes; + if ((flush == MZ_FINISH) && (first_call)) + { + // MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file. + decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF; + in_bytes = pStream->avail_in; + out_bytes = pStream->avail_out; + status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, + &out_bytes, decomp_flags); + pState->m_last_status = status; + pStream->next_in += (mz_uint)in_bytes; + pStream->avail_in -= (mz_uint)in_bytes; + pStream->total_in += (mz_uint)in_bytes; + pStream->adler = tinfl_get_adler32(&pState->m_decomp); + pStream->next_out += (mz_uint)out_bytes; + pStream->avail_out -= (mz_uint)out_bytes; + pStream->total_out += (mz_uint)out_bytes; - if (status < 0) - return MZ_DATA_ERROR; - else if (status != TINFL_STATUS_DONE) - { - pState->m_last_status = TINFL_STATUS_FAILED; - return MZ_BUF_ERROR; - } - return MZ_STREAM_END; - } - // flush != MZ_FINISH then we must assume there's more input. - if (flush != MZ_FINISH) decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT; + if (status < 0) + return MZ_DATA_ERROR; + else if (status != TINFL_STATUS_DONE) + { + pState->m_last_status = TINFL_STATUS_FAILED; + return MZ_BUF_ERROR; + } + return MZ_STREAM_END; + } + // flush != MZ_FINISH then we must assume there's more input. + if (flush != MZ_FINISH) decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT; - if (pState->m_dict_avail) - { - n = MZ_MIN(pState->m_dict_avail, pStream->avail_out); - memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); - pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n; - pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1); - return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK; - } + if (pState->m_dict_avail) + { + n = MZ_MIN(pState->m_dict_avail, pStream->avail_out); + memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); + pStream->next_out += n; + pStream->avail_out -= n; + pStream->total_out += n; + pState->m_dict_avail -= n; + pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1); + return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK; + } - for ( ; ; ) - { - in_bytes = pStream->avail_in; - out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs; + for (; ;) + { + in_bytes = pStream->avail_in; + out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs; - status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags); - pState->m_last_status = status; + status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, + pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags); + pState->m_last_status = status; - pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; - pStream->total_in += (mz_uint)in_bytes; pStream->adler = tinfl_get_adler32(&pState->m_decomp); + pStream->next_in += (mz_uint)in_bytes; + pStream->avail_in -= (mz_uint)in_bytes; + pStream->total_in += (mz_uint)in_bytes; + pStream->adler = tinfl_get_adler32(&pState->m_decomp); - pState->m_dict_avail = (mz_uint)out_bytes; + pState->m_dict_avail = (mz_uint)out_bytes; - n = MZ_MIN(pState->m_dict_avail, pStream->avail_out); - memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); - pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n; - pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1); + n = MZ_MIN(pState->m_dict_avail, pStream->avail_out); + memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); + pStream->next_out += n; + pStream->avail_out -= n; + pStream->total_out += n; + pState->m_dict_avail -= n; + pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1); - if (status < 0) - return MZ_DATA_ERROR; // Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well). - else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in)) - return MZ_BUF_ERROR; // Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH. - else if (flush == MZ_FINISH) - { - // The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH. - if (status == TINFL_STATUS_DONE) - return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END; - // status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong. - else if (!pStream->avail_out) - return MZ_BUF_ERROR; - } - else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail)) - break; - } + if (status < 0) + return MZ_DATA_ERROR; + // Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well). + else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in)) + return MZ_BUF_ERROR; + // Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH. + else if (flush == MZ_FINISH) + { + // The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH. + if (status == TINFL_STATUS_DONE) + return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END; + // status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong. + else if (!pStream->avail_out) + return MZ_BUF_ERROR; + } + else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail)) + break; + } - return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK; + return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK; } int mz_inflateEnd(mz_streamp pStream) { - if (!pStream) - return MZ_STREAM_ERROR; - if (pStream->state) - { - pStream->zfree(pStream->opaque, pStream->state); - pStream->state = NULL; - } - return MZ_OK; + if (!pStream) + return MZ_STREAM_ERROR; + if (pStream->state) + { + pStream->zfree(pStream->opaque, pStream->state); + pStream->state = NULL; + } + return MZ_OK; } -int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len) +int mz_uncompress(unsigned char* pDest, mz_ulong* pDest_len, const unsigned char* pSource, mz_ulong source_len) { - mz_stream stream; - int status; - memset(&stream, 0, sizeof(stream)); + mz_stream stream; + int status; + memset(&stream, 0, sizeof(stream)); - // In case mz_ulong is 64-bits (argh I hate longs). - if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR; + // In case mz_ulong is 64-bits (argh I hate longs). + if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR; - stream.next_in = pSource; - stream.avail_in = (mz_uint32)source_len; - stream.next_out = pDest; - stream.avail_out = (mz_uint32)*pDest_len; + stream.next_in = pSource; + stream.avail_in = (mz_uint32)source_len; + stream.next_out = pDest; + stream.avail_out = (mz_uint32)*pDest_len; - status = mz_inflateInit(&stream); - if (status != MZ_OK) - return status; + status = mz_inflateInit(&stream); + if (status != MZ_OK) + return status; - status = mz_inflate(&stream, MZ_FINISH); - if (status != MZ_STREAM_END) - { - mz_inflateEnd(&stream); - return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status; - } - *pDest_len = stream.total_out; + status = mz_inflate(&stream, MZ_FINISH); + if (status != MZ_STREAM_END) + { + mz_inflateEnd(&stream); + return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status; + } + *pDest_len = stream.total_out; - return mz_inflateEnd(&stream); + return mz_inflateEnd(&stream); } -const char *mz_error(int err) +const char* mz_error(int err) { - static struct { int m_err; const char *m_pDesc; } s_error_descs[] = - { - { MZ_OK, "" }, { MZ_STREAM_END, "stream end" }, { MZ_NEED_DICT, "need dictionary" }, { MZ_ERRNO, "file error" }, { MZ_STREAM_ERROR, "stream error" }, - { MZ_DATA_ERROR, "data error" }, { MZ_MEM_ERROR, "out of memory" }, { MZ_BUF_ERROR, "buf error" }, { MZ_VERSION_ERROR, "version error" }, { MZ_PARAM_ERROR, "parameter error" } - }; - mz_uint i; for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i) if (s_error_descs[i].m_err == err) return s_error_descs[i].m_pDesc; - return NULL; + static struct + { + int m_err; + const char* m_pDesc; + } s_error_descs[] = + { + {MZ_OK, ""}, {MZ_STREAM_END, "stream end"}, {MZ_NEED_DICT, "need dictionary"}, {MZ_ERRNO, "file error"}, + {MZ_STREAM_ERROR, "stream error"}, + {MZ_DATA_ERROR, "data error"}, {MZ_MEM_ERROR, "out of memory"}, {MZ_BUF_ERROR, "buf error"}, + {MZ_VERSION_ERROR, "version error"}, {MZ_PARAM_ERROR, "parameter error"} + }; + mz_uint i; + for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i) if (s_error_descs[i].m_err == err) return + s_error_descs[i].m_pDesc; + return NULL; } #endif //MINIZ_NO_ZLIB_APIS @@ -655,485 +724,769 @@ const char *mz_error(int err) code_len = TINFL_FAST_LOOKUP_BITS; do { temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; } while (temp < 0); \ } sym = temp; bit_buf >>= code_len; num_bits -= code_len; } MZ_MACRO_END -tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags) +tinfl_status tinfl_decompress(tinfl_decompressor* r, const mz_uint8* pIn_buf_next, size_t* pIn_buf_size, + mz_uint8* pOut_buf_start, mz_uint8* pOut_buf_next, size_t* pOut_buf_size, + const mz_uint32 decomp_flags) { - static const int s_length_base[31] = { 3,4,5,6,7,8,9,10,11,13, 15,17,19,23,27,31,35,43,51,59, 67,83,99,115,131,163,195,227,258,0,0 }; - static const int s_length_extra[31]= { 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; - static const int s_dist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, 257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; - static const int s_dist_extra[32] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; - static const mz_uint8 s_length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; - static const int s_min_table_sizes[3] = { 257, 1, 4 }; + static const int s_length_base[31] = { + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, + 0, 0 + }; + static const int s_length_extra[31] = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0 + }; + static const int s_dist_base[32] = { + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0 + }; + static const int s_dist_extra[32] = { + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 + }; + static const mz_uint8 s_length_dezigzag[19] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + static const int s_min_table_sizes[3] = {257, 1, 4}; - tinfl_status status = TINFL_STATUS_FAILED; mz_uint32 num_bits, dist, counter, num_extra; tinfl_bit_buf_t bit_buf; - const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size; - mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size; - size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start; + tinfl_status status = TINFL_STATUS_FAILED; + mz_uint32 num_bits, dist, counter, num_extra; + tinfl_bit_buf_t bit_buf; + const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size; + mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size; + size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) + ? (size_t)-1 + : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start; - // Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter). - if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start)) { *pIn_buf_size = *pOut_buf_size = 0; return TINFL_STATUS_BAD_PARAM; } + // Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter). + if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start)) + { + *pIn_buf_size = *pOut_buf_size = 0; + return TINFL_STATUS_BAD_PARAM; + } - num_bits = r->m_num_bits; bit_buf = r->m_bit_buf; dist = r->m_dist; counter = r->m_counter; num_extra = r->m_num_extra; dist_from_out_buf_start = r->m_dist_from_out_buf_start; - TINFL_CR_BEGIN + num_bits = r->m_num_bits; + bit_buf = r->m_bit_buf; + dist = r->m_dist; + counter = r->m_counter; + num_extra = r->m_num_extra; + dist_from_out_buf_start = r->m_dist_from_out_buf_start; + TINFL_CR_BEGIN - bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0; r->m_z_adler32 = r->m_check_adler32 = 1; - if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) - { - TINFL_GET_BYTE(1, r->m_zhdr0); TINFL_GET_BYTE(2, r->m_zhdr1); - counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8)); - if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (unsigned int)(1U << (8U + (r->m_zhdr0 >> 4))))); - if (counter) { TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); } - } + bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0; + r->m_z_adler32 = r->m_check_adler32 = 1; + if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) + { + TINFL_GET_BYTE(1, r->m_zhdr0); + TINFL_GET_BYTE(2, r->m_zhdr1); + counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8)); + if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > + 32768U) || ((out_buf_size_mask + 1) < (unsigned int)(1U << (8U + (r->m_zhdr0 >> 4))))); + if (counter) { TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); } + } - do - { - TINFL_GET_BITS(3, r->m_final, 3); r->m_type = r->m_final >> 1; - if (r->m_type == 0) - { - TINFL_SKIP_BITS(5, num_bits & 7); - for (counter = 0; counter < 4; ++counter) { if (num_bits) TINFL_GET_BITS(6, r->m_raw_header[counter], 8); else TINFL_GET_BYTE(7, r->m_raw_header[counter]); } - if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) { TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED); } - while ((counter) && (num_bits)) - { - TINFL_GET_BITS(51, dist, 8); - while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); } - *pOut_buf_cur++ = (mz_uint8)dist; - counter--; - } - while (counter) - { - size_t n; while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); } - while (pIn_buf_cur >= pIn_buf_end) - { - if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) - { - TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT); - } - else - { - TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED); - } - } - n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter); - TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); pIn_buf_cur += n; pOut_buf_cur += n; counter -= (mz_uint)n; - } - } - else if (r->m_type == 3) - { - TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED); - } - else - { - if (r->m_type == 1) - { - mz_uint8 *p = r->m_tables[0].m_code_size; mz_uint i; - r->m_table_sizes[0] = 288; r->m_table_sizes[1] = 32; TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32); - for ( i = 0; i <= 143; ++i) *p++ = 8; - for ( ; i <= 255; ++i) *p++ = 9; - for ( ; i <= 279; ++i) *p++ = 7; - for ( ; i <= 287; ++i) *p++ = 8; - } - else - { - for (counter = 0; counter < 3; counter++) { TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); r->m_table_sizes[counter] += s_min_table_sizes[counter]; } - MZ_CLEAR_OBJ(r->m_tables[2].m_code_size); for (counter = 0; counter < r->m_table_sizes[2]; counter++) { mz_uint s; TINFL_GET_BITS(14, s, 3); r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; } - r->m_table_sizes[2] = 19; - } - for ( ; (int)r->m_type >= 0; r->m_type--) - { - int tree_next, tree_cur; tinfl_huff_table *pTable; - mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; pTable = &r->m_tables[r->m_type]; MZ_CLEAR_OBJ(total_syms); MZ_CLEAR_OBJ(pTable->m_look_up); MZ_CLEAR_OBJ(pTable->m_tree); - for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) total_syms[pTable->m_code_size[i]]++; - used_syms = 0, total = 0; next_code[0] = next_code[1] = 0; - for (i = 1; i <= 15; ++i) { used_syms += total_syms[i]; next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); } - if ((65536 != total) && (used_syms > 1)) - { - TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED); - } - for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index) - { - mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index]; if (!code_size) continue; - cur_code = next_code[code_size]++; for (l = code_size; l > 0; l--, cur_code >>= 1) rev_code = (rev_code << 1) | (cur_code & 1); - if (code_size <= TINFL_FAST_LOOKUP_BITS) { mz_int16 k = (mz_int16)((code_size << 9) | sym_index); while (rev_code < TINFL_FAST_LOOKUP_SIZE) { pTable->m_look_up[rev_code] = k; rev_code += (1 << code_size); } continue; } - if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)])) { pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } - rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1); - for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--) - { - tree_cur -= ((rev_code >>= 1) & 1); - if (!pTable->m_tree[-tree_cur - 1]) { pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } else tree_cur = pTable->m_tree[-tree_cur - 1]; - } - tree_cur -= ((rev_code >>= 1) & 1); pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index; - } - if (r->m_type == 2) - { - for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]); ) - { - mz_uint s; TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]); if (dist < 16) { r->m_len_codes[counter++] = (mz_uint8)dist; continue; } - if ((dist == 16) && (!counter)) - { - TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED); - } - num_extra = "\02\03\07"[dist - 16]; TINFL_GET_BITS(18, s, num_extra); s += "\03\03\013"[dist - 16]; - TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); counter += s; - } - if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter) - { - TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED); - } - TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]); TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]); - } - } - for ( ; ; ) - { - mz_uint8 *pSrc; - for ( ; ; ) - { - if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2)) - { - TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]); - if (counter >= 256) - break; - while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); } - *pOut_buf_cur++ = (mz_uint8)counter; - } - else - { - int sym2; mz_uint code_len; + do + { + TINFL_GET_BITS(3, r->m_final, 3); + r->m_type = r->m_final >> 1; + if (r->m_type == 0) + { + TINFL_SKIP_BITS(5, num_bits & 7); + for (counter = 0; counter < 4; ++counter) + { + if (num_bits) + TINFL_GET_BITS(6, r->m_raw_header[counter], 8); + else + TINFL_GET_BYTE(7, r->m_raw_header[counter]); + } + if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | + (r->m_raw_header[3] << 8)))) { TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED); } + while ((counter) && (num_bits)) + { + TINFL_GET_BITS(51, dist, 8); + while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); } + *pOut_buf_cur++ = (mz_uint8)dist; + counter--; + } + while (counter) + { + size_t n; + while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); } + while (pIn_buf_cur >= pIn_buf_end) + { + if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) + { + TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT); + } + else + { + TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED); + } + } + n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter); + TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); + pIn_buf_cur += n; + pOut_buf_cur += n; + counter -= (mz_uint)n; + } + } + else if (r->m_type == 3) + { + TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED); + } + else + { + if (r->m_type == 1) + { + mz_uint8* p = r->m_tables[0].m_code_size; + mz_uint i; + r->m_table_sizes[0] = 288; + r->m_table_sizes[1] = 32; + TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32); + for (i = 0; i <= 143; ++i) *p++ = 8; + for (; i <= 255; ++i) *p++ = 9; + for (; i <= 279; ++i) *p++ = 7; + for (; i <= 287; ++i) *p++ = 8; + } + else + { + for (counter = 0; counter < 3; counter++) + { + TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); + r->m_table_sizes[counter] += s_min_table_sizes[counter]; + } + MZ_CLEAR_OBJ(r->m_tables[2].m_code_size); + for (counter = 0; counter < r->m_table_sizes[2]; counter++) + { + mz_uint s; + TINFL_GET_BITS(14, s, 3); + r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; + } + r->m_table_sizes[2] = 19; + } + for (; (int)r->m_type >= 0; r->m_type--) + { + int tree_next, tree_cur; + tinfl_huff_table* pTable; + mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; + pTable = &r->m_tables[r->m_type]; + MZ_CLEAR_OBJ(total_syms); + MZ_CLEAR_OBJ(pTable->m_look_up); + MZ_CLEAR_OBJ(pTable->m_tree); + for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) total_syms[pTable->m_code_size[i]]++; + used_syms = 0, total = 0; + next_code[0] = next_code[1] = 0; + for (i = 1; i <= 15; ++i) + { + used_syms += total_syms[i]; + next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); + } + if ((65536 != total) && (used_syms > 1)) + { + TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED); + } + for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index) + { + mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index]; + if (!code_size) continue; + cur_code = next_code[code_size]++; + for (l = code_size; l > 0; l--, cur_code >>= 1) rev_code = (rev_code << 1) | (cur_code & 1); + if (code_size <= TINFL_FAST_LOOKUP_BITS) + { + mz_int16 k = (mz_int16)((code_size << 9) | sym_index); + while (rev_code < TINFL_FAST_LOOKUP_SIZE) + { + pTable->m_look_up[rev_code] = k; + rev_code += (1 << code_size); + } + continue; + } + if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)])) + { + pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next; + tree_cur = tree_next; + tree_next -= 2; + } + rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1); + for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--) + { + tree_cur -= ((rev_code >>= 1) & 1); + if (!pTable->m_tree[-tree_cur - 1]) + { + pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next; + tree_cur = tree_next; + tree_next -= 2; + } + else tree_cur = pTable->m_tree[-tree_cur - 1]; + } + tree_cur -= ((rev_code >>= 1) & 1); + pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index; + } + if (r->m_type == 2) + { + for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]);) + { + mz_uint s; + TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]); + if (dist < 16) + { + r->m_len_codes[counter++] = (mz_uint8)dist; + continue; + } + if ((dist == 16) && (!counter)) + { + TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED); + } + num_extra = "\02\03\07"[dist - 16]; + TINFL_GET_BITS(18, s, num_extra); + s += "\03\03\013"[dist - 16]; + TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); + counter += s; + } + if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter) + { + TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED); + } + TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]); + TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]); + } + } + for (; ;) + { + mz_uint8* pSrc; + for (; ;) + { + if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2)) + { + TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]); + if (counter >= 256) + break; + while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); } + *pOut_buf_cur++ = (mz_uint8)counter; + } + else + { + int sym2; + mz_uint code_len; #if TINFL_USE_64BIT_BITBUF - if (num_bits < 30) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits); pIn_buf_cur += 4; num_bits += 32; } + if (num_bits < 30) + { + bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits); + pIn_buf_cur += 4; + num_bits += 32; + } #else if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; } #endif - if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) - code_len = sym2 >> 9; - else - { - code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0); - } - counter = sym2; bit_buf >>= code_len; num_bits -= code_len; - if (counter & 256) - break; + if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) + code_len = sym2 >> 9; + else + { + code_len = TINFL_FAST_LOOKUP_BITS; + do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } + while (sym2 < 0); + } + counter = sym2; + bit_buf >>= code_len; + num_bits -= code_len; + if (counter & 256) + break; #if !TINFL_USE_64BIT_BITBUF if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; } #endif - if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) - code_len = sym2 >> 9; - else - { - code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0); - } - bit_buf >>= code_len; num_bits -= code_len; + if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) + code_len = sym2 >> 9; + else + { + code_len = TINFL_FAST_LOOKUP_BITS; + do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } + while (sym2 < 0); + } + bit_buf >>= code_len; + num_bits -= code_len; - pOut_buf_cur[0] = (mz_uint8)counter; - if (sym2 & 256) - { - pOut_buf_cur++; - counter = sym2; - break; - } - pOut_buf_cur[1] = (mz_uint8)sym2; - pOut_buf_cur += 2; - } - } - if ((counter &= 511) == 256) break; + pOut_buf_cur[0] = (mz_uint8)counter; + if (sym2 & 256) + { + pOut_buf_cur++; + counter = sym2; + break; + } + pOut_buf_cur[1] = (mz_uint8)sym2; + pOut_buf_cur += 2; + } + } + if ((counter &= 511) == 256) break; - num_extra = s_length_extra[counter - 257]; counter = s_length_base[counter - 257]; - if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(25, extra_bits, num_extra); counter += extra_bits; } + num_extra = s_length_extra[counter - 257]; + counter = s_length_base[counter - 257]; + if (num_extra) + { + mz_uint extra_bits; + TINFL_GET_BITS(25, extra_bits, num_extra); + counter += extra_bits; + } - TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]); - num_extra = s_dist_extra[dist]; dist = s_dist_base[dist]; - if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(27, extra_bits, num_extra); dist += extra_bits; } + TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]); + num_extra = s_dist_extra[dist]; + dist = s_dist_base[dist]; + if (num_extra) + { + mz_uint extra_bits; + TINFL_GET_BITS(27, extra_bits, num_extra); + dist += extra_bits; + } - dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start; - if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) - { - TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED); - } + dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start; + if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) + { + TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED); + } - pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask); + pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask); - if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end) - { - while (counter--) - { - while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); } - *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask]; - } - continue; - } + if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end) + { + while (counter--) + { + while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); } + *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask]; + } + continue; + } #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES - else if ((counter >= 9) && (counter <= dist)) - { - const mz_uint8 *pSrc_end = pSrc + (counter & ~7); - do - { - ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0]; - ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1]; - pOut_buf_cur += 8; - } while ((pSrc += 8) < pSrc_end); - if ((counter &= 7) < 3) - { - if (counter) - { - pOut_buf_cur[0] = pSrc[0]; - if (counter > 1) - pOut_buf_cur[1] = pSrc[1]; - pOut_buf_cur += counter; - } - continue; - } - } + else if ((counter >= 9) && (counter <= dist)) + { + const mz_uint8* pSrc_end = pSrc + (counter & ~7); + do + { + ((mz_uint32*)pOut_buf_cur)[0] = ((const mz_uint32*)pSrc)[0]; + ((mz_uint32*)pOut_buf_cur)[1] = ((const mz_uint32*)pSrc)[1]; + pOut_buf_cur += 8; + } + while ((pSrc += 8) < pSrc_end); + if ((counter &= 7) < 3) + { + if (counter) + { + pOut_buf_cur[0] = pSrc[0]; + if (counter > 1) + pOut_buf_cur[1] = pSrc[1]; + pOut_buf_cur += counter; + } + continue; + } + } #endif - do - { - pOut_buf_cur[0] = pSrc[0]; - pOut_buf_cur[1] = pSrc[1]; - pOut_buf_cur[2] = pSrc[2]; - pOut_buf_cur += 3; pSrc += 3; - } while ((int)(counter -= 3) > 2); - if ((int)counter > 0) - { - pOut_buf_cur[0] = pSrc[0]; - if ((int)counter > 1) - pOut_buf_cur[1] = pSrc[1]; - pOut_buf_cur += counter; - } - } - } - } while (!(r->m_final & 1)); - if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) - { - TINFL_SKIP_BITS(32, num_bits & 7); for (counter = 0; counter < 4; ++counter) { mz_uint s; if (num_bits) TINFL_GET_BITS(41, s, 8); else TINFL_GET_BYTE(42, s); r->m_z_adler32 = (r->m_z_adler32 << 8) | s; } - } - TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE); - TINFL_CR_FINISH + do + { + pOut_buf_cur[0] = pSrc[0]; + pOut_buf_cur[1] = pSrc[1]; + pOut_buf_cur[2] = pSrc[2]; + pOut_buf_cur += 3; + pSrc += 3; + } + while ((int)(counter -= 3) > 2); + if ((int)counter > 0) + { + pOut_buf_cur[0] = pSrc[0]; + if ((int)counter > 1) + pOut_buf_cur[1] = pSrc[1]; + pOut_buf_cur += counter; + } + } + } + } + while (!(r->m_final & 1)); + if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) + { + TINFL_SKIP_BITS(32, num_bits & 7); + for (counter = 0; counter < 4; ++counter) + { + mz_uint s; + if (num_bits) + TINFL_GET_BITS(41, s, 8); + else + TINFL_GET_BYTE(42, s); + r->m_z_adler32 = (r->m_z_adler32 << 8) | s; + } + } + TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE); + TINFL_CR_FINISH common_exit: - r->m_num_bits = num_bits; r->m_bit_buf = bit_buf; r->m_dist = dist; r->m_counter = counter; r->m_num_extra = num_extra; r->m_dist_from_out_buf_start = dist_from_out_buf_start; - *pIn_buf_size = pIn_buf_cur - pIn_buf_next; *pOut_buf_size = pOut_buf_cur - pOut_buf_next; - if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0)) - { - const mz_uint8 *ptr = pOut_buf_next; size_t buf_len = *pOut_buf_size; - mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; size_t block_len = buf_len % 5552; - while (buf_len) - { - for (i = 0; i + 7 < block_len; i += 8, ptr += 8) - { - s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1; - s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1; - } - for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1; - s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552; - } - r->m_check_adler32 = (s2 << 16) + s1; if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32)) status = TINFL_STATUS_ADLER32_MISMATCH; - } - return status; + r->m_num_bits = num_bits; + r->m_bit_buf = bit_buf; + r->m_dist = dist; + r->m_counter = counter; + r->m_num_extra = num_extra; + r->m_dist_from_out_buf_start = dist_from_out_buf_start; + *pIn_buf_size = pIn_buf_cur - pIn_buf_next; + *pOut_buf_size = pOut_buf_cur - pOut_buf_next; + if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0)) + { + const mz_uint8* ptr = pOut_buf_next; + size_t buf_len = *pOut_buf_size; + mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; + size_t block_len = buf_len % 5552; + while (buf_len) + { + for (i = 0; i + 7 < block_len; i += 8, ptr += 8) + { + s1 += ptr[0], s2 += s1; + s1 += ptr[1], s2 += s1; + s1 += ptr[2], s2 += s1; + s1 += ptr[3], s2 += s1; + s1 += ptr[4], s2 += s1; + s1 += ptr[5], s2 += s1; + s1 += ptr[6], s2 += s1; + s1 += ptr[7], s2 += s1; + } + for (; i < block_len; ++i) s1 += *ptr++, s2 += s1; + s1 %= 65521U, s2 %= 65521U; + buf_len -= block_len; + block_len = 5552; + } + r->m_check_adler32 = (s2 << 16) + s1; + if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r-> + m_z_adler32)) status = TINFL_STATUS_ADLER32_MISMATCH; + } + return status; } // Higher level helper functions. -void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags) +void* tinfl_decompress_mem_to_heap(const void* pSrc_buf, size_t src_buf_len, size_t* pOut_len, int flags) { - tinfl_decompressor decomp; void *pBuf = NULL, *pNew_buf; size_t src_buf_ofs = 0, out_buf_capacity = 0; - *pOut_len = 0; - tinfl_init(&decomp); - for ( ; ; ) - { - size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity; - tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8*)pBuf, pBuf ? (mz_uint8*)pBuf + *pOut_len : NULL, &dst_buf_size, - (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); - if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) - { - MZ_FREE(pBuf); *pOut_len = 0; return NULL; - } - src_buf_ofs += src_buf_size; - *pOut_len += dst_buf_size; - if (status == TINFL_STATUS_DONE) break; - new_out_buf_capacity = out_buf_capacity * 2; if (new_out_buf_capacity < 128) new_out_buf_capacity = 128; - pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity); - if (!pNew_buf) - { - MZ_FREE(pBuf); *pOut_len = 0; return NULL; - } - pBuf = pNew_buf; out_buf_capacity = new_out_buf_capacity; - } - return pBuf; + tinfl_decompressor decomp; + void *pBuf = NULL, *pNew_buf; + size_t src_buf_ofs = 0, out_buf_capacity = 0; + *pOut_len = 0; + tinfl_init(&decomp); + for (; ;) + { + size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, + new_out_buf_capacity; + tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf + src_buf_ofs, &src_buf_size, + (mz_uint8*)pBuf, pBuf ? (mz_uint8*)pBuf + *pOut_len : NULL, &dst_buf_size, + (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | + TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); + if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) + { + MZ_FREE(pBuf); + *pOut_len = 0; + return NULL; + } + src_buf_ofs += src_buf_size; + *pOut_len += dst_buf_size; + if (status == TINFL_STATUS_DONE) break; + new_out_buf_capacity = out_buf_capacity * 2; + if (new_out_buf_capacity < 128) new_out_buf_capacity = 128; + pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity); + if (!pNew_buf) + { + MZ_FREE(pBuf); + *pOut_len = 0; + return NULL; + } + pBuf = pNew_buf; + out_buf_capacity = new_out_buf_capacity; + } + return pBuf; } -size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags) +size_t tinfl_decompress_mem_to_mem(void* pOut_buf, size_t out_buf_len, const void* pSrc_buf, size_t src_buf_len, + int flags) { - tinfl_decompressor decomp; tinfl_status status; tinfl_init(&decomp); - status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf, &src_buf_len, (mz_uint8*)pOut_buf, (mz_uint8*)pOut_buf, &out_buf_len, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); - return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len; + tinfl_decompressor decomp; + tinfl_status status; + tinfl_init(&decomp); + status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf, &src_buf_len, (mz_uint8*)pOut_buf, (mz_uint8*)pOut_buf, + &out_buf_len, + (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); + return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len; } -int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) +int tinfl_decompress_mem_to_callback(const void* pIn_buf, size_t* pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, + void* pPut_buf_user, int flags) { - int result = 0; - tinfl_decompressor decomp; - mz_uint8 *pDict = (mz_uint8*)MZ_MALLOC(TINFL_LZ_DICT_SIZE); size_t in_buf_ofs = 0, dict_ofs = 0; - if (!pDict) - return TINFL_STATUS_FAILED; - tinfl_init(&decomp); - for ( ; ; ) - { - size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs; - tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size, - (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))); - in_buf_ofs += in_buf_size; - if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user))) - break; - if (status != TINFL_STATUS_HAS_MORE_OUTPUT) - { - result = (status == TINFL_STATUS_DONE); - break; - } - dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1); - } - MZ_FREE(pDict); - *pIn_buf_size = in_buf_ofs; - return result; + int result = 0; + tinfl_decompressor decomp; + mz_uint8* pDict = (mz_uint8*)MZ_MALLOC(TINFL_LZ_DICT_SIZE); + size_t in_buf_ofs = 0, dict_ofs = 0; + if (!pDict) + return TINFL_STATUS_FAILED; + tinfl_init(&decomp); + for (; ;) + { + size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs; + tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pIn_buf + in_buf_ofs, &in_buf_size, pDict, + pDict + dict_ofs, &dst_buf_size, + (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | + TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))); + in_buf_ofs += in_buf_size; + if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user))) + break; + if (status != TINFL_STATUS_HAS_MORE_OUTPUT) + { + result = (status == TINFL_STATUS_DONE); + break; + } + dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1); + } + MZ_FREE(pDict); + *pIn_buf_size = in_buf_ofs; + return result; } // ------------------- Low-level Compression (independent from all decompression API's) // Purposely making these tables static for faster init and thread safety. static const mz_uint16 s_tdefl_len_sym[256] = { - 257,258,259,260,261,262,263,264,265,265,266,266,267,267,268,268,269,269,269,269,270,270,270,270,271,271,271,271,272,272,272,272, - 273,273,273,273,273,273,273,273,274,274,274,274,274,274,274,274,275,275,275,275,275,275,275,275,276,276,276,276,276,276,276,276, - 277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278, - 279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280, - 281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281, - 282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282, - 283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283, - 284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,285 }; + 257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, 267, 268, 268, 269, 269, 269, 269, 270, 270, 270, + 270, 271, 271, 271, 271, 272, 272, 272, 272, + 273, 273, 273, 273, 273, 273, 273, 273, 274, 274, 274, 274, 274, 274, 274, 274, 275, 275, 275, 275, 275, 275, 275, + 275, 276, 276, 276, 276, 276, 276, 276, 276, + 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 278, 278, 278, 278, 278, 278, 278, + 278, 278, 278, 278, 278, 278, 278, 278, 278, + 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 280, 280, 280, 280, 280, 280, 280, + 280, 280, 280, 280, 280, 280, 280, 280, 280, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, 282, + 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, + 283, 283, 283, 283, 283, 283, 283, 283, 283, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 285 +}; static const mz_uint8 s_tdefl_len_extra[256] = { - 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0 }; + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0 +}; static const mz_uint8 s_tdefl_small_dist_sym[512] = { - 0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11, - 11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13, - 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14, - 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, - 14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, - 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17 }; + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17 +}; static const mz_uint8 s_tdefl_small_dist_extra[512] = { - 0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7 }; + 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7 +}; static const mz_uint8 s_tdefl_large_dist_sym[128] = { - 0,0,18,19,20,20,21,21,22,22,22,22,23,23,23,23,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28, - 28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29 }; + 0, 0, 18, 19, 20, 20, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, + 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; static const mz_uint8 s_tdefl_large_dist_extra[128] = { - 0,0,8,8,9,9,9,9,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, - 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, - 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13 }; + 0, 0, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13 +}; // Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values. -typedef struct { mz_uint16 m_key, m_sym_index; } tdefl_sym_freq; +typedef struct +{ + mz_uint16 m_key, m_sym_index; +} tdefl_sym_freq; + static tdefl_sym_freq* tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq* pSyms0, tdefl_sym_freq* pSyms1) { - mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2]; tdefl_sym_freq* pCur_syms = pSyms0, *pNew_syms = pSyms1; MZ_CLEAR_OBJ(hist); - for (i = 0; i < num_syms; i++) { mz_uint freq = pSyms0[i].m_key; hist[freq & 0xFF]++; hist[256 + ((freq >> 8) & 0xFF)]++; } - while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) total_passes--; - for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8) - { - const mz_uint32* pHist = &hist[pass << 8]; - mz_uint offsets[256], cur_ofs = 0; - for (i = 0; i < 256; i++) { offsets[i] = cur_ofs; cur_ofs += pHist[i]; } - for (i = 0; i < num_syms; i++) pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i]; - { tdefl_sym_freq* t = pCur_syms; pCur_syms = pNew_syms; pNew_syms = t; } - } - return pCur_syms; + mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2]; + tdefl_sym_freq *pCur_syms = pSyms0, *pNew_syms = pSyms1; + MZ_CLEAR_OBJ(hist); + for (i = 0; i < num_syms; i++) + { + mz_uint freq = pSyms0[i].m_key; + hist[freq & 0xFF]++; + hist[256 + ((freq >> 8) & 0xFF)]++; + } + while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) total_passes--; + for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8) + { + const mz_uint32* pHist = &hist[pass << 8]; + mz_uint offsets[256], cur_ofs = 0; + for (i = 0; i < 256; i++) + { + offsets[i] = cur_ofs; + cur_ofs += pHist[i]; + } + for (i = 0; i < num_syms; i++) pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i]; + { + tdefl_sym_freq* t = pCur_syms; + pCur_syms = pNew_syms; + pNew_syms = t; + } + } + return pCur_syms; } // tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996. -static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n) +static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq* A, int n) { - int root, leaf, next, avbl, used, dpth; - if (n==0) return; else if (n==1) { A[0].m_key = 1; return; } - A[0].m_key += A[1].m_key; root = 0; leaf = 2; - for (next=1; next < n-1; next++) - { - if (leaf>=n || A[root].m_key=n || (root=0; next--) A[next].m_key = A[A[next].m_key].m_key+1; - avbl = 1; used = dpth = 0; root = n-2; next = n-1; - while (avbl>0) - { - while (root>=0 && (int)A[root].m_key==dpth) { used++; root--; } - while (avbl>used) { A[next--].m_key = (mz_uint16)(dpth); avbl--; } - avbl = 2*used; dpth++; used = 0; - } + int root, leaf, next, avbl, used, dpth; + if (n == 0) return; + else if (n == 1) + { + A[0].m_key = 1; + return; + } + A[0].m_key += A[1].m_key; + root = 0; + leaf = 2; + for (next = 1; next < n - 1; next++) + { + if (leaf >= n || A[root].m_key < A[leaf].m_key) + { + A[next].m_key = A[root].m_key; + A[root++].m_key = (mz_uint16)next; + } + else A[next].m_key = A[leaf++].m_key; + if (leaf >= n || (root < next && A[root].m_key < A[leaf].m_key)) + { + A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key); + A[root++].m_key = (mz_uint16)next; + } + else A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key); + } + A[n - 2].m_key = 0; + for (next = n - 3; next >= 0; next--) A[next].m_key = A[A[next].m_key].m_key + 1; + avbl = 1; + used = dpth = 0; + root = n - 2; + next = n - 1; + while (avbl > 0) + { + while (root >= 0 && (int)A[root].m_key == dpth) + { + used++; + root--; + } + while (avbl > used) + { + A[next--].m_key = (mz_uint16)(dpth); + avbl--; + } + avbl = 2 * used; + dpth++; + used = 0; + } } // Limits canonical Huffman code table's max code size. enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 }; -static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size) + +static void tdefl_huffman_enforce_max_code_size(int* pNum_codes, int code_list_len, int max_code_size) { - int i; mz_uint32 total = 0; if (code_list_len <= 1) return; - for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++) pNum_codes[max_code_size] += pNum_codes[i]; - for (i = max_code_size; i > 0; i--) total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i)); - while (total != (1UL << max_code_size)) - { - pNum_codes[max_code_size]--; - for (i = max_code_size - 1; i > 0; i--) if (pNum_codes[i]) { pNum_codes[i]--; pNum_codes[i + 1] += 2; break; } - total--; - } + int i; + mz_uint32 total = 0; + if (code_list_len <= 1) return; + for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++) pNum_codes[max_code_size] += pNum_codes[i]; + for (i = max_code_size; i > 0; i--) total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i)); + while (total != (1UL << max_code_size)) + { + pNum_codes[max_code_size]--; + for (i = max_code_size - 1; i > 0; i--) if (pNum_codes[i]) + { + pNum_codes[i]--; + pNum_codes[i + 1] += 2; + break; + } + total--; + } } -static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table) +static void tdefl_optimize_huffman_table(tdefl_compressor* d, int table_num, int table_len, int code_size_limit, + int static_table) { - int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE]; mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1]; MZ_CLEAR_OBJ(num_codes); - if (static_table) - { - for (i = 0; i < table_len; i++) num_codes[d->m_huff_code_sizes[table_num][i]]++; - } - else - { - tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms; - int num_used_syms = 0; - const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0]; - for (i = 0; i < table_len; i++) if (pSym_count[i]) { syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i]; syms0[num_used_syms++].m_sym_index = (mz_uint16)i; } + int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE]; + mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1]; + MZ_CLEAR_OBJ(num_codes); + if (static_table) + { + for (i = 0; i < table_len; i++) num_codes[d->m_huff_code_sizes[table_num][i]]++; + } + else + { + tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms; + int num_used_syms = 0; + const mz_uint16* pSym_count = &d->m_huff_count[table_num][0]; + for (i = 0; i < table_len; i++) if (pSym_count[i]) + { + syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i]; + syms0[num_used_syms++].m_sym_index = (mz_uint16)i; + } - pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1); tdefl_calculate_minimum_redundancy(pSyms, num_used_syms); + pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1); + tdefl_calculate_minimum_redundancy(pSyms, num_used_syms); - for (i = 0; i < num_used_syms; i++) num_codes[pSyms[i].m_key]++; + for (i = 0; i < num_used_syms; i++) num_codes[pSyms[i].m_key]++; - tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit); + tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit); - MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]); MZ_CLEAR_OBJ(d->m_huff_codes[table_num]); - for (i = 1, j = num_used_syms; i <= code_size_limit; i++) - for (l = num_codes[i]; l > 0; l--) d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i); - } + MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]); + MZ_CLEAR_OBJ(d->m_huff_codes[table_num]); + for (i = 1, j = num_used_syms; i <= code_size_limit; i++) + for (l = num_codes[i]; l > 0; l--) d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i); + } - next_code[1] = 0; for (j = 0, i = 2; i <= code_size_limit; i++) next_code[i] = j = ((j + num_codes[i - 1]) << 1); + next_code[1] = 0; + for (j = 0, i = 2; i <= code_size_limit; i++) next_code[i] = j = ((j + num_codes[i - 1]) << 1); - for (i = 0; i < table_len; i++) - { - mz_uint rev_code = 0, code, code_size; if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) continue; - code = next_code[code_size]++; for (l = code_size; l > 0; l--, code >>= 1) rev_code = (rev_code << 1) | (code & 1); - d->m_huff_codes[table_num][i] = (mz_uint16)rev_code; - } + for (i = 0; i < table_len; i++) + { + mz_uint rev_code = 0, code, code_size; + if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) continue; + code = next_code[code_size]++; + for (l = code_size; l > 0; l--, code >>= 1) rev_code = (rev_code << 1) | (code & 1); + d->m_huff_codes[table_num][i] = (mz_uint16)rev_code; + } } #define TDEFL_PUT_BITS(b, l) do { \ @@ -1164,178 +1517,199 @@ static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1); packed_code_sizes[num_packed_code_sizes++] = 18; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \ } rle_z_count = 0; } } -static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; +static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = { + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 +}; -static void tdefl_start_dynamic_block(tdefl_compressor *d) +static void tdefl_start_dynamic_block(tdefl_compressor* d) { - int num_lit_codes, num_dist_codes, num_bit_lengths; mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index; - mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF; + int num_lit_codes, num_dist_codes, num_bit_lengths; + mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index; + mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], packed_code_sizes[ + TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF; - d->m_huff_count[0][256] = 1; + d->m_huff_count[0][256] = 1; - tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE); - tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE); + tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE); + tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE); - for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--) if (d->m_huff_code_sizes[0][num_lit_codes - 1]) break; - for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--) if (d->m_huff_code_sizes[1][num_dist_codes - 1]) break; + for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--) if (d->m_huff_code_sizes[0][num_lit_codes - 1]) break + ; + for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--) if (d->m_huff_code_sizes[1][num_dist_codes - 1]) + break; - memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes); - memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes); - total_code_sizes_to_pack = num_lit_codes + num_dist_codes; num_packed_code_sizes = 0; rle_z_count = 0; rle_repeat_count = 0; + memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes); + memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes); + total_code_sizes_to_pack = num_lit_codes + num_dist_codes; + num_packed_code_sizes = 0; + rle_z_count = 0; + rle_repeat_count = 0; - memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2); - for (i = 0; i < total_code_sizes_to_pack; i++) - { - mz_uint8 code_size = code_sizes_to_pack[i]; - if (!code_size) - { - TDEFL_RLE_PREV_CODE_SIZE(); - if (++rle_z_count == 138) { TDEFL_RLE_ZERO_CODE_SIZE(); } - } - else - { - TDEFL_RLE_ZERO_CODE_SIZE(); - if (code_size != prev_code_size) - { - TDEFL_RLE_PREV_CODE_SIZE(); - d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1); packed_code_sizes[num_packed_code_sizes++] = code_size; - } - else if (++rle_repeat_count == 6) - { - TDEFL_RLE_PREV_CODE_SIZE(); - } - } - prev_code_size = code_size; - } - if (rle_repeat_count) { TDEFL_RLE_PREV_CODE_SIZE(); } else { TDEFL_RLE_ZERO_CODE_SIZE(); } + memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2); + for (i = 0; i < total_code_sizes_to_pack; i++) + { + mz_uint8 code_size = code_sizes_to_pack[i]; + if (!code_size) + { + TDEFL_RLE_PREV_CODE_SIZE(); + if (++rle_z_count == 138) { TDEFL_RLE_ZERO_CODE_SIZE(); } + } + else + { + TDEFL_RLE_ZERO_CODE_SIZE(); + if (code_size != prev_code_size) + { + TDEFL_RLE_PREV_CODE_SIZE(); + d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1); + packed_code_sizes[num_packed_code_sizes++] = code_size; + } + else if (++rle_repeat_count == 6) + { + TDEFL_RLE_PREV_CODE_SIZE(); + } + } + prev_code_size = code_size; + } + if (rle_repeat_count) { TDEFL_RLE_PREV_CODE_SIZE(); } + else { TDEFL_RLE_ZERO_CODE_SIZE(); } - tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE); + tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE); - TDEFL_PUT_BITS(2, 2); + TDEFL_PUT_BITS(2, 2); - TDEFL_PUT_BITS(num_lit_codes - 257, 5); - TDEFL_PUT_BITS(num_dist_codes - 1, 5); + TDEFL_PUT_BITS(num_lit_codes - 257, 5); + TDEFL_PUT_BITS(num_dist_codes - 1, 5); - for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--) if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]]) break; - num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1)); TDEFL_PUT_BITS(num_bit_lengths - 4, 4); - for (i = 0; (int)i < num_bit_lengths; i++) TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3); + for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--) if (d->m_huff_code_sizes[2][ + s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]]) break; + num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1)); + TDEFL_PUT_BITS(num_bit_lengths - 4, 4); + for (i = 0; (int)i < num_bit_lengths; i++) + TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3); - for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes; ) - { - mz_uint code = packed_code_sizes[packed_code_sizes_index++]; MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2); - TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]); - if (code >= 16) TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]); - } + for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes;) + { + mz_uint code = packed_code_sizes[packed_code_sizes_index++]; + MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2); + TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]); + if (code >= 16) + TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]); + } } -static void tdefl_start_static_block(tdefl_compressor *d) +static void tdefl_start_static_block(tdefl_compressor* d) { - mz_uint i; - mz_uint8 *p = &d->m_huff_code_sizes[0][0]; + mz_uint i; + mz_uint8* p = &d->m_huff_code_sizes[0][0]; - for (i = 0; i <= 143; ++i) *p++ = 8; - for ( ; i <= 255; ++i) *p++ = 9; - for ( ; i <= 279; ++i) *p++ = 7; - for ( ; i <= 287; ++i) *p++ = 8; + for (i = 0; i <= 143; ++i) *p++ = 8; + for (; i <= 255; ++i) *p++ = 9; + for (; i <= 279; ++i) *p++ = 7; + for (; i <= 287; ++i) *p++ = 8; - memset(d->m_huff_code_sizes[1], 5, 32); + memset(d->m_huff_code_sizes[1], 5, 32); - tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE); - tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE); + tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE); + tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE); - TDEFL_PUT_BITS(1, 2); + TDEFL_PUT_BITS(1, 2); } -static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; +static const mz_uint mz_bitmasks[17] = { + 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, + 0x3FFF, 0x7FFF, 0xFFFF +}; #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS -static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) +static mz_bool tdefl_compress_lz_codes(tdefl_compressor* d) { - mz_uint flags; - mz_uint8 *pLZ_codes; - mz_uint8 *pOutput_buf = d->m_pOutput_buf; - mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf; - mz_uint64 bit_buffer = d->m_bit_buffer; - mz_uint bits_in = d->m_bits_in; + mz_uint flags; + mz_uint8* pLZ_codes; + mz_uint8* pOutput_buf = d->m_pOutput_buf; + mz_uint8* pLZ_code_buf_end = d->m_pLZ_code_buf; + mz_uint64 bit_buffer = d->m_bit_buffer; + mz_uint bits_in = d->m_bits_in; #define TDEFL_PUT_BITS_FAST(b, l) { bit_buffer |= (((mz_uint64)(b)) << bits_in); bits_in += (l); } - flags = 1; - for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1) - { - if (flags == 1) - flags = *pLZ_codes++ | 0x100; + flags = 1; + for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1) + { + if (flags == 1) + flags = *pLZ_codes++ | 0x100; - if (flags & 1) - { - mz_uint s0, s1, n0, n1, sym, num_extra_bits; - mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1); pLZ_codes += 3; + if (flags & 1) + { + mz_uint s0, s1, n0, n1, sym, num_extra_bits; + mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16*)(pLZ_codes + 1); + pLZ_codes += 3; - MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); - TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]); + MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], + d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); + TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]); - // This sequence coaxes MSVC into using cmov's vs. jmp's. - s0 = s_tdefl_small_dist_sym[match_dist & 511]; - n0 = s_tdefl_small_dist_extra[match_dist & 511]; - s1 = s_tdefl_large_dist_sym[match_dist >> 8]; - n1 = s_tdefl_large_dist_extra[match_dist >> 8]; - sym = (match_dist < 512) ? s0 : s1; - num_extra_bits = (match_dist < 512) ? n0 : n1; + // This sequence coaxes MSVC into using cmov's vs. jmp's. + s0 = s_tdefl_small_dist_sym[match_dist & 511]; + n0 = s_tdefl_small_dist_extra[match_dist & 511]; + s1 = s_tdefl_large_dist_sym[match_dist >> 8]; + n1 = s_tdefl_large_dist_extra[match_dist >> 8]; + sym = (match_dist < 512) ? s0 : s1; + num_extra_bits = (match_dist < 512) ? n0 : n1; - MZ_ASSERT(d->m_huff_code_sizes[1][sym]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]); - TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits); - } - else - { - mz_uint lit = *pLZ_codes++; - MZ_ASSERT(d->m_huff_code_sizes[0][lit]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + MZ_ASSERT(d->m_huff_code_sizes[1][sym]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]); + TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits); + } + else + { + mz_uint lit = *pLZ_codes++; + MZ_ASSERT(d->m_huff_code_sizes[0][lit]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); - if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) - { - flags >>= 1; - lit = *pLZ_codes++; - MZ_ASSERT(d->m_huff_code_sizes[0][lit]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) + { + flags >>= 1; + lit = *pLZ_codes++; + MZ_ASSERT(d->m_huff_code_sizes[0][lit]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); - if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) - { - flags >>= 1; - lit = *pLZ_codes++; - MZ_ASSERT(d->m_huff_code_sizes[0][lit]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); - } - } - } + if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) + { + flags >>= 1; + lit = *pLZ_codes++; + MZ_ASSERT(d->m_huff_code_sizes[0][lit]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + } + } + } - if (pOutput_buf >= d->m_pOutput_buf_end) - return MZ_FALSE; + if (pOutput_buf >= d->m_pOutput_buf_end) + return MZ_FALSE; - *(mz_uint64*)pOutput_buf = bit_buffer; - pOutput_buf += (bits_in >> 3); - bit_buffer >>= (bits_in & ~7); - bits_in &= 7; - } + *(mz_uint64*)pOutput_buf = bit_buffer; + pOutput_buf += (bits_in >> 3); + bit_buffer >>= (bits_in & ~7); + bits_in &= 7; + } #undef TDEFL_PUT_BITS_FAST - d->m_pOutput_buf = pOutput_buf; - d->m_bits_in = 0; - d->m_bit_buffer = 0; + d->m_pOutput_buf = pOutput_buf; + d->m_bits_in = 0; + d->m_bit_buffer = 0; - while (bits_in) - { - mz_uint32 n = MZ_MIN(bits_in, 16); - TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n); - bit_buffer >>= n; - bits_in -= n; - } + while (bits_in) + { + mz_uint32 n = MZ_MIN(bits_in, 16); + TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n); + bit_buffer >>= n; + bits_in -= n; + } - TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]); + TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]); - return (d->m_pOutput_buf < d->m_pOutput_buf_end); + return (d->m_pOutput_buf < d->m_pOutput_buf_end); } #else static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) @@ -1383,153 +1757,196 @@ static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) } #endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS -static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block) +static mz_bool tdefl_compress_block(tdefl_compressor* d, mz_bool static_block) { - if (static_block) - tdefl_start_static_block(d); - else - tdefl_start_dynamic_block(d); - return tdefl_compress_lz_codes(d); + if (static_block) + tdefl_start_static_block(d); + else + tdefl_start_dynamic_block(d); + return tdefl_compress_lz_codes(d); } -static int tdefl_flush_block(tdefl_compressor *d, int flush) +static int tdefl_flush_block(tdefl_compressor* d, int flush) { - mz_uint saved_bit_buf, saved_bits_in; - mz_uint8 *pSaved_output_buf; - mz_bool comp_block_succeeded = MZ_FALSE; - int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size; - mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs) : d->m_output_buf; + mz_uint saved_bit_buf, saved_bits_in; + mz_uint8* pSaved_output_buf; + mz_bool comp_block_succeeded = MZ_FALSE; + int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d-> + m_lz_code_buf_dict_pos) <= d->m_dict_size; + mz_uint8* pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= + TDEFL_OUT_BUF_SIZE)) + ? ((mz_uint8*)d->m_pOut_buf + d->m_out_buf_ofs) + : d->m_output_buf; - d->m_pOutput_buf = pOutput_buf_start; - d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16; + d->m_pOutput_buf = pOutput_buf_start; + d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16; - MZ_ASSERT(!d->m_output_flush_remaining); - d->m_output_flush_ofs = 0; - d->m_output_flush_remaining = 0; + MZ_ASSERT(!d->m_output_flush_remaining); + d->m_output_flush_ofs = 0; + d->m_output_flush_remaining = 0; - *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left); - d->m_pLZ_code_buf -= (d->m_num_flags_left == 8); + *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left); + d->m_pLZ_code_buf -= (d->m_num_flags_left == 8); - if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index)) - { - TDEFL_PUT_BITS(0x78, 8); TDEFL_PUT_BITS(0x01, 8); - } + if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index)) + { + TDEFL_PUT_BITS(0x78, 8); + TDEFL_PUT_BITS(0x01, 8); + } - TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1); + TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1); - pSaved_output_buf = d->m_pOutput_buf; saved_bit_buf = d->m_bit_buffer; saved_bits_in = d->m_bits_in; + pSaved_output_buf = d->m_pOutput_buf; + saved_bit_buf = d->m_bit_buffer; + saved_bits_in = d->m_bits_in; - if (!use_raw_block) - comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48)); + if (!use_raw_block) + comp_block_succeeded = tdefl_compress_block( + d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48)); - // If the block gets expanded, forget the current contents of the output buffer and send a raw block instead. - if ( ((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) && - ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size) ) - { - mz_uint i; d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; - TDEFL_PUT_BITS(0, 2); - if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } - for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF) - { - TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16); - } - for (i = 0; i < d->m_total_lz_bytes; ++i) - { - TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8); - } - } - // Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes. - else if (!comp_block_succeeded) - { - d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; - tdefl_compress_block(d, MZ_TRUE); - } + // If the block gets expanded, forget the current contents of the output buffer and send a raw block instead. + if (((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes + ))) && + ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size)) + { + mz_uint i; + d->m_pOutput_buf = pSaved_output_buf; + d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; + TDEFL_PUT_BITS(0, 2); + if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } + for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF) + { + TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16); + } + for (i = 0; i < d->m_total_lz_bytes; ++i) + { + TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8); + } + } + // Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes. + else if (!comp_block_succeeded) + { + d->m_pOutput_buf = pSaved_output_buf; + d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; + tdefl_compress_block(d, MZ_TRUE); + } - if (flush) - { - if (flush == TDEFL_FINISH) - { - if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } - if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) { mz_uint i, a = d->m_adler32; for (i = 0; i < 4; i++) { TDEFL_PUT_BITS((a >> 24) & 0xFF, 8); a <<= 8; } } - } - else - { - mz_uint i, z = 0; TDEFL_PUT_BITS(0, 3); if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } for (i = 2; i; --i, z ^= 0xFFFF) { TDEFL_PUT_BITS(z & 0xFFFF, 16); } - } - } + if (flush) + { + if (flush == TDEFL_FINISH) + { + if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } + if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) + { + mz_uint i, a = d->m_adler32; + for (i = 0; i < 4; i++) + { + TDEFL_PUT_BITS((a >> 24) & 0xFF, 8); + a <<= 8; + } + } + } + else + { + mz_uint i, z = 0; + TDEFL_PUT_BITS(0, 3); + if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } + for (i = 2; i; --i, z ^= 0xFFFF) { TDEFL_PUT_BITS(z & 0xFFFF, 16); } + } + } - MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end); + MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end); - memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); - memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); + memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); + memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); - d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8; d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes; d->m_total_lz_bytes = 0; d->m_block_index++; + d->m_pLZ_code_buf = d->m_lz_code_buf + 1; + d->m_pLZ_flags = d->m_lz_code_buf; + d->m_num_flags_left = 8; + d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes; + d->m_total_lz_bytes = 0; + d->m_block_index++; - if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0) - { - if (d->m_pPut_buf_func) - { - *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf; - if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user)) - return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED); - } - else if (pOutput_buf_start == d->m_output_buf) - { - int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs)); - memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy); - d->m_out_buf_ofs += bytes_to_copy; - if ((n -= bytes_to_copy) != 0) - { - d->m_output_flush_ofs = bytes_to_copy; - d->m_output_flush_remaining = n; - } - } - else - { - d->m_out_buf_ofs += n; - } - } + if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0) + { + if (d->m_pPut_buf_func) + { + *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8*)d->m_pIn_buf; + if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user)) + return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED); + } + else if (pOutput_buf_start == d->m_output_buf) + { + int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs)); + memcpy((mz_uint8*)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy); + d->m_out_buf_ofs += bytes_to_copy; + if ((n -= bytes_to_copy) != 0) + { + d->m_output_flush_ofs = bytes_to_copy; + d->m_output_flush_remaining = n; + } + } + else + { + d->m_out_buf_ofs += n; + } + } - return d->m_output_flush_remaining; + return d->m_output_flush_remaining; } #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES #define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16*)(p) -static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) + +static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor* d, mz_uint lookahead_pos, mz_uint max_dist, + mz_uint max_match_len, mz_uint* pMatch_dist, mz_uint* pMatch_len) { - mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len; - mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; - const mz_uint16 *s = (const mz_uint16*)(d->m_dict + pos), *p, *q; - mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD(s); - MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return; - for ( ; ; ) - { - for ( ; ; ) - { - if (--num_probes_left == 0) return; - #define TDEFL_PROBE \ + mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos + , probe_len; + mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; + const mz_uint16 *s = (const mz_uint16*)(d->m_dict + pos), *p, *q; + mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD(s); + MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); + if (max_match_len <= match_len) return; + for (; ;) + { + for (; ;) + { + if (--num_probes_left == 0) return; +#define TDEFL_PROBE \ next_probe_pos = d->m_next[probe_pos]; \ if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \ probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) break; - TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE; - } - if (!dist) break; - q = (const mz_uint16*)(d->m_dict + probe_pos); - if (TDEFL_READ_UNALIGNED_WORD(q) != s01) continue; - p = s; probe_len = 32; - do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && - (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) ); - if (!probe_len) - { - *pMatch_dist = dist; *pMatch_len = MZ_MIN(max_match_len, TDEFL_MAX_MATCH_LEN); break; - } - else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8*)p == *(const mz_uint8*)q)) > match_len) - { - *pMatch_dist = dist; if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len) break; - c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]); - } - } + TDEFL_PROBE; + TDEFL_PROBE; + TDEFL_PROBE; + } + if (!dist) break; + q = (const mz_uint16*)(d->m_dict + probe_pos); + if (TDEFL_READ_UNALIGNED_WORD(q) != s01) continue; + p = s; + probe_len = 32; + do + { + } + while ((TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == + TDEFL_READ_UNALIGNED_WORD(++q)) && + (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == + TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0)); + if (!probe_len) + { + *pMatch_dist = dist; + *pMatch_len = MZ_MIN(max_match_len, TDEFL_MAX_MATCH_LEN); + break; + } + else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8*)p == *(const mz_uint8*)q)) > match_len) + { + *pMatch_dist = dist; + if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len) break; + c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]); + } + } } #else static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) @@ -1562,471 +1979,600 @@ static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahe #endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN -static mz_bool tdefl_compress_fast(tdefl_compressor *d) +static mz_bool tdefl_compress_fast(tdefl_compressor* d) { - // Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio. - mz_uint lookahead_pos = d->m_lookahead_pos, lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size, total_lz_bytes = d->m_total_lz_bytes, num_flags_left = d->m_num_flags_left; - mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags; - mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; + // Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio. + mz_uint lookahead_pos = d->m_lookahead_pos, lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size, + total_lz_bytes = d->m_total_lz_bytes, num_flags_left = d->m_num_flags_left; + mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags; + mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; - while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size))) - { - const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096; - mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; - mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size); - d->m_src_buf_left -= num_bytes_to_process; - lookahead_size += num_bytes_to_process; + while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size))) + { + const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096; + mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; + mz_uint num_bytes_to_process = (mz_uint) + MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size); + d->m_src_buf_left -= num_bytes_to_process; + lookahead_size += num_bytes_to_process; - while (num_bytes_to_process) - { - mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process); - memcpy(d->m_dict + dst_pos, d->m_pSrc, n); - if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) - memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos)); - d->m_pSrc += n; - dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK; - num_bytes_to_process -= n; - } + while (num_bytes_to_process) + { + mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process); + memcpy(d->m_dict + dst_pos, d->m_pSrc, n); + if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) + memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos)); + d->m_pSrc += n; + dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK; + num_bytes_to_process -= n; + } - dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size); - if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE)) break; + dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size); + if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE)) break; - while (lookahead_size >= 4) - { - mz_uint cur_match_dist, cur_match_len = 1; - mz_uint8 *pCur_dict = d->m_dict + cur_pos; - mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF; - mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK; - mz_uint probe_pos = d->m_hash[hash]; - d->m_hash[hash] = (mz_uint16)lookahead_pos; + while (lookahead_size >= 4) + { + mz_uint cur_match_dist, cur_match_len = 1; + mz_uint8* pCur_dict = d->m_dict + cur_pos; + mz_uint first_trigram = (*(const mz_uint32*)pCur_dict) & 0xFFFFFF; + mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & + TDEFL_LEVEL1_HASH_SIZE_MASK; + mz_uint probe_pos = d->m_hash[hash]; + d->m_hash[hash] = (mz_uint16)lookahead_pos; - if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((*(const mz_uint32 *)(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram)) - { - const mz_uint16 *p = (const mz_uint16 *)pCur_dict; - const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos); - mz_uint32 probe_len = 32; - do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && - (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) ); - cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q); - if (!probe_len) - cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0; + if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((*(const mz_uint32*)(d->m_dict + + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram)) + { + const mz_uint16* p = (const mz_uint16*)pCur_dict; + const mz_uint16* q = (const mz_uint16*)(d->m_dict + probe_pos); + mz_uint32 probe_len = 32; + do + { + } + while ((TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) + == TDEFL_READ_UNALIGNED_WORD(++q)) && + (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == + TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0)); + cur_match_len = ((mz_uint)(p - (const mz_uint16*)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8*)p == *(const + mz_uint8*)q); + if (!probe_len) + cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0; - if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U))) - { - cur_match_len = 1; - *pLZ_code_buf++ = (mz_uint8)first_trigram; - *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); - d->m_huff_count[0][(mz_uint8)first_trigram]++; - } - else - { - mz_uint32 s0, s1; - cur_match_len = MZ_MIN(cur_match_len, lookahead_size); + if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= + 8U * 1024U))) + { + cur_match_len = 1; + *pLZ_code_buf++ = (mz_uint8)first_trigram; + *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); + d->m_huff_count[0][(mz_uint8)first_trigram]++; + } + else + { + mz_uint32 s0, s1; + cur_match_len = MZ_MIN(cur_match_len, lookahead_size); - MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE)); + MZ_ASSERT( + (cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= + TDEFL_LZ_DICT_SIZE)); - cur_match_dist--; + cur_match_dist--; - pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN); - *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist; - pLZ_code_buf += 3; - *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80); + pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN); + *(mz_uint16*)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist; + pLZ_code_buf += 3; + *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80); - s0 = s_tdefl_small_dist_sym[cur_match_dist & 511]; - s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8]; - d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++; + s0 = s_tdefl_small_dist_sym[cur_match_dist & 511]; + s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8]; + d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++; - d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++; - } - } - else - { - *pLZ_code_buf++ = (mz_uint8)first_trigram; - *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); - d->m_huff_count[0][(mz_uint8)first_trigram]++; - } + d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++; + } + } + else + { + *pLZ_code_buf++ = (mz_uint8)first_trigram; + *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); + d->m_huff_count[0][(mz_uint8)first_trigram]++; + } - if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; } + if (--num_flags_left == 0) + { + num_flags_left = 8; + pLZ_flags = pLZ_code_buf++; + } - total_lz_bytes += cur_match_len; - lookahead_pos += cur_match_len; - dict_size = MZ_MIN(dict_size + cur_match_len, TDEFL_LZ_DICT_SIZE); - cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK; - MZ_ASSERT(lookahead_size >= cur_match_len); - lookahead_size -= cur_match_len; + total_lz_bytes += cur_match_len; + lookahead_pos += cur_match_len; + dict_size = MZ_MIN(dict_size + cur_match_len, TDEFL_LZ_DICT_SIZE); + cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK; + MZ_ASSERT(lookahead_size >= cur_match_len); + lookahead_size -= cur_match_len; - if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) - { - int n; - d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size; - d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; - if ((n = tdefl_flush_block(d, 0)) != 0) - return (n < 0) ? MZ_FALSE : MZ_TRUE; - total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left; - } - } + if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) + { + int n; + d->m_lookahead_pos = lookahead_pos; + d->m_lookahead_size = lookahead_size; + d->m_dict_size = dict_size; + d->m_total_lz_bytes = total_lz_bytes; + d->m_pLZ_code_buf = pLZ_code_buf; + d->m_pLZ_flags = pLZ_flags; + d->m_num_flags_left = num_flags_left; + if ((n = tdefl_flush_block(d, 0)) != 0) + return (n < 0) ? MZ_FALSE : MZ_TRUE; + total_lz_bytes = d->m_total_lz_bytes; + pLZ_code_buf = d->m_pLZ_code_buf; + pLZ_flags = d->m_pLZ_flags; + num_flags_left = d->m_num_flags_left; + } + } - while (lookahead_size) - { - mz_uint8 lit = d->m_dict[cur_pos]; + while (lookahead_size) + { + mz_uint8 lit = d->m_dict[cur_pos]; - total_lz_bytes++; - *pLZ_code_buf++ = lit; - *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); - if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; } + total_lz_bytes++; + *pLZ_code_buf++ = lit; + *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); + if (--num_flags_left == 0) + { + num_flags_left = 8; + pLZ_flags = pLZ_code_buf++; + } - d->m_huff_count[0][lit]++; + d->m_huff_count[0][lit]++; - lookahead_pos++; - dict_size = MZ_MIN(dict_size + 1, TDEFL_LZ_DICT_SIZE); - cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; - lookahead_size--; + lookahead_pos++; + dict_size = MZ_MIN(dict_size + 1, TDEFL_LZ_DICT_SIZE); + cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; + lookahead_size--; - if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) - { - int n; - d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size; - d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; - if ((n = tdefl_flush_block(d, 0)) != 0) - return (n < 0) ? MZ_FALSE : MZ_TRUE; - total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left; - } - } - } + if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) + { + int n; + d->m_lookahead_pos = lookahead_pos; + d->m_lookahead_size = lookahead_size; + d->m_dict_size = dict_size; + d->m_total_lz_bytes = total_lz_bytes; + d->m_pLZ_code_buf = pLZ_code_buf; + d->m_pLZ_flags = pLZ_flags; + d->m_num_flags_left = num_flags_left; + if ((n = tdefl_flush_block(d, 0)) != 0) + return (n < 0) ? MZ_FALSE : MZ_TRUE; + total_lz_bytes = d->m_total_lz_bytes; + pLZ_code_buf = d->m_pLZ_code_buf; + pLZ_flags = d->m_pLZ_flags; + num_flags_left = d->m_num_flags_left; + } + } + } - d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size; - d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; - return MZ_TRUE; + d->m_lookahead_pos = lookahead_pos; + d->m_lookahead_size = lookahead_size; + d->m_dict_size = dict_size; + d->m_total_lz_bytes = total_lz_bytes; + d->m_pLZ_code_buf = pLZ_code_buf; + d->m_pLZ_flags = pLZ_flags; + d->m_num_flags_left = num_flags_left; + return MZ_TRUE; } #endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN -static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit) +static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor* d, mz_uint8 lit) { - d->m_total_lz_bytes++; - *d->m_pLZ_code_buf++ = lit; - *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; } - d->m_huff_count[0][lit]++; + d->m_total_lz_bytes++; + *d->m_pLZ_code_buf++ = lit; + *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1); + if (--d->m_num_flags_left == 0) + { + d->m_num_flags_left = 8; + d->m_pLZ_flags = d->m_pLZ_code_buf++; + } + d->m_huff_count[0][lit]++; } -static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist) +static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor* d, mz_uint match_len, mz_uint match_dist) { - mz_uint32 s0, s1; + mz_uint32 s0, s1; - MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE)); + MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE)); - d->m_total_lz_bytes += match_len; + d->m_total_lz_bytes += match_len; - d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN); + d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN); - match_dist -= 1; - d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF); - d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8); d->m_pLZ_code_buf += 3; + match_dist -= 1; + d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF); + d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8); + d->m_pLZ_code_buf += 3; - *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; } + *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80); + if (--d->m_num_flags_left == 0) + { + d->m_num_flags_left = 8; + d->m_pLZ_flags = d->m_pLZ_code_buf++; + } - s0 = s_tdefl_small_dist_sym[match_dist & 511]; s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127]; - d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++; + s0 = s_tdefl_small_dist_sym[match_dist & 511]; + s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127]; + d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++; - if (match_len >= TDEFL_MIN_MATCH_LEN) d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++; + if (match_len >= TDEFL_MIN_MATCH_LEN) d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++; } -static mz_bool tdefl_compress_normal(tdefl_compressor *d) +static mz_bool tdefl_compress_normal(tdefl_compressor* d) { - const mz_uint8 *pSrc = d->m_pSrc; size_t src_buf_left = d->m_src_buf_left; - tdefl_flush flush = d->m_flush; + const mz_uint8* pSrc = d->m_pSrc; + size_t src_buf_left = d->m_src_buf_left; + tdefl_flush flush = d->m_flush; - while ((src_buf_left) || ((flush) && (d->m_lookahead_size))) - { - mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos; - // Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN. - if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1)) - { - mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK, ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2; - mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK]; - mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size); - const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process; - src_buf_left -= num_bytes_to_process; - d->m_lookahead_size += num_bytes_to_process; - while (pSrc != pSrc_end) - { - mz_uint8 c = *pSrc++; d->m_dict[dst_pos] = c; if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; - hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); - d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos); - dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; ins_pos++; - } - } - else - { - while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) - { - mz_uint8 c = *pSrc++; - mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; - src_buf_left--; - d->m_dict[dst_pos] = c; - if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) - d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; - if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN) - { - mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2; - mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) ^ (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); - d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos); - } - } - } - d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size); - if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) - break; + while ((src_buf_left) || ((flush) && (d->m_lookahead_size))) + { + mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos; + // Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN. + if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1)) + { + mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK, ins_pos = d-> + m_lookahead_pos + d->m_lookahead_size - 2; + mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) + & TDEFL_LZ_DICT_SIZE_MASK]; + mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size); + const mz_uint8* pSrc_end = pSrc + num_bytes_to_process; + src_buf_left -= num_bytes_to_process; + d->m_lookahead_size += num_bytes_to_process; + while (pSrc != pSrc_end) + { + mz_uint8 c = *pSrc++; + d->m_dict[dst_pos] = c; + if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; + hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); + d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; + d->m_hash[hash] = (mz_uint16)(ins_pos); + dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; + ins_pos++; + } + } + else + { + while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) + { + mz_uint8 c = *pSrc++; + mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; + src_buf_left--; + d->m_dict[dst_pos] = c; + if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) + d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; + if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN) + { + mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2; + mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) ^ (d->m_dict[ + (ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); + d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; + d->m_hash[hash] = (mz_uint16)(ins_pos); + } + } + } + d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size); + if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) + break; - // Simple lazy/greedy parsing state machine. - len_to_move = 1; cur_match_dist = 0; cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1); cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; - if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS)) - { - if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) - { - mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK]; - cur_match_len = 0; while (cur_match_len < d->m_lookahead_size) { if (d->m_dict[cur_pos + cur_match_len] != c) break; cur_match_len++; } - if (cur_match_len < TDEFL_MIN_MATCH_LEN) cur_match_len = 0; else cur_match_dist = 1; - } - } - else - { - tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len); - } - if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U)) || (cur_pos == cur_match_dist) || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5))) - { - cur_match_dist = cur_match_len = 0; - } - if (d->m_saved_match_len) - { - if (cur_match_len > d->m_saved_match_len) - { - tdefl_record_literal(d, (mz_uint8)d->m_saved_lit); - if (cur_match_len >= 128) - { - tdefl_record_match(d, cur_match_len, cur_match_dist); - d->m_saved_match_len = 0; len_to_move = cur_match_len; - } - else - { - d->m_saved_lit = d->m_dict[cur_pos]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len; - } - } - else - { - tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist); - len_to_move = d->m_saved_match_len - 1; d->m_saved_match_len = 0; - } - } - else if (!cur_match_dist) - tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]); - else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128)) - { - tdefl_record_match(d, cur_match_len, cur_match_dist); - len_to_move = cur_match_len; - } - else - { - d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len; - } - // Move the lookahead forward by len_to_move bytes. - d->m_lookahead_pos += len_to_move; - MZ_ASSERT(d->m_lookahead_size >= len_to_move); - d->m_lookahead_size -= len_to_move; - d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, TDEFL_LZ_DICT_SIZE); - // Check if it's time to flush the current LZ codes to the internal output buffer. - if ( (d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) || - ( (d->m_total_lz_bytes > 31*1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) ) - { - int n; - d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left; - if ((n = tdefl_flush_block(d, 0)) != 0) - return (n < 0) ? MZ_FALSE : MZ_TRUE; - } - } + // Simple lazy/greedy parsing state machine. + len_to_move = 1; + cur_match_dist = 0; + cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1); + cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; + if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS)) + { + if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) + { + mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK]; + cur_match_len = 0; + while (cur_match_len < d->m_lookahead_size) + { + if (d->m_dict[cur_pos + cur_match_len] != c) break; + cur_match_len++; + } + if (cur_match_len < TDEFL_MIN_MATCH_LEN) cur_match_len = 0; + else cur_match_dist = 1; + } + } + else + { + tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len); + } + if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U)) || (cur_pos == cur_match_dist) || ( + (d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5))) + { + cur_match_dist = cur_match_len = 0; + } + if (d->m_saved_match_len) + { + if (cur_match_len > d->m_saved_match_len) + { + tdefl_record_literal(d, (mz_uint8)d->m_saved_lit); + if (cur_match_len >= 128) + { + tdefl_record_match(d, cur_match_len, cur_match_dist); + d->m_saved_match_len = 0; + len_to_move = cur_match_len; + } + else + { + d->m_saved_lit = d->m_dict[cur_pos]; + d->m_saved_match_dist = cur_match_dist; + d->m_saved_match_len = cur_match_len; + } + } + else + { + tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist); + len_to_move = d->m_saved_match_len - 1; + d->m_saved_match_len = 0; + } + } + else if (!cur_match_dist) + tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]); + else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128)) + { + tdefl_record_match(d, cur_match_len, cur_match_dist); + len_to_move = cur_match_len; + } + else + { + d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]; + d->m_saved_match_dist = cur_match_dist; + d->m_saved_match_len = cur_match_len; + } + // Move the lookahead forward by len_to_move bytes. + d->m_lookahead_pos += len_to_move; + MZ_ASSERT(d->m_lookahead_size >= len_to_move); + d->m_lookahead_size -= len_to_move; + d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, TDEFL_LZ_DICT_SIZE); + // Check if it's time to flush the current LZ codes to the internal output buffer. + if ((d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) || + ((d->m_total_lz_bytes > 31 * 1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d-> + m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))) + { + int n; + d->m_pSrc = pSrc; + d->m_src_buf_left = src_buf_left; + if ((n = tdefl_flush_block(d, 0)) != 0) + return (n < 0) ? MZ_FALSE : MZ_TRUE; + } + } - d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left; - return MZ_TRUE; + d->m_pSrc = pSrc; + d->m_src_buf_left = src_buf_left; + return MZ_TRUE; } -static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d) +static tdefl_status tdefl_flush_output_buffer(tdefl_compressor* d) { - if (d->m_pIn_buf_size) - { - *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf; - } + if (d->m_pIn_buf_size) + { + *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8*)d->m_pIn_buf; + } - if (d->m_pOut_buf_size) - { - size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining); - memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n); - d->m_output_flush_ofs += (mz_uint)n; - d->m_output_flush_remaining -= (mz_uint)n; - d->m_out_buf_ofs += n; + if (d->m_pOut_buf_size) + { + size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining); + memcpy((mz_uint8*)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n); + d->m_output_flush_ofs += (mz_uint)n; + d->m_output_flush_remaining -= (mz_uint)n; + d->m_out_buf_ofs += n; - *d->m_pOut_buf_size = d->m_out_buf_ofs; - } + *d->m_pOut_buf_size = d->m_out_buf_ofs; + } - return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY; + return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY; } -tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush) +tdefl_status tdefl_compress(tdefl_compressor* d, const void* pIn_buf, size_t* pIn_buf_size, void* pOut_buf, + size_t* pOut_buf_size, tdefl_flush flush) { - if (!d) - { - if (pIn_buf_size) *pIn_buf_size = 0; - if (pOut_buf_size) *pOut_buf_size = 0; - return TDEFL_STATUS_BAD_PARAM; - } + if (!d) + { + if (pIn_buf_size) *pIn_buf_size = 0; + if (pOut_buf_size) *pOut_buf_size = 0; + return TDEFL_STATUS_BAD_PARAM; + } - d->m_pIn_buf = pIn_buf; d->m_pIn_buf_size = pIn_buf_size; - d->m_pOut_buf = pOut_buf; d->m_pOut_buf_size = pOut_buf_size; - d->m_pSrc = (const mz_uint8 *)(pIn_buf); d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0; - d->m_out_buf_ofs = 0; - d->m_flush = flush; + d->m_pIn_buf = pIn_buf; + d->m_pIn_buf_size = pIn_buf_size; + d->m_pOut_buf = pOut_buf; + d->m_pOut_buf_size = pOut_buf_size; + d->m_pSrc = (const mz_uint8*)(pIn_buf); + d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0; + d->m_out_buf_ofs = 0; + d->m_flush = flush; - if ( ((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) || - (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf) ) - { - if (pIn_buf_size) *pIn_buf_size = 0; - if (pOut_buf_size) *pOut_buf_size = 0; - return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM); - } - d->m_wants_to_finish |= (flush == TDEFL_FINISH); + if (((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != + TDEFL_STATUS_OKAY) || + (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size + && *pOut_buf_size && !pOut_buf)) + { + if (pIn_buf_size) *pIn_buf_size = 0; + if (pOut_buf_size) *pOut_buf_size = 0; + return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM); + } + d->m_wants_to_finish |= (flush == TDEFL_FINISH); - if ((d->m_output_flush_remaining) || (d->m_finished)) - return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); + if ((d->m_output_flush_remaining) || (d->m_finished)) + return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN - if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) && - ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) && - ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0)) - { - if (!tdefl_compress_fast(d)) - return d->m_prev_return_status; - } - else + if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) && + ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) && + ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0)) + { + if (!tdefl_compress_fast(d)) + return d->m_prev_return_status; + } + else #endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN - { - if (!tdefl_compress_normal(d)) - return d->m_prev_return_status; - } + { + if (!tdefl_compress_normal(d)) + return d->m_prev_return_status; + } - if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf)) - d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf); + if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf)) + d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8*)pIn_buf, + d->m_pSrc - (const mz_uint8*)pIn_buf); - if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining)) - { - if (tdefl_flush_block(d, flush) < 0) - return d->m_prev_return_status; - d->m_finished = (flush == TDEFL_FINISH); - if (flush == TDEFL_FULL_FLUSH) { MZ_CLEAR_OBJ(d->m_hash); MZ_CLEAR_OBJ(d->m_next); d->m_dict_size = 0; } - } + if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining)) + { + if (tdefl_flush_block(d, flush) < 0) + return d->m_prev_return_status; + d->m_finished = (flush == TDEFL_FINISH); + if (flush == TDEFL_FULL_FLUSH) + { + MZ_CLEAR_OBJ(d->m_hash); + MZ_CLEAR_OBJ(d->m_next); + d->m_dict_size = 0; + } + } - return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); + return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); } -tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush) +tdefl_status tdefl_compress_buffer(tdefl_compressor* d, const void* pIn_buf, size_t in_buf_size, tdefl_flush flush) { - MZ_ASSERT(d->m_pPut_buf_func); return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush); + MZ_ASSERT(d->m_pPut_buf_func); + return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush); } -tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) +tdefl_status tdefl_init(tdefl_compressor* d, tdefl_put_buf_func_ptr pPut_buf_func, void* pPut_buf_user, int flags) { - d->m_pPut_buf_func = pPut_buf_func; d->m_pPut_buf_user = pPut_buf_user; - d->m_flags = (mz_uint)(flags); d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3; d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0; - d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3; - if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) { - MZ_CLEAR_OBJ(d->m_hash); - MZ_CLEAR_OBJ(d->m_dict); - } - d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0; - d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0; - d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8; - d->m_pOutput_buf = d->m_output_buf; d->m_pOutput_buf_end = d->m_output_buf; d->m_prev_return_status = TDEFL_STATUS_OKAY; - d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0; d->m_adler32 = 1; - d->m_pIn_buf = NULL; d->m_pOut_buf = NULL; - d->m_pIn_buf_size = NULL; d->m_pOut_buf_size = NULL; - d->m_flush = TDEFL_NO_FLUSH; d->m_pSrc = NULL; d->m_src_buf_left = 0; d->m_out_buf_ofs = 0; - memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); - memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); - return TDEFL_STATUS_OKAY; + d->m_pPut_buf_func = pPut_buf_func; + d->m_pPut_buf_user = pPut_buf_user; + d->m_flags = (mz_uint)(flags); + d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3; + d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0; + d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3; + if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) + { + MZ_CLEAR_OBJ(d->m_hash); + MZ_CLEAR_OBJ(d->m_dict); + } + d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d-> + m_bits_in = 0; + d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d-> + m_wants_to_finish = 0; + d->m_pLZ_code_buf = d->m_lz_code_buf + 1; + d->m_pLZ_flags = d->m_lz_code_buf; + d->m_num_flags_left = 8; + d->m_pOutput_buf = d->m_output_buf; + d->m_pOutput_buf_end = d->m_output_buf; + d->m_prev_return_status = TDEFL_STATUS_OKAY; + d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0; + d->m_adler32 = 1; + d->m_pIn_buf = NULL; + d->m_pOut_buf = NULL; + d->m_pIn_buf_size = NULL; + d->m_pOut_buf_size = NULL; + d->m_flush = TDEFL_NO_FLUSH; + d->m_pSrc = NULL; + d->m_src_buf_left = 0; + d->m_out_buf_ofs = 0; + memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); + memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); + return TDEFL_STATUS_OKAY; } -tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d) +tdefl_status tdefl_get_prev_return_status(tdefl_compressor* d) { - return d->m_prev_return_status; + return d->m_prev_return_status; } -mz_uint32 tdefl_get_adler32(tdefl_compressor *d) +mz_uint32 tdefl_get_adler32(tdefl_compressor* d) { - return d->m_adler32; + return d->m_adler32; } -mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) +mz_bool tdefl_compress_mem_to_output(const void* pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, + void* pPut_buf_user, int flags) { - tdefl_compressor *pComp; mz_bool succeeded; if (((buf_len) && (!pBuf)) || (!pPut_buf_func)) return MZ_FALSE; - pComp = (tdefl_compressor*)MZ_MALLOC(sizeof(tdefl_compressor)); if (!pComp) return MZ_FALSE; - succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY); - succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE); - MZ_FREE(pComp); return succeeded; + tdefl_compressor* pComp; + mz_bool succeeded; + if (((buf_len) && (!pBuf)) || (!pPut_buf_func)) return MZ_FALSE; + pComp = (tdefl_compressor*)MZ_MALLOC(sizeof(tdefl_compressor)); + if (!pComp) return MZ_FALSE; + succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY); + succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE); + MZ_FREE(pComp); + return succeeded; } typedef struct { - size_t m_size, m_capacity; - mz_uint8 *m_pBuf; - mz_bool m_expandable; + size_t m_size, m_capacity; + mz_uint8* m_pBuf; + mz_bool m_expandable; } tdefl_output_buffer; -static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser) +static mz_bool tdefl_output_buffer_putter(const void* pBuf, int len, void* pUser) { - tdefl_output_buffer *p = (tdefl_output_buffer *)pUser; - size_t new_size = p->m_size + len; - if (new_size > p->m_capacity) - { - size_t new_capacity = p->m_capacity; mz_uint8 *pNew_buf; if (!p->m_expandable) return MZ_FALSE; - do { new_capacity = MZ_MAX(128U, new_capacity << 1U); } while (new_size > new_capacity); - pNew_buf = (mz_uint8*)MZ_REALLOC(p->m_pBuf, new_capacity); if (!pNew_buf) return MZ_FALSE; - p->m_pBuf = pNew_buf; p->m_capacity = new_capacity; - } - memcpy((mz_uint8*)p->m_pBuf + p->m_size, pBuf, len); p->m_size = new_size; - return MZ_TRUE; + tdefl_output_buffer* p = (tdefl_output_buffer*)pUser; + size_t new_size = p->m_size + len; + if (new_size > p->m_capacity) + { + size_t new_capacity = p->m_capacity; + mz_uint8* pNew_buf; + if (!p->m_expandable) return MZ_FALSE; + do { new_capacity = MZ_MAX(128U, new_capacity << 1U); } + while (new_size > new_capacity); + pNew_buf = (mz_uint8*)MZ_REALLOC(p->m_pBuf, new_capacity); + if (!pNew_buf) return MZ_FALSE; + p->m_pBuf = pNew_buf; + p->m_capacity = new_capacity; + } + memcpy((mz_uint8*)p->m_pBuf + p->m_size, pBuf, len); + p->m_size = new_size; + return MZ_TRUE; } -void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags) +void* tdefl_compress_mem_to_heap(const void* pSrc_buf, size_t src_buf_len, size_t* pOut_len, int flags) { - tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf); - if (!pOut_len) return MZ_FALSE; else *pOut_len = 0; - out_buf.m_expandable = MZ_TRUE; - if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return NULL; - *pOut_len = out_buf.m_size; return out_buf.m_pBuf; + tdefl_output_buffer out_buf; + MZ_CLEAR_OBJ(out_buf); + if (!pOut_len) return MZ_FALSE; + else *pOut_len = 0; + out_buf.m_expandable = MZ_TRUE; + if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return NULL; + *pOut_len = out_buf.m_size; + return out_buf.m_pBuf; } -size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags) +size_t tdefl_compress_mem_to_mem(void* pOut_buf, size_t out_buf_len, const void* pSrc_buf, size_t src_buf_len, + int flags) { - tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf); - if (!pOut_buf) return 0; - out_buf.m_pBuf = (mz_uint8*)pOut_buf; out_buf.m_capacity = out_buf_len; - if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return 0; - return out_buf.m_size; + tdefl_output_buffer out_buf; + MZ_CLEAR_OBJ(out_buf); + if (!pOut_buf) return 0; + out_buf.m_pBuf = (mz_uint8*)pOut_buf; + out_buf.m_capacity = out_buf_len; + if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return 0; + return out_buf.m_size; } #ifndef MINIZ_NO_ZLIB_APIS -static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 }; +static const mz_uint s_tdefl_num_probes[11] = {0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500}; // level may actually range from [0,10] (10 is a "hidden" max level, where we want a bit more compression and it's fine if throughput to fall off a cliff on some files). mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy) { - mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0); - if (window_bits > 0) comp_flags |= TDEFL_WRITE_ZLIB_HEADER; + mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ( + (level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0); + if (window_bits > 0) comp_flags |= TDEFL_WRITE_ZLIB_HEADER; - if (!level) comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS; - else if (strategy == MZ_FILTERED) comp_flags |= TDEFL_FILTER_MATCHES; - else if (strategy == MZ_HUFFMAN_ONLY) comp_flags &= ~TDEFL_MAX_PROBES_MASK; - else if (strategy == MZ_FIXED) comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS; - else if (strategy == MZ_RLE) comp_flags |= TDEFL_RLE_MATCHES; + if (!level) comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS; + else if (strategy == MZ_FILTERED) comp_flags |= TDEFL_FILTER_MATCHES; + else if (strategy == MZ_HUFFMAN_ONLY) comp_flags &= ~TDEFL_MAX_PROBES_MASK; + else if (strategy == MZ_FIXED) comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS; + else if (strategy == MZ_RLE) comp_flags |= TDEFL_RLE_MATCHES; - return comp_flags; + return comp_flags; } #endif //MINIZ_NO_ZLIB_APIS @@ -2038,39 +2584,76 @@ mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int // Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at // http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/. // This is actually a modification of Alex's original code so PNG files generated by this function pass pngcheck. -void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip) +void* tdefl_write_image_to_png_file_in_memory_ex(const void* pImage, int w, int h, int num_chans, size_t* pLen_out, + mz_uint level, mz_bool flip) { - // Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was defined. - static const mz_uint s_tdefl_png_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 }; - tdefl_compressor *pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); tdefl_output_buffer out_buf; int i, bpl = w * num_chans, y, z; mz_uint32 c; *pLen_out = 0; - if (!pComp) return NULL; - MZ_CLEAR_OBJ(out_buf); out_buf.m_expandable = MZ_TRUE; out_buf.m_capacity = 57+MZ_MAX(64, (1+bpl)*h); if (NULL == (out_buf.m_pBuf = (mz_uint8*)MZ_MALLOC(out_buf.m_capacity))) { MZ_FREE(pComp); return NULL; } - // write dummy header - for (z = 41; z; --z) tdefl_output_buffer_putter(&z, 1, &out_buf); - // compress image data - tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER); - for (y = 0; y < h; ++y) { tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH); tdefl_compress_buffer(pComp, (mz_uint8*)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH); } - if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE) { MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; } - // write real header - *pLen_out = out_buf.m_size-41; - { - static const mz_uint8 chans[] = {0x00, 0x00, 0x04, 0x02, 0x06}; - mz_uint8 pnghdr[41]={0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52, - 0,0,(mz_uint8)(w>>8),(mz_uint8)w,0,0,(mz_uint8)(h>>8),(mz_uint8)h,8,chans[num_chans],0,0,0,0,0,0,0, - (mz_uint8)(*pLen_out>>24),(mz_uint8)(*pLen_out>>16),(mz_uint8)(*pLen_out>>8),(mz_uint8)*pLen_out,0x49,0x44,0x41,0x54}; - c=(mz_uint32)mz_crc32(MZ_CRC32_INIT,pnghdr+12,17); for (i=0; i<4; ++i, c<<=8) ((mz_uint8*)(pnghdr+29))[i]=(mz_uint8)(c>>24); - memcpy(out_buf.m_pBuf, pnghdr, 41); - } - // write footer (IDAT CRC-32, followed by IEND chunk) - if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) { *pLen_out = 0; MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; } - c = (mz_uint32)mz_crc32(MZ_CRC32_INIT,out_buf.m_pBuf+41-4, *pLen_out+4); for (i=0; i<4; ++i, c<<=8) (out_buf.m_pBuf+out_buf.m_size-16)[i] = (mz_uint8)(c >> 24); - // compute final size of file, grab compressed data buffer and return - *pLen_out += 57; MZ_FREE(pComp); return out_buf.m_pBuf; + // Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was defined. + static const mz_uint s_tdefl_png_num_probes[11] = {0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500}; + tdefl_compressor* pComp = (tdefl_compressor*)MZ_MALLOC(sizeof(tdefl_compressor)); + tdefl_output_buffer out_buf; + int i, bpl = w * num_chans, y, z; + mz_uint32 c; + *pLen_out = 0; + if (!pComp) return NULL; + MZ_CLEAR_OBJ(out_buf); + out_buf.m_expandable = MZ_TRUE; + out_buf.m_capacity = 57 + MZ_MAX(64, (1+bpl)*h); + if (NULL == (out_buf.m_pBuf = (mz_uint8*)MZ_MALLOC(out_buf.m_capacity))) + { + MZ_FREE(pComp); + return NULL; + } + // write dummy header + for (z = 41; z; --z) tdefl_output_buffer_putter(&z, 1, &out_buf); + // compress image data + tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, + s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER); + for (y = 0; y < h; ++y) + { + tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH); + tdefl_compress_buffer(pComp, (mz_uint8*)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH); + } + if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE) + { + MZ_FREE(pComp); + MZ_FREE(out_buf.m_pBuf); + return NULL; + } + // write real header + *pLen_out = out_buf.m_size - 41; + { + static const mz_uint8 chans[] = {0x00, 0x00, 0x04, 0x02, 0x06}; + mz_uint8 pnghdr[41] = { + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, + 0, 0, (mz_uint8)(w >> 8), (mz_uint8)w, 0, 0, (mz_uint8)(h >> 8), (mz_uint8)h, 8, chans[num_chans], 0, 0, 0, 0, + 0, 0, 0, + (mz_uint8)(*pLen_out >> 24), (mz_uint8)(*pLen_out >> 16), (mz_uint8)(*pLen_out >> 8), (mz_uint8)*pLen_out, + 0x49, 0x44, 0x41, 0x54 + }; + c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, pnghdr + 12, 17); + for (i = 0; i < 4; ++i, c <<= 8) ((mz_uint8*)(pnghdr + 29))[i] = (mz_uint8)(c >> 24); + memcpy(out_buf.m_pBuf, pnghdr, 41); + } + // write footer (IDAT CRC-32, followed by IEND chunk) + if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) + { + *pLen_out = 0; + MZ_FREE(pComp); + MZ_FREE(out_buf.m_pBuf); + return NULL; + } + c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, out_buf.m_pBuf + 41 - 4, *pLen_out + 4); + for (i = 0; i < 4; ++i, c <<= 8) (out_buf.m_pBuf + out_buf.m_size - 16)[i] = (mz_uint8)(c >> 24); + // compute final size of file, grab compressed data buffer and return + *pLen_out += 57; + MZ_FREE(pComp); + return out_buf.m_pBuf; } -void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out) + +void* tdefl_write_image_to_png_file_in_memory(const void* pImage, int w, int h, int num_chans, size_t* pLen_out) { - // Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's where #defined out) - return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE); + // Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's where #defined out) + return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE); } #ifdef _MSC_VER @@ -2084,46 +2667,47 @@ void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, #ifdef MINIZ_NO_STDIO #define MZ_FILE void * #else - #include - #include +#include +#include - #if defined(_MSC_VER) || defined(__MINGW64__) - static FILE *mz_fopen(const char *pFilename, const char *pMode) - { - FILE* pFile = NULL; - #ifdef _MSC_VER - _wfopen_s(&pFile, utf8::utf8::decode(pFilename).c_str(), utf8::utf8::decode(pMode).c_str()); - #else +#if defined(_MSC_VER) || defined(__MINGW64__) +static FILE* mz_fopen(const char* pFilename, const char* pMode) +{ + FILE* pFile = NULL; +#ifdef _MSC_VER + _wfopen_s(&pFile, utf8::utf8::decode(pFilename).c_str(), utf8::utf8::decode(pMode).c_str()); +#else fopen_s(&pFile, pFilename, pMode); - #endif - return pFile; - } - static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) - { - FILE* pFile = NULL; - if (freopen_s(&pFile, pPath, pMode, pStream)) - return NULL; - return pFile; - } - #ifndef MINIZ_NO_TIME +#endif + return pFile; +} + +static FILE* mz_freopen(const char* pPath, const char* pMode, FILE* pStream) +{ + FILE* pFile = NULL; + if (freopen_s(&pFile, pPath, pMode, pStream)) + return NULL; + return pFile; +} +#ifndef MINIZ_NO_TIME +#include +#endif +#define MZ_FILE FILE +#define MZ_FOPEN mz_fopen +#define MZ_FCLOSE fclose +#define MZ_FREAD fread +#define MZ_FWRITE fwrite +#define MZ_FTELL64 _ftelli64 +#define MZ_FSEEK64 _fseeki64 +#define MZ_FILE_STAT_STRUCT _stat +#define MZ_FILE_STAT _stat +#define MZ_FFLUSH fflush +#define MZ_FREOPEN mz_freopen +#define MZ_DELETE_FILE remove +#elif defined(__MINGW32__) +#ifndef MINIZ_NO_TIME #include - #endif - #define MZ_FILE FILE - #define MZ_FOPEN mz_fopen - #define MZ_FCLOSE fclose - #define MZ_FREAD fread - #define MZ_FWRITE fwrite - #define MZ_FTELL64 _ftelli64 - #define MZ_FSEEK64 _fseeki64 - #define MZ_FILE_STAT_STRUCT _stat - #define MZ_FILE_STAT _stat - #define MZ_FFLUSH fflush - #define MZ_FREOPEN mz_freopen - #define MZ_DELETE_FILE remove - #elif defined(__MINGW32__) - #ifndef MINIZ_NO_TIME - #include - #endif +#endif #define MZ_FILE FILE #define MZ_FOPEN(f, m) fopen(f, m) #define MZ_FCLOSE fclose @@ -2136,10 +2720,10 @@ void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, #define MZ_FFLUSH fflush #define MZ_FREOPEN(f, m, s) freopen(f, m, s) #define MZ_DELETE_FILE remove - #elif defined(__TINYC__) - #ifndef MINIZ_NO_TIME +#elif defined(__TINYC__) +#ifndef MINIZ_NO_TIME #include - #endif +#endif #define MZ_FILE FILE #define MZ_FOPEN(f, m) fopen(f, m) #define MZ_FCLOSE fclose @@ -2152,10 +2736,10 @@ void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, #define MZ_FFLUSH fflush #define MZ_FREOPEN(f, m, s) freopen(f, m, s) #define MZ_DELETE_FILE remove - #elif defined(__GNUC__) && _LARGEFILE64_SOURCE - #ifndef MINIZ_NO_TIME +#elif defined(__GNUC__) && _LARGEFILE64_SOURCE +#ifndef MINIZ_NO_TIME #include - #endif +#endif #define MZ_FILE FILE #define MZ_FOPEN(f, m) fopen64(f, m) #define MZ_FCLOSE fclose @@ -2168,10 +2752,10 @@ void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, #define MZ_FFLUSH fflush #define MZ_FREOPEN(p, m, s) freopen64(p, m, s) #define MZ_DELETE_FILE remove - #else - #ifndef MINIZ_NO_TIME +#else +#ifndef MINIZ_NO_TIME #include - #endif +#endif #define MZ_FILE FILE #define MZ_FOPEN(f, m) fopen(f, m) #define MZ_FCLOSE fclose @@ -2184,7 +2768,7 @@ void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, #define MZ_FFLUSH fflush #define MZ_FREOPEN(f, m, s) freopen(f, m, s) #define MZ_DELETE_FILE remove - #endif // #ifdef _MSC_VER +#endif // #ifdef _MSC_VER #endif // #ifdef MINIZ_NO_STDIO #define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c)) @@ -2192,1014 +2776,1155 @@ void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, // Various ZIP archive enums. To completely avoid cross platform compiler alignment and platform endian issues, miniz.c doesn't use structs for any of this stuff. enum { - // ZIP archive identifiers and record sizes - MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50, MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50, MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50, - MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22, - // Central directory header record offsets - MZ_ZIP_CDH_SIG_OFS = 0, MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4, MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6, MZ_ZIP_CDH_BIT_FLAG_OFS = 8, - MZ_ZIP_CDH_METHOD_OFS = 10, MZ_ZIP_CDH_FILE_TIME_OFS = 12, MZ_ZIP_CDH_FILE_DATE_OFS = 14, MZ_ZIP_CDH_CRC32_OFS = 16, - MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20, MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24, MZ_ZIP_CDH_FILENAME_LEN_OFS = 28, MZ_ZIP_CDH_EXTRA_LEN_OFS = 30, - MZ_ZIP_CDH_COMMENT_LEN_OFS = 32, MZ_ZIP_CDH_DISK_START_OFS = 34, MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36, MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38, MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42, - // Local directory header offsets - MZ_ZIP_LDH_SIG_OFS = 0, MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4, MZ_ZIP_LDH_BIT_FLAG_OFS = 6, MZ_ZIP_LDH_METHOD_OFS = 8, MZ_ZIP_LDH_FILE_TIME_OFS = 10, - MZ_ZIP_LDH_FILE_DATE_OFS = 12, MZ_ZIP_LDH_CRC32_OFS = 14, MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18, MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22, - MZ_ZIP_LDH_FILENAME_LEN_OFS = 26, MZ_ZIP_LDH_EXTRA_LEN_OFS = 28, - // End of central directory offsets - MZ_ZIP_ECDH_SIG_OFS = 0, MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4, MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6, MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8, - MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10, MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12, MZ_ZIP_ECDH_CDIR_OFS_OFS = 16, MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20, + // ZIP archive identifiers and record sizes + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50, + MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50, + MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50, + MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30, + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46, + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22, + // Central directory header record offsets + MZ_ZIP_CDH_SIG_OFS = 0, + MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4, + MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6, + MZ_ZIP_CDH_BIT_FLAG_OFS = 8, + MZ_ZIP_CDH_METHOD_OFS = 10, + MZ_ZIP_CDH_FILE_TIME_OFS = 12, + MZ_ZIP_CDH_FILE_DATE_OFS = 14, + MZ_ZIP_CDH_CRC32_OFS = 16, + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20, + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24, + MZ_ZIP_CDH_FILENAME_LEN_OFS = 28, + MZ_ZIP_CDH_EXTRA_LEN_OFS = 30, + MZ_ZIP_CDH_COMMENT_LEN_OFS = 32, + MZ_ZIP_CDH_DISK_START_OFS = 34, + MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36, + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38, + MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42, + // Local directory header offsets + MZ_ZIP_LDH_SIG_OFS = 0, + MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4, + MZ_ZIP_LDH_BIT_FLAG_OFS = 6, + MZ_ZIP_LDH_METHOD_OFS = 8, + MZ_ZIP_LDH_FILE_TIME_OFS = 10, + MZ_ZIP_LDH_FILE_DATE_OFS = 12, + MZ_ZIP_LDH_CRC32_OFS = 14, + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18, + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22, + MZ_ZIP_LDH_FILENAME_LEN_OFS = 26, + MZ_ZIP_LDH_EXTRA_LEN_OFS = 28, + // End of central directory offsets + MZ_ZIP_ECDH_SIG_OFS = 0, + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4, + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6, + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8, + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10, + MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12, + MZ_ZIP_ECDH_CDIR_OFS_OFS = 16, + MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20, }; typedef struct { - void *m_p; - size_t m_size, m_capacity; - mz_uint m_element_size; + void* m_p; + size_t m_size, m_capacity; + mz_uint m_element_size; } mz_zip_array; struct mz_zip_internal_state_tag { - mz_zip_array m_central_dir; - mz_zip_array m_central_dir_offsets; - mz_zip_array m_sorted_central_dir_offsets; - MZ_FILE *m_pFile; - void *m_pMem; - size_t m_mem_size; - size_t m_mem_capacity; + mz_zip_array m_central_dir; + mz_zip_array m_central_dir_offsets; + mz_zip_array m_sorted_central_dir_offsets; + MZ_FILE* m_pFile; + void* m_pMem; + size_t m_mem_size; + size_t m_mem_capacity; }; #define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size #define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index] -static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray) +static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive* pZip, mz_zip_array* pArray) { - pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p); - memset(pArray, 0, sizeof(mz_zip_array)); + pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p); + memset(pArray, 0, sizeof(mz_zip_array)); } -static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing) +static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive* pZip, mz_zip_array* pArray, size_t min_new_capacity, + mz_uint growing) { - void *pNew_p; size_t new_capacity = min_new_capacity; MZ_ASSERT(pArray->m_element_size); if (pArray->m_capacity >= min_new_capacity) return MZ_TRUE; - if (growing) { new_capacity = MZ_MAX(1, pArray->m_capacity); while (new_capacity < min_new_capacity) new_capacity *= 2; } - if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity))) return MZ_FALSE; - pArray->m_p = pNew_p; pArray->m_capacity = new_capacity; - return MZ_TRUE; + void* pNew_p; + size_t new_capacity = min_new_capacity; + MZ_ASSERT(pArray->m_element_size); + if (pArray->m_capacity >= min_new_capacity) return MZ_TRUE; + if (growing) + { + new_capacity = MZ_MAX(1, pArray->m_capacity); + while (new_capacity < min_new_capacity) new_capacity *= 2; + } + if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity))) + return MZ_FALSE; + pArray->m_p = pNew_p; + pArray->m_capacity = new_capacity; + return MZ_TRUE; } -static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing) +static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive* pZip, mz_zip_array* pArray, size_t new_capacity, + mz_uint growing) { - if (new_capacity > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing)) return MZ_FALSE; } - return MZ_TRUE; + if (new_capacity > pArray->m_capacity) + { + if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing)) return MZ_FALSE; + } + return MZ_TRUE; } -static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing) +static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive* pZip, mz_zip_array* pArray, size_t new_size, + mz_uint growing) { - if (new_size > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing)) return MZ_FALSE; } - pArray->m_size = new_size; - return MZ_TRUE; + if (new_size > pArray->m_capacity) + { + if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing)) return MZ_FALSE; + } + pArray->m_size = new_size; + return MZ_TRUE; } -static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip, mz_zip_array *pArray, size_t n) +static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive* pZip, mz_zip_array* pArray, size_t n) { - return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE); + return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE); } -static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n) +static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive* pZip, mz_zip_array* pArray, const void* pElements, + size_t n) { - size_t orig_size = pArray->m_size; if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE)) return MZ_FALSE; - memcpy((mz_uint8*)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size); - return MZ_TRUE; + size_t orig_size = pArray->m_size; + if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE)) return MZ_FALSE; + memcpy((mz_uint8*)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size); + return MZ_TRUE; } #ifndef MINIZ_NO_TIME static time_t mz_zip_dos_to_time_t(int dos_time, int dos_date) { - struct tm tm; - memset(&tm, 0, sizeof(tm)); tm.tm_isdst = -1; - tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900; tm.tm_mon = ((dos_date >> 5) & 15) - 1; tm.tm_mday = dos_date & 31; - tm.tm_hour = (dos_time >> 11) & 31; tm.tm_min = (dos_time >> 5) & 63; tm.tm_sec = (dos_time << 1) & 62; - return mktime(&tm); + struct tm tm; + memset(&tm, 0, sizeof(tm)); + tm.tm_isdst = -1; + tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900; + tm.tm_mon = ((dos_date >> 5) & 15) - 1; + tm.tm_mday = dos_date & 31; + tm.tm_hour = (dos_time >> 11) & 31; + tm.tm_min = (dos_time >> 5) & 63; + tm.tm_sec = (dos_time << 1) & 62; + return mktime(&tm); } -static void mz_zip_time_to_dos_time(time_t time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date) +static void mz_zip_time_to_dos_time(time_t time, mz_uint16* pDOS_time, mz_uint16* pDOS_date) { #ifdef _MSC_VER - struct tm tm_struct; - struct tm *tm = &tm_struct; - errno_t err = localtime_s(tm, &time); - if (err) - { - *pDOS_date = 0; *pDOS_time = 0; - return; - } + struct tm tm_struct; + struct tm* tm = &tm_struct; + errno_t err = localtime_s(tm, &time); + if (err) + { + *pDOS_date = 0; + *pDOS_time = 0; + return; + } #else struct tm *tm = localtime(&time); #endif - *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1)); - *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday); + *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1)); + *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday); } #endif #ifndef MINIZ_NO_STDIO -static mz_bool mz_zip_get_file_modified_time(const char *pFilename, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date) +static mz_bool mz_zip_get_file_modified_time(const char* pFilename, mz_uint16* pDOS_time, mz_uint16* pDOS_date) { #ifdef MINIZ_NO_TIME (void)pFilename; *pDOS_date = *pDOS_time = 0; #else - struct MZ_FILE_STAT_STRUCT file_stat; - // On Linux with x86 glibc, this call will fail on large files (>= 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh. - if (MZ_FILE_STAT(pFilename, &file_stat) != 0) - return MZ_FALSE; - mz_zip_time_to_dos_time(file_stat.st_mtime, pDOS_time, pDOS_date); + struct MZ_FILE_STAT_STRUCT file_stat; + // On Linux with x86 glibc, this call will fail on large files (>= 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh. + if (MZ_FILE_STAT(pFilename, &file_stat) != 0) + return MZ_FALSE; + mz_zip_time_to_dos_time(file_stat.st_mtime, pDOS_time, pDOS_date); #endif // #ifdef MINIZ_NO_TIME - return MZ_TRUE; + return MZ_TRUE; } #ifndef MINIZ_NO_TIME -static mz_bool mz_zip_set_file_times(const char *pFilename, time_t access_time, time_t modified_time) +static mz_bool mz_zip_set_file_times(const char* pFilename, time_t access_time, time_t modified_time) { - struct utimbuf t; t.actime = access_time; t.modtime = modified_time; - return !utime(pFilename, &t); + struct utimbuf t; + t.actime = access_time; + t.modtime = modified_time; + return !utime(pFilename, &t); } #endif // #ifndef MINIZ_NO_TIME #endif // #ifndef MINIZ_NO_STDIO -static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint32 flags) +static mz_bool mz_zip_reader_init_internal(mz_zip_archive* pZip, mz_uint32 flags) { - (void)flags; - if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) - return MZ_FALSE; + (void)flags; + if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) + return MZ_FALSE; - if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func; - if (!pZip->m_pFree) pZip->m_pFree = def_free_func; - if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func; + if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func; + if (!pZip->m_pFree) pZip->m_pFree = def_free_func; + if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func; - pZip->m_zip_mode = MZ_ZIP_MODE_READING; - pZip->m_archive_size = 0; - pZip->m_central_directory_file_ofs = 0; - pZip->m_total_files = 0; + pZip->m_zip_mode = MZ_ZIP_MODE_READING; + pZip->m_archive_size = 0; + pZip->m_central_directory_file_ofs = 0; + pZip->m_total_files = 0; - if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) - return MZ_FALSE; - memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32)); - return MZ_TRUE; + if (NULL == (pZip->m_pState = (mz_zip_internal_state*)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, + sizeof(mz_zip_internal_state)))) + return MZ_FALSE; + memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32)); + return MZ_TRUE; } -static MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, mz_uint r_index) +static MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(const mz_zip_array* pCentral_dir_array, + const mz_zip_array* pCentral_dir_offsets, mz_uint l_index, + mz_uint r_index) { - const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE; - const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index)); - mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS), r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS); - mz_uint8 l = 0, r = 0; - pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; - pE = pL + MZ_MIN(l_len, r_len); - while (pL < pE) - { - if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) - break; - pL++; pR++; - } - return (pL == pE) ? (l_len < r_len) : (l < r); + const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, + MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE; + const mz_uint8* pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, + MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index)); + mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS), r_len = MZ_READ_LE16( + pR + MZ_ZIP_CDH_FILENAME_LEN_OFS); + mz_uint8 l = 0, r = 0; + pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; + pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; + pE = pL + MZ_MIN(l_len, r_len); + while (pL < pE) + { + if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) + break; + pL++; + pR++; + } + return (pL == pE) ? (l_len < r_len) : (l < r); } #define MZ_SWAP_UINT32(a, b) do { mz_uint32 t = a; a = b; b = t; } MZ_MACRO_END // Heap sort of lowercased filenames, used to help accelerate plain central directory searches by mz_zip_reader_locate_file(). (Could also use qsort(), but it could allocate memory.) -static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip) +static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive* pZip) { - mz_zip_internal_state *pState = pZip->m_pState; - const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets; - const mz_zip_array *pCentral_dir = &pState->m_central_dir; - mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0); - const int size = pZip->m_total_files; - int start = (size - 2) >> 1, end; - while (start >= 0) - { - int child, root = start; - for ( ; ; ) - { - if ((child = (root << 1) + 1) >= size) - break; - child += (((child + 1) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1]))); - if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child])) - break; - MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child; - } - start--; - } + mz_zip_internal_state* pState = pZip->m_pState; + const mz_zip_array* pCentral_dir_offsets = &pState->m_central_dir_offsets; + const mz_zip_array* pCentral_dir = &pState->m_central_dir; + mz_uint32* pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0); + const int size = pZip->m_total_files; + int start = (size - 2) >> 1, end; + while (start >= 0) + { + int child, root = start; + for (; ;) + { + if ((child = (root << 1) + 1) >= size) + break; + child += (((child + 1) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, + pIndices[child], pIndices[child + 1]))); + if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child])) + break; + MZ_SWAP_UINT32(pIndices[root], pIndices[child]); + root = child; + } + start--; + } - end = size - 1; - while (end > 0) - { - int child, root = 0; - MZ_SWAP_UINT32(pIndices[end], pIndices[0]); - for ( ; ; ) - { - if ((child = (root << 1) + 1) >= end) - break; - child += (((child + 1) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1])); - if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child])) - break; - MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child; - } - end--; - } + end = size - 1; + while (end > 0) + { + int child, root = 0; + MZ_SWAP_UINT32(pIndices[end], pIndices[0]); + for (; ;) + { + if ((child = (root << 1) + 1) >= end) + break; + child += (((child + 1) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, + pIndices[child], pIndices[child + 1])); + if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child])) + break; + MZ_SWAP_UINT32(pIndices[root], pIndices[child]); + root = child; + } + end--; + } } -static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint32 flags) +static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive* pZip, mz_uint32 flags) { - mz_uint cdir_size, num_this_disk, cdir_disk_index; - mz_uint64 cdir_ofs; - mz_int64 cur_file_ofs; - const mz_uint8 *p; - mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; mz_uint8 *pBuf = (mz_uint8 *)buf_u32; - mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0); - // Basic sanity checks - reject files which are too small, and check the first 4 bytes of the file to make sure a local header is there. - if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) - return MZ_FALSE; - // Find the end of central directory record by scanning the file from the end towards the beginning. - cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0); - for ( ; ; ) - { - int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs); - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n) - return MZ_FALSE; - for (i = n - 4; i >= 0; --i) - if (MZ_READ_LE32(pBuf + i) == MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) - break; - if (i >= 0) - { - cur_file_ofs += i; - break; - } - if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (0xFFFF + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE))) - return MZ_FALSE; - cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0); - } - // Read and verify the end of central directory record. - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) - return MZ_FALSE; - if ((MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) || - ((pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS)) != MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS))) - return MZ_FALSE; + mz_uint cdir_size, num_this_disk, cdir_disk_index; + mz_uint64 cdir_ofs; + mz_int64 cur_file_ofs; + const mz_uint8* p; + mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; + mz_uint8* pBuf = (mz_uint8*)buf_u32; + mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0); + // Basic sanity checks - reject files which are too small, and check the first 4 bytes of the file to make sure a local header is there. + if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) + return MZ_FALSE; + // Find the end of central directory record by scanning the file from the end towards the beginning. + cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0); + for (; ;) + { + int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs); + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n) + return MZ_FALSE; + for (i = n - 4; i >= 0; --i) + if (MZ_READ_LE32(pBuf + i) == MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) + break; + if (i >= 0) + { + cur_file_ofs += i; + break; + } + if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (0xFFFF + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)) + ) + return MZ_FALSE; + cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0); + } + // Read and verify the end of central directory record. + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) + return MZ_FALSE; + if ((MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) || + ((pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS)) != MZ_READ_LE16( + pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS))) + return MZ_FALSE; - num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS); - cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS); - if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1))) - return MZ_FALSE; + num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS); + cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS); + if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1))) + return MZ_FALSE; - if ((cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS)) < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) - return MZ_FALSE; + if ((cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS)) < pZip->m_total_files * + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) + return MZ_FALSE; - cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS); - if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size) - return MZ_FALSE; + cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS); + if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size) + return MZ_FALSE; - pZip->m_central_directory_file_ofs = cdir_ofs; + pZip->m_central_directory_file_ofs = cdir_ofs; - if (pZip->m_total_files) - { - mz_uint i, n; + if (pZip->m_total_files) + { + mz_uint i, n; - // Read the entire central directory into a heap block, and allocate another heap block to hold the unsorted central dir file record offsets, and another to hold the sorted indices. - if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) || - (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE))) - return MZ_FALSE; + // Read the entire central directory into a heap block, and allocate another heap block to hold the unsorted central dir file record offsets, and another to hold the sorted indices. + if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) || + (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE))) + return MZ_FALSE; - if (sort_central_dir) - { - if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE)) - return MZ_FALSE; - } + if (sort_central_dir) + { + if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE)) + return MZ_FALSE; + } - if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size) - return MZ_FALSE; + if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size) + return MZ_FALSE; - // Now create an index into the central directory file records, do some basic sanity checking on each record, and check for zip64 entries (which are not yet supported). - p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p; - for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i) - { - mz_uint total_header_size, comp_size, decomp_size, disk_index; - if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)) - return MZ_FALSE; - MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, i) = (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p); - if (sort_central_dir) - MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i; - comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); - decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); - if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size) || (decomp_size == 0xFFFFFFFF) || (comp_size == 0xFFFFFFFF)) - return MZ_FALSE; - disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS); - if ((disk_index != num_this_disk) && (disk_index != 1)) - return MZ_FALSE; - if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size) - return MZ_FALSE; - if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > n) - return MZ_FALSE; - n -= total_header_size; p += total_header_size; - } - } + // Now create an index into the central directory file records, do some basic sanity checking on each record, and check for zip64 entries (which are not yet supported). + p = (const mz_uint8*)pZip->m_pState->m_central_dir.m_p; + for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i) + { + mz_uint total_header_size, comp_size, decomp_size, disk_index; + if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)) + return MZ_FALSE; + MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, i) = (mz_uint32)(p - (const mz_uint8*) + pZip->m_pState->m_central_dir.m_p); + if (sort_central_dir) + MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i; + comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); + decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); + if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size) + || (decomp_size == 0xFFFFFFFF) || (comp_size == 0xFFFFFFFF)) + return MZ_FALSE; + disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS); + if ((disk_index != num_this_disk) && (disk_index != 1)) + return MZ_FALSE; + if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > + pZip->m_archive_size) + return MZ_FALSE; + if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > n) + return MZ_FALSE; + n -= total_header_size; + p += total_header_size; + } + } - if (sort_central_dir) - mz_zip_reader_sort_central_dir_offsets_by_filename(pZip); + if (sort_central_dir) + mz_zip_reader_sort_central_dir_offsets_by_filename(pZip); - return MZ_TRUE; + return MZ_TRUE; } -mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags) +mz_bool mz_zip_reader_init(mz_zip_archive* pZip, mz_uint64 size, mz_uint32 flags) { - if ((!pZip) || (!pZip->m_pRead)) - return MZ_FALSE; - if (!mz_zip_reader_init_internal(pZip, flags)) - return MZ_FALSE; - pZip->m_archive_size = size; - if (!mz_zip_reader_read_central_dir(pZip, flags)) - { - mz_zip_reader_end(pZip); - return MZ_FALSE; - } - return MZ_TRUE; + if ((!pZip) || (!pZip->m_pRead)) + return MZ_FALSE; + if (!mz_zip_reader_init_internal(pZip, flags)) + return MZ_FALSE; + pZip->m_archive_size = size; + if (!mz_zip_reader_read_central_dir(pZip, flags)) + { + mz_zip_reader_end(pZip); + return MZ_FALSE; + } + return MZ_TRUE; } -static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n) +static size_t mz_zip_mem_read_func(void* pOpaque, mz_uint64 file_ofs, void* pBuf, size_t n) { - mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; - size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n); - memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s); - return s; + mz_zip_archive* pZip = (mz_zip_archive*)pOpaque; + size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n); + memcpy(pBuf, (const mz_uint8*)pZip->m_pState->m_pMem + file_ofs, s); + return s; } -mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags) +mz_bool mz_zip_reader_init_mem(mz_zip_archive* pZip, const void* pMem, size_t size, mz_uint32 flags) { - if (!mz_zip_reader_init_internal(pZip, flags)) - return MZ_FALSE; - pZip->m_archive_size = size; - pZip->m_pRead = mz_zip_mem_read_func; - pZip->m_pIO_opaque = pZip; + if (!mz_zip_reader_init_internal(pZip, flags)) + return MZ_FALSE; + pZip->m_archive_size = size; + pZip->m_pRead = mz_zip_mem_read_func; + pZip->m_pIO_opaque = pZip; #ifdef __cplusplus - pZip->m_pState->m_pMem = const_cast(pMem); + pZip->m_pState->m_pMem = const_cast(pMem); #else pZip->m_pState->m_pMem = (void *)pMem; #endif - pZip->m_pState->m_mem_size = size; - if (!mz_zip_reader_read_central_dir(pZip, flags)) - { - mz_zip_reader_end(pZip); - return MZ_FALSE; - } - return MZ_TRUE; + pZip->m_pState->m_mem_size = size; + if (!mz_zip_reader_read_central_dir(pZip, flags)) + { + mz_zip_reader_end(pZip); + return MZ_FALSE; + } + return MZ_TRUE; } #ifndef MINIZ_NO_STDIO -static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n) +static size_t mz_zip_file_read_func(void* pOpaque, mz_uint64 file_ofs, void* pBuf, size_t n) { - mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; - mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile); - if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET)))) - return 0; - return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile); + mz_zip_archive* pZip = (mz_zip_archive*)pOpaque; + mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile); + if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64( + pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET)))) + return 0; + return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile); } -mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags) +mz_bool mz_zip_reader_init_file(mz_zip_archive* pZip, const char* pFilename, mz_uint32 flags) { - mz_uint64 file_size; - MZ_FILE *pFile = MZ_FOPEN(pFilename, "rb"); - if (!pFile) - return MZ_FALSE; - if (MZ_FSEEK64(pFile, 0, SEEK_END)) - { - MZ_FCLOSE(pFile); - return MZ_FALSE; - } - file_size = MZ_FTELL64(pFile); - if (!mz_zip_reader_init_internal(pZip, flags)) - { - MZ_FCLOSE(pFile); - return MZ_FALSE; - } - pZip->m_pRead = mz_zip_file_read_func; - pZip->m_pIO_opaque = pZip; - pZip->m_pState->m_pFile = pFile; - pZip->m_archive_size = file_size; - if (!mz_zip_reader_read_central_dir(pZip, flags)) - { - mz_zip_reader_end(pZip); - return MZ_FALSE; - } - return MZ_TRUE; + mz_uint64 file_size; + MZ_FILE* pFile = MZ_FOPEN(pFilename, "rb"); + if (!pFile) + return MZ_FALSE; + if (MZ_FSEEK64(pFile, 0, SEEK_END)) + { + MZ_FCLOSE(pFile); + return MZ_FALSE; + } + file_size = MZ_FTELL64(pFile); + if (!mz_zip_reader_init_internal(pZip, flags)) + { + MZ_FCLOSE(pFile); + return MZ_FALSE; + } + pZip->m_pRead = mz_zip_file_read_func; + pZip->m_pIO_opaque = pZip; + pZip->m_pState->m_pFile = pFile; + pZip->m_archive_size = file_size; + if (!mz_zip_reader_read_central_dir(pZip, flags)) + { + mz_zip_reader_end(pZip); + return MZ_FALSE; + } + return MZ_TRUE; } #endif // #ifndef MINIZ_NO_STDIO -mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip) +mz_uint mz_zip_reader_get_num_files(mz_zip_archive* pZip) { - return pZip ? pZip->m_total_files : 0; + return pZip ? pZip->m_total_files : 0; } -static MZ_FORCEINLINE const mz_uint8 *mz_zip_reader_get_cdh(mz_zip_archive *pZip, mz_uint file_index) +static MZ_FORCEINLINE const mz_uint8* mz_zip_reader_get_cdh(mz_zip_archive* pZip, mz_uint file_index) { - if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) - return NULL; - return &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index)); + if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) + return NULL; + return &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, + MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index)); } -mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index) +mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive* pZip, mz_uint file_index) { - mz_uint m_bit_flag; - const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); - if (!p) - return MZ_FALSE; - m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); - return (m_bit_flag & 1); + mz_uint m_bit_flag; + const mz_uint8* p = mz_zip_reader_get_cdh(pZip, file_index); + if (!p) + return MZ_FALSE; + m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); + return (m_bit_flag & 1); } -mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index) +mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive* pZip, mz_uint file_index) { - mz_uint filename_len, external_attr; - const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); - if (!p) - return MZ_FALSE; + mz_uint filename_len, external_attr; + const mz_uint8* p = mz_zip_reader_get_cdh(pZip, file_index); + if (!p) + return MZ_FALSE; - // First see if the filename ends with a '/' character. - filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); - if (filename_len) - { - if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/') - return MZ_TRUE; - } + // First see if the filename ends with a '/' character. + filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); + if (filename_len) + { + if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/') + return MZ_TRUE; + } - // Bugfix: This code was also checking if the internal attribute was non-zero, which wasn't correct. - // Most/all zip writers (hopefully) set DOS file/directory attributes in the low 16-bits, so check for the DOS directory flag and ignore the source OS ID in the created by field. - // FIXME: Remove this check? Is it necessary - we already check the filename. - external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS); - if ((external_attr & 0x10) != 0) - return MZ_TRUE; + // Bugfix: This code was also checking if the internal attribute was non-zero, which wasn't correct. + // Most/all zip writers (hopefully) set DOS file/directory attributes in the low 16-bits, so check for the DOS directory flag and ignore the source OS ID in the created by field. + // FIXME: Remove this check? Is it necessary - we already check the filename. + external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS); + if ((external_attr & 0x10) != 0) + return MZ_TRUE; - return MZ_FALSE; + return MZ_FALSE; } -mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat) +mz_bool mz_zip_reader_file_stat(mz_zip_archive* pZip, mz_uint file_index, mz_zip_archive_file_stat* pStat) { - mz_uint n; - const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); - if ((!p) || (!pStat)) - return MZ_FALSE; + mz_uint n; + const mz_uint8* p = mz_zip_reader_get_cdh(pZip, file_index); + if ((!p) || (!pStat)) + return MZ_FALSE; - // Unpack the central directory record. - pStat->m_file_index = file_index; - pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index); - pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS); - pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS); - pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); - pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS); + // Unpack the central directory record. + pStat->m_file_index = file_index; + pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index); + pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS); + pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS); + pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); + pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS); #ifndef MINIZ_NO_TIME - pStat->m_time = mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS), MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS)); + pStat->m_time = mz_zip_dos_to_time_t( + MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS), MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS)); #endif - pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS); - pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); - pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); - pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS); - pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS); - pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS); + pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS); + pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); + pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); + pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS); + pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS); + pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS); - // Copy as much of the filename and comment as possible. - n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1); - memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); pStat->m_filename[n] = '\0'; + // Copy as much of the filename and comment as possible. + n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); + n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1); + memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); + pStat->m_filename[n] = '\0'; - n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1); - pStat->m_comment_size = n; - memcpy(pStat->m_comment, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS), n); pStat->m_comment[n] = '\0'; + n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS); + n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1); + pStat->m_comment_size = n; + memcpy(pStat->m_comment, + p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16( + p + MZ_ZIP_CDH_EXTRA_LEN_OFS), n); + pStat->m_comment[n] = '\0'; - return MZ_TRUE; + return MZ_TRUE; } -mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size) +mz_uint mz_zip_reader_get_filename(mz_zip_archive* pZip, mz_uint file_index, char* pFilename, mz_uint filename_buf_size) { - mz_uint n; - const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); - if (!p) { if (filename_buf_size) pFilename[0] = '\0'; return 0; } - n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); - if (filename_buf_size) - { - n = MZ_MIN(n, filename_buf_size - 1); - memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); - pFilename[n] = '\0'; - } - return n + 1; + mz_uint n; + const mz_uint8* p = mz_zip_reader_get_cdh(pZip, file_index); + if (!p) + { + if (filename_buf_size) pFilename[0] = '\0'; + return 0; + } + n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); + if (filename_buf_size) + { + n = MZ_MIN(n, filename_buf_size - 1); + memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); + pFilename[n] = '\0'; + } + return n + 1; } -static MZ_FORCEINLINE mz_bool mz_zip_reader_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags) +static MZ_FORCEINLINE mz_bool mz_zip_reader_string_equal(const char* pA, const char* pB, mz_uint len, mz_uint flags) { - mz_uint i; - if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE) - return 0 == memcmp(pA, pB, len); - for (i = 0; i < len; ++i) - if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i])) - return MZ_FALSE; - return MZ_TRUE; + mz_uint i; + if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE) + return 0 == memcmp(pA, pB, len); + for (i = 0; i < len; ++i) + if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i])) + return MZ_FALSE; + return MZ_TRUE; } -static MZ_FORCEINLINE int mz_zip_reader_filename_compare(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, const char *pR, mz_uint r_len) +static MZ_FORCEINLINE int mz_zip_reader_filename_compare(const mz_zip_array* pCentral_dir_array, + const mz_zip_array* pCentral_dir_offsets, mz_uint l_index, + const char* pR, mz_uint r_len) { - const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE; - mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS); - mz_uint8 l = 0, r = 0; - pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; - pE = pL + MZ_MIN(l_len, r_len); - while (pL < pE) - { - if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) - break; - pL++; pR++; - } - return (pL == pE) ? (int)(l_len - r_len) : (l - r); + const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, + MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE; + mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS); + mz_uint8 l = 0, r = 0; + pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; + pE = pL + MZ_MIN(l_len, r_len); + while (pL < pE) + { + if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) + break; + pL++; + pR++; + } + return (pL == pE) ? (int)(l_len - r_len) : (l - r); } -static int mz_zip_reader_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename) +static int mz_zip_reader_locate_file_binary_search(mz_zip_archive* pZip, const char* pFilename) { - mz_zip_internal_state *pState = pZip->m_pState; - const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets; - const mz_zip_array *pCentral_dir = &pState->m_central_dir; - mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0); - const int size = pZip->m_total_files; - const mz_uint filename_len = (mz_uint)strlen(pFilename); - int l = 0, h = size - 1; - while (l <= h) - { - int m = (l + h) >> 1, file_index = pIndices[m], comp = mz_zip_reader_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len); - if (!comp) - return file_index; - else if (comp < 0) - l = m + 1; - else - h = m - 1; - } - return -1; + mz_zip_internal_state* pState = pZip->m_pState; + const mz_zip_array* pCentral_dir_offsets = &pState->m_central_dir_offsets; + const mz_zip_array* pCentral_dir = &pState->m_central_dir; + mz_uint32* pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0); + const int size = pZip->m_total_files; + const mz_uint filename_len = (mz_uint)strlen(pFilename); + int l = 0, h = size - 1; + while (l <= h) + { + int m = (l + h) >> 1, file_index = pIndices[m], comp = mz_zip_reader_filename_compare( + pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len); + if (!comp) + return file_index; + else if (comp < 0) + l = m + 1; + else + h = m - 1; + } + return -1; } -int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags) +int mz_zip_reader_locate_file(mz_zip_archive* pZip, const char* pName, const char* pComment, mz_uint flags) { - mz_uint file_index; size_t name_len, comment_len; - if ((!pZip) || (!pZip->m_pState) || (!pName) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) - return -1; - if (((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size)) - return mz_zip_reader_locate_file_binary_search(pZip, pName); - name_len = strlen(pName); if (name_len > 0xFFFF) return -1; - comment_len = pComment ? strlen(pComment) : 0; if (comment_len > 0xFFFF) return -1; - for (file_index = 0; file_index < pZip->m_total_files; file_index++) - { - const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index)); - mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS); - const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; - if (filename_len < name_len) - continue; - if (comment_len) - { - mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS), file_comment_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS); - const char *pFile_comment = pFilename + filename_len + file_extra_len; - if ((file_comment_len != comment_len) || (!mz_zip_reader_string_equal(pComment, pFile_comment, file_comment_len, flags))) - continue; - } - if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len)) - { - int ofs = filename_len - 1; - do - { - if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':')) - break; - } while (--ofs >= 0); - ofs++; - pFilename += ofs; filename_len -= ofs; - } - if ((filename_len == name_len) && (mz_zip_reader_string_equal(pName, pFilename, filename_len, flags))) - return file_index; - } - return -1; + mz_uint file_index; + size_t name_len, comment_len; + if ((!pZip) || (!pZip->m_pState) || (!pName) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) + return -1; + if (((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState-> + m_sorted_central_dir_offsets.m_size)) + return mz_zip_reader_locate_file_binary_search(pZip, pName); + name_len = strlen(pName); + if (name_len > 0xFFFF) return -1; + comment_len = pComment ? strlen(pComment) : 0; + if (comment_len > 0xFFFF) return -1; + for (file_index = 0; file_index < pZip->m_total_files; file_index++) + { + const mz_uint8* pHeader = &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, + MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, + mz_uint32, file_index)); + mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS); + const char* pFilename = (const char*)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; + if (filename_len < name_len) + continue; + if (comment_len) + { + mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS), file_comment_len = MZ_READ_LE16( + pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS); + const char* pFile_comment = pFilename + filename_len + file_extra_len; + if ((file_comment_len != comment_len) || (!mz_zip_reader_string_equal( + pComment, pFile_comment, file_comment_len, flags))) + continue; + } + if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len)) + { + int ofs = filename_len - 1; + do + { + if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':')) + break; + } + while (--ofs >= 0); + ofs++; + pFilename += ofs; + filename_len -= ofs; + } + if ((filename_len == name_len) && (mz_zip_reader_string_equal(pName, pFilename, filename_len, flags))) + return file_index; + } + return -1; } -mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size) +mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive* pZip, mz_uint file_index, void* pBuf, size_t buf_size, + mz_uint flags, void* pUser_read_buf, size_t user_read_buf_size) { - int status = TINFL_STATUS_DONE; - mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail; - mz_zip_archive_file_stat file_stat; - void *pRead_buf; - mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; - tinfl_decompressor inflator; + int status = TINFL_STATUS_DONE; + mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, + read_buf_avail; + mz_zip_archive_file_stat file_stat; + void* pRead_buf; + mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; + mz_uint8* pLocal_header = (mz_uint8*)local_header_u32; + tinfl_decompressor inflator; - if ((buf_size) && (!pBuf)) - return MZ_FALSE; + if ((buf_size) && (!pBuf)) + return MZ_FALSE; - if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) - return MZ_FALSE; + if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) + return MZ_FALSE; - // Empty file, or a directory (but not always a directory - I've seen odd zips with directories that have compressed data which inflates to 0 bytes) - if (!file_stat.m_comp_size) - return MZ_TRUE; + // Empty file, or a directory (but not always a directory - I've seen odd zips with directories that have compressed data which inflates to 0 bytes) + if (!file_stat.m_comp_size) + return MZ_TRUE; - // Entry is a subdirectory (I've seen old zips with dir entries which have compressed deflate data which inflates to 0 bytes, but these entries claim to uncompress to 512 bytes in the headers). - // I'm torn how to handle this case - should it fail instead? - if (mz_zip_reader_is_file_a_directory(pZip, file_index)) - return MZ_TRUE; + // Entry is a subdirectory (I've seen old zips with dir entries which have compressed deflate data which inflates to 0 bytes, but these entries claim to uncompress to 512 bytes in the headers). + // I'm torn how to handle this case - should it fail instead? + if (mz_zip_reader_is_file_a_directory(pZip, file_index)) + return MZ_TRUE; - // Encryption and patch files are not supported. - if (file_stat.m_bit_flag & (1 | 32)) - return MZ_FALSE; + // Encryption and patch files are not supported. + if (file_stat.m_bit_flag & (1 | 32)) + return MZ_FALSE; - // This function only supports stored and deflate. - if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) - return MZ_FALSE; + // This function only supports stored and deflate. + if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) + return MZ_FALSE; - // Ensure supplied output buffer is large enough. - needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size; - if (buf_size < needed_size) - return MZ_FALSE; + // Ensure supplied output buffer is large enough. + needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size; + if (buf_size < needed_size) + return MZ_FALSE; - // Read and parse the local directory entry. - cur_file_ofs = file_stat.m_local_header_ofs; - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) - return MZ_FALSE; - if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) - return MZ_FALSE; + // Read and parse the local directory entry. + cur_file_ofs = file_stat.m_local_header_ofs; + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + return MZ_FALSE; + if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) + return MZ_FALSE; - cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); - if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) - return MZ_FALSE; + cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); + if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) + return MZ_FALSE; - if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) - { - // The file is stored or the caller has requested the compressed data. - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size) - return MZ_FALSE; - return ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) != 0) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) == file_stat.m_crc32); - } + if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) + { + // The file is stored or the caller has requested the compressed data. + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size) + return MZ_FALSE; + return ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) != 0) || (mz_crc32( + MZ_CRC32_INIT, (const mz_uint8*)pBuf, (size_t)file_stat.m_uncomp_size) == file_stat.m_crc32); + } - // Decompress the file either directly from memory or from a file input buffer. - tinfl_init(&inflator); + // Decompress the file either directly from memory or from a file input buffer. + tinfl_init(&inflator); - if (pZip->m_pState->m_pMem) - { - // Read directly from the archive in memory. - pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs; - read_buf_size = read_buf_avail = file_stat.m_comp_size; - comp_remaining = 0; - } - else if (pUser_read_buf) - { - // Use a user provided read buffer. - if (!user_read_buf_size) - return MZ_FALSE; - pRead_buf = (mz_uint8 *)pUser_read_buf; - read_buf_size = user_read_buf_size; - read_buf_avail = 0; - comp_remaining = file_stat.m_comp_size; - } - else - { - // Temporarily allocate a read buffer. - read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE); + if (pZip->m_pState->m_pMem) + { + // Read directly from the archive in memory. + pRead_buf = (mz_uint8*)pZip->m_pState->m_pMem + cur_file_ofs; + read_buf_size = read_buf_avail = file_stat.m_comp_size; + comp_remaining = 0; + } + else if (pUser_read_buf) + { + // Use a user provided read buffer. + if (!user_read_buf_size) + return MZ_FALSE; + pRead_buf = (mz_uint8*)pUser_read_buf; + read_buf_size = user_read_buf_size; + read_buf_avail = 0; + comp_remaining = file_stat.m_comp_size; + } + else + { + // Temporarily allocate a read buffer. + read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE); #ifdef _MSC_VER - if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF)) + if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF)) #else if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF)) #endif - return MZ_FALSE; - if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) - return MZ_FALSE; - read_buf_avail = 0; - comp_remaining = file_stat.m_comp_size; - } + return MZ_FALSE; + if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) + return MZ_FALSE; + read_buf_avail = 0; + comp_remaining = file_stat.m_comp_size; + } - do - { - size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs); - if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) - { - read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) - { - status = TINFL_STATUS_FAILED; - break; - } - cur_file_ofs += read_buf_avail; - comp_remaining -= read_buf_avail; - read_buf_ofs = 0; - } - in_buf_size = (size_t)read_buf_avail; - status = tinfl_decompress(&inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0)); - read_buf_avail -= in_buf_size; - read_buf_ofs += in_buf_size; - out_buf_ofs += out_buf_size; - } while (status == TINFL_STATUS_NEEDS_MORE_INPUT); + do + { + size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs); + if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) + { + read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) + { + status = TINFL_STATUS_FAILED; + break; + } + cur_file_ofs += read_buf_avail; + comp_remaining -= read_buf_avail; + read_buf_ofs = 0; + } + in_buf_size = (size_t)read_buf_avail; + status = tinfl_decompress(&inflator, (mz_uint8*)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8*)pBuf, + (mz_uint8*)pBuf + out_buf_ofs, &out_buf_size, + TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | (comp_remaining + ? TINFL_FLAG_HAS_MORE_INPUT + : 0)); + read_buf_avail -= in_buf_size; + read_buf_ofs += in_buf_size; + out_buf_ofs += out_buf_size; + } + while (status == TINFL_STATUS_NEEDS_MORE_INPUT); - if (status == TINFL_STATUS_DONE) - { - // Make sure the entire file was decompressed, and check its CRC. - if ((out_buf_ofs != file_stat.m_uncomp_size) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)) - status = TINFL_STATUS_FAILED; - } + if (status == TINFL_STATUS_DONE) + { + // Make sure the entire file was decompressed, and check its CRC. + if ((out_buf_ofs != file_stat.m_uncomp_size) || (mz_crc32( + MZ_CRC32_INIT, (const mz_uint8*)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)) + status = TINFL_STATUS_FAILED; + } - if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf)) - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf)) + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - return status == TINFL_STATUS_DONE; + return status == TINFL_STATUS_DONE; } -mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size) +mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive* pZip, const char* pFilename, void* pBuf, + size_t buf_size, mz_uint flags, void* pUser_read_buf, + size_t user_read_buf_size) { - int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags); - if (file_index < 0) - return MZ_FALSE; - return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size); + int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags); + if (file_index < 0) + return MZ_FALSE; + return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, + user_read_buf_size); } -mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags) +mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive* pZip, mz_uint file_index, void* pBuf, size_t buf_size, + mz_uint flags) { - return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0); + return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0); } -mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags) +mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive* pZip, const char* pFilename, void* pBuf, size_t buf_size, + mz_uint flags) { - return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0); + return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0); } -void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags) +void* mz_zip_reader_extract_to_heap(mz_zip_archive* pZip, mz_uint file_index, size_t* pSize, mz_uint flags) { - mz_uint64 comp_size, uncomp_size, alloc_size; - const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); - void *pBuf; + mz_uint64 comp_size, uncomp_size, alloc_size; + const mz_uint8* p = mz_zip_reader_get_cdh(pZip, file_index); + void* pBuf; - if (pSize) - *pSize = 0; - if (!p) - return NULL; + if (pSize) + *pSize = 0; + if (!p) + return NULL; - comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); - uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); + comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); + uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); - alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size; + alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size; #ifdef _MSC_VER - if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF)) + if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF)) #else if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF)) #endif - return NULL; - if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size))) - return NULL; + return NULL; + if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size))) + return NULL; - if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags)) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - return NULL; - } + if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags)) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return NULL; + } - if (pSize) *pSize = (size_t)alloc_size; - return pBuf; + if (pSize) *pSize = (size_t)alloc_size; + return pBuf; } -void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags) +void* mz_zip_reader_extract_file_to_heap(mz_zip_archive* pZip, const char* pFilename, size_t* pSize, mz_uint flags) { - int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags); - if (file_index < 0) - { - if (pSize) *pSize = 0; - return MZ_FALSE; - } - return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags); + int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags); + if (file_index < 0) + { + if (pSize) *pSize = 0; + return MZ_FALSE; + } + return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags); } -mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags) +mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive* pZip, mz_uint file_index, mz_file_write_func pCallback, + void* pOpaque, mz_uint flags) { - int status = TINFL_STATUS_DONE; mz_uint file_crc32 = MZ_CRC32_INIT; - mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs; - mz_zip_archive_file_stat file_stat; - void *pRead_buf = NULL; void *pWrite_buf = NULL; - mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; + int status = TINFL_STATUS_DONE; + mz_uint file_crc32 = MZ_CRC32_INIT; + mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs; + mz_zip_archive_file_stat file_stat; + void* pRead_buf = NULL; + void* pWrite_buf = NULL; + mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; + mz_uint8* pLocal_header = (mz_uint8*)local_header_u32; - if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) - return MZ_FALSE; + if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) + return MZ_FALSE; - // Empty file, or a directory (but not always a directory - I've seen odd zips with directories that have compressed data which inflates to 0 bytes) - if (!file_stat.m_comp_size) - return MZ_TRUE; + // Empty file, or a directory (but not always a directory - I've seen odd zips with directories that have compressed data which inflates to 0 bytes) + if (!file_stat.m_comp_size) + return MZ_TRUE; - // Entry is a subdirectory (I've seen old zips with dir entries which have compressed deflate data which inflates to 0 bytes, but these entries claim to uncompress to 512 bytes in the headers). - // I'm torn how to handle this case - should it fail instead? - if (mz_zip_reader_is_file_a_directory(pZip, file_index)) - return MZ_TRUE; + // Entry is a subdirectory (I've seen old zips with dir entries which have compressed deflate data which inflates to 0 bytes, but these entries claim to uncompress to 512 bytes in the headers). + // I'm torn how to handle this case - should it fail instead? + if (mz_zip_reader_is_file_a_directory(pZip, file_index)) + return MZ_TRUE; - // Encryption and patch files are not supported. - if (file_stat.m_bit_flag & (1 | 32)) - return MZ_FALSE; + // Encryption and patch files are not supported. + if (file_stat.m_bit_flag & (1 | 32)) + return MZ_FALSE; - // This function only supports stored and deflate. - if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) - return MZ_FALSE; + // This function only supports stored and deflate. + if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) + return MZ_FALSE; - // Read and parse the local directory entry. - cur_file_ofs = file_stat.m_local_header_ofs; - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) - return MZ_FALSE; - if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) - return MZ_FALSE; + // Read and parse the local directory entry. + cur_file_ofs = file_stat.m_local_header_ofs; + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + return MZ_FALSE; + if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) + return MZ_FALSE; - cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); - if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) - return MZ_FALSE; + cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); + if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) + return MZ_FALSE; - // Decompress the file either directly from memory or from a file input buffer. - if (pZip->m_pState->m_pMem) - { - pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs; - read_buf_size = read_buf_avail = file_stat.m_comp_size; - comp_remaining = 0; - } - else - { - read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE); - if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) - return MZ_FALSE; - read_buf_avail = 0; - comp_remaining = file_stat.m_comp_size; - } + // Decompress the file either directly from memory or from a file input buffer. + if (pZip->m_pState->m_pMem) + { + pRead_buf = (mz_uint8*)pZip->m_pState->m_pMem + cur_file_ofs; + read_buf_size = read_buf_avail = file_stat.m_comp_size; + comp_remaining = 0; + } + else + { + read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE); + if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) + return MZ_FALSE; + read_buf_avail = 0; + comp_remaining = file_stat.m_comp_size; + } - if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) - { - // The file is stored or the caller has requested the compressed data. - if (pZip->m_pState->m_pMem) - { + if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) + { + // The file is stored or the caller has requested the compressed data. + if (pZip->m_pState->m_pMem) + { #ifdef _MSC_VER - if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF)) + if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF)) #else if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF)) #endif - return MZ_FALSE; - if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size) - status = TINFL_STATUS_FAILED; - else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) - file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size); - cur_file_ofs += file_stat.m_comp_size; - out_buf_ofs += file_stat.m_comp_size; - comp_remaining = 0; - } - else - { - while (comp_remaining) - { - read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) - { - status = TINFL_STATUS_FAILED; - break; - } + return MZ_FALSE; + if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size) + status = TINFL_STATUS_FAILED; + else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) + file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8*)pRead_buf, (size_t)file_stat.m_comp_size); + cur_file_ofs += file_stat.m_comp_size; + out_buf_ofs += file_stat.m_comp_size; + comp_remaining = 0; + } + else + { + while (comp_remaining) + { + read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) + { + status = TINFL_STATUS_FAILED; + break; + } - if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) - file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail); + if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) + file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8*)pRead_buf, (size_t)read_buf_avail); - if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) - { - status = TINFL_STATUS_FAILED; - break; - } - cur_file_ofs += read_buf_avail; - out_buf_ofs += read_buf_avail; - comp_remaining -= read_buf_avail; - } - } - } - else - { - tinfl_decompressor inflator; - tinfl_init(&inflator); + if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) + { + status = TINFL_STATUS_FAILED; + break; + } + cur_file_ofs += read_buf_avail; + out_buf_ofs += read_buf_avail; + comp_remaining -= read_buf_avail; + } + } + } + else + { + tinfl_decompressor inflator; + tinfl_init(&inflator); - if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE))) - status = TINFL_STATUS_FAILED; - else - { - do - { - mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1)); - size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1)); - if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) - { - read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) - { - status = TINFL_STATUS_FAILED; - break; - } - cur_file_ofs += read_buf_avail; - comp_remaining -= read_buf_avail; - read_buf_ofs = 0; - } + if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE))) + status = TINFL_STATUS_FAILED; + else + { + do + { + mz_uint8* pWrite_buf_cur = (mz_uint8*)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1)); + size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1)); + if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) + { + read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) + { + status = TINFL_STATUS_FAILED; + break; + } + cur_file_ofs += read_buf_avail; + comp_remaining -= read_buf_avail; + read_buf_ofs = 0; + } - in_buf_size = (size_t)read_buf_avail; - status = tinfl_decompress(&inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size, comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0); - read_buf_avail -= in_buf_size; - read_buf_ofs += in_buf_size; + in_buf_size = (size_t)read_buf_avail; + status = tinfl_decompress(&inflator, (const mz_uint8*)pRead_buf + read_buf_ofs, &in_buf_size, + (mz_uint8*)pWrite_buf, pWrite_buf_cur, &out_buf_size, + comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0); + read_buf_avail -= in_buf_size; + read_buf_ofs += in_buf_size; - if (out_buf_size) - { - if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size) - { - status = TINFL_STATUS_FAILED; - break; - } - file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size); - if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size) - { - status = TINFL_STATUS_FAILED; - break; - } - } - } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT)); - } - } + if (out_buf_size) + { + if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size) + { + status = TINFL_STATUS_FAILED; + break; + } + file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size); + if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size) + { + status = TINFL_STATUS_FAILED; + break; + } + } + } + while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT)); + } + } - if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) - { - // Make sure the entire file was decompressed, and check its CRC. - if ((out_buf_ofs != file_stat.m_uncomp_size) || (file_crc32 != file_stat.m_crc32)) - status = TINFL_STATUS_FAILED; - } + if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) + { + // Make sure the entire file was decompressed, and check its CRC. + if ((out_buf_ofs != file_stat.m_uncomp_size) || (file_crc32 != file_stat.m_crc32)) + status = TINFL_STATUS_FAILED; + } - if (!pZip->m_pState->m_pMem) - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - if (pWrite_buf) - pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf); + if (!pZip->m_pState->m_pMem) + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + if (pWrite_buf) + pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf); - return status == TINFL_STATUS_DONE; + return status == TINFL_STATUS_DONE; } -mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags) +mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive* pZip, const char* pFilename, + mz_file_write_func pCallback, void* pOpaque, mz_uint flags) { - int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags); - if (file_index < 0) - return MZ_FALSE; - return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags); + int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags); + if (file_index < 0) + return MZ_FALSE; + return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags); } #ifndef MINIZ_NO_STDIO -static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, const void *pBuf, size_t n) +static size_t mz_zip_file_write_callback(void* pOpaque, mz_uint64 ofs, const void* pBuf, size_t n) { - (void)ofs; return MZ_FWRITE(pBuf, 1, n, (MZ_FILE*)pOpaque); + (void)ofs; + return MZ_FWRITE(pBuf, 1, n, (MZ_FILE*)pOpaque); } -mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags) +mz_bool mz_zip_reader_extract_to_file(mz_zip_archive* pZip, mz_uint file_index, const char* pDst_filename, + mz_uint flags) { - mz_bool status; - mz_zip_archive_file_stat file_stat; - MZ_FILE *pFile; - if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) - return MZ_FALSE; - pFile = MZ_FOPEN(pDst_filename, "wb"); - if (!pFile) - return MZ_FALSE; - status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags); - if (MZ_FCLOSE(pFile) == EOF) - return MZ_FALSE; + mz_bool status; + mz_zip_archive_file_stat file_stat; + MZ_FILE* pFile; + if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) + return MZ_FALSE; + pFile = MZ_FOPEN(pDst_filename, "wb"); + if (!pFile) + return MZ_FALSE; + status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags); + if (MZ_FCLOSE(pFile) == EOF) + return MZ_FALSE; #ifndef MINIZ_NO_TIME - if (status) - mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time); + if (status) + mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time); #endif - return status; + return status; } #endif // #ifndef MINIZ_NO_STDIO -mz_bool mz_zip_reader_end(mz_zip_archive *pZip) +mz_bool mz_zip_reader_end(mz_zip_archive* pZip) { - if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) - return MZ_FALSE; + if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING + )) + return MZ_FALSE; - if (pZip->m_pState) - { - mz_zip_internal_state *pState = pZip->m_pState; pZip->m_pState = NULL; - mz_zip_array_clear(pZip, &pState->m_central_dir); - mz_zip_array_clear(pZip, &pState->m_central_dir_offsets); - mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets); + if (pZip->m_pState) + { + mz_zip_internal_state* pState = pZip->m_pState; + pZip->m_pState = NULL; + mz_zip_array_clear(pZip, &pState->m_central_dir); + mz_zip_array_clear(pZip, &pState->m_central_dir_offsets); + mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets); #ifndef MINIZ_NO_STDIO - if (pState->m_pFile) - { - MZ_FCLOSE(pState->m_pFile); - pState->m_pFile = NULL; - } + if (pState->m_pFile) + { + MZ_FCLOSE(pState->m_pFile); + pState->m_pFile = NULL; + } #endif // #ifndef MINIZ_NO_STDIO - pZip->m_pFree(pZip->m_pAlloc_opaque, pState); - } - pZip->m_zip_mode = MZ_ZIP_MODE_INVALID; + pZip->m_pFree(pZip->m_pAlloc_opaque, pState); + } + pZip->m_zip_mode = MZ_ZIP_MODE_INVALID; - return MZ_TRUE; + return MZ_TRUE; } #ifndef MINIZ_NO_STDIO -mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags) +mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive* pZip, const char* pArchive_filename, + const char* pDst_filename, mz_uint flags) { - int file_index = mz_zip_reader_locate_file(pZip, pArchive_filename, NULL, flags); - if (file_index < 0) - return MZ_FALSE; - return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags); + int file_index = mz_zip_reader_locate_file(pZip, pArchive_filename, NULL, flags); + if (file_index < 0) + return MZ_FALSE; + return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags); } #endif @@ -3207,916 +3932,1002 @@ mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pAr #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS -static void mz_write_le16(mz_uint8 *p, mz_uint16 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); } -static void mz_write_le32(mz_uint8 *p, mz_uint32 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); p[2] = (mz_uint8)(v >> 16); p[3] = (mz_uint8)(v >> 24); } +static void mz_write_le16(mz_uint8* p, mz_uint16 v) +{ + p[0] = (mz_uint8)v; + p[1] = (mz_uint8)(v >> 8); +} + +static void mz_write_le32(mz_uint8* p, mz_uint32 v) +{ + p[0] = (mz_uint8)v; + p[1] = (mz_uint8)(v >> 8); + p[2] = (mz_uint8)(v >> 16); + p[3] = (mz_uint8)(v >> 24); +} + #define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v)) #define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v)) -mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size) +mz_bool mz_zip_writer_init(mz_zip_archive* pZip, mz_uint64 existing_size) { - if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) - return MZ_FALSE; + if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) + return MZ_FALSE; - if (pZip->m_file_offset_alignment) - { - // Ensure user specified file offset alignment is a power of 2. - if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1)) - return MZ_FALSE; - } + if (pZip->m_file_offset_alignment) + { + // Ensure user specified file offset alignment is a power of 2. + if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1)) + return MZ_FALSE; + } - if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func; - if (!pZip->m_pFree) pZip->m_pFree = def_free_func; - if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func; + if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func; + if (!pZip->m_pFree) pZip->m_pFree = def_free_func; + if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func; - pZip->m_zip_mode = MZ_ZIP_MODE_WRITING; - pZip->m_archive_size = existing_size; - pZip->m_central_directory_file_ofs = 0; - pZip->m_total_files = 0; + pZip->m_zip_mode = MZ_ZIP_MODE_WRITING; + pZip->m_archive_size = existing_size; + pZip->m_central_directory_file_ofs = 0; + pZip->m_total_files = 0; - if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) - return MZ_FALSE; - memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32)); - return MZ_TRUE; + if (NULL == (pZip->m_pState = (mz_zip_internal_state*)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, + sizeof(mz_zip_internal_state)))) + return MZ_FALSE; + memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32)); + return MZ_TRUE; } -static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n) +static size_t mz_zip_heap_write_func(void* pOpaque, mz_uint64 file_ofs, const void* pBuf, size_t n) { - mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; - mz_zip_internal_state *pState = pZip->m_pState; - mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size); + mz_zip_archive* pZip = (mz_zip_archive*)pOpaque; + mz_zip_internal_state* pState = pZip->m_pState; + mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size); #ifdef _MSC_VER - if ((!n) || ((0, sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))) + if ((!n) || ((0, sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))) #else if ((!n) || ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))) #endif - return 0; - if (new_size > pState->m_mem_capacity) - { - void *pNew_block; - size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity); while (new_capacity < new_size) new_capacity *= 2; - if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity))) - return 0; - pState->m_pMem = pNew_block; pState->m_mem_capacity = new_capacity; - } - memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n); - pState->m_mem_size = (size_t)new_size; - return n; + return 0; + if (new_size > pState->m_mem_capacity) + { + void* pNew_block; + size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity); + while (new_capacity < new_size) new_capacity *= 2; + if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity))) + return 0; + pState->m_pMem = pNew_block; + pState->m_mem_capacity = new_capacity; + } + memcpy((mz_uint8*)pState->m_pMem + file_ofs, pBuf, n); + pState->m_mem_size = (size_t)new_size; + return n; } -mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size) +mz_bool mz_zip_writer_init_heap(mz_zip_archive* pZip, size_t size_to_reserve_at_beginning, + size_t initial_allocation_size) { - pZip->m_pWrite = mz_zip_heap_write_func; - pZip->m_pIO_opaque = pZip; - if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning)) - return MZ_FALSE; - if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning))) - { - if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size))) - { - mz_zip_writer_end(pZip); - return MZ_FALSE; - } - pZip->m_pState->m_mem_capacity = initial_allocation_size; - } - return MZ_TRUE; + pZip->m_pWrite = mz_zip_heap_write_func; + pZip->m_pIO_opaque = pZip; + if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning)) + return MZ_FALSE; + if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning))) + { + if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size))) + { + mz_zip_writer_end(pZip); + return MZ_FALSE; + } + pZip->m_pState->m_mem_capacity = initial_allocation_size; + } + return MZ_TRUE; } #ifndef MINIZ_NO_STDIO -static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n) +static size_t mz_zip_file_write_func(void* pOpaque, mz_uint64 file_ofs, const void* pBuf, size_t n) { - mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; - mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile); - if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET)))) - return 0; - return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile); + mz_zip_archive* pZip = (mz_zip_archive*)pOpaque; + mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile); + if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64( + pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET)))) + return 0; + return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile); } -mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning) +mz_bool mz_zip_writer_init_file(mz_zip_archive* pZip, const char* pFilename, mz_uint64 size_to_reserve_at_beginning) { - MZ_FILE *pFile; - pZip->m_pWrite = mz_zip_file_write_func; - pZip->m_pIO_opaque = pZip; - if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning)) - return MZ_FALSE; - if (NULL == (pFile = MZ_FOPEN(pFilename, "wb"))) - { - mz_zip_writer_end(pZip); - return MZ_FALSE; - } - pZip->m_pState->m_pFile = pFile; - if (size_to_reserve_at_beginning) - { - mz_uint64 cur_ofs = 0; char buf[4096]; MZ_CLEAR_OBJ(buf); - do - { - size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n) - { - mz_zip_writer_end(pZip); - return MZ_FALSE; - } - cur_ofs += n; size_to_reserve_at_beginning -= n; - } while (size_to_reserve_at_beginning); - } - return MZ_TRUE; + MZ_FILE* pFile; + pZip->m_pWrite = mz_zip_file_write_func; + pZip->m_pIO_opaque = pZip; + if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning)) + return MZ_FALSE; + if (NULL == (pFile = MZ_FOPEN(pFilename, "wb"))) + { + mz_zip_writer_end(pZip); + return MZ_FALSE; + } + pZip->m_pState->m_pFile = pFile; + if (size_to_reserve_at_beginning) + { + mz_uint64 cur_ofs = 0; + char buf[4096]; + MZ_CLEAR_OBJ(buf); + do + { + size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning); + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n) + { + mz_zip_writer_end(pZip); + return MZ_FALSE; + } + cur_ofs += n; + size_to_reserve_at_beginning -= n; + } + while (size_to_reserve_at_beginning); + } + return MZ_TRUE; } #endif // #ifndef MINIZ_NO_STDIO -mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename) +mz_bool mz_zip_writer_init_from_reader(mz_zip_archive* pZip, const char* pFilename) { - mz_zip_internal_state *pState; - if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) - return MZ_FALSE; - // No sense in trying to write to an archive that's already at the support max size - if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)) - return MZ_FALSE; + mz_zip_internal_state* pState; + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) + return MZ_FALSE; + // No sense in trying to write to an archive that's already at the support max size + if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)) + return MZ_FALSE; - pState = pZip->m_pState; + pState = pZip->m_pState; - if (pState->m_pFile) - { + if (pState->m_pFile) + { #ifdef MINIZ_NO_STDIO pFilename; return MZ_FALSE; #else - // Archive is being read from stdio - try to reopen as writable. - if (pZip->m_pIO_opaque != pZip) - return MZ_FALSE; - if (!pFilename) - return MZ_FALSE; - pZip->m_pWrite = mz_zip_file_write_func; - if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile))) - { - // The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it. - mz_zip_reader_end(pZip); - return MZ_FALSE; - } + // Archive is being read from stdio - try to reopen as writable. + if (pZip->m_pIO_opaque != pZip) + return MZ_FALSE; + if (!pFilename) + return MZ_FALSE; + pZip->m_pWrite = mz_zip_file_write_func; + if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile))) + { + // The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it. + mz_zip_reader_end(pZip); + return MZ_FALSE; + } #endif // #ifdef MINIZ_NO_STDIO - } - else if (pState->m_pMem) - { - // Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback. - if (pZip->m_pIO_opaque != pZip) - return MZ_FALSE; - pState->m_mem_capacity = pState->m_mem_size; - pZip->m_pWrite = mz_zip_heap_write_func; - } - // Archive is being read via a user provided read function - make sure the user has specified a write function too. - else if (!pZip->m_pWrite) - return MZ_FALSE; + } + else if (pState->m_pMem) + { + // Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback. + if (pZip->m_pIO_opaque != pZip) + return MZ_FALSE; + pState->m_mem_capacity = pState->m_mem_size; + pZip->m_pWrite = mz_zip_heap_write_func; + } + // Archive is being read via a user provided read function - make sure the user has specified a write function too. + else if (!pZip->m_pWrite) + return MZ_FALSE; - // Start writing new files at the archive's current central directory location. - pZip->m_archive_size = pZip->m_central_directory_file_ofs; - pZip->m_zip_mode = MZ_ZIP_MODE_WRITING; - pZip->m_central_directory_file_ofs = 0; + // Start writing new files at the archive's current central directory location. + pZip->m_archive_size = pZip->m_central_directory_file_ofs; + pZip->m_zip_mode = MZ_ZIP_MODE_WRITING; + pZip->m_central_directory_file_ofs = 0; - return MZ_TRUE; + return MZ_TRUE; } -mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags) +mz_bool mz_zip_writer_add_mem(mz_zip_archive* pZip, const char* pArchive_name, const void* pBuf, size_t buf_size, + mz_uint level_and_flags) { - return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0); + return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0); } typedef struct { - mz_zip_archive *m_pZip; - mz_uint64 m_cur_archive_file_ofs; - mz_uint64 m_comp_size; + mz_zip_archive* m_pZip; + mz_uint64 m_cur_archive_file_ofs; + mz_uint64 m_comp_size; } mz_zip_writer_add_state; -static mz_bool mz_zip_writer_add_put_buf_callback(const void* pBuf, int len, void *pUser) +static mz_bool mz_zip_writer_add_put_buf_callback(const void* pBuf, int len, void* pUser) { - mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser; - if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len) - return MZ_FALSE; - pState->m_cur_archive_file_ofs += len; - pState->m_comp_size += len; - return MZ_TRUE; + mz_zip_writer_add_state* pState = (mz_zip_writer_add_state*)pUser; + if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len) + return MZ_FALSE; + pState->m_cur_archive_file_ofs += len; + pState->m_comp_size += len; + return MZ_TRUE; } -static mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date) +static mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive* pZip, mz_uint8* pDst, mz_uint16 filename_size, + mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, + mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, + mz_uint16 dos_time, mz_uint16 dos_date) { - (void)pZip; - memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE); - MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date); - MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32); - MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, comp_size); - MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, uncomp_size); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size); - return MZ_TRUE; + (void)pZip; + memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE); + MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date); + MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32); + MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, comp_size); + MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, uncomp_size); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size); + return MZ_TRUE; } -static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes) +static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive* pZip, mz_uint8* pDst, mz_uint16 filename_size, + mz_uint16 extra_size, mz_uint16 comment_size, + mz_uint64 uncomp_size, mz_uint64 comp_size, + mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, + mz_uint16 dos_time, mz_uint16 dos_date, + mz_uint64 local_header_ofs, mz_uint32 ext_attributes) { - (void)pZip; - memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, comp_size); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, uncomp_size); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_header_ofs); - return MZ_TRUE; + (void)pZip; + memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, comp_size); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, uncomp_size); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_header_ofs); + return MZ_TRUE; } -static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size, const void *pExtra, mz_uint16 extra_size, const void *pComment, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes) +static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive* pZip, const char* pFilename, mz_uint16 filename_size, + const void* pExtra, mz_uint16 extra_size, const void* pComment, + mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, + mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, + mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, + mz_uint32 ext_attributes) { - mz_zip_internal_state *pState = pZip->m_pState; - mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size; - size_t orig_central_dir_size = pState->m_central_dir.m_size; - mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE]; + mz_zip_internal_state* pState = pZip->m_pState; + mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size; + size_t orig_central_dir_size = pState->m_central_dir.m_size; + mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE]; - // No zip64 support yet - if ((local_header_ofs > 0xFFFFFFFF) || (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + comment_size) > 0xFFFFFFFF)) - return MZ_FALSE; + // No zip64 support yet + if ((local_header_ofs > 0xFFFFFFFF) || (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + + filename_size + extra_size + comment_size) > 0xFFFFFFFF)) + return MZ_FALSE; - if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, extra_size, comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes)) - return MZ_FALSE; + if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, extra_size, comment_size, + uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, + dos_date, local_header_ofs, ext_attributes)) + return MZ_FALSE; - if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) || - (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) || - (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) || - (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) || - (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, ¢ral_dir_ofs, 1))) - { - // Try to push the central directory array back into its original state. - mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); - return MZ_FALSE; - } + if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) || + (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) || + (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) || + (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) || + (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, ¢ral_dir_ofs, 1))) + { + // Try to push the central directory array back into its original state. + mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); + return MZ_FALSE; + } - return MZ_TRUE; + return MZ_TRUE; } -static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name) +static mz_bool mz_zip_writer_validate_archive_name(const char* pArchive_name) { - // Basic ZIP archive filename validity checks: Valid filenames cannot start with a forward slash, cannot contain a drive letter, and cannot use DOS-style backward slashes. - if (*pArchive_name == '/') - return MZ_FALSE; - while (*pArchive_name) - { - if ((*pArchive_name == '\\') || (*pArchive_name == ':')) - return MZ_FALSE; - pArchive_name++; - } - return MZ_TRUE; + // Basic ZIP archive filename validity checks: Valid filenames cannot start with a forward slash, cannot contain a drive letter, and cannot use DOS-style backward slashes. + if (*pArchive_name == '/') + return MZ_FALSE; + while (*pArchive_name) + { + if ((*pArchive_name == '\\') || (*pArchive_name == ':')) + return MZ_FALSE; + pArchive_name++; + } + return MZ_TRUE; } -static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip) +static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive* pZip) { - mz_uint32 n; - if (!pZip->m_file_offset_alignment) - return 0; - n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1)); - return (pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1); + mz_uint32 n; + if (!pZip->m_file_offset_alignment) + return 0; + n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1)); + return (pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1); } -static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_file_ofs, mz_uint32 n) +static mz_bool mz_zip_writer_write_zeros(mz_zip_archive* pZip, mz_uint64 cur_file_ofs, mz_uint32 n) { - char buf[4096]; - memset(buf, 0, MZ_MIN(sizeof(buf), n)); - while (n) - { - mz_uint32 s = MZ_MIN(sizeof(buf), n); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s) - return MZ_FALSE; - cur_file_ofs += s; n -= s; - } - return MZ_TRUE; + char buf[4096]; + memset(buf, 0, MZ_MIN(sizeof(buf), n)); + while (n) + { + mz_uint32 s = MZ_MIN(sizeof(buf), n); + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s) + return MZ_FALSE; + cur_file_ofs += s; + n -= s; + } + return MZ_TRUE; } -mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32) +mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive* pZip, const char* pArchive_name, const void* pBuf, size_t buf_size, + const void* pComment, mz_uint16 comment_size, mz_uint level_and_flags, + mz_uint64 uncomp_size, mz_uint32 uncomp_crc32) { - mz_uint16 method = 0, dos_time = 0, dos_date = 0; - mz_uint level, ext_attributes = 0, num_alignment_padding_bytes; - mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0; - size_t archive_name_size; - mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; - tdefl_compressor *pComp = NULL; - mz_bool store_data_uncompressed; - mz_zip_internal_state *pState; + mz_uint16 method = 0, dos_time = 0, dos_date = 0; + mz_uint level, ext_attributes = 0, num_alignment_padding_bytes; + mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0; + size_t archive_name_size; + mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; + tdefl_compressor* pComp = NULL; + mz_bool store_data_uncompressed; + mz_zip_internal_state* pState; - if ((int)level_and_flags < 0) - level_and_flags = MZ_DEFAULT_LEVEL; - level = level_and_flags & 0xF; - store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)); + if ((int)level_and_flags < 0) + level_and_flags = MZ_DEFAULT_LEVEL; + level = level_and_flags & 0xF; + store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)); - if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) || (!pArchive_name) || ((comment_size) && (!pComment)) || (pZip->m_total_files == 0xFFFF) || (level > MZ_UBER_COMPRESSION)) - return MZ_FALSE; + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) || (! + pArchive_name) || ((comment_size) && (!pComment)) || (pZip->m_total_files == 0xFFFF) || (level > + MZ_UBER_COMPRESSION)) + return MZ_FALSE; - pState = pZip->m_pState; + pState = pZip->m_pState; - if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size)) - return MZ_FALSE; - // No zip64 support yet - if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF)) - return MZ_FALSE; - if (!mz_zip_writer_validate_archive_name(pArchive_name)) - return MZ_FALSE; + if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size)) + return MZ_FALSE; + // No zip64 support yet + if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF)) + return MZ_FALSE; + if (!mz_zip_writer_validate_archive_name(pArchive_name)) + return MZ_FALSE; #ifndef MINIZ_NO_TIME - { - time_t cur_time; time(&cur_time); - mz_zip_time_to_dos_time(cur_time, &dos_time, &dos_date); - } + { + time_t cur_time; + time(&cur_time); + mz_zip_time_to_dos_time(cur_time, &dos_time, &dos_date); + } #endif // #ifndef MINIZ_NO_TIME - archive_name_size = strlen(pArchive_name); - if (archive_name_size > 0xFFFF) - return MZ_FALSE; + archive_name_size = strlen(pArchive_name); + if (archive_name_size > 0xFFFF) + return MZ_FALSE; - num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); + num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); - // no zip64 support yet - if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF)) - return MZ_FALSE; + // no zip64 support yet + if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF)) + return MZ_FALSE; - if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/')) - { - // Set DOS Subdirectory attribute bit. - ext_attributes |= 0x10; - // Subdirectories cannot contain data. - if ((buf_size) || (uncomp_size)) - return MZ_FALSE; - } + if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/')) + { + // Set DOS Subdirectory attribute bit. + ext_attributes |= 0x10; + // Subdirectories cannot contain data. + if ((buf_size) || (uncomp_size)) + return MZ_FALSE; + } - // Try to do any allocations before writing to the archive, so if an allocation fails the file remains unmodified. (A good idea if we're doing an in-place modification.) - if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size)) || (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1))) - return MZ_FALSE; + // Try to do any allocations before writing to the archive, so if an allocation fails the file remains unmodified. (A good idea if we're doing an in-place modification.) + if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size)) || (! + mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1))) + return MZ_FALSE; - if ((!store_data_uncompressed) && (buf_size)) - { - if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)))) - return MZ_FALSE; - } + if ((!store_data_uncompressed) && (buf_size)) + { + if (NULL == (pComp = (tdefl_compressor*)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)))) + return MZ_FALSE; + } - if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header))) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - return MZ_FALSE; - } - local_dir_header_ofs += num_alignment_padding_bytes; - if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } - cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header); + if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header))) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + return MZ_FALSE; + } + local_dir_header_ofs += num_alignment_padding_bytes; + if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } + cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header); - MZ_CLEAR_OBJ(local_dir_header); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - return MZ_FALSE; - } - cur_archive_file_ofs += archive_name_size; + MZ_CLEAR_OBJ(local_dir_header); + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + return MZ_FALSE; + } + cur_archive_file_ofs += archive_name_size; - if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) - { - uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8*)pBuf, buf_size); - uncomp_size = buf_size; - if (uncomp_size <= 3) - { - level = 0; - store_data_uncompressed = MZ_TRUE; - } - } + if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) + { + uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8*)pBuf, buf_size); + uncomp_size = buf_size; + if (uncomp_size <= 3) + { + level = 0; + store_data_uncompressed = MZ_TRUE; + } + } - if (store_data_uncompressed) - { - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - return MZ_FALSE; - } + if (store_data_uncompressed) + { + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + return MZ_FALSE; + } - cur_archive_file_ofs += buf_size; - comp_size = buf_size; + cur_archive_file_ofs += buf_size; + comp_size = buf_size; - if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) - method = MZ_DEFLATED; - } - else if (buf_size) - { - mz_zip_writer_add_state state; + if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) + method = MZ_DEFLATED; + } + else if (buf_size) + { + mz_zip_writer_add_state state; - state.m_pZip = pZip; - state.m_cur_archive_file_ofs = cur_archive_file_ofs; - state.m_comp_size = 0; + state.m_pZip = pZip; + state.m_cur_archive_file_ofs = cur_archive_file_ofs; + state.m_comp_size = 0; - if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) || - (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE)) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - return MZ_FALSE; - } + if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, + tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) || + (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE)) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + return MZ_FALSE; + } - comp_size = state.m_comp_size; - cur_archive_file_ofs = state.m_cur_archive_file_ofs; + comp_size = state.m_comp_size; + cur_archive_file_ofs = state.m_cur_archive_file_ofs; - method = MZ_DEFLATED; - } + method = MZ_DEFLATED; + } - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - pComp = NULL; + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + pComp = NULL; - // no zip64 support yet - if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF)) - return MZ_FALSE; + // no zip64 support yet + if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF)) + return MZ_FALSE; - if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date)) - return MZ_FALSE; + if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, + comp_size, uncomp_crc32, method, 0, dos_time, dos_date)) + return MZ_FALSE; - if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) - return MZ_FALSE; + if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof( + local_dir_header)) + return MZ_FALSE; - if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes)) - return MZ_FALSE; + if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, + comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, + dos_date, local_dir_header_ofs, ext_attributes)) + return MZ_FALSE; - pZip->m_total_files++; - pZip->m_archive_size = cur_archive_file_ofs; + pZip->m_total_files++; + pZip->m_archive_size = cur_archive_file_ofs; - return MZ_TRUE; + return MZ_TRUE; } #ifndef MINIZ_NO_STDIO -mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags) +mz_bool mz_zip_writer_add_file(mz_zip_archive* pZip, const char* pArchive_name, const char* pSrc_filename, + const void* pComment, mz_uint16 comment_size, mz_uint level_and_flags) { - mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes; - mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0; - mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = 0, comp_size = 0; - size_t archive_name_size; - mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; - MZ_FILE *pSrc_file = NULL; + mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes; + mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0; + mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = 0, + comp_size = 0; + size_t archive_name_size; + mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; + MZ_FILE* pSrc_file = NULL; - if ((int)level_and_flags < 0) - level_and_flags = MZ_DEFAULT_LEVEL; - level = level_and_flags & 0xF; + if ((int)level_and_flags < 0) + level_and_flags = MZ_DEFAULT_LEVEL; + level = level_and_flags & 0xF; - if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION)) - return MZ_FALSE; - if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) - return MZ_FALSE; - if (!mz_zip_writer_validate_archive_name(pArchive_name)) - return MZ_FALSE; + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) + && (!pComment)) || (level > MZ_UBER_COMPRESSION)) + return MZ_FALSE; + if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) + return MZ_FALSE; + if (!mz_zip_writer_validate_archive_name(pArchive_name)) + return MZ_FALSE; - archive_name_size = strlen(pArchive_name); - if (archive_name_size > 0xFFFF) - return MZ_FALSE; + archive_name_size = strlen(pArchive_name); + if (archive_name_size > 0xFFFF) + return MZ_FALSE; - num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); + num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); - // no zip64 support yet - if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF)) - return MZ_FALSE; + // no zip64 support yet + if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF)) + return MZ_FALSE; - if (!mz_zip_get_file_modified_time(pSrc_filename, &dos_time, &dos_date)) - return MZ_FALSE; - - pSrc_file = MZ_FOPEN(pSrc_filename, "rb"); - if (!pSrc_file) - return MZ_FALSE; - MZ_FSEEK64(pSrc_file, 0, SEEK_END); - uncomp_size = MZ_FTELL64(pSrc_file); - MZ_FSEEK64(pSrc_file, 0, SEEK_SET); + if (!mz_zip_get_file_modified_time(pSrc_filename, &dos_time, &dos_date)) + return MZ_FALSE; - if (uncomp_size > 0xFFFFFFFF) - { - // No zip64 support yet - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } - if (uncomp_size <= 3) - level = 0; + pSrc_file = MZ_FOPEN(pSrc_filename, "rb"); + if (!pSrc_file) + return MZ_FALSE; + MZ_FSEEK64(pSrc_file, 0, SEEK_END); + uncomp_size = MZ_FTELL64(pSrc_file); + MZ_FSEEK64(pSrc_file, 0, SEEK_SET); - if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header))) - { - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } - local_dir_header_ofs += num_alignment_padding_bytes; - if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } - cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header); + if (uncomp_size > 0xFFFFFFFF) + { + // No zip64 support yet + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } + if (uncomp_size <= 3) + level = 0; - MZ_CLEAR_OBJ(local_dir_header); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) - { - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } - cur_archive_file_ofs += archive_name_size; + if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header))) + { + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } + local_dir_header_ofs += num_alignment_padding_bytes; + if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } + cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header); - if (uncomp_size) - { - mz_uint64 uncomp_remaining = uncomp_size; - void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE); - if (!pRead_buf) - { - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } + MZ_CLEAR_OBJ(local_dir_header); + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) + { + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } + cur_archive_file_ofs += archive_name_size; - if (!level) - { - while (uncomp_remaining) - { - mz_uint n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining); - if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n)) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } - uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n); - uncomp_remaining -= n; - cur_archive_file_ofs += n; - } - comp_size = uncomp_size; - } - else - { - mz_bool result = MZ_FALSE; - mz_zip_writer_add_state state; - tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)); - if (!pComp) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } + if (uncomp_size) + { + mz_uint64 uncomp_remaining = uncomp_size; + void* pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE); + if (!pRead_buf) + { + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } - state.m_pZip = pZip; - state.m_cur_archive_file_ofs = cur_archive_file_ofs; - state.m_comp_size = 0; + if (!level) + { + while (uncomp_remaining) + { + mz_uint n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining); + if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) || (pZip->m_pWrite( + pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n)) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } + uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8*)pRead_buf, n); + uncomp_remaining -= n; + cur_archive_file_ofs += n; + } + comp_size = uncomp_size; + } + else + { + mz_bool result = MZ_FALSE; + mz_zip_writer_add_state state; + tdefl_compressor* pComp = (tdefl_compressor*)pZip-> + m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)); + if (!pComp) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } - if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } + state.m_pZip = pZip; + state.m_cur_archive_file_ofs = cur_archive_file_ofs; + state.m_comp_size = 0; - for ( ; ; ) - { - size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, MZ_ZIP_MAX_IO_BUF_SIZE); - tdefl_status status; + if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, + tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } - if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size) - break; + for (; ;) + { + size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, MZ_ZIP_MAX_IO_BUF_SIZE); + tdefl_status status; - uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size); - uncomp_remaining -= in_buf_size; + if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size) + break; - status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? TDEFL_NO_FLUSH : TDEFL_FINISH); - if (status == TDEFL_STATUS_DONE) - { - result = MZ_TRUE; - break; - } - else if (status != TDEFL_STATUS_OKAY) - break; - } + uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8*)pRead_buf, in_buf_size); + uncomp_remaining -= in_buf_size; - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, + uncomp_remaining ? TDEFL_NO_FLUSH : TDEFL_FINISH); + if (status == TDEFL_STATUS_DONE) + { + result = MZ_TRUE; + break; + } + else if (status != TDEFL_STATUS_OKAY) + break; + } - if (!result) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - comp_size = state.m_comp_size; - cur_archive_file_ofs = state.m_cur_archive_file_ofs; + if (!result) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } - method = MZ_DEFLATED; - } + comp_size = state.m_comp_size; + cur_archive_file_ofs = state.m_cur_archive_file_ofs; - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - } + method = MZ_DEFLATED; + } - MZ_FCLOSE(pSrc_file); pSrc_file = NULL; + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + } - // no zip64 support yet - if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF)) - return MZ_FALSE; + MZ_FCLOSE(pSrc_file); + pSrc_file = NULL; - if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date)) - return MZ_FALSE; + // no zip64 support yet + if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF)) + return MZ_FALSE; - if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) - return MZ_FALSE; + if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, + comp_size, uncomp_crc32, method, 0, dos_time, dos_date)) + return MZ_FALSE; - if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes)) - return MZ_FALSE; + if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof( + local_dir_header)) + return MZ_FALSE; - pZip->m_total_files++; - pZip->m_archive_size = cur_archive_file_ofs; + if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, + comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, + dos_date, local_dir_header_ofs, ext_attributes)) + return MZ_FALSE; - return MZ_TRUE; + pZip->m_total_files++; + pZip->m_archive_size = cur_archive_file_ofs; + + return MZ_TRUE; } #endif // #ifndef MINIZ_NO_STDIO -mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index) +mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive* pZip, mz_zip_archive* pSource_zip, mz_uint file_index) { - mz_uint n, bit_flags, num_alignment_padding_bytes; - mz_uint64 comp_bytes_remaining, local_dir_header_ofs; - mz_uint64 cur_src_file_ofs, cur_dst_file_ofs; - mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; - mz_uint8 central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE]; - size_t orig_central_dir_size; - mz_zip_internal_state *pState; - void *pBuf; const mz_uint8 *pSrc_central_header; + mz_uint n, bit_flags, num_alignment_padding_bytes; + mz_uint64 comp_bytes_remaining, local_dir_header_ofs; + mz_uint64 cur_src_file_ofs, cur_dst_file_ofs; + mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; + mz_uint8* pLocal_header = (mz_uint8*)local_header_u32; + mz_uint8 central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE]; + size_t orig_central_dir_size; + mz_zip_internal_state* pState; + void* pBuf; + const mz_uint8* pSrc_central_header; - if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING)) - return MZ_FALSE; - if (NULL == (pSrc_central_header = mz_zip_reader_get_cdh(pSource_zip, file_index))) - return MZ_FALSE; - pState = pZip->m_pState; + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING)) + return MZ_FALSE; + if (NULL == (pSrc_central_header = mz_zip_reader_get_cdh(pSource_zip, file_index))) + return MZ_FALSE; + pState = pZip->m_pState; - num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); + num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); - // no zip64 support yet - if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)) - return MZ_FALSE; + // no zip64 support yet + if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)) + return MZ_FALSE; - cur_src_file_ofs = MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS); - cur_dst_file_ofs = pZip->m_archive_size; + cur_src_file_ofs = MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS); + cur_dst_file_ofs = pZip->m_archive_size; - if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) - return MZ_FALSE; - if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) - return MZ_FALSE; - cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE; + if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + return MZ_FALSE; + if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) + return MZ_FALSE; + cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE; - if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes)) - return MZ_FALSE; - cur_dst_file_ofs += num_alignment_padding_bytes; - local_dir_header_ofs = cur_dst_file_ofs; - if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } + if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes)) + return MZ_FALSE; + cur_dst_file_ofs += num_alignment_padding_bytes; + local_dir_header_ofs = cur_dst_file_ofs; + if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) - return MZ_FALSE; - cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE; + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + return MZ_FALSE; + cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE; - n = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); - comp_bytes_remaining = n + MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); + n = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16( + pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); + comp_bytes_remaining = n + MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); - if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)MZ_MAX(sizeof(mz_uint32) * 4, MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining))))) - return MZ_FALSE; + if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, + (size_t)MZ_MAX(sizeof(mz_uint32) * 4, + MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining))))) + return MZ_FALSE; - while (comp_bytes_remaining) - { - n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining); - if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - return MZ_FALSE; - } - cur_src_file_ofs += n; + while (comp_bytes_remaining) + { + n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining); + if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return MZ_FALSE; + } + cur_src_file_ofs += n; - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - return MZ_FALSE; - } - cur_dst_file_ofs += n; + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return MZ_FALSE; + } + cur_dst_file_ofs += n; - comp_bytes_remaining -= n; - } + comp_bytes_remaining -= n; + } - bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS); - if (bit_flags & 8) - { - // Copy data descriptor - if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - return MZ_FALSE; - } + bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS); + if (bit_flags & 8) + { + // Copy data descriptor + if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof( + mz_uint32) * 4) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return MZ_FALSE; + } - n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == 0x08074b50) ? 4 : 3); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - return MZ_FALSE; - } + n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == 0x08074b50) ? 4 : 3); + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return MZ_FALSE; + } - cur_src_file_ofs += n; - cur_dst_file_ofs += n; - } - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + cur_src_file_ofs += n; + cur_dst_file_ofs += n; + } + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - // no zip64 support yet - if (cur_dst_file_ofs > 0xFFFFFFFF) - return MZ_FALSE; + // no zip64 support yet + if (cur_dst_file_ofs > 0xFFFFFFFF) + return MZ_FALSE; - orig_central_dir_size = pState->m_central_dir.m_size; + orig_central_dir_size = pState->m_central_dir.m_size; - memcpy(central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE); - MZ_WRITE_LE32(central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs); - if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) - return MZ_FALSE; + memcpy(central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE); + MZ_WRITE_LE32(central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs); + if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) + return MZ_FALSE; - n = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS); - if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n)) - { - mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); - return MZ_FALSE; - } + n = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS) + + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16( + pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS); + if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n)) + { + mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); + return MZ_FALSE; + } - if (pState->m_central_dir.m_size > 0xFFFFFFFF) - return MZ_FALSE; - n = (mz_uint32)orig_central_dir_size; - if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1)) - { - mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); - return MZ_FALSE; - } + if (pState->m_central_dir.m_size > 0xFFFFFFFF) + return MZ_FALSE; + n = (mz_uint32)orig_central_dir_size; + if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1)) + { + mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); + return MZ_FALSE; + } - pZip->m_total_files++; - pZip->m_archive_size = cur_dst_file_ofs; + pZip->m_total_files++; + pZip->m_archive_size = cur_dst_file_ofs; - return MZ_TRUE; + return MZ_TRUE; } -mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip) +mz_bool mz_zip_writer_finalize_archive(mz_zip_archive* pZip) { - mz_zip_internal_state *pState; - mz_uint64 central_dir_ofs, central_dir_size; - mz_uint8 hdr[MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE]; + mz_zip_internal_state* pState; + mz_uint64 central_dir_ofs, central_dir_size; + mz_uint8 hdr[MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE]; - if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING)) - return MZ_FALSE; + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING)) + return MZ_FALSE; - pState = pZip->m_pState; + pState = pZip->m_pState; - // no zip64 support yet - if ((pZip->m_total_files > 0xFFFF) || ((pZip->m_archive_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)) - return MZ_FALSE; + // no zip64 support yet + if ((pZip->m_total_files > 0xFFFF) || ((pZip->m_archive_size + pState->m_central_dir.m_size + + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)) + return MZ_FALSE; - central_dir_ofs = 0; - central_dir_size = 0; - if (pZip->m_total_files) - { - // Write central directory - central_dir_ofs = pZip->m_archive_size; - central_dir_size = pState->m_central_dir.m_size; - pZip->m_central_directory_file_ofs = central_dir_ofs; - if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs, pState->m_central_dir.m_p, (size_t)central_dir_size) != central_dir_size) - return MZ_FALSE; - pZip->m_archive_size += central_dir_size; - } + central_dir_ofs = 0; + central_dir_size = 0; + if (pZip->m_total_files) + { + // Write central directory + central_dir_ofs = pZip->m_archive_size; + central_dir_size = pState->m_central_dir.m_size; + pZip->m_central_directory_file_ofs = central_dir_ofs; + if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs, pState->m_central_dir.m_p, (size_t)central_dir_size) != + central_dir_size) + return MZ_FALSE; + pZip->m_archive_size += central_dir_size; + } - // Write end of central directory record - MZ_CLEAR_OBJ(hdr); - MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG); - MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, pZip->m_total_files); - MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files); - MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, central_dir_size); - MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, central_dir_ofs); + // Write end of central directory record + MZ_CLEAR_OBJ(hdr); + MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG); + MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, pZip->m_total_files); + MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files); + MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, central_dir_size); + MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, central_dir_ofs); - if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, sizeof(hdr)) != sizeof(hdr)) - return MZ_FALSE; + if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, sizeof(hdr)) != sizeof(hdr)) + return MZ_FALSE; #ifndef MINIZ_NO_STDIO - if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF)) - return MZ_FALSE; + if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF)) + return MZ_FALSE; #endif // #ifndef MINIZ_NO_STDIO - pZip->m_archive_size += sizeof(hdr); + pZip->m_archive_size += sizeof(hdr); - pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED; - return MZ_TRUE; + pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED; + return MZ_TRUE; } -mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize) +mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive* pZip, void** pBuf, size_t* pSize) { - if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pSize)) - return MZ_FALSE; - if (pZip->m_pWrite != mz_zip_heap_write_func) - return MZ_FALSE; - if (!mz_zip_writer_finalize_archive(pZip)) - return MZ_FALSE; + if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pSize)) + return MZ_FALSE; + if (pZip->m_pWrite != mz_zip_heap_write_func) + return MZ_FALSE; + if (!mz_zip_writer_finalize_archive(pZip)) + return MZ_FALSE; - *pBuf = pZip->m_pState->m_pMem; - *pSize = pZip->m_pState->m_mem_size; - pZip->m_pState->m_pMem = NULL; - pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0; - return MZ_TRUE; + *pBuf = pZip->m_pState->m_pMem; + *pSize = pZip->m_pState->m_mem_size; + pZip->m_pState->m_pMem = NULL; + pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0; + return MZ_TRUE; } -mz_bool mz_zip_writer_end(mz_zip_archive *pZip) +mz_bool mz_zip_writer_end(mz_zip_archive* pZip) { - mz_zip_internal_state *pState; - mz_bool status = MZ_TRUE; - if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) && (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED))) - return MZ_FALSE; + mz_zip_internal_state* pState; + mz_bool status = MZ_TRUE; + if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || ((pZip->m_zip_mode != + MZ_ZIP_MODE_WRITING) && (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED))) + return MZ_FALSE; - pState = pZip->m_pState; - pZip->m_pState = NULL; - mz_zip_array_clear(pZip, &pState->m_central_dir); - mz_zip_array_clear(pZip, &pState->m_central_dir_offsets); - mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets); + pState = pZip->m_pState; + pZip->m_pState = NULL; + mz_zip_array_clear(pZip, &pState->m_central_dir); + mz_zip_array_clear(pZip, &pState->m_central_dir_offsets); + mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets); #ifndef MINIZ_NO_STDIO - if (pState->m_pFile) - { - MZ_FCLOSE(pState->m_pFile); - pState->m_pFile = NULL; - } + if (pState->m_pFile) + { + MZ_FCLOSE(pState->m_pFile); + pState->m_pFile = NULL; + } #endif // #ifndef MINIZ_NO_STDIO - if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem)) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem); - pState->m_pMem = NULL; - } + if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem)) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem); + pState->m_pMem = NULL; + } - pZip->m_pFree(pZip->m_pAlloc_opaque, pState); - pZip->m_zip_mode = MZ_ZIP_MODE_INVALID; - return status; + pZip->m_pFree(pZip->m_pAlloc_opaque, pState); + pZip->m_zip_mode = MZ_ZIP_MODE_INVALID; + return status; } #ifndef MINIZ_NO_STDIO -mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags) +mz_bool mz_zip_add_mem_to_archive_file_in_place(const char* pZip_filename, const char* pArchive_name, const void* pBuf, + size_t buf_size, const void* pComment, mz_uint16 comment_size, + mz_uint level_and_flags) { - mz_bool status, created_new_archive = MZ_FALSE; - mz_zip_archive zip_archive; - struct MZ_FILE_STAT_STRUCT file_stat; - MZ_CLEAR_OBJ(zip_archive); - if ((int)level_and_flags < 0) - level_and_flags = MZ_DEFAULT_LEVEL; - if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION)) - return MZ_FALSE; - if (!mz_zip_writer_validate_archive_name(pArchive_name)) - return MZ_FALSE; - if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0) - { - // Create a new archive. - if (!mz_zip_writer_init_file(&zip_archive, pZip_filename, 0)) - return MZ_FALSE; - created_new_archive = MZ_TRUE; - } - else - { - // Append to an existing archive. - if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY)) - return MZ_FALSE; - if (!mz_zip_writer_init_from_reader(&zip_archive, pZip_filename)) - { - mz_zip_reader_end(&zip_archive); - return MZ_FALSE; - } - } - status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0); - // Always finalize, even if adding failed for some reason, so we have a valid central directory. (This may not always succeed, but we can try.) - if (!mz_zip_writer_finalize_archive(&zip_archive)) - status = MZ_FALSE; - if (!mz_zip_writer_end(&zip_archive)) - status = MZ_FALSE; - if ((!status) && (created_new_archive)) - { - // It's a new archive and something went wrong, so just delete it. - int ignoredStatus = MZ_DELETE_FILE(pZip_filename); - (void)ignoredStatus; - } - return status; + mz_bool status, created_new_archive = MZ_FALSE; + mz_zip_archive zip_archive; + struct MZ_FILE_STAT_STRUCT file_stat; + MZ_CLEAR_OBJ(zip_archive); + if ((int)level_and_flags < 0) + level_and_flags = MZ_DEFAULT_LEVEL; + if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || (( + level_and_flags & 0xF) > MZ_UBER_COMPRESSION)) + return MZ_FALSE; + if (!mz_zip_writer_validate_archive_name(pArchive_name)) + return MZ_FALSE; + if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0) + { + // Create a new archive. + if (!mz_zip_writer_init_file(&zip_archive, pZip_filename, 0)) + return MZ_FALSE; + created_new_archive = MZ_TRUE; + } + else + { + // Append to an existing archive. + if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, + level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY)) + return MZ_FALSE; + if (!mz_zip_writer_init_from_reader(&zip_archive, pZip_filename)) + { + mz_zip_reader_end(&zip_archive); + return MZ_FALSE; + } + } + status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, + level_and_flags, 0, 0); + // Always finalize, even if adding failed for some reason, so we have a valid central directory. (This may not always succeed, but we can try.) + if (!mz_zip_writer_finalize_archive(&zip_archive)) + status = MZ_FALSE; + if (!mz_zip_writer_end(&zip_archive)) + status = MZ_FALSE; + if ((!status) && (created_new_archive)) + { + // It's a new archive and something went wrong, so just delete it. + int ignoredStatus = MZ_DELETE_FILE(pZip_filename); + (void)ignoredStatus; + } + return status; } -void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags) +void* mz_zip_extract_archive_file_to_heap(const char* pZip_filename, const char* pArchive_name, size_t* pSize, + mz_uint flags) { - int file_index; - mz_zip_archive zip_archive; - void *p = NULL; + int file_index; + mz_zip_archive zip_archive; + void* p = NULL; - if (pSize) - *pSize = 0; + if (pSize) + *pSize = 0; - if ((!pZip_filename) || (!pArchive_name)) - return NULL; + if ((!pZip_filename) || (!pArchive_name)) + return NULL; - MZ_CLEAR_OBJ(zip_archive); - if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY)) - return NULL; + MZ_CLEAR_OBJ(zip_archive); + if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY)) + return NULL; - if ((file_index = mz_zip_reader_locate_file(&zip_archive, pArchive_name, NULL, flags)) >= 0) - p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags); + if ((file_index = mz_zip_reader_locate_file(&zip_archive, pArchive_name, NULL, flags)) >= 0) + p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags); - mz_zip_reader_end(&zip_archive); - return p; + mz_zip_reader_end(&zip_archive); + return p; } #endif // #ifndef MINIZ_NO_STDIO diff --git a/Utilities/miniz.h b/Utilities/miniz.h index a7e550f..7b78c6d 100644 --- a/Utilities/miniz.h +++ b/Utilities/miniz.h @@ -199,7 +199,7 @@ #endif #if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS) - #include +#include #endif #if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(i386) || defined(__ia64__) || defined(__x86_64__) @@ -232,15 +232,15 @@ extern "C" { typedef unsigned long mz_ulong; // mz_free() internally uses the MZ_FREE() macro (which by default calls free() unless you've modified the MZ_MALLOC macro) to release a block allocated from the heap. -void mz_free(void *p); +void mz_free(void* p); #define MZ_ADLER32_INIT (1) // mz_adler32() returns the initial adler-32 value to use when called with ptr==NULL. -mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len); +mz_ulong mz_adler32(mz_ulong adler, const unsigned char* ptr, size_t buf_len); #define MZ_CRC32_INIT (0) // mz_crc32() returns the initial CRC-32 value to use when called with ptr==NULL. -mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len); +mz_ulong mz_crc32(mz_ulong crc, const unsigned char* ptr, size_t buf_len); // Compression strategies. enum { MZ_DEFAULT_STRATEGY = 0, MZ_FILTERED = 1, MZ_HUFFMAN_ONLY = 2, MZ_RLE = 3, MZ_FIXED = 4 }; @@ -252,9 +252,9 @@ enum { MZ_DEFAULT_STRATEGY = 0, MZ_FILTERED = 1, MZ_HUFFMAN_ONLY = 2, MZ_RLE = 3 // Heap allocation callbacks. // Note that mz_alloc_func parameter types purpsosely differ from zlib's: items/size is size_t, not unsigned long. -typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size); -typedef void (*mz_free_func)(void *opaque, void *address); -typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items, size_t size); +typedef void*(*mz_alloc_func)(void* opaque, size_t items, size_t size); +typedef void (*mz_free_func)(void* opaque, void* address); +typedef void*(*mz_realloc_func)(void* opaque, void* address, size_t items, size_t size); #define MZ_VERSION "9.1.15" #define MZ_VERNUM 0x91F0 @@ -267,10 +267,30 @@ typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items, size enum { MZ_NO_FLUSH = 0, MZ_PARTIAL_FLUSH = 1, MZ_SYNC_FLUSH = 2, MZ_FULL_FLUSH = 3, MZ_FINISH = 4, MZ_BLOCK = 5 }; // Return status codes. MZ_PARAM_ERROR is non-standard. -enum { MZ_OK = 0, MZ_STREAM_END = 1, MZ_NEED_DICT = 2, MZ_ERRNO = -1, MZ_STREAM_ERROR = -2, MZ_DATA_ERROR = -3, MZ_MEM_ERROR = -4, MZ_BUF_ERROR = -5, MZ_VERSION_ERROR = -6, MZ_PARAM_ERROR = -10000 }; +enum +{ + MZ_OK = 0, + MZ_STREAM_END = 1, + MZ_NEED_DICT = 2, + MZ_ERRNO = -1, + MZ_STREAM_ERROR = -2, + MZ_DATA_ERROR = -3, + MZ_MEM_ERROR = -4, + MZ_BUF_ERROR = -5, + MZ_VERSION_ERROR = -6, + MZ_PARAM_ERROR = -10000 +}; // Compression levels: 0-9 are the standard zlib-style levels, 10 is best possible compression (not zlib compatible, and may be very slow), MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL. -enum { MZ_NO_COMPRESSION = 0, MZ_BEST_SPEED = 1, MZ_BEST_COMPRESSION = 9, MZ_UBER_COMPRESSION = 10, MZ_DEFAULT_LEVEL = 6, MZ_DEFAULT_COMPRESSION = -1 }; +enum +{ + MZ_NO_COMPRESSION = 0, + MZ_BEST_SPEED = 1, + MZ_BEST_COMPRESSION = 9, + MZ_UBER_COMPRESSION = 10, + MZ_DEFAULT_LEVEL = 6, + MZ_DEFAULT_COMPRESSION = -1 +}; // Window bits #define MZ_DEFAULT_WINDOW_BITS 15 @@ -280,30 +300,30 @@ struct mz_internal_state; // Compression/decompression stream struct. typedef struct mz_stream_s { - const unsigned char *next_in; // pointer to next byte to read - unsigned int avail_in; // number of bytes available at next_in - mz_ulong total_in; // total number of bytes consumed so far + const unsigned char* next_in; // pointer to next byte to read + unsigned int avail_in; // number of bytes available at next_in + mz_ulong total_in; // total number of bytes consumed so far - unsigned char *next_out; // pointer to next byte to write - unsigned int avail_out; // number of bytes that can be written to next_out - mz_ulong total_out; // total number of bytes produced so far + unsigned char* next_out; // pointer to next byte to write + unsigned int avail_out; // number of bytes that can be written to next_out + mz_ulong total_out; // total number of bytes produced so far - char *msg; // error msg (unused) - struct mz_internal_state *state; // internal state, allocated by zalloc/zfree + char* msg; // error msg (unused) + struct mz_internal_state* state; // internal state, allocated by zalloc/zfree - mz_alloc_func zalloc; // optional heap allocation function (defaults to malloc) - mz_free_func zfree; // optional heap free function (defaults to free) - void *opaque; // heap alloc function user pointer + mz_alloc_func zalloc; // optional heap allocation function (defaults to malloc) + mz_free_func zfree; // optional heap free function (defaults to free) + void* opaque; // heap alloc function user pointer - int data_type; // data_type (unused) - mz_ulong adler; // adler32 of the source or uncompressed data - mz_ulong reserved; // not used + int data_type; // data_type (unused) + mz_ulong adler; // adler32 of the source or uncompressed data + mz_ulong reserved; // not used } mz_stream; -typedef mz_stream *mz_streamp; +typedef mz_stream* mz_streamp; // Returns the version string of miniz.c. -const char *mz_version(void); +const char* mz_version(void); // mz_deflateInit() initializes a compressor with default options: // Parameters: @@ -351,8 +371,9 @@ mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len); // Single-call compression functions mz_compress() and mz_compress2(): // Returns MZ_OK on success, or one of the error codes from mz_deflate() on failure. -int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len); -int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level); +int mz_compress(unsigned char* pDest, mz_ulong* pDest_len, const unsigned char* pSource, mz_ulong source_len); +int mz_compress2(unsigned char* pDest, mz_ulong* pDest_len, const unsigned char* pSource, mz_ulong source_len, + int level); // mz_compressBound() returns a (very) conservative upper bound on the amount of data that could be generated by calling mz_compress(). mz_ulong mz_compressBound(mz_ulong source_len); @@ -385,84 +406,84 @@ int mz_inflateEnd(mz_streamp pStream); // Single-call decompression. // Returns MZ_OK on success, or one of the error codes from mz_inflate() on failure. -int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len); +int mz_uncompress(unsigned char* pDest, mz_ulong* pDest_len, const unsigned char* pSource, mz_ulong source_len); // Returns a string description of the specified error code, or NULL if the error code is invalid. -const char *mz_error(int err); +const char* mz_error(int err); // Redefine zlib-compatible names to miniz equivalents, so miniz.c can be used as a drop-in replacement for the subset of zlib that miniz.c supports. // Define MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility if you use zlib in the same project. #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES - typedef unsigned char Byte; - typedef unsigned int uInt; - typedef mz_ulong uLong; - typedef Byte Bytef; - typedef uInt uIntf; - typedef char charf; - typedef int intf; - typedef void *voidpf; - typedef uLong uLongf; - typedef void *voidp; - typedef void *const voidpc; - #define Z_NULL 0 - #define Z_NO_FLUSH MZ_NO_FLUSH - #define Z_PARTIAL_FLUSH MZ_PARTIAL_FLUSH - #define Z_SYNC_FLUSH MZ_SYNC_FLUSH - #define Z_FULL_FLUSH MZ_FULL_FLUSH - #define Z_FINISH MZ_FINISH - #define Z_BLOCK MZ_BLOCK - #define Z_OK MZ_OK - #define Z_STREAM_END MZ_STREAM_END - #define Z_NEED_DICT MZ_NEED_DICT - #define Z_ERRNO MZ_ERRNO - #define Z_STREAM_ERROR MZ_STREAM_ERROR - #define Z_DATA_ERROR MZ_DATA_ERROR - #define Z_MEM_ERROR MZ_MEM_ERROR - #define Z_BUF_ERROR MZ_BUF_ERROR - #define Z_VERSION_ERROR MZ_VERSION_ERROR - #define Z_PARAM_ERROR MZ_PARAM_ERROR - #define Z_NO_COMPRESSION MZ_NO_COMPRESSION - #define Z_BEST_SPEED MZ_BEST_SPEED - #define Z_BEST_COMPRESSION MZ_BEST_COMPRESSION - #define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION - #define Z_DEFAULT_STRATEGY MZ_DEFAULT_STRATEGY - #define Z_FILTERED MZ_FILTERED - #define Z_HUFFMAN_ONLY MZ_HUFFMAN_ONLY - #define Z_RLE MZ_RLE - #define Z_FIXED MZ_FIXED - #define Z_DEFLATED MZ_DEFLATED - #define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS - #define alloc_func mz_alloc_func - #define free_func mz_free_func - #define internal_state mz_internal_state - #define z_stream mz_stream - #define deflateInit mz_deflateInit - #define deflateInit2 mz_deflateInit2 - #define deflateReset mz_deflateReset - #define deflate mz_deflate - #define deflateEnd mz_deflateEnd - #define deflateBound mz_deflateBound - #define compress mz_compress - #define compress2 mz_compress2 - #define compressBound mz_compressBound - #define inflateInit mz_inflateInit - #define inflateInit2 mz_inflateInit2 - #define inflate mz_inflate - #define inflateEnd mz_inflateEnd - #define uncompress mz_uncompress - #define crc32 mz_crc32 - #define adler32 mz_adler32 - #define MAX_WBITS 15 - #define MAX_MEM_LEVEL 9 - #define zError mz_error - #define ZLIB_VERSION MZ_VERSION - #define ZLIB_VERNUM MZ_VERNUM - #define ZLIB_VER_MAJOR MZ_VER_MAJOR - #define ZLIB_VER_MINOR MZ_VER_MINOR - #define ZLIB_VER_REVISION MZ_VER_REVISION - #define ZLIB_VER_SUBREVISION MZ_VER_SUBREVISION - #define zlibVersion mz_version - #define zlib_version mz_version() +typedef unsigned char Byte; +typedef unsigned int uInt; +typedef mz_ulong uLong; +typedef Byte Bytef; +typedef uInt uIntf; +typedef char charf; +typedef int intf; +typedef void* voidpf; +typedef uLong uLongf; +typedef void* voidp; +typedef void* const voidpc; +#define Z_NULL 0 +#define Z_NO_FLUSH MZ_NO_FLUSH +#define Z_PARTIAL_FLUSH MZ_PARTIAL_FLUSH +#define Z_SYNC_FLUSH MZ_SYNC_FLUSH +#define Z_FULL_FLUSH MZ_FULL_FLUSH +#define Z_FINISH MZ_FINISH +#define Z_BLOCK MZ_BLOCK +#define Z_OK MZ_OK +#define Z_STREAM_END MZ_STREAM_END +#define Z_NEED_DICT MZ_NEED_DICT +#define Z_ERRNO MZ_ERRNO +#define Z_STREAM_ERROR MZ_STREAM_ERROR +#define Z_DATA_ERROR MZ_DATA_ERROR +#define Z_MEM_ERROR MZ_MEM_ERROR +#define Z_BUF_ERROR MZ_BUF_ERROR +#define Z_VERSION_ERROR MZ_VERSION_ERROR +#define Z_PARAM_ERROR MZ_PARAM_ERROR +#define Z_NO_COMPRESSION MZ_NO_COMPRESSION +#define Z_BEST_SPEED MZ_BEST_SPEED +#define Z_BEST_COMPRESSION MZ_BEST_COMPRESSION +#define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION +#define Z_DEFAULT_STRATEGY MZ_DEFAULT_STRATEGY +#define Z_FILTERED MZ_FILTERED +#define Z_HUFFMAN_ONLY MZ_HUFFMAN_ONLY +#define Z_RLE MZ_RLE +#define Z_FIXED MZ_FIXED +#define Z_DEFLATED MZ_DEFLATED +#define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS +#define alloc_func mz_alloc_func +#define free_func mz_free_func +#define internal_state mz_internal_state +#define z_stream mz_stream +#define deflateInit mz_deflateInit +#define deflateInit2 mz_deflateInit2 +#define deflateReset mz_deflateReset +#define deflate mz_deflate +#define deflateEnd mz_deflateEnd +#define deflateBound mz_deflateBound +#define compress mz_compress +#define compress2 mz_compress2 +#define compressBound mz_compressBound +#define inflateInit mz_inflateInit +#define inflateInit2 mz_inflateInit2 +#define inflate mz_inflate +#define inflateEnd mz_inflateEnd +#define uncompress mz_uncompress +#define crc32 mz_crc32 +#define adler32 mz_adler32 +#define MAX_WBITS 15 +#define MAX_MEM_LEVEL 9 +#define zError mz_error +#define ZLIB_VERSION MZ_VERSION +#define ZLIB_VERNUM MZ_VERNUM +#define ZLIB_VER_MAJOR MZ_VER_MAJOR +#define ZLIB_VER_MINOR MZ_VER_MINOR +#define ZLIB_VER_REVISION MZ_VER_REVISION +#define ZLIB_VER_SUBREVISION MZ_VER_SUBREVISION +#define zlibVersion mz_version +#define zlib_version mz_version() #endif // #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES #endif // MINIZ_NO_ZLIB_APIS @@ -483,7 +504,7 @@ typedef int mz_bool; // An attempt to work around MSVC's spammy "warning C4127: conditional expression is constant" message. #ifdef _MSC_VER - #define MZ_MACRO_END while (0, 0) +#define MZ_MACRO_END while (0, 0) #else #define MZ_MACRO_END while (0) #endif @@ -494,143 +515,153 @@ typedef int mz_bool; enum { - MZ_ZIP_MAX_IO_BUF_SIZE = 64*1024, - MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 260, - MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 256 + MZ_ZIP_MAX_IO_BUF_SIZE = 64 * 1024, + MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 260, + MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 256 }; typedef struct { - mz_uint32 m_file_index; - mz_uint32 m_central_dir_ofs; - mz_uint16 m_version_made_by; - mz_uint16 m_version_needed; - mz_uint16 m_bit_flag; - mz_uint16 m_method; + mz_uint32 m_file_index; + mz_uint32 m_central_dir_ofs; + mz_uint16 m_version_made_by; + mz_uint16 m_version_needed; + mz_uint16 m_bit_flag; + mz_uint16 m_method; #ifndef MINIZ_NO_TIME - time_t m_time; + time_t m_time; #endif - mz_uint32 m_crc32; - mz_uint64 m_comp_size; - mz_uint64 m_uncomp_size; - mz_uint16 m_internal_attr; - mz_uint32 m_external_attr; - mz_uint64 m_local_header_ofs; - mz_uint32 m_comment_size; - char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE]; - char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE]; + mz_uint32 m_crc32; + mz_uint64 m_comp_size; + mz_uint64 m_uncomp_size; + mz_uint16 m_internal_attr; + mz_uint32 m_external_attr; + mz_uint64 m_local_header_ofs; + mz_uint32 m_comment_size; + char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE]; + char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE]; } mz_zip_archive_file_stat; -typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n); -typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n); +typedef size_t (*mz_file_read_func)(void* pOpaque, mz_uint64 file_ofs, void* pBuf, size_t n); +typedef size_t (*mz_file_write_func)(void* pOpaque, mz_uint64 file_ofs, const void* pBuf, size_t n); struct mz_zip_internal_state_tag; typedef struct mz_zip_internal_state_tag mz_zip_internal_state; typedef enum { - MZ_ZIP_MODE_INVALID = 0, - MZ_ZIP_MODE_READING = 1, - MZ_ZIP_MODE_WRITING = 2, - MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3 + MZ_ZIP_MODE_INVALID = 0, + MZ_ZIP_MODE_READING = 1, + MZ_ZIP_MODE_WRITING = 2, + MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3 } mz_zip_mode; typedef struct mz_zip_archive_tag { - mz_uint64 m_archive_size; - mz_uint64 m_central_directory_file_ofs; - mz_uint m_total_files; - mz_zip_mode m_zip_mode; + mz_uint64 m_archive_size; + mz_uint64 m_central_directory_file_ofs; + mz_uint m_total_files; + mz_zip_mode m_zip_mode; - mz_uint m_file_offset_alignment; + mz_uint m_file_offset_alignment; - mz_alloc_func m_pAlloc; - mz_free_func m_pFree; - mz_realloc_func m_pRealloc; - void *m_pAlloc_opaque; + mz_alloc_func m_pAlloc; + mz_free_func m_pFree; + mz_realloc_func m_pRealloc; + void* m_pAlloc_opaque; - mz_file_read_func m_pRead; - mz_file_write_func m_pWrite; - void *m_pIO_opaque; - - mz_zip_internal_state *m_pState; + mz_file_read_func m_pRead; + mz_file_write_func m_pWrite; + void* m_pIO_opaque; + mz_zip_internal_state* m_pState; } mz_zip_archive; typedef enum { - MZ_ZIP_FLAG_CASE_SENSITIVE = 0x0100, - MZ_ZIP_FLAG_IGNORE_PATH = 0x0200, - MZ_ZIP_FLAG_COMPRESSED_DATA = 0x0400, - MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800 + MZ_ZIP_FLAG_CASE_SENSITIVE = 0x0100, + MZ_ZIP_FLAG_IGNORE_PATH = 0x0200, + MZ_ZIP_FLAG_COMPRESSED_DATA = 0x0400, + MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800 } mz_zip_flags; // ZIP archive reading // Inits a ZIP archive reader. // These functions read and validate the archive's central directory. -mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags); -mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags); +mz_bool mz_zip_reader_init(mz_zip_archive* pZip, mz_uint64 size, mz_uint32 flags); +mz_bool mz_zip_reader_init_mem(mz_zip_archive* pZip, const void* pMem, size_t size, mz_uint32 flags); #ifndef MINIZ_NO_STDIO -mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags); +mz_bool mz_zip_reader_init_file(mz_zip_archive* pZip, const char* pFilename, mz_uint32 flags); #endif // Returns the total number of files in the archive. -mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip); +mz_uint mz_zip_reader_get_num_files(mz_zip_archive* pZip); // Returns detailed information about an archive file entry. -mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat); +mz_bool mz_zip_reader_file_stat(mz_zip_archive* pZip, mz_uint file_index, mz_zip_archive_file_stat* pStat); // Determines if an archive file entry is a directory entry. -mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index); -mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index); +mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive* pZip, mz_uint file_index); +mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive* pZip, mz_uint file_index); // Retrieves the filename of an archive file entry. // Returns the number of bytes written to pFilename, or if filename_buf_size is 0 this function returns the number of bytes needed to fully store the filename. -mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size); +mz_uint mz_zip_reader_get_filename(mz_zip_archive* pZip, mz_uint file_index, char* pFilename, + mz_uint filename_buf_size); // Attempts to locates a file in the archive's central directory. // Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH // Returns -1 if the file cannot be found. -int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags); +int mz_zip_reader_locate_file(mz_zip_archive* pZip, const char* pName, const char* pComment, mz_uint flags); // Extracts a archive file to a memory buffer using no memory allocation. -mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size); -mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size); +mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive* pZip, mz_uint file_index, void* pBuf, size_t buf_size, + mz_uint flags, void* pUser_read_buf, size_t user_read_buf_size); +mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive* pZip, const char* pFilename, void* pBuf, + size_t buf_size, mz_uint flags, void* pUser_read_buf, + size_t user_read_buf_size); // Extracts a archive file to a memory buffer. -mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags); -mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags); +mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive* pZip, mz_uint file_index, void* pBuf, size_t buf_size, + mz_uint flags); +mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive* pZip, const char* pFilename, void* pBuf, size_t buf_size, + mz_uint flags); // Extracts a archive file to a dynamically allocated heap buffer. -void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags); -void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags); +void* mz_zip_reader_extract_to_heap(mz_zip_archive* pZip, mz_uint file_index, size_t* pSize, mz_uint flags); +void* mz_zip_reader_extract_file_to_heap(mz_zip_archive* pZip, const char* pFilename, size_t* pSize, mz_uint flags); // Extracts a archive file using a callback function to output the file's data. -mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags); -mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags); +mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive* pZip, mz_uint file_index, mz_file_write_func pCallback, + void* pOpaque, mz_uint flags); +mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive* pZip, const char* pFilename, + mz_file_write_func pCallback, void* pOpaque, mz_uint flags); #ifndef MINIZ_NO_STDIO // Extracts a archive file to a disk file and sets its last accessed and modified times. // This function only extracts files, not archive directory records. -mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags); -mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags); +mz_bool mz_zip_reader_extract_to_file(mz_zip_archive* pZip, mz_uint file_index, const char* pDst_filename, + mz_uint flags); +mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive* pZip, const char* pArchive_filename, + const char* pDst_filename, mz_uint flags); #endif // Ends archive reading, freeing all allocations, and closing the input archive file if mz_zip_reader_init_file() was used. -mz_bool mz_zip_reader_end(mz_zip_archive *pZip); +mz_bool mz_zip_reader_end(mz_zip_archive* pZip); // ZIP archive writing #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS // Inits a ZIP archive writer. -mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size); -mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size); +mz_bool mz_zip_writer_init(mz_zip_archive* pZip, mz_uint64 existing_size); +mz_bool mz_zip_writer_init_heap(mz_zip_archive* pZip, size_t size_to_reserve_at_beginning, + size_t initial_allocation_size); #ifndef MINIZ_NO_STDIO -mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning); +mz_bool mz_zip_writer_init_file(mz_zip_archive* pZip, const char* pFilename, mz_uint64 size_to_reserve_at_beginning); #endif // Converts a ZIP archive reader object into a writer object, to allow efficient in-place file appends to occur on an existing archive. @@ -639,43 +670,50 @@ mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_ // Finally, for archives opened using mz_zip_reader_init, the mz_zip_archive's user provided m_pWrite function cannot be NULL. // Note: In-place archive modification is not recommended unless you know what you're doing, because if execution stops or something goes wrong before // the archive is finalized the file's central directory will be hosed. -mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename); +mz_bool mz_zip_writer_init_from_reader(mz_zip_archive* pZip, const char* pFilename); // Adds the contents of a memory buffer to an archive. These functions record the current local time into the archive. // To add a directory entry, call this method with an archive name ending in a forwardslash with empty buffer. // level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. -mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags); -mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32); +mz_bool mz_zip_writer_add_mem(mz_zip_archive* pZip, const char* pArchive_name, const void* pBuf, size_t buf_size, + mz_uint level_and_flags); +mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive* pZip, const char* pArchive_name, const void* pBuf, size_t buf_size, + const void* pComment, mz_uint16 comment_size, mz_uint level_and_flags, + mz_uint64 uncomp_size, mz_uint32 uncomp_crc32); #ifndef MINIZ_NO_STDIO // Adds the contents of a disk file to an archive. This function also records the disk file's modified time into the archive. // level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. -mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags); +mz_bool mz_zip_writer_add_file(mz_zip_archive* pZip, const char* pArchive_name, const char* pSrc_filename, + const void* pComment, mz_uint16 comment_size, mz_uint level_and_flags); #endif // Adds a file to an archive by fully cloning the data from another archive. // This function fully clones the source file's compressed data (no recompression), along with its full filename, extra data, and comment fields. -mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index); +mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive* pZip, mz_zip_archive* pSource_zip, mz_uint file_index); // Finalizes the archive by writing the central directory records followed by the end of central directory record. // After an archive is finalized, the only valid call on the mz_zip_archive struct is mz_zip_writer_end(). // An archive must be manually finalized by calling this function for it to be valid. -mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip); -mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize); +mz_bool mz_zip_writer_finalize_archive(mz_zip_archive* pZip); +mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive* pZip, void** pBuf, size_t* pSize); // Ends archive writing, freeing all allocations, and closing the output file if mz_zip_writer_init_file() was used. // Note for the archive to be valid, it must have been finalized before ending. -mz_bool mz_zip_writer_end(mz_zip_archive *pZip); +mz_bool mz_zip_writer_end(mz_zip_archive* pZip); // Misc. high-level helper functions: // mz_zip_add_mem_to_archive_file_in_place() efficiently (but not atomically) appends a memory blob to a ZIP archive. // level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. -mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags); +mz_bool mz_zip_add_mem_to_archive_file_in_place(const char* pZip_filename, const char* pArchive_name, const void* pBuf, + size_t buf_size, const void* pComment, mz_uint16 comment_size, + mz_uint level_and_flags); // Reads a single file from an archive into a heap block. // Returns NULL on failure. -void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint zip_flags); +void* mz_zip_extract_archive_file_to_heap(const char* pZip_filename, const char* pArchive_name, size_t* pSize, + mz_uint zip_flags); #endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS @@ -690,10 +728,10 @@ void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char // TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the decompressed bytes. enum { - TINFL_FLAG_PARSE_ZLIB_HEADER = 1, - TINFL_FLAG_HAS_MORE_INPUT = 2, - TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4, - TINFL_FLAG_COMPUTE_ADLER32 = 8 + TINFL_FLAG_PARSE_ZLIB_HEADER = 1, + TINFL_FLAG_HAS_MORE_INPUT = 2, + TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4, + TINFL_FLAG_COMPUTE_ADLER32 = 8 }; // High level decompression functions: @@ -704,19 +742,22 @@ enum // Function returns a pointer to the decompressed data, or NULL on failure. // *pOut_len will be set to the decompressed data's size, which could be larger than src_buf_len on uncompressible data. // The caller must call mz_free() on the returned block when it's no longer needed. -void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags); +void* tinfl_decompress_mem_to_heap(const void* pSrc_buf, size_t src_buf_len, size_t* pOut_len, int flags); // tinfl_decompress_mem_to_mem() decompresses a block in memory to another block in memory. // Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes written on success. #define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1)) -size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags); +size_t tinfl_decompress_mem_to_mem(void* pOut_buf, size_t out_buf_len, const void* pSrc_buf, size_t src_buf_len, + int flags); // tinfl_decompress_mem_to_callback() decompresses a block in memory to an internal 32KB buffer, and a user provided callback function will be called to flush the buffer. // Returns 1 on success or 0 on failure. -typedef int (*tinfl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser); -int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); +typedef int (*tinfl_put_buf_func_ptr)(const void* pBuf, int len, void* pUser); +int tinfl_decompress_mem_to_callback(const void* pIn_buf, size_t* pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, + void* pPut_buf_user, int flags); -struct tinfl_decompressor_tag; typedef struct tinfl_decompressor_tag tinfl_decompressor; +struct tinfl_decompressor_tag; +typedef struct tinfl_decompressor_tag tinfl_decompressor; // Max size of LZ dictionary. #define TINFL_LZ_DICT_SIZE 32768 @@ -724,12 +765,12 @@ struct tinfl_decompressor_tag; typedef struct tinfl_decompressor_tag tinfl_decom // Return status. typedef enum { - TINFL_STATUS_BAD_PARAM = -3, - TINFL_STATUS_ADLER32_MISMATCH = -2, - TINFL_STATUS_FAILED = -1, - TINFL_STATUS_DONE = 0, - TINFL_STATUS_NEEDS_MORE_INPUT = 1, - TINFL_STATUS_HAS_MORE_OUTPUT = 2 + TINFL_STATUS_BAD_PARAM = -3, + TINFL_STATUS_ADLER32_MISMATCH = -2, + TINFL_STATUS_FAILED = -1, + TINFL_STATUS_DONE = 0, + TINFL_STATUS_NEEDS_MORE_INPUT = 1, + TINFL_STATUS_HAS_MORE_OUTPUT = 2 } tinfl_status; // Initializes the decompressor to its initial state. @@ -738,28 +779,34 @@ typedef enum // Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability. // This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output. -tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags); +tinfl_status tinfl_decompress(tinfl_decompressor* r, const mz_uint8* pIn_buf_next, size_t* pIn_buf_size, + mz_uint8* pOut_buf_start, mz_uint8* pOut_buf_next, size_t* pOut_buf_size, + const mz_uint32 decomp_flags); // Internal/private bits follow. enum { - TINFL_MAX_HUFF_TABLES = 3, TINFL_MAX_HUFF_SYMBOLS_0 = 288, TINFL_MAX_HUFF_SYMBOLS_1 = 32, TINFL_MAX_HUFF_SYMBOLS_2 = 19, - TINFL_FAST_LOOKUP_BITS = 10, TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS + TINFL_MAX_HUFF_TABLES = 3, + TINFL_MAX_HUFF_SYMBOLS_0 = 288, + TINFL_MAX_HUFF_SYMBOLS_1 = 32, + TINFL_MAX_HUFF_SYMBOLS_2 = 19, + TINFL_FAST_LOOKUP_BITS = 10, + TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS }; typedef struct { - mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0]; - mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2]; + mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0]; + mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2]; } tinfl_huff_table; #if MINIZ_HAS_64BIT_REGISTERS - #define TINFL_USE_64BIT_BITBUF 1 +#define TINFL_USE_64BIT_BITBUF 1 #endif #if TINFL_USE_64BIT_BITBUF - typedef mz_uint64 tinfl_bit_buf_t; - #define TINFL_BITBUF_SIZE (64) +typedef mz_uint64 tinfl_bit_buf_t; +#define TINFL_BITBUF_SIZE (64) #else typedef mz_uint32 tinfl_bit_buf_t; #define TINFL_BITBUF_SIZE (32) @@ -767,11 +814,12 @@ typedef struct struct tinfl_decompressor_tag { - mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES]; - tinfl_bit_buf_t m_bit_buf; - size_t m_dist_from_out_buf_start; - tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES]; - mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137]; + mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, + m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES]; + tinfl_bit_buf_t m_bit_buf; + size_t m_dist_from_out_buf_start; + tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES]; + mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137]; }; // ------------------- Low-level Compression API Definitions @@ -783,7 +831,9 @@ struct tinfl_decompressor_tag // TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap compression), 4095=Huffman+LZ (slowest/best compression). enum { - TDEFL_HUFFMAN_ONLY = 0, TDEFL_DEFAULT_MAX_PROBES = 128, TDEFL_MAX_PROBES_MASK = 0xFFF + TDEFL_HUFFMAN_ONLY = 0, + TDEFL_DEFAULT_MAX_PROBES = 128, + TDEFL_MAX_PROBES_MASK = 0xFFF }; // TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before the deflate data, and the Adler-32 of the source data at the end. Otherwise, you'll get raw deflate data. @@ -797,14 +847,14 @@ enum // The low 12 bits are reserved to control the max # of hash probes per dictionary lookup (see TDEFL_MAX_PROBES_MASK). enum { - TDEFL_WRITE_ZLIB_HEADER = 0x01000, - TDEFL_COMPUTE_ADLER32 = 0x02000, - TDEFL_GREEDY_PARSING_FLAG = 0x04000, - TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000, - TDEFL_RLE_MATCHES = 0x10000, - TDEFL_FILTER_MATCHES = 0x20000, - TDEFL_FORCE_ALL_STATIC_BLOCKS = 0x40000, - TDEFL_FORCE_ALL_RAW_BLOCKS = 0x80000 + TDEFL_WRITE_ZLIB_HEADER = 0x01000, + TDEFL_COMPUTE_ADLER32 = 0x02000, + TDEFL_GREEDY_PARSING_FLAG = 0x04000, + TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000, + TDEFL_RLE_MATCHES = 0x10000, + TDEFL_FILTER_MATCHES = 0x20000, + TDEFL_FORCE_ALL_STATIC_BLOCKS = 0x40000, + TDEFL_FORCE_ALL_RAW_BLOCKS = 0x80000 }; // High level compression functions: @@ -816,11 +866,12 @@ enum // Function returns a pointer to the compressed data, or NULL on failure. // *pOut_len will be set to the compressed data's size, which could be larger than src_buf_len on uncompressible data. // The caller must free() the returned block when it's no longer needed. -void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags); +void* tdefl_compress_mem_to_heap(const void* pSrc_buf, size_t src_buf_len, size_t* pOut_len, int flags); // tdefl_compress_mem_to_mem() compresses a block in memory to another block in memory. // Returns 0 on failure. -size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags); +size_t tdefl_compress_mem_to_mem(void* pOut_buf, size_t out_buf_len, const void* pSrc_buf, size_t src_buf_len, + int flags); // Compresses an image to a compressed PNG file in memory. // On entry: @@ -832,68 +883,90 @@ size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void // Function returns a pointer to the compressed data, or NULL on failure. // *pLen_out will be set to the size of the PNG image file. // The caller must mz_free() the returned heap block (which will typically be larger than *pLen_out) when it's no longer needed. -void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip); -void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out); +void* tdefl_write_image_to_png_file_in_memory_ex(const void* pImage, int w, int h, int num_chans, size_t* pLen_out, + mz_uint level, mz_bool flip); +void* tdefl_write_image_to_png_file_in_memory(const void* pImage, int w, int h, int num_chans, size_t* pLen_out); // Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time. -typedef mz_bool (*tdefl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser); +typedef mz_bool (*tdefl_put_buf_func_ptr)(const void* pBuf, int len, void* pUser); // tdefl_compress_mem_to_output() compresses a block to an output stream. The above helpers use this function internally. -mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); +mz_bool tdefl_compress_mem_to_output(const void* pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, + void* pPut_buf_user, int flags); -enum { TDEFL_MAX_HUFF_TABLES = 3, TDEFL_MAX_HUFF_SYMBOLS_0 = 288, TDEFL_MAX_HUFF_SYMBOLS_1 = 32, TDEFL_MAX_HUFF_SYMBOLS_2 = 19, TDEFL_LZ_DICT_SIZE = 32768, TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1, TDEFL_MIN_MATCH_LEN = 3, TDEFL_MAX_MATCH_LEN = 258 }; +enum +{ + TDEFL_MAX_HUFF_TABLES = 3, + TDEFL_MAX_HUFF_SYMBOLS_0 = 288, + TDEFL_MAX_HUFF_SYMBOLS_1 = 32, + TDEFL_MAX_HUFF_SYMBOLS_2 = 19, + TDEFL_LZ_DICT_SIZE = 32768, + TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1, + TDEFL_MIN_MATCH_LEN = 3, + TDEFL_MAX_MATCH_LEN = 258 +}; // TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed output block (using static/fixed Huffman codes). #if TDEFL_LESS_MEMORY enum { TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 12, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS }; #else -enum { TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 15, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS }; +enum +{ + TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024, + TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10, + TDEFL_MAX_HUFF_SYMBOLS = 288, + TDEFL_LZ_HASH_BITS = 15, + TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, + TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, + TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS +}; #endif // The low-level tdefl functions below may be used directly if the above helper functions aren't flexible enough. The low-level functions don't make any heap allocations, unlike the above helper functions. typedef enum { - TDEFL_STATUS_BAD_PARAM = -2, - TDEFL_STATUS_PUT_BUF_FAILED = -1, - TDEFL_STATUS_OKAY = 0, - TDEFL_STATUS_DONE = 1, + TDEFL_STATUS_BAD_PARAM = -2, + TDEFL_STATUS_PUT_BUF_FAILED = -1, + TDEFL_STATUS_OKAY = 0, + TDEFL_STATUS_DONE = 1, } tdefl_status; // Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums typedef enum { - TDEFL_NO_FLUSH = 0, - TDEFL_SYNC_FLUSH = 2, - TDEFL_FULL_FLUSH = 3, - TDEFL_FINISH = 4 + TDEFL_NO_FLUSH = 0, + TDEFL_SYNC_FLUSH = 2, + TDEFL_FULL_FLUSH = 3, + TDEFL_FINISH = 4 } tdefl_flush; // tdefl's compression state structure. typedef struct { - tdefl_put_buf_func_ptr m_pPut_buf_func; - void *m_pPut_buf_user; - mz_uint m_flags, m_max_probes[2]; - int m_greedy_parsing; - mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size; - mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end; - mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in, m_bit_buffer; - mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit, m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index, m_wants_to_finish; - tdefl_status m_prev_return_status; - const void *m_pIn_buf; - void *m_pOut_buf; - size_t *m_pIn_buf_size, *m_pOut_buf_size; - tdefl_flush m_flush; - const mz_uint8 *m_pSrc; - size_t m_src_buf_left, m_out_buf_ofs; - mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1]; - mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; - mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; - mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; - mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE]; - mz_uint16 m_next[TDEFL_LZ_DICT_SIZE]; - mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE]; - mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE]; + tdefl_put_buf_func_ptr m_pPut_buf_func; + void* m_pPut_buf_user; + mz_uint m_flags, m_max_probes[2]; + int m_greedy_parsing; + mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size; + mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end; + mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in, m_bit_buffer; + mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit, m_output_flush_ofs, m_output_flush_remaining, m_finished, + m_block_index, m_wants_to_finish; + tdefl_status m_prev_return_status; + const void* m_pIn_buf; + void* m_pOut_buf; + size_t *m_pIn_buf_size, *m_pOut_buf_size; + tdefl_flush m_flush; + const mz_uint8* m_pSrc; + size_t m_src_buf_left, m_out_buf_ofs; + mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1]; + mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; + mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; + mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; + mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE]; + mz_uint16 m_next[TDEFL_LZ_DICT_SIZE]; + mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE]; + mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE]; } tdefl_compressor; // Initializes the compressor. @@ -901,17 +974,18 @@ typedef struct // pBut_buf_func: If NULL, output data will be supplied to the specified callback. In this case, the user should call the tdefl_compress_buffer() API for compression. // If pBut_buf_func is NULL the user should always call the tdefl_compress() API. // flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.) -tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); +tdefl_status tdefl_init(tdefl_compressor* d, tdefl_put_buf_func_ptr pPut_buf_func, void* pPut_buf_user, int flags); // Compresses a block of data, consuming as much of the specified input buffer as possible, and writing as much compressed data to the specified output buffer as possible. -tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush); +tdefl_status tdefl_compress(tdefl_compressor* d, const void* pIn_buf, size_t* pIn_buf_size, void* pOut_buf, + size_t* pOut_buf_size, tdefl_flush flush); // tdefl_compress_buffer() is only usable when the tdefl_init() is called with a non-NULL tdefl_put_buf_func_ptr. // tdefl_compress_buffer() always consumes the entire input buffer. -tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush); +tdefl_status tdefl_compress_buffer(tdefl_compressor* d, const void* pIn_buf, size_t in_buf_size, tdefl_flush flush); -tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d); -mz_uint32 tdefl_get_adler32(tdefl_compressor *d); +tdefl_status tdefl_get_prev_return_status(tdefl_compressor* d); +mz_uint32 tdefl_get_adler32(tdefl_compressor* d); // Can't use tdefl_create_comp_flags_from_zip_params if MINIZ_NO_ZLIB_APIS isn't defined, because it uses some of its macros. #ifndef MINIZ_NO_ZLIB_APIS @@ -927,4 +1001,3 @@ mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int #endif #endif // MINIZ_HEADER_INCLUDED - diff --git a/Utilities/orfanidis_eq.h b/Utilities/orfanidis_eq.h index 012f448..a7938f3 100644 --- a/Utilities/orfanidis_eq.h +++ b/Utilities/orfanidis_eq.h @@ -6,7 +6,8 @@ using namespace std; -namespace orfanidis_eq { +namespace orfanidis_eq +{ //Eq data types. typedef double eq_single_t; typedef double eq_double_t; @@ -22,18 +23,20 @@ namespace orfanidis_eq { chebyshev2 } filter_type; - static const char *get_eq_text(filter_type type) { - switch(type) { - case none: - return "not initialized"; - case butterworth: - return "butterworth"; - case chebyshev1: - return "chebyshev1"; - case chebyshev2: - return "chebyshev2"; - default: - return "none"; + static const char* get_eq_text(filter_type type) + { + switch (type) + { + case none: + return "not initialized"; + case butterworth: + return "butterworth"; + case chebyshev1: + return "chebyshev1"; + case chebyshev2: + return "chebyshev2"; + default: + return "none"; } } @@ -83,36 +86,44 @@ namespace orfanidis_eq { int db_min_max; std::vector lin_gains; - int lin_gains_index(eq_double_t x) { + int lin_gains_index(eq_double_t x) + { int int_x = (int)x; - if((x >= -db_min_max) && (x < db_min_max - 1)) + if ((x >= -db_min_max) && (x < db_min_max - 1)) return db_min_max + int_x; return db_min_max; } - conversions() {} + conversions() + { + } public: - conversions(int min_max) { + conversions(int min_max) + { db_min_max = min_max; //Update table (vector elements) for fast conversions int step = -min_max; - while(step <= min_max) + while (step <= min_max) lin_gains.push_back(db_2_lin(step++)); } - inline eq_double_t fast_db_2_lin(eq_double_t x) { + inline eq_double_t fast_db_2_lin(eq_double_t x) + { int int_part = (int)x; eq_double_t frac_part = x - int_part; return lin_gains[lin_gains_index(int_part)] * (1 - frac_part) + - (lin_gains[lin_gains_index(int_part + 1)])*frac_part; + (lin_gains[lin_gains_index(int_part + 1)]) * frac_part; } - inline eq_double_t fast_lin_2_db(eq_double_t x) { - if((x >= lin_gains[0]) && (x < lin_gains[lin_gains.size() - 1])) { - for(unsigned int i = 0; i < lin_gains.size() - 2; i++) - if((x >= lin_gains[i]) && (x < lin_gains[i + 1])) { + inline eq_double_t fast_lin_2_db(eq_double_t x) + { + if ((x >= lin_gains[0]) && (x < lin_gains[lin_gains.size() - 1])) + { + for (unsigned int i = 0; i < lin_gains.size() - 2; i++) + if ((x >= lin_gains[i]) && (x < lin_gains[i + 1])) + { int int_part = i - db_min_max; eq_double_t frac_part = x - (int)(x); return int_part + frac_part; @@ -121,20 +132,24 @@ namespace orfanidis_eq { return 0; } - inline static eq_double_t db_2_lin(eq_double_t x) { + inline static eq_double_t db_2_lin(eq_double_t x) + { return pow(10, x / 20); } - inline static eq_double_t lin_2_db(eq_double_t x) { + inline static eq_double_t lin_2_db(eq_double_t x) + { return 20 * log10(x); } - inline static eq_double_t rad_2_hz(eq_double_t x, eq_double_t fs) { - return 2 * pi / x*fs; + inline static eq_double_t rad_2_hz(eq_double_t x, eq_double_t fs) + { + return 2 * pi / x * fs; } - inline static eq_double_t hz_2_rad(eq_double_t x, eq_double_t fs) { - return 2 * pi*x / fs; + inline static eq_double_t hz_2_rad(eq_double_t x, eq_double_t fs) + { + return 2 * pi * x / fs; } }; @@ -150,9 +165,13 @@ namespace orfanidis_eq { eq_double_t max_freq; band_freqs(eq_double_t f1, eq_double_t f0, eq_double_t f2) : - min_freq(f1), center_freq(f0), max_freq(f2) {} + min_freq(f1), center_freq(f0), max_freq(f2) + { + } - ~band_freqs() {} + ~band_freqs() + { + } }; //------------ Frequency grid class ------------ @@ -162,18 +181,26 @@ namespace orfanidis_eq { std::vector freqs_; public: - freq_grid() {} - freq_grid(const freq_grid& fg) { this->freqs_ = fg.freqs_; } - ~freq_grid() {} + freq_grid() + { + } - eq_error_t set_band(eq_double_t fmin, eq_double_t f0, eq_double_t fmax) { + freq_grid(const freq_grid& fg) { this->freqs_ = fg.freqs_; } + + ~freq_grid() + { + } + + eq_error_t set_band(eq_double_t fmin, eq_double_t f0, eq_double_t fmax) + { freqs_.clear(); return add_band(fmin, f0, fmax); } //fc, fmin, fmax - eq_error_t add_band(eq_double_t fmin, eq_double_t f0, eq_double_t fmax) { - if(fmin < f0 && f0 < fmax) + eq_error_t add_band(eq_double_t fmin, eq_double_t f0, eq_double_t fmax) + { + if (fmin < f0 && f0 < fmax) freqs_.push_back(band_freqs(fmin, f0, fmax)); else return invalid_input_data_error; @@ -181,106 +208,121 @@ namespace orfanidis_eq { } //f0, deltaf = fmax - fmin - eq_error_t add_band(eq_double_t f0, eq_double_t df) { - if(f0 >= df / 2) { + eq_error_t add_band(eq_double_t f0, eq_double_t df) + { + if (f0 >= df / 2) + { eq_double_t fmin = f0 - df / 2; eq_double_t fmax = f0 + df / 2; freqs_.push_back(band_freqs(fmin, f0, fmax)); - } else + } + else return invalid_input_data_error; return no_error; } - eq_error_t set_5_bands(eq_double_t center_freq = bands_grid_center_freq_hz) { + eq_error_t set_5_bands(eq_double_t center_freq = bands_grid_center_freq_hz) + { freqs_.clear(); - if(lowest_audio_freq_hz < center_freq && - center_freq < highest_audio_freq_hz) { - + if (lowest_audio_freq_hz < center_freq && + center_freq < highest_audio_freq_hz) + { //Find lowest center frequency in band eq_double_t lowest_center_freq = center_freq; - while(lowest_center_freq > lowest_grid_center_freq_hz) + while (lowest_center_freq > lowest_grid_center_freq_hz) lowest_center_freq /= 4.0; - if(lowest_center_freq < lowest_grid_center_freq_hz) + if (lowest_center_freq < lowest_grid_center_freq_hz) lowest_center_freq *= 4.0; //Calculate freq's eq_double_t f0 = lowest_center_freq; - for(unsigned int i = 0; i < 5; i++) { + for (unsigned int i = 0; i < 5; i++) + { freqs_.push_back(band_freqs(f0 / 2, f0, f0 * 2)); f0 *= 4; } - } else + } + else return invalid_input_data_error; return no_error; } - eq_error_t set_10_bands(eq_double_t center_freq = bands_grid_center_freq_hz) { + eq_error_t set_10_bands(eq_double_t center_freq = bands_grid_center_freq_hz) + { freqs_.clear(); - if(lowest_audio_freq_hz < center_freq && - center_freq < highest_audio_freq_hz) { - + if (lowest_audio_freq_hz < center_freq && + center_freq < highest_audio_freq_hz) + { //Find lowest center frequency in band eq_double_t lowest_center_freq = center_freq; - while(lowest_center_freq > lowest_grid_center_freq_hz) + while (lowest_center_freq > lowest_grid_center_freq_hz) lowest_center_freq /= 2; - if(lowest_center_freq < lowest_grid_center_freq_hz) + if (lowest_center_freq < lowest_grid_center_freq_hz) lowest_center_freq *= 2; //Calculate freq's eq_double_t f0 = lowest_center_freq; - for(unsigned int i = 0; i < 10; i++) { - freqs_.push_back(band_freqs(f0 / pow(2, 0.5), f0, f0*pow(2, 0.5))); + for (unsigned int i = 0; i < 10; i++) + { + freqs_.push_back(band_freqs(f0 / pow(2, 0.5), f0, f0 * pow(2, 0.5))); f0 *= 2; } - } else + } + else return invalid_input_data_error; return no_error; } - eq_error_t set_20_bands(eq_double_t center_freq = bands_grid_center_freq_hz) { + eq_error_t set_20_bands(eq_double_t center_freq = bands_grid_center_freq_hz) + { freqs_.clear(); - if(lowest_audio_freq_hz < center_freq && - center_freq < highest_audio_freq_hz) { - + if (lowest_audio_freq_hz < center_freq && + center_freq < highest_audio_freq_hz) + { //Find lowest center frequency in band eq_double_t lowest_center_freq = center_freq; - while(lowest_center_freq > lowest_audio_freq_hz) + while (lowest_center_freq > lowest_audio_freq_hz) lowest_center_freq /= pow(2, 0.5); - if(lowest_center_freq < lowest_audio_freq_hz) + if (lowest_center_freq < lowest_audio_freq_hz) lowest_center_freq *= pow(2, 0.5); //Calculate freq's eq_double_t f0 = lowest_center_freq; - for(unsigned int i = 0; i < 20; i++) { + for (unsigned int i = 0; i < 20; i++) + { freqs_.push_back(band_freqs(f0 / pow(2, 0.25), - f0, f0*pow(2, 0.25))); + f0, f0 * pow(2, 0.25))); f0 *= pow(2, 0.5); } - } else + } + else return invalid_input_data_error; return no_error; } - eq_error_t set_30_bands(eq_double_t center_freq = bands_grid_center_freq_hz) { + eq_error_t set_30_bands(eq_double_t center_freq = bands_grid_center_freq_hz) + { freqs_.clear(); - if(lowest_audio_freq_hz < center_freq && - center_freq < highest_audio_freq_hz) { - + if (lowest_audio_freq_hz < center_freq && + center_freq < highest_audio_freq_hz) + { //Find lowest center frequency in band eq_double_t lowest_center_freq = center_freq; - while(lowest_center_freq > lowest_audio_freq_hz) + while (lowest_center_freq > lowest_audio_freq_hz) lowest_center_freq /= pow(2.0, 1.0 / 3.0); - if(lowest_center_freq < lowest_audio_freq_hz) + if (lowest_center_freq < lowest_audio_freq_hz) lowest_center_freq *= pow(2.0, 1.0 / 3.0); //Calculate freq's eq_double_t f0 = lowest_center_freq; - for(unsigned int i = 0; i < 30; i++) { + for (unsigned int i = 0; i < 30; i++) + { freqs_.push_back(band_freqs(f0 / pow(2.0, 1.0 / 6.0), - f0, f0*pow(2.0, 1.0 / 6.0))); + f0, f0 * pow(2.0, 1.0 / 6.0))); f0 *= pow(2, 1.0 / 3.0); } - } else + } + else return invalid_input_data_error; return no_error; } @@ -289,33 +331,41 @@ namespace orfanidis_eq { std::vector get_freqs() { return freqs_; } - unsigned int get_freq(unsigned int number) { - if(number < freqs_.size()) + unsigned int get_freq(unsigned int number) + { + if (number < freqs_.size()) return (unsigned int)freqs_[number].center_freq; else return 0; } - unsigned int get_rounded_freq(unsigned int number) { - if(number < freqs_.size()) { + unsigned int get_rounded_freq(unsigned int number) + { + if (number < freqs_.size()) + { unsigned int freq = (unsigned int)freqs_[number].center_freq; - if(freq < 100) + if (freq < 100) return freq; - else if(freq >= 100 && freq < 1000) { + else if (freq >= 100 && freq < 1000) + { unsigned int rest = freq % 10; - if(rest < 5) + if (rest < 5) return freq - rest; else return freq - rest + 10; - } else if(freq >= 1000 && freq < 10000) { + } + else if (freq >= 1000 && freq < 10000) + { unsigned int rest = freq % 100; - if(rest < 50) + if (rest < 50) return freq - rest; else return freq - rest + 100; - } else if(freq >= 10000) { + } + else if (freq >= 10000) + { unsigned int rest = freq % 1000; - if(rest < 500) + if (rest < 500) return freq - rest; else return freq - rest + 1000; @@ -329,24 +379,34 @@ namespace orfanidis_eq { class fo_section { protected: - eq_single_t b0; eq_single_t b1; eq_single_t b2; eq_single_t b3; eq_single_t b4; - eq_single_t a0; eq_single_t a1; eq_single_t a2; eq_single_t a3; eq_single_t a4; + eq_single_t b0; + eq_single_t b1; + eq_single_t b2; + eq_single_t b3; + eq_single_t b4; + eq_single_t a0; + eq_single_t a1; + eq_single_t a2; + eq_single_t a3; + eq_single_t a4; eq_single_t numBuf[fo_section_order]; eq_single_t denumBuf[fo_section_order]; - inline eq_single_t df1_fo_process(eq_single_t in) { + inline eq_single_t df1_fo_process(eq_single_t in) + { eq_single_t out = 0; - out += b0*in; - out += (b1*numBuf[0] - denumBuf[0] * a1); - out += (b2*numBuf[1] - denumBuf[1] * a2); - out += (b3*numBuf[2] - denumBuf[2] * a3); - out += (b4*numBuf[3] - denumBuf[3] * a4); + out += b0 * in; + out += (b1 * numBuf[0] - denumBuf[0] * a1); + out += (b2 * numBuf[1] - denumBuf[1] * a2); + out += (b3 * numBuf[2] - denumBuf[2] * a3); + out += (b4 * numBuf[3] - denumBuf[3] * a4); numBuf[3] = numBuf[2]; numBuf[2] = numBuf[1]; numBuf[1] = numBuf[0]; - if(in < 0.000000000001 && in > -0.000000000001) { + if (in < 0.000000000001 && in > -0.000000000001) + { //Prevent denormalized values (causes extreme performance loss) in = 0; } @@ -355,56 +415,78 @@ namespace orfanidis_eq { denumBuf[3] = denumBuf[2]; denumBuf[2] = denumBuf[1]; denumBuf[1] = denumBuf[0]; - if(out < 0.000000000001 && out > -0.000000000001) { + if (out < 0.000000000001 && out > -0.000000000001) + { //Prevent denormalized values (causes extreme performance loss) out = 0; } *denumBuf = out; - return(out); + return (out); } public: - fo_section() { - b0 = 1; b1 = 0; b2 = 0; b3 = 0; b4 = 0; - a0 = 1; a1 = 0; a2 = 0; a3 = 0; a4 = 0; + fo_section() + { + b0 = 1; + b1 = 0; + b2 = 0; + b3 = 0; + b4 = 0; + a0 = 1; + a1 = 0; + a2 = 0; + a3 = 0; + a4 = 0; - for(unsigned int i = 0; i < fo_section_order; i++) { + for (unsigned int i = 0; i < fo_section_order; i++) + { numBuf[i] = 0; denumBuf[i] = 0; } } - virtual ~fo_section() {} + virtual ~fo_section() + { + } - eq_single_t process(eq_single_t in) { + eq_single_t process(eq_single_t in) + { return df1_fo_process(in); } - virtual fo_section get() { + virtual fo_section get() + { return *this; } }; class butterworth_fo_section : public fo_section { - butterworth_fo_section() {} - butterworth_fo_section(butterworth_fo_section&) {} + butterworth_fo_section() + { + } + + butterworth_fo_section(butterworth_fo_section&) + { + } + public: butterworth_fo_section(eq_double_t beta, - eq_double_t s, eq_double_t g, eq_double_t g0, - eq_double_t D, eq_double_t c0) { - b0 = (g*g*beta*beta + 2 * g*g0*s*beta + g0*g0) / D; - b1 = -4 * c0*(g0*g0 + g*g0*s*beta) / D; - b2 = 2 * (g0*g0*(1 + 2 * c0*c0) - g*g*beta*beta) / D; - b3 = -4 * c0*(g0*g0 - g*g0*s*beta) / D; - b4 = (g*g*beta*beta - 2 * g*g0*s*beta + g0*g0) / D; + eq_double_t s, eq_double_t g, eq_double_t g0, + eq_double_t D, eq_double_t c0) + { + b0 = (g * g * beta * beta + 2 * g * g0 * s * beta + g0 * g0) / D; + b1 = -4 * c0 * (g0 * g0 + g * g0 * s * beta) / D; + b2 = 2 * (g0 * g0 * (1 + 2 * c0 * c0) - g * g * beta * beta) / D; + b3 = -4 * c0 * (g0 * g0 - g * g0 * s * beta) / D; + b4 = (g * g * beta * beta - 2 * g * g0 * s * beta + g0 * g0) / D; a0 = 1; - a1 = -4 * c0*(1 + s*beta) / D; - a2 = 2 * (1 + 2 * c0*c0 - beta*beta) / D; - a3 = -4 * c0*(1 - s*beta) / D; - a4 = (beta*beta - 2 * s*beta + 1) / D; + a1 = -4 * c0 * (1 + s * beta) / D; + a2 = 2 * (1 + 2 * c0 * c0 - beta * beta) / D; + a3 = -4 * c0 * (1 - s * beta) / D; + a4 = (beta * beta - 2 * s * beta + 1) / D; } fo_section get() { return *this; } @@ -412,24 +494,31 @@ namespace orfanidis_eq { class chebyshev_type1_fo_section : public fo_section { - chebyshev_type1_fo_section() {} - chebyshev_type1_fo_section(chebyshev_type1_fo_section&) {} + chebyshev_type1_fo_section() + { + } + + chebyshev_type1_fo_section(chebyshev_type1_fo_section&) + { + } + public: chebyshev_type1_fo_section(eq_double_t a, - eq_double_t c, eq_double_t tetta_b, - eq_double_t g0, eq_double_t s, eq_double_t b, - eq_double_t D, eq_double_t c0) { - b0 = ((b*b + g0*g0*c*c)*tetta_b*tetta_b + 2 * g0*b*s*tetta_b + g0*g0) / D; - b1 = -4 * c0*(g0*g0 + g0*b*s*tetta_b) / D; - b2 = 2 * (g0*g0*(1 + 2 * c0*c0) - (b*b + g0*g0*c*c)*tetta_b*tetta_b) / D; - b3 = -4 * c0*(g0*g0 - g0*b*s*tetta_b) / D; - b4 = ((b*b + g0*g0*c*c)*tetta_b*tetta_b - 2 * g0*b*s*tetta_b + g0*g0) / D; + eq_double_t c, eq_double_t tetta_b, + eq_double_t g0, eq_double_t s, eq_double_t b, + eq_double_t D, eq_double_t c0) + { + b0 = ((b * b + g0 * g0 * c * c) * tetta_b * tetta_b + 2 * g0 * b * s * tetta_b + g0 * g0) / D; + b1 = -4 * c0 * (g0 * g0 + g0 * b * s * tetta_b) / D; + b2 = 2 * (g0 * g0 * (1 + 2 * c0 * c0) - (b * b + g0 * g0 * c * c) * tetta_b * tetta_b) / D; + b3 = -4 * c0 * (g0 * g0 - g0 * b * s * tetta_b) / D; + b4 = ((b * b + g0 * g0 * c * c) * tetta_b * tetta_b - 2 * g0 * b * s * tetta_b + g0 * g0) / D; a0 = 1; - a1 = -4 * c0*(1 + a*s*tetta_b) / D; - a2 = 2 * (1 + 2 * c0*c0 - (a*a + c*c)*tetta_b*tetta_b) / D; - a3 = -4 * c0*(1 - a*s*tetta_b) / D; - a4 = ((a*a + c*c)*tetta_b*tetta_b - 2 * a*s*tetta_b + 1) / D; + a1 = -4 * c0 * (1 + a * s * tetta_b) / D; + a2 = 2 * (1 + 2 * c0 * c0 - (a * a + c * c) * tetta_b * tetta_b) / D; + a3 = -4 * c0 * (1 - a * s * tetta_b) / D; + a4 = ((a * a + c * c) * tetta_b * tetta_b - 2 * a * s * tetta_b + 1) / D; } fo_section get() { return *this; } @@ -437,24 +526,31 @@ namespace orfanidis_eq { class chebyshev_type2_fo_section : public fo_section { - chebyshev_type2_fo_section() {} - chebyshev_type2_fo_section(chebyshev_type2_fo_section&) {} + chebyshev_type2_fo_section() + { + } + + chebyshev_type2_fo_section(chebyshev_type2_fo_section&) + { + } + public: chebyshev_type2_fo_section(eq_double_t a, - eq_double_t c, eq_double_t tetta_b, - eq_double_t g, eq_double_t s, eq_double_t b, - eq_double_t D, eq_double_t c0) { - b0 = (g*g*tetta_b*tetta_b + 2 * g*b*s*tetta_b + b*b + g*g*c*c) / D; - b1 = -4 * c0*(b*b + g*g*c*c + g*b*s*tetta_b) / D; - b2 = 2 * ((b*b + g*g*c*c)*(1 + 2 * c0*c0) - g*g*tetta_b*tetta_b) / D; - b3 = -4 * c0*(b*b + g*g*c*c - g*b*s*tetta_b) / D; - b4 = (g*g*tetta_b*tetta_b - 2 * g*b*s*tetta_b + b*b + g*g*c*c) / D; + eq_double_t c, eq_double_t tetta_b, + eq_double_t g, eq_double_t s, eq_double_t b, + eq_double_t D, eq_double_t c0) + { + b0 = (g * g * tetta_b * tetta_b + 2 * g * b * s * tetta_b + b * b + g * g * c * c) / D; + b1 = -4 * c0 * (b * b + g * g * c * c + g * b * s * tetta_b) / D; + b2 = 2 * ((b * b + g * g * c * c) * (1 + 2 * c0 * c0) - g * g * tetta_b * tetta_b) / D; + b3 = -4 * c0 * (b * b + g * g * c * c - g * b * s * tetta_b) / D; + b4 = (g * g * tetta_b * tetta_b - 2 * g * b * s * tetta_b + b * b + g * g * c * c) / D; a0 = 1; - a1 = -4 * c0*(a*a + c*c + a*s*tetta_b) / D; - a2 = 2 * ((a*a + c*c)*(1 + 2 * c0*c0) - tetta_b*tetta_b) / D; - a3 = -4 * c0*(a*a + c*c - a*s*tetta_b) / D; - a4 = (tetta_b*tetta_b - 2 * a*s*tetta_b + a*a + c*c) / D; + a1 = -4 * c0 * (a * a + c * c + a * s * tetta_b) / D; + a2 = 2 * ((a * a + c * c) * (1 + 2 * c0 * c0) - tetta_b * tetta_b) / D; + a3 = -4 * c0 * (a * a + c * c - a * s * tetta_b) / D; + a4 = (tetta_b * tetta_b - 2 * a * s * tetta_b + a * a + c * c) / D; } fo_section get() { return *this; } @@ -464,8 +560,13 @@ namespace orfanidis_eq { class bp_filter { public: - bp_filter() {} - virtual ~bp_filter() {} + bp_filter() + { + } + + virtual ~bp_filter() + { + } virtual eq_single_t process(eq_single_t in) = 0; }; @@ -475,17 +576,23 @@ namespace orfanidis_eq { private: std::vector sections_; - butterworth_bp_filter() {} + butterworth_bp_filter() + { + } + public: - butterworth_bp_filter(butterworth_bp_filter& f) { + butterworth_bp_filter(butterworth_bp_filter& f) + { this->sections_ = f.sections_; } butterworth_bp_filter(unsigned int N, - eq_double_t w0, eq_double_t wb, - eq_double_t G, eq_double_t Gb, eq_double_t G0) { + eq_double_t w0, eq_double_t wb, + eq_double_t G, eq_double_t Gb, eq_double_t G0) + { //Case if G == 0 : allpass - if(G == 0 && G0 == 0) { + if (G == 0 && G0 == 0) + { sections_.push_back(fo_section()); return; } @@ -499,49 +606,55 @@ namespace orfanidis_eq { Gb = conversions::db_2_lin(Gb); G0 = conversions::db_2_lin(G0); - eq_double_t epsilon = pow(((eq_double_t)(G*G - Gb*Gb)) / - (Gb*Gb - G0*G0), 0.5); + eq_double_t epsilon = pow(((eq_double_t)(G * G - Gb * Gb)) / + (Gb * Gb - G0 * G0), 0.5); eq_double_t g = pow(((eq_double_t)G), 1.0 / ((eq_double_t)N)); eq_double_t g0 = pow(((eq_double_t)G0), 1.0 / ((eq_double_t)N)); - eq_double_t beta = pow(((eq_double_t)epsilon), -1.0 / ((eq_double_t)N))* + eq_double_t beta = pow(((eq_double_t)epsilon), -1.0 / ((eq_double_t)N)) * tan(wb / 2.0); eq_double_t c0 = cos(w0); - if(w0 == 0) c0 = 1; - if(w0 == pi / 2) c0 = 0; - if(w0 == pi) c0 = -1; + if (w0 == 0) c0 = 1; + if (w0 == pi / 2) c0 = 0; + if (w0 == pi) c0 = -1; //Calculate every section - for(unsigned int i = 1; i <= L; i++) { - eq_double_t ui = (2.0*i - 1) / N; - eq_double_t si = sin(pi*ui / 2.0); + for (unsigned int i = 1; i <= L; i++) + { + eq_double_t ui = (2.0 * i - 1) / N; + eq_double_t si = sin(pi * ui / 2.0); - eq_double_t Di = beta*beta + 2 * si*beta + 1; + eq_double_t Di = beta * beta + 2 * si * beta + 1; sections_.push_back - (butterworth_fo_section(beta, si, g, g0, Di, c0)); + (butterworth_fo_section(beta, si, g, g0, Di, c0)); } } - ~butterworth_bp_filter() {} + ~butterworth_bp_filter() + { + } - static eq_single_t compute_bw_gain_db(eq_single_t gain) { + static eq_single_t compute_bw_gain_db(eq_single_t gain) + { eq_single_t bw_gain = 0; - if(gain <= -6) + if (gain <= -6) bw_gain = gain + common_base_gain_db; - else if(gain > -6 && gain < 6) - bw_gain = gain*0.5; - else if(gain >= 6) + else if (gain > -6 && gain < 6) + bw_gain = gain * 0.5; + else if (gain >= 6) bw_gain = gain - common_base_gain_db; return bw_gain; } - virtual eq_single_t process(eq_single_t in) { + virtual eq_single_t process(eq_single_t in) + { eq_single_t p0 = in; eq_single_t p1 = 0; //Process FO sections in serial connection - for(size_t i = 0, len = sections_.size(); i < len; i++) { + for (size_t i = 0, len = sections_.size(); i < len; i++) + { p1 = sections_[i].process(p0); p0 = p1; } @@ -555,13 +668,18 @@ namespace orfanidis_eq { private: std::vector sections_; - chebyshev_type1_bp_filter() {} + chebyshev_type1_bp_filter() + { + } + public: chebyshev_type1_bp_filter(unsigned int N, - eq_double_t w0, eq_double_t wb, - eq_double_t G, eq_double_t Gb, eq_double_t G0) { + eq_double_t w0, eq_double_t wb, + eq_double_t G, eq_double_t Gb, eq_double_t G0) + { //Case if G == 0 : allpass - if(G == 0 && G0 == 0) { + if (G == 0 && G0 == 0) + { sections_.push_back(fo_section()); return; } @@ -575,55 +693,61 @@ namespace orfanidis_eq { Gb = conversions::db_2_lin(Gb); G0 = conversions::db_2_lin(G0); - eq_double_t epsilon = pow((eq_double_t)(G*G - Gb*Gb) / - (Gb*Gb - G0*G0), 0.5); + eq_double_t epsilon = pow((eq_double_t)(G * G - Gb * Gb) / + (Gb * Gb - G0 * G0), 0.5); eq_double_t g0 = pow((eq_double_t)(G0), 1.0 / N); eq_double_t alfa = pow(1.0 / epsilon + pow(1 + pow(epsilon, -2.0), 0.5), 1.0 / N); eq_double_t beta = - pow(G / epsilon + Gb*pow(1 + pow(epsilon, -2.0), 0.5), 1.0 / N); - eq_double_t a = 0.5*(alfa - 1.0 / alfa); - eq_double_t b = 0.5*(beta - g0*g0*(1 / beta)); + pow(G / epsilon + Gb * pow(1 + pow(epsilon, -2.0), 0.5), 1.0 / N); + eq_double_t a = 0.5 * (alfa - 1.0 / alfa); + eq_double_t b = 0.5 * (beta - g0 * g0 * (1 / beta)); eq_double_t tetta_b = tan(wb / 2); eq_double_t c0 = cos(w0); - if(w0 == 0) c0 = 1; - if(w0 == pi / 2) c0 = 0; - if(w0 == pi) c0 = -1; + if (w0 == 0) c0 = 1; + if (w0 == pi / 2) c0 = 0; + if (w0 == pi) c0 = -1; //Calculate every section - for(unsigned int i = 1; i <= L; i++) { - eq_double_t ui = (2.0*i - 1.0) / N; - eq_double_t ci = cos(pi*ui / 2.0); - eq_double_t si = sin(pi*ui / 2.0); + for (unsigned int i = 1; i <= L; i++) + { + eq_double_t ui = (2.0 * i - 1.0) / N; + eq_double_t ci = cos(pi * ui / 2.0); + eq_double_t si = sin(pi * ui / 2.0); - eq_double_t Di = (a*a + ci*ci)*tetta_b*tetta_b + - 2.0*a*si*tetta_b + 1; + eq_double_t Di = (a * a + ci * ci) * tetta_b * tetta_b + + 2.0 * a * si * tetta_b + 1; sections_.push_back( chebyshev_type1_fo_section(a, ci, tetta_b, g0, si, b, Di, c0)); } } - ~chebyshev_type1_bp_filter() {} + ~chebyshev_type1_bp_filter() + { + } - static eq_single_t compute_bw_gain_db(eq_single_t gain) { + static eq_single_t compute_bw_gain_db(eq_single_t gain) + { eq_single_t bw_gain = 0; - if(gain <= -6) + if (gain <= -6) bw_gain = gain + 1; - else if(gain > -6 && gain < 6) - bw_gain = gain*0.9; - else if(gain >= 6) + else if (gain > -6 && gain < 6) + bw_gain = gain * 0.9; + else if (gain >= 6) bw_gain = gain - 1; return bw_gain; } - eq_single_t process(eq_single_t in) { + eq_single_t process(eq_single_t in) + { eq_single_t p0 = in; eq_single_t p1 = 0; //Process FO sections in serial connection - for(size_t i = 0, len = sections_.size(); i < len; i++) { + for (size_t i = 0, len = sections_.size(); i < len; i++) + { p1 = sections_[i].process(p0); p0 = p1; } @@ -637,13 +761,18 @@ namespace orfanidis_eq { private: std::vector sections_; - chebyshev_type2_bp_filter() {} + chebyshev_type2_bp_filter() + { + } + public: chebyshev_type2_bp_filter(unsigned int N, - eq_double_t w0, eq_double_t wb, - eq_double_t G, eq_double_t Gb, eq_double_t G0) { + eq_double_t w0, eq_double_t wb, + eq_double_t G, eq_double_t Gb, eq_double_t G0) + { //Case if G == 0 : allpass - if(G == 0 && G0 == 0) { + if (G == 0 && G0 == 0) + { sections_.push_back(fo_section()); return; } @@ -657,52 +786,58 @@ namespace orfanidis_eq { Gb = conversions::db_2_lin(Gb); G0 = conversions::db_2_lin(G0); - eq_double_t epsilon = pow((eq_double_t)((G*G - Gb*Gb) / - (Gb*Gb - G0*G0)), 0.5); + eq_double_t epsilon = pow((eq_double_t)((G * G - Gb * Gb) / + (Gb * Gb - G0 * G0)), 0.5); eq_double_t g = pow((eq_double_t)(G), 1.0 / N); - eq_double_t eu = pow(epsilon + sqrt(1 + epsilon*epsilon), 1.0 / N); - eq_double_t ew = pow(G0*epsilon + Gb*sqrt(1 + epsilon*epsilon), 1.0 / N); + eq_double_t eu = pow(epsilon + sqrt(1 + epsilon * epsilon), 1.0 / N); + eq_double_t ew = pow(G0 * epsilon + Gb * sqrt(1 + epsilon * epsilon), 1.0 / N); eq_double_t a = (eu - 1.0 / eu) / 2.0; - eq_double_t b = (ew - g*g / ew) / 2.0; + eq_double_t b = (ew - g * g / ew) / 2.0; eq_double_t tetta_b = tan(wb / 2); eq_double_t c0 = cos(w0); - if(w0 == 0) c0 = 1; - if(w0 == pi / 2) c0 = 0; - if(w0 == pi) c0 = -1; + if (w0 == 0) c0 = 1; + if (w0 == pi / 2) c0 = 0; + if (w0 == pi) c0 = -1; //Calculate every section - for(unsigned int i = 1; i <= L; i++) { - eq_double_t ui = (2.0*i - 1.0) / N; - eq_double_t ci = cos(pi*ui / 2.0); - eq_double_t si = sin(pi*ui / 2.0); - eq_double_t Di = tetta_b*tetta_b + 2 * a*si*tetta_b + a*a + ci*ci; + for (unsigned int i = 1; i <= L; i++) + { + eq_double_t ui = (2.0 * i - 1.0) / N; + eq_double_t ci = cos(pi * ui / 2.0); + eq_double_t si = sin(pi * ui / 2.0); + eq_double_t Di = tetta_b * tetta_b + 2 * a * si * tetta_b + a * a + ci * ci; sections_.push_back( chebyshev_type2_fo_section(a, ci, tetta_b, g, si, b, Di, c0)); } } - ~chebyshev_type2_bp_filter() {} + ~chebyshev_type2_bp_filter() + { + } - static eq_single_t compute_bw_gain_db(eq_single_t gain) { + static eq_single_t compute_bw_gain_db(eq_single_t gain) + { eq_single_t bw_gain = 0; - if(gain <= -6) + if (gain <= -6) bw_gain = -common_base_gain_db; - else if(gain > -6 && gain < 6) - bw_gain = gain*0.3; - else if(gain >= 6) + else if (gain > -6 && gain < 6) + bw_gain = gain * 0.3; + else if (gain >= 6) bw_gain = common_base_gain_db; return bw_gain; } - eq_single_t process(eq_single_t in) { + eq_single_t process(eq_single_t in) + { eq_single_t p0 = in; eq_single_t p1 = 0; //Process FO sections in serial connection - for(size_t i = 0, len = sections_.size(); i < len; i++) { + for (size_t i = 0, len = sections_.size(); i < len; i++) + { p1 = sections_[i].process(p0); p0 = p1; } @@ -723,31 +858,40 @@ namespace orfanidis_eq { std::vector filters_; filter_type current_eq_type_; - eq1() :conv_(eq_min_max_gain_db) {} - eq1(const eq1&) :conv_(eq_min_max_gain_db) {} + eq1() : conv_(eq_min_max_gain_db) + { + } - void cleanup_filters_array() { - for(unsigned int j = 0; j < filters_.size(); j++) + eq1(const eq1&) : conv_(eq_min_max_gain_db) + { + } + + void cleanup_filters_array() + { + for (unsigned int j = 0; j < filters_.size(); j++) delete filters_[j]; } public: - eq1(const freq_grid *fg, filter_type eq_t) : conv_(eq_min_max_gain_db) { + eq1(const freq_grid* fg, filter_type eq_t) : conv_(eq_min_max_gain_db) + { sampling_frequency_ = default_sample_freq_hz; freq_grid_ = *fg; current_eq_type_ = eq_t; set_eq(freq_grid_, eq_t); } + ~eq1() { cleanup_filters_array(); } - eq_error_t set_eq(freq_grid& fg, filter_type eqt) { + eq_error_t set_eq(freq_grid& fg, filter_type eqt) + { band_gains_.clear(); cleanup_filters_array(); filters_.clear(); freq_grid_ = fg; - for(unsigned int i = 0; i < freq_grid_.get_number_of_bands(); i++) { - + for (unsigned int i = 0; i < freq_grid_.get_number_of_bands(); i++) + { eq_double_t wb = conversions::hz_2_rad( freq_grid_.get_freqs()[i].max_freq - freq_grid_.get_freqs()[i].min_freq, @@ -757,8 +901,10 @@ namespace orfanidis_eq { freq_grid_.get_freqs()[i].center_freq, sampling_frequency_); - switch(eqt) { - case (butterworth): { + switch (eqt) + { + case (butterworth): + { butterworth_bp_filter* bf = new butterworth_bp_filter( default_eq_band_filters_order, @@ -773,7 +919,8 @@ namespace orfanidis_eq { break; } - case (chebyshev1): { + case (chebyshev1): + { chebyshev_type1_bp_filter* cf1 = new chebyshev_type1_bp_filter( default_eq_band_filters_order, @@ -788,7 +935,8 @@ namespace orfanidis_eq { break; } - case (chebyshev2): { + case (chebyshev2): + { chebyshev_type2_bp_filter* cf2 = new chebyshev_type2_bp_filter( default_eq_band_filters_order, @@ -803,10 +951,9 @@ namespace orfanidis_eq { break; } - default: - current_eq_type_ = none; - return invalid_input_data_error; - + default: + current_eq_type_ = none; + return invalid_input_data_error; } band_gains_.push_back(max_base_gain_db); } @@ -820,7 +967,8 @@ namespace orfanidis_eq { return set_eq(freq_grid_, eqt); } - eq_error_t set_sample_rate(eq_double_t sr) { + eq_error_t set_sample_rate(eq_double_t sr) + { eq_error_t err = no_error; sampling_frequency_ = sr; err = set_eq(freq_grid_, current_eq_type_); @@ -828,8 +976,9 @@ namespace orfanidis_eq { return err; } - eq_error_t change_gains(std::vector band_gains) { - if(band_gains_.size() == band_gains.size()) + eq_error_t change_gains(std::vector band_gains) + { + if (band_gains_.size() == band_gains.size()) band_gains_ = band_gains; else return invalid_input_data_error; @@ -837,9 +986,10 @@ namespace orfanidis_eq { return no_error; } - eq_error_t change_gains_db(std::vector band_gains) { - if(band_gains_.size() == band_gains.size()) - for(unsigned int j = 0; j < get_number_of_bands(); j++) + eq_error_t change_gains_db(std::vector band_gains) + { + if (band_gains_.size() == band_gains.size()) + for (unsigned int j = 0; j < get_number_of_bands(); j++) band_gains_[j] = conv_.fast_db_2_lin(band_gains[j]); else return invalid_input_data_error; @@ -848,8 +998,9 @@ namespace orfanidis_eq { } eq_error_t change_band_gain(unsigned int band_number, - eq_single_t band_gain) { - if(band_number < get_number_of_bands()) + eq_single_t band_gain) + { + if (band_number < get_number_of_bands()) band_gains_[band_number] = band_gain; else return invalid_input_data_error; @@ -857,8 +1008,9 @@ namespace orfanidis_eq { return no_error; } - eq_error_t change_band_gain_db(unsigned int band_number, eq_single_t band_gain) { - if(band_number < get_number_of_bands()) + eq_error_t change_band_gain_db(unsigned int band_number, eq_single_t band_gain) + { + if (band_number < get_number_of_bands()) band_gains_[band_number] = conv_.fast_db_2_lin(band_gain); else return invalid_input_data_error; @@ -866,20 +1018,23 @@ namespace orfanidis_eq { return no_error; } - eq_error_t sbs_process_band(unsigned int band_number, eq_single_t *in, eq_single_t *out) { + eq_error_t sbs_process_band(unsigned int band_number, eq_single_t* in, eq_single_t* out) + { //if(band_number < get_number_of_bands()) - *out = band_gains_[band_number] * + *out = band_gains_[band_number] * filters_[band_number]->process(*in); //else - //return invalid_input_data_error; + //return invalid_input_data_error; return no_error; } - eq_error_t sbs_process(eq_single_t *in, eq_single_t *out) { + eq_error_t sbs_process(eq_single_t* in, eq_single_t* out) + { eq_error_t err = no_error; eq_single_t acc_out = 0; - for(unsigned int j = 0, len = get_number_of_bands(); j < len; j++) { + for (unsigned int j = 0, len = get_number_of_bands(); j < len; j++) + { eq_single_t band_out = 0; err = sbs_process_band(j, in, &band_out); acc_out += band_out; @@ -891,9 +1046,12 @@ namespace orfanidis_eq { filter_type get_eq_type() { return current_eq_type_; } const char* get_string_eq_type() { return get_eq_text(current_eq_type_); } - unsigned int get_number_of_bands() { + + unsigned int get_number_of_bands() + { return freq_grid_.get_number_of_bands(); } + const char* get_version() { return eq_version; } }; @@ -916,25 +1074,29 @@ namespace orfanidis_eq { std::vector filters_; filter_type current_channel_type_; - eq_channel() {} - - unsigned int get_flt_index(eq_single_t gain_db) { - unsigned int number_of_filters = (unsigned int)filters_.size(); - eq_single_t scale_coef = gain_db / min_max_gain_db_; - return (unsigned int)((number_of_filters / 2) + (number_of_filters / 2)*scale_coef); + eq_channel() + { } - void cleanup_filters_array() { - for(unsigned int j = 0; j < filters_.size(); j++) + unsigned int get_flt_index(eq_single_t gain_db) + { + unsigned int number_of_filters = (unsigned int)filters_.size(); + eq_single_t scale_coef = gain_db / min_max_gain_db_; + return (unsigned int)((number_of_filters / 2) + (number_of_filters / 2) * scale_coef); + } + + void cleanup_filters_array() + { + for (unsigned int j = 0; j < filters_.size(); j++) delete filters_[j]; } public: eq_channel(filter_type ft, - eq_single_t fs, eq_single_t f0, eq_single_t fb, - eq_single_t min_max_gain_db = p_eq_min_max_gain_db, - eq_single_t step_db = p_eq_gain_step_db) { - + eq_single_t fs, eq_single_t f0, eq_single_t fb, + eq_single_t min_max_gain_db = p_eq_min_max_gain_db, + eq_single_t step_db = p_eq_gain_step_db) + { //Init data fields sampling_frequency_ = fs; f0_ = f0; @@ -952,16 +1114,18 @@ namespace orfanidis_eq { ~eq_channel() { cleanup_filters_array(); } - eq_error_t set_channel(filter_type ft, eq_single_t fs) { - + eq_error_t set_channel(filter_type ft, eq_single_t fs) + { eq_double_t wb = conversions::hz_2_rad(fb_, sampling_frequency_); eq_double_t w0 = conversions::hz_2_rad(f0_, sampling_frequency_); - for(eq_single_t gain = -min_max_gain_db_; gain <= min_max_gain_db_; - gain += gain_step_db_) { - - switch(ft) { - case (butterworth): { + for (eq_single_t gain = -min_max_gain_db_; gain <= min_max_gain_db_; + gain += gain_step_db_) + { + switch (ft) + { + case (butterworth): + { eq_single_t bw_gain = butterworth_bp_filter::compute_bw_gain_db(gain); @@ -978,7 +1142,8 @@ namespace orfanidis_eq { filters_.push_back(bf); break; } - case (chebyshev1): { + case (chebyshev1): + { eq_single_t bw_gain = chebyshev_type1_bp_filter::compute_bw_gain_db(gain); @@ -995,7 +1160,8 @@ namespace orfanidis_eq { filters_.push_back(cf1); break; } - case (chebyshev2): { + case (chebyshev2): + { eq_single_t bw_gain = chebyshev_type2_bp_filter::compute_bw_gain_db(gain); @@ -1012,7 +1178,8 @@ namespace orfanidis_eq { filters_.push_back(cf2); break; } - default: { + default: + { current_channel_type_ = none; return invalid_input_data_error; } @@ -1026,17 +1193,21 @@ namespace orfanidis_eq { return no_error; } - eq_error_t set_gain_db(eq_single_t db) { - if(db > -min_max_gain_db_ && db < min_max_gain_db_) { + eq_error_t set_gain_db(eq_single_t db) + { + if (db > -min_max_gain_db_ && db < min_max_gain_db_) + { current_gain_db_ = db; current_filter_index_ = get_flt_index(db); - } else + } + else return invalid_input_data_error; return no_error; } - eq_error_t sbs_process(eq_single_t *in, eq_single_t *out) { + eq_error_t sbs_process(eq_single_t* in, eq_single_t* out) + { *out = filters_[current_filter_index_]->process(*in); return no_error; } @@ -1053,30 +1224,35 @@ namespace orfanidis_eq { std::vector channels_; filter_type current_eq_type_; - void cleanup_channels_array() { - for(unsigned int j = 0; j < channels_.size(); j++) + void cleanup_channels_array() + { + for (unsigned int j = 0; j < channels_.size(); j++) delete channels_[j]; } public: - eq2(freq_grid &fg, filter_type eq_t) : conv_(eq_min_max_gain_db) { + eq2(freq_grid& fg, filter_type eq_t) : conv_(eq_min_max_gain_db) + { sampling_frequency_ = default_sample_freq_hz; freq_grid_ = fg; current_eq_type_ = eq_t; set_eq(freq_grid_, eq_t); } + ~eq2() { cleanup_channels_array(); } - eq_error_t set_eq(const freq_grid& fg, filter_type ft) { + eq_error_t set_eq(const freq_grid& fg, filter_type ft) + { cleanup_channels_array(); channels_.clear(); freq_grid_ = fg; - for(unsigned int i = 0; i < freq_grid_.get_number_of_bands(); i++) { + for (unsigned int i = 0; i < freq_grid_.get_number_of_bands(); i++) + { band_freqs b_fres = freq_grid_.get_freqs()[i]; eq_channel* eq_ch = new eq_channel(ft, sampling_frequency_, - b_fres.center_freq, b_fres.max_freq - b_fres.min_freq); + b_fres.center_freq, b_fres.max_freq - b_fres.min_freq); channels_.push_back(eq_ch); channels_[i]->set_gain_db(p_eq_default_gain_db); @@ -1086,20 +1262,23 @@ namespace orfanidis_eq { return no_error; } - eq_error_t set_eq(filter_type ft) { + eq_error_t set_eq(filter_type ft) + { eq_error_t err = set_eq(freq_grid_, ft); return err; } - eq_error_t set_sample_rate(eq_double_t sr) { + eq_error_t set_sample_rate(eq_double_t sr) + { sampling_frequency_ = sr; eq_error_t err = set_eq(current_eq_type_); return err; } - eq_error_t change_gains(std::vector band_gains) { - if(channels_.size() == band_gains.size()) - for(unsigned int j = 0; j < channels_.size(); j++) + eq_error_t change_gains(std::vector band_gains) + { + if (channels_.size() == band_gains.size()) + for (unsigned int j = 0; j < channels_.size(); j++) channels_[j]->set_gain_db(conv_.fast_lin_2_db(band_gains[j])); else return invalid_input_data_error; @@ -1107,9 +1286,10 @@ namespace orfanidis_eq { return no_error; } - eq_error_t change_gains_db(std::vector band_gains) { - if(channels_.size() == band_gains.size()) - for(unsigned int j = 0; j < channels_.size(); j++) + eq_error_t change_gains_db(std::vector band_gains) + { + if (channels_.size() == band_gains.size()) + for (unsigned int j = 0; j < channels_.size(); j++) channels_[j]->set_gain_db(band_gains[j]); else return invalid_input_data_error; @@ -1118,8 +1298,9 @@ namespace orfanidis_eq { } eq_error_t change_band_gain(unsigned int band_number, - eq_single_t band_gain) { - if(band_number < channels_.size()) + eq_single_t band_gain) + { + if (band_number < channels_.size()) channels_[band_number]->set_gain_db(conv_.fast_lin_2_db(band_gain)); else return invalid_input_data_error; @@ -1128,8 +1309,9 @@ namespace orfanidis_eq { } eq_error_t change_band_gain_db(unsigned int band_number, - eq_single_t band_gain) { - if(band_number < channels_.size()) + eq_single_t band_gain) + { + if (band_number < channels_.size()) channels_[band_number]->set_gain_db(band_gain); else return invalid_input_data_error; @@ -1138,8 +1320,9 @@ namespace orfanidis_eq { } eq_error_t sbs_process_band(unsigned int band_number, - eq_single_t *in, eq_single_t *out) { - if(band_number < get_number_of_bands()) + eq_single_t* in, eq_single_t* out) + { + if (band_number < get_number_of_bands()) channels_[band_number]->sbs_process(in, out); else return invalid_input_data_error; @@ -1147,10 +1330,11 @@ namespace orfanidis_eq { return no_error; } - eq_error_t sbs_process(eq_single_t *in, eq_single_t *out) { + eq_error_t sbs_process(eq_single_t* in, eq_single_t* out) + { eq_error_t err = no_error; eq_single_t in_out = *in; - for(unsigned int i = 0; i < get_number_of_bands(); i++) + for (unsigned int i = 0; i < get_number_of_bands(); i++) err = sbs_process_band(i, &in_out, &in_out); *out = in_out; @@ -1160,11 +1344,13 @@ namespace orfanidis_eq { filter_type get_eq_type() { return current_eq_type_; } const char* get_string_eq_type() { return get_eq_text(current_eq_type_); } - unsigned int get_number_of_bands() { + + unsigned int get_number_of_bands() + { return freq_grid_.get_number_of_bands(); } + const char* get_version() { return eq_version; } }; - } //namespace orfanidis_eq #endif //ORFANIDIS_EQ_H_ diff --git a/Utilities/sha1.cpp b/Utilities/sha1.cpp index e794dab..8d3b2b8 100644 --- a/Utilities/sha1.cpp +++ b/Utilities/sha1.cpp @@ -24,11 +24,11 @@ #include -static const size_t BLOCK_INTS = 16; /* number of 32bit integers per SHA1 block */ +static const size_t BLOCK_INTS = 16; /* number of 32bit integers per SHA1 block */ static const size_t BLOCK_BYTES = BLOCK_INTS * 4; -static void reset(uint32_t digest[], std::string &buffer, uint64_t &transforms) +static void reset(uint32_t digest[], std::string& buffer, uint64_t& transforms) { /* SHA1 initialization constants */ digest[0] = 0x67452301; @@ -59,41 +59,46 @@ static uint32_t blk(const uint32_t block[BLOCK_INTS], const size_t i) * (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ -static void R0(const uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t &w, const uint32_t x, const uint32_t y, uint32_t &z, const size_t i) +static void R0(const uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t& w, const uint32_t x, const uint32_t y, + uint32_t& z, const size_t i) { - z += ((w&(x^y)) ^ y) + block[i] + 0x5a827999 + rol(v, 5); + z += ((w & (x ^ y)) ^ y) + block[i] + 0x5a827999 + rol(v, 5); w = rol(w, 30); } -static void R1(uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t &w, const uint32_t x, const uint32_t y, uint32_t &z, const size_t i) +static void R1(uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t& w, const uint32_t x, const uint32_t y, + uint32_t& z, const size_t i) { block[i] = blk(block, i); - z += ((w&(x^y)) ^ y) + block[i] + 0x5a827999 + rol(v, 5); + z += ((w & (x ^ y)) ^ y) + block[i] + 0x5a827999 + rol(v, 5); w = rol(w, 30); } -static void R2(uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t &w, const uint32_t x, const uint32_t y, uint32_t &z, const size_t i) +static void R2(uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t& w, const uint32_t x, const uint32_t y, + uint32_t& z, const size_t i) { block[i] = blk(block, i); - z += (w^x^y) + block[i] + 0x6ed9eba1 + rol(v, 5); + z += (w ^ x ^ y) + block[i] + 0x6ed9eba1 + rol(v, 5); w = rol(w, 30); } -static void R3(uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t &w, const uint32_t x, const uint32_t y, uint32_t &z, const size_t i) +static void R3(uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t& w, const uint32_t x, const uint32_t y, + uint32_t& z, const size_t i) { block[i] = blk(block, i); - z += (((w | x)&y) | (w&x)) + block[i] + 0x8f1bbcdc + rol(v, 5); + z += (((w | x) & y) | (w & x)) + block[i] + 0x8f1bbcdc + rol(v, 5); w = rol(w, 30); } -static void R4(uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t &w, const uint32_t x, const uint32_t y, uint32_t &z, const size_t i) +static void R4(uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t& w, const uint32_t x, const uint32_t y, + uint32_t& z, const size_t i) { block[i] = blk(block, i); - z += (w^x^y) + block[i] + 0xca62c1d6 + rol(v, 5); + z += (w ^ x ^ y) + block[i] + 0xca62c1d6 + rol(v, 5); w = rol(w, 30); } @@ -102,7 +107,7 @@ static void R4(uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t &w, const * Hash a single 512-bit block. This is the core of the algorithm. */ -static void transform(uint32_t digest[], uint32_t block[BLOCK_INTS], uint64_t &transforms) +static void transform(uint32_t digest[], uint32_t block[BLOCK_INTS], uint64_t& transforms) { /* Copy digest[] to working vars */ uint32_t a = digest[0]; @@ -205,10 +210,11 @@ static void transform(uint32_t digest[], uint32_t block[BLOCK_INTS], uint64_t &t } -static void buffer_to_block(const std::string &buffer, uint32_t block[BLOCK_INTS]) +static void buffer_to_block(const std::string& buffer, uint32_t block[BLOCK_INTS]) { /* Convert the std::string (byte buffer) to a uint32_t array (MSB) */ - for(size_t i = 0; i < BLOCK_INTS; i++) { + for (size_t i = 0; i < BLOCK_INTS; i++) + { block[i] = (buffer[4 * i + 3] & 0xff) | (buffer[4 * i + 2] & 0xff) << 8 | (buffer[4 * i + 1] & 0xff) << 16 @@ -223,22 +229,24 @@ SHA1::SHA1() } -void SHA1::update(const std::string &s) +void SHA1::update(const std::string& s) { std::istringstream is(s); update(is); } -void SHA1::update(std::istream &is) +void SHA1::update(std::istream& is) { char sbuf[BLOCK_BYTES]; uint32_t block[BLOCK_INTS]; - while(true) { + while (true) + { is.read(sbuf, BLOCK_BYTES - buffer.size()); buffer.append(sbuf, (size_t)is.gcount()); - if(buffer.size() != BLOCK_BYTES) { + if (buffer.size() != BLOCK_BYTES) + { return; } @@ -256,21 +264,24 @@ void SHA1::update(std::istream &is) std::string SHA1::final() { /* Total number of hashed bits */ - uint64_t total_bits = (transforms*BLOCK_BYTES + buffer.size()) * 8; + uint64_t total_bits = (transforms * BLOCK_BYTES + buffer.size()) * 8; /* Padding */ buffer += (char)0x80; size_t orig_size = buffer.size(); - while(buffer.size() < BLOCK_BYTES) { + while (buffer.size() < BLOCK_BYTES) + { buffer += (char)0x00; } uint32_t block[BLOCK_INTS]; buffer_to_block(buffer, block); - if(orig_size > BLOCK_BYTES - 8) { + if (orig_size > BLOCK_BYTES - 8) + { transform(digest, block, transforms); - for(size_t i = 0; i < BLOCK_INTS - 2; i++) { + for (size_t i = 0; i < BLOCK_INTS - 2; i++) + { block[i] = 0; } } @@ -282,7 +293,8 @@ std::string SHA1::final() /* Hex std::string */ std::ostringstream result; - for(size_t i = 0; i < sizeof(digest) / sizeof(digest[0]); i++) { + for (size_t i = 0; i < sizeof(digest) / sizeof(digest[0]); i++) + { result << std::uppercase << std::hex << std::setfill('0') << std::setw(8); result << digest[i]; } @@ -293,11 +305,11 @@ std::string SHA1::final() return result.str(); } -std::string SHA1::GetHash(vector &data) +std::string SHA1::GetHash(vector& data) { std::stringstream ss; ss.write((char*)data.data(), data.size()); - + SHA1 checksum; checksum.update(ss); return checksum.final(); @@ -313,14 +325,14 @@ std::string SHA1::GetHash(uint8_t* data, size_t size) return checksum.final(); } -std::string SHA1::GetHash(std::istream &stream) +std::string SHA1::GetHash(std::istream& stream) { SHA1 checksum; checksum.update(stream); return checksum.final(); } -std::string SHA1::GetHash(const std::string &filename) +std::string SHA1::GetHash(const std::string& filename) { std::ifstream stream(filename.c_str(), std::ios::binary); SHA1 checksum; diff --git a/Utilities/sha1.h b/Utilities/sha1.h index d25250c..2a6a8e6 100644 --- a/Utilities/sha1.h +++ b/Utilities/sha1.h @@ -26,17 +26,17 @@ class SHA1 { public: - SHA1(); - void update(const std::string &s); - void update(std::istream &is); - std::string final(); - static std::string GetHash(const std::string &filename); - static std::string GetHash(std::istream &stream); - static std::string GetHash(vector &data); - static std::string GetHash(uint8_t* data, size_t size); + SHA1(); + void update(const std::string& s); + void update(std::istream& is); + std::string final(); + static std::string GetHash(const std::string& filename); + static std::string GetHash(std::istream& stream); + static std::string GetHash(vector& data); + static std::string GetHash(uint8_t* data, size_t size); private: - uint32_t digest[5]; - std::string buffer; - uint64_t transforms; + uint32_t digest[5]; + std::string buffer; + uint64_t transforms; }; diff --git a/Utilities/snes_ntsc.cpp b/Utilities/snes_ntsc.cpp index 85ff666..be0218c 100644 --- a/Utilities/snes_ntsc.cpp +++ b/Utilities/snes_ntsc.cpp @@ -14,10 +14,10 @@ details. You should have received a copy of the GNU Lesser General Public License along with this module; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -snes_ntsc_setup_t const snes_ntsc_monochrome = { 0,-1, 0, 0,.2, 0,.2,-.2,-.2,-1, 1, 0, 0 }; -snes_ntsc_setup_t const snes_ntsc_composite = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }; -snes_ntsc_setup_t const snes_ntsc_svideo = { 0, 0, 0, 0,.2, 0,.2, -1, -1, 0, 1, 0, 0 }; -snes_ntsc_setup_t const snes_ntsc_rgb = { 0, 0, 0, 0,.2, 0,.7, -1, -1,-1, 1, 0, 0 }; +snes_ntsc_setup_t const snes_ntsc_monochrome = {0, -1, 0, 0, .2, 0, .2, -.2, -.2, -1, 1, 0, 0}; +snes_ntsc_setup_t const snes_ntsc_composite = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}; +snes_ntsc_setup_t const snes_ntsc_svideo = {0, 0, 0, 0, .2, 0, .2, -1, -1, 0, 1, 0, 0}; +snes_ntsc_setup_t const snes_ntsc_rgb = {0, 0, 0, 0, .2, 0, .7, -1, -1, -1, 1, 0, 0}; #define alignment_count 3 #define burst_count 3 @@ -34,62 +34,62 @@ snes_ntsc_setup_t const snes_ntsc_rgb = { 0, 0, 0, 0,.2, 0,.7, -1, -1,-1 #include "snes_ntsc_impl.h" /* 3 input pixels -> 8 composite samples */ -pixel_info_t const snes_ntsc_pixels [alignment_count] = { - { PIXEL_OFFSET( -4, -9 ), { 1, 1, .6667f, 0 } }, - { PIXEL_OFFSET( -2, -7 ), { .3333f, 1, 1, .3333f } }, - { PIXEL_OFFSET( 0, -5 ), { 0, .6667f, 1, 1 } }, +pixel_info_t const snes_ntsc_pixels[alignment_count] = { + {PIXEL_OFFSET(-4, -9), {1, 1, .6667f, 0}}, + {PIXEL_OFFSET(-2, -7), {.3333f, 1, 1, .3333f}}, + {PIXEL_OFFSET(0, -5), {0, .6667f, 1, 1}}, }; -static void merge_kernel_fields( snes_ntsc_rgb_t* io ) +static void merge_kernel_fields(snes_ntsc_rgb_t* io) { int n; - for ( n = burst_size; n; --n ) + for (n = burst_size; n; --n) { - snes_ntsc_rgb_t p0 = io [burst_size * 0] + rgb_bias; - snes_ntsc_rgb_t p1 = io [burst_size * 1] + rgb_bias; - snes_ntsc_rgb_t p2 = io [burst_size * 2] + rgb_bias; + snes_ntsc_rgb_t p0 = io[burst_size * 0] + rgb_bias; + snes_ntsc_rgb_t p1 = io[burst_size * 1] + rgb_bias; + snes_ntsc_rgb_t p2 = io[burst_size * 2] + rgb_bias; /* merge colors without losing precision */ - io [burst_size * 0] = - ((p0 + p1 - ((p0 ^ p1) & snes_ntsc_rgb_builder)) >> 1) - rgb_bias; - io [burst_size * 1] = - ((p1 + p2 - ((p1 ^ p2) & snes_ntsc_rgb_builder)) >> 1) - rgb_bias; - io [burst_size * 2] = - ((p2 + p0 - ((p2 ^ p0) & snes_ntsc_rgb_builder)) >> 1) - rgb_bias; + io[burst_size * 0] = + ((p0 + p1 - ((p0 ^ p1) & snes_ntsc_rgb_builder)) >> 1) - rgb_bias; + io[burst_size * 1] = + ((p1 + p2 - ((p1 ^ p2) & snes_ntsc_rgb_builder)) >> 1) - rgb_bias; + io[burst_size * 2] = + ((p2 + p0 - ((p2 ^ p0) & snes_ntsc_rgb_builder)) >> 1) - rgb_bias; ++io; } } -static void correct_errors( snes_ntsc_rgb_t color, snes_ntsc_rgb_t* out ) +static void correct_errors(snes_ntsc_rgb_t color, snes_ntsc_rgb_t* out) { int n; - for ( n = burst_count; n; --n ) + for (n = burst_count; n; --n) { unsigned i; - for ( i = 0; i < rgb_kernel_size / 2; i++ ) + for (i = 0; i < rgb_kernel_size / 2; i++) { snes_ntsc_rgb_t error = color - - out [i ] - out [(i+12)%14+14] - out [(i+10)%14+28] - - out [i + 7] - out [i + 5 +14] - out [i + 3 +28]; - DISTRIBUTE_ERROR( i+3+28, i+5+14, i+7 ); + out[i] - out[(i + 12) % 14 + 14] - out[(i + 10) % 14 + 28] - + out[i + 7] - out[i + 5 + 14] - out[i + 3 + 28]; + DISTRIBUTE_ERROR(i+3+28, i+5+14, i+7); } out += alignment_count * rgb_kernel_size; } } -void snes_ntsc_init( snes_ntsc_t* ntsc, snes_ntsc_setup_t const* setup ) +void snes_ntsc_init(snes_ntsc_t* ntsc, snes_ntsc_setup_t const* setup) { int merge_fields; int entry; init_t impl; - if ( !setup ) + if (!setup) setup = &snes_ntsc_composite; - init( &impl, setup ); - + init(&impl, setup); + merge_fields = setup->merge_fields; - if ( setup->artifacts <= -1 && setup->fringing <= -1 ) + if (setup->artifacts <= -1 && setup->fringing <= -1) merge_fields = 1; - - for ( entry = 0; entry < snes_ntsc_palette_size; entry++ ) + + for (entry = 0; entry < snes_ntsc_palette_size; entry++) { /* Reduce number of significant bits of source color. Clearing the low bits of R and B were least notictable. Modifying green was too @@ -97,8 +97,8 @@ void snes_ntsc_init( snes_ntsc_t* ntsc, snes_ntsc_setup_t const* setup ) int ir = entry >> 8 & 0x1E; int ig = entry >> 4 & 0x1F; int ib = entry << 1 & 0x1E; - - #if SNES_NTSC_BSNES_COLORTBL + +#if SNES_NTSC_BSNES_COLORTBL if ( setup->bsnes_colortbl ) { int bgr15 = (ib << 10) | (ig << 5) | ir; @@ -107,145 +107,145 @@ void snes_ntsc_init( snes_ntsc_t* ntsc, snes_ntsc_setup_t const* setup ) ig = rgb16 >> 6 & 0x1F; ib = rgb16 & 0x1E; } - #endif - +#endif + { - float rr = impl.to_float [ir]; - float gg = impl.to_float [ig]; - float bb = impl.to_float [ib]; - - float y, i, q = RGB_TO_YIQ( rr, gg, bb, y, i ); - - int r, g, b = YIQ_TO_RGB( y, i, q, impl.to_rgb, int, r, g ); - snes_ntsc_rgb_t rgb = PACK_RGB( r, g, b ); - - snes_ntsc_rgb_t* out = ntsc->table [entry]; - gen_kernel( &impl, y, i, q, out ); - if ( merge_fields ) - merge_kernel_fields( out ); - correct_errors( rgb, out ); + float rr = impl.to_float[ir]; + float gg = impl.to_float[ig]; + float bb = impl.to_float[ib]; + + float y, i, q = RGB_TO_YIQ(rr, gg, bb, y, i); + + int r, g, b = YIQ_TO_RGB(y, i, q, impl.to_rgb, int, r, g); + snes_ntsc_rgb_t rgb = PACK_RGB(r, g, b); + + snes_ntsc_rgb_t* out = ntsc->table[entry]; + gen_kernel(&impl, y, i, q, out); + if (merge_fields) + merge_kernel_fields(out); + correct_errors(rgb, out); } } } #ifndef SNES_NTSC_NO_BLITTERS -void snes_ntsc_blit( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, long in_row_width, - int burst_phase, int in_width, int in_height, void* rgb_out, long out_pitch ) +void snes_ntsc_blit(snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, long in_row_width, + int burst_phase, int in_width, int in_height, void* rgb_out, long out_pitch) { int chunk_count = (in_width - 1) / snes_ntsc_in_chunk; - for ( ; in_height; --in_height ) + for (; in_height; --in_height) { SNES_NTSC_IN_T const* line_in = input; - SNES_NTSC_BEGIN_ROW( ntsc, burst_phase, - snes_ntsc_black, snes_ntsc_black, SNES_NTSC_ADJ_IN( *line_in ) ); - snes_ntsc_out_t* restrict line_out = (snes_ntsc_out_t*) rgb_out; + SNES_NTSC_BEGIN_ROW(ntsc, burst_phase, + snes_ntsc_black, snes_ntsc_black, SNES_NTSC_ADJ_IN( *line_in )); + snes_ntsc_out_t* restrict line_out = (snes_ntsc_out_t*)rgb_out; int n; ++line_in; - - for ( n = chunk_count; n; --n ) + + for (n = chunk_count; n; --n) { /* order of input and output pixels must not be altered */ - SNES_NTSC_COLOR_IN( 0, SNES_NTSC_ADJ_IN( line_in [0] ) ); - SNES_NTSC_RGB_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH ); - SNES_NTSC_RGB_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 1, SNES_NTSC_ADJ_IN( line_in [1] ) ); - SNES_NTSC_RGB_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH ); - SNES_NTSC_RGB_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 2, SNES_NTSC_ADJ_IN( line_in [2] ) ); - SNES_NTSC_RGB_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH ); - SNES_NTSC_RGB_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH ); - SNES_NTSC_RGB_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH ); - - line_in += 3; + SNES_NTSC_COLOR_IN(0, SNES_NTSC_ADJ_IN( line_in [0] )); + SNES_NTSC_RGB_OUT(0, line_out [0], SNES_NTSC_OUT_DEPTH); + SNES_NTSC_RGB_OUT(1, line_out [1], SNES_NTSC_OUT_DEPTH); + + SNES_NTSC_COLOR_IN(1, SNES_NTSC_ADJ_IN( line_in [1] )); + SNES_NTSC_RGB_OUT(2, line_out [2], SNES_NTSC_OUT_DEPTH); + SNES_NTSC_RGB_OUT(3, line_out [3], SNES_NTSC_OUT_DEPTH); + + SNES_NTSC_COLOR_IN(2, SNES_NTSC_ADJ_IN( line_in [2] )); + SNES_NTSC_RGB_OUT(4, line_out [4], SNES_NTSC_OUT_DEPTH); + SNES_NTSC_RGB_OUT(5, line_out [5], SNES_NTSC_OUT_DEPTH); + SNES_NTSC_RGB_OUT(6, line_out [6], SNES_NTSC_OUT_DEPTH); + + line_in += 3; line_out += 7; } - + /* finish final pixels */ - SNES_NTSC_COLOR_IN( 0, snes_ntsc_black ); - SNES_NTSC_RGB_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH ); - SNES_NTSC_RGB_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 1, snes_ntsc_black ); - SNES_NTSC_RGB_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH ); - SNES_NTSC_RGB_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 2, snes_ntsc_black ); - SNES_NTSC_RGB_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH ); - SNES_NTSC_RGB_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH ); - SNES_NTSC_RGB_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH ); - + SNES_NTSC_COLOR_IN(0, snes_ntsc_black); + SNES_NTSC_RGB_OUT(0, line_out [0], SNES_NTSC_OUT_DEPTH); + SNES_NTSC_RGB_OUT(1, line_out [1], SNES_NTSC_OUT_DEPTH); + + SNES_NTSC_COLOR_IN(1, snes_ntsc_black); + SNES_NTSC_RGB_OUT(2, line_out [2], SNES_NTSC_OUT_DEPTH); + SNES_NTSC_RGB_OUT(3, line_out [3], SNES_NTSC_OUT_DEPTH); + + SNES_NTSC_COLOR_IN(2, snes_ntsc_black); + SNES_NTSC_RGB_OUT(4, line_out [4], SNES_NTSC_OUT_DEPTH); + SNES_NTSC_RGB_OUT(5, line_out [5], SNES_NTSC_OUT_DEPTH); + SNES_NTSC_RGB_OUT(6, line_out [6], SNES_NTSC_OUT_DEPTH); + burst_phase = (burst_phase + 1) % snes_ntsc_burst_count; input += in_row_width; - rgb_out = (char*) rgb_out + out_pitch; + rgb_out = (char*)rgb_out + out_pitch; } } -void snes_ntsc_blit_hires( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, long in_row_width, - int burst_phase, int in_width, int in_height, void* rgb_out, long out_pitch ) +void snes_ntsc_blit_hires(snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, long in_row_width, + int burst_phase, int in_width, int in_height, void* rgb_out, long out_pitch) { int chunk_count = (in_width - 2) / (snes_ntsc_in_chunk * 2); - for ( ; in_height; --in_height ) + for (; in_height; --in_height) { SNES_NTSC_IN_T const* line_in = input; - SNES_NTSC_HIRES_ROW( ntsc, burst_phase, - snes_ntsc_black, snes_ntsc_black, snes_ntsc_black, - SNES_NTSC_ADJ_IN( line_in [0] ), - SNES_NTSC_ADJ_IN( line_in [1] ) ); - snes_ntsc_out_t* restrict line_out = (snes_ntsc_out_t*) rgb_out; + SNES_NTSC_HIRES_ROW(ntsc, burst_phase, + snes_ntsc_black, snes_ntsc_black, snes_ntsc_black, + SNES_NTSC_ADJ_IN( line_in [0] ), + SNES_NTSC_ADJ_IN( line_in [1] )); + snes_ntsc_out_t* restrict line_out = (snes_ntsc_out_t*)rgb_out; int n; line_in += 2; - - for ( n = chunk_count; n; --n ) + + for (n = chunk_count; n; --n) { /* twice as many input pixels per chunk */ - SNES_NTSC_COLOR_IN( 0, SNES_NTSC_ADJ_IN( line_in [0] ) ); - SNES_NTSC_HIRES_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 1, SNES_NTSC_ADJ_IN( line_in [1] ) ); - SNES_NTSC_HIRES_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 2, SNES_NTSC_ADJ_IN( line_in [2] ) ); - SNES_NTSC_HIRES_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 3, SNES_NTSC_ADJ_IN( line_in [3] ) ); - SNES_NTSC_HIRES_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 4, SNES_NTSC_ADJ_IN( line_in [4] ) ); - SNES_NTSC_HIRES_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 5, SNES_NTSC_ADJ_IN( line_in [5] ) ); - SNES_NTSC_HIRES_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH ); - SNES_NTSC_HIRES_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH ); - - line_in += 6; + SNES_NTSC_COLOR_IN(0, SNES_NTSC_ADJ_IN( line_in [0] )); + SNES_NTSC_HIRES_OUT(0, line_out [0], SNES_NTSC_OUT_DEPTH); + + SNES_NTSC_COLOR_IN(1, SNES_NTSC_ADJ_IN( line_in [1] )); + SNES_NTSC_HIRES_OUT(1, line_out [1], SNES_NTSC_OUT_DEPTH); + + SNES_NTSC_COLOR_IN(2, SNES_NTSC_ADJ_IN( line_in [2] )); + SNES_NTSC_HIRES_OUT(2, line_out [2], SNES_NTSC_OUT_DEPTH); + + SNES_NTSC_COLOR_IN(3, SNES_NTSC_ADJ_IN( line_in [3] )); + SNES_NTSC_HIRES_OUT(3, line_out [3], SNES_NTSC_OUT_DEPTH); + + SNES_NTSC_COLOR_IN(4, SNES_NTSC_ADJ_IN( line_in [4] )); + SNES_NTSC_HIRES_OUT(4, line_out [4], SNES_NTSC_OUT_DEPTH); + + SNES_NTSC_COLOR_IN(5, SNES_NTSC_ADJ_IN( line_in [5] )); + SNES_NTSC_HIRES_OUT(5, line_out [5], SNES_NTSC_OUT_DEPTH); + SNES_NTSC_HIRES_OUT(6, line_out [6], SNES_NTSC_OUT_DEPTH); + + line_in += 6; line_out += 7; } - - SNES_NTSC_COLOR_IN( 0, snes_ntsc_black ); - SNES_NTSC_HIRES_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 1, snes_ntsc_black ); - SNES_NTSC_HIRES_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 2, snes_ntsc_black ); - SNES_NTSC_HIRES_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 3, snes_ntsc_black ); - SNES_NTSC_HIRES_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 4, snes_ntsc_black ); - SNES_NTSC_HIRES_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 5, snes_ntsc_black ); - SNES_NTSC_HIRES_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH ); - SNES_NTSC_HIRES_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH ); - + + SNES_NTSC_COLOR_IN(0, snes_ntsc_black); + SNES_NTSC_HIRES_OUT(0, line_out [0], SNES_NTSC_OUT_DEPTH); + + SNES_NTSC_COLOR_IN(1, snes_ntsc_black); + SNES_NTSC_HIRES_OUT(1, line_out [1], SNES_NTSC_OUT_DEPTH); + + SNES_NTSC_COLOR_IN(2, snes_ntsc_black); + SNES_NTSC_HIRES_OUT(2, line_out [2], SNES_NTSC_OUT_DEPTH); + + SNES_NTSC_COLOR_IN(3, snes_ntsc_black); + SNES_NTSC_HIRES_OUT(3, line_out [3], SNES_NTSC_OUT_DEPTH); + + SNES_NTSC_COLOR_IN(4, snes_ntsc_black); + SNES_NTSC_HIRES_OUT(4, line_out [4], SNES_NTSC_OUT_DEPTH); + + SNES_NTSC_COLOR_IN(5, snes_ntsc_black); + SNES_NTSC_HIRES_OUT(5, line_out [5], SNES_NTSC_OUT_DEPTH); + SNES_NTSC_HIRES_OUT(6, line_out [6], SNES_NTSC_OUT_DEPTH); + burst_phase = (burst_phase + 1) % snes_ntsc_burst_count; input += in_row_width; - rgb_out = (char*) rgb_out + out_pitch; + rgb_out = (char*)rgb_out + out_pitch; } } diff --git a/Utilities/snes_ntsc.h b/Utilities/snes_ntsc.h index 9f2f28f..eae5b2a 100644 --- a/Utilities/snes_ntsc.h +++ b/Utilities/snes_ntsc.h @@ -7,7 +7,7 @@ #include "snes_ntsc_config.h" #ifdef __cplusplus - extern "C" { +extern "C" { #endif /* Image parameters, ranging from -1.0 to 1.0. Actual internal values shown @@ -15,46 +15,46 @@ in parenthesis and should remain fairly stable in future versions. */ typedef struct snes_ntsc_setup_t { /* Basic parameters */ - double hue; /* -1 = -180 degrees +1 = +180 degrees */ + double hue; /* -1 = -180 degrees +1 = +180 degrees */ double saturation; /* -1 = grayscale (0.0) +1 = oversaturated colors (2.0) */ - double contrast; /* -1 = dark (0.5) +1 = light (1.5) */ + double contrast; /* -1 = dark (0.5) +1 = light (1.5) */ double brightness; /* -1 = dark (0.5) +1 = light (1.5) */ - double sharpness; /* edge contrast enhancement/blurring */ - + double sharpness; /* edge contrast enhancement/blurring */ + /* Advanced parameters */ - double gamma; /* -1 = dark (1.5) +1 = light (0.5) */ + double gamma; /* -1 = dark (1.5) +1 = light (0.5) */ double resolution; /* image resolution */ - double artifacts; /* artifacts caused by color changes */ - double fringing; /* color artifacts caused by brightness changes */ - double bleed; /* color bleed (color resolution reduction) */ - int merge_fields; /* if 1, merges even and odd fields together to reduce flicker */ + double artifacts; /* artifacts caused by color changes */ + double fringing; /* color artifacts caused by brightness changes */ + double bleed; /* color bleed (color resolution reduction) */ + int merge_fields; /* if 1, merges even and odd fields together to reduce flicker */ float const* decoder_matrix; /* optional RGB decoder matrix, 6 elements */ - + unsigned long const* bsnes_colortbl; /* undocumented; set to 0 */ } snes_ntsc_setup_t; /* Video format presets */ extern snes_ntsc_setup_t const snes_ntsc_composite; /* color bleeding + artifacts */ -extern snes_ntsc_setup_t const snes_ntsc_svideo; /* color bleeding only */ -extern snes_ntsc_setup_t const snes_ntsc_rgb; /* crisp image */ -extern snes_ntsc_setup_t const snes_ntsc_monochrome;/* desaturated + artifacts */ +extern snes_ntsc_setup_t const snes_ntsc_svideo; /* color bleeding only */ +extern snes_ntsc_setup_t const snes_ntsc_rgb; /* crisp image */ +extern snes_ntsc_setup_t const snes_ntsc_monochrome; /* desaturated + artifacts */ /* Initializes and adjusts parameters. Can be called multiple times on the same snes_ntsc_t object. Can pass NULL for either parameter. */ typedef struct snes_ntsc_t snes_ntsc_t; -void snes_ntsc_init( snes_ntsc_t* ntsc, snes_ntsc_setup_t const* setup ); +void snes_ntsc_init(snes_ntsc_t* ntsc, snes_ntsc_setup_t const* setup); /* Filters one or more rows of pixels. Input pixel format is set by SNES_NTSC_IN_FORMAT and output RGB depth is set by SNES_NTSC_OUT_DEPTH. Both default to 16-bit RGB. In_row_width is the number of pixels to get to the next input row. Out_pitch is the number of *bytes* to get to the next output row. */ -void snes_ntsc_blit( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, - long in_row_width, int burst_phase, int in_width, int in_height, - void* rgb_out, long out_pitch ); +void snes_ntsc_blit(snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, + long in_row_width, int burst_phase, int in_width, int in_height, + void* rgb_out, long out_pitch); -void snes_ntsc_blit_hires( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, - long in_row_width, int burst_phase, int in_width, int in_height, - void* rgb_out, long out_pitch ); +void snes_ntsc_blit_hires(snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, + long in_row_width, int burst_phase, int in_width, int in_height, + void* rgb_out, long out_pitch); /* Number of output pixels written by low-res blitter for given input width. Width might be rounded down slightly; use SNES_NTSC_IN_WIDTH() on result to find rounded @@ -71,10 +71,10 @@ value. */ /* Interface for user-defined custom blitters */ -enum { snes_ntsc_in_chunk = 3 }; /* number of input pixels read per chunk */ -enum { snes_ntsc_out_chunk = 7 }; /* number of output pixels generated per chunk */ -enum { snes_ntsc_black = 0 }; /* palette index for black */ -enum { snes_ntsc_burst_count = 3 }; /* burst phase cycles through 0, 1, and 2 */ +enum { snes_ntsc_in_chunk = 3 }; /* number of input pixels read per chunk */ +enum { snes_ntsc_out_chunk = 7 }; /* number of output pixels generated per chunk */ +enum { snes_ntsc_black = 0 }; /* palette index for black */ +enum { snes_ntsc_burst_count = 3 }; /* burst phase cycles through 0, 1, and 2 */ /* Begins outputting row and starts three pixels. First pixel will be cut off a bit. Use snes_ntsc_black for unused pixels. Declares variables, so must be before first @@ -132,11 +132,16 @@ statement in a block (unless you're using C++). */ /* private */ enum { snes_ntsc_entry_size = 128 }; + enum { snes_ntsc_palette_size = 0x2000 }; + typedef unsigned long snes_ntsc_rgb_t; -struct snes_ntsc_t { - snes_ntsc_rgb_t table [snes_ntsc_palette_size] [snes_ntsc_entry_size]; + +struct snes_ntsc_t +{ + snes_ntsc_rgb_t table[snes_ntsc_palette_size][snes_ntsc_entry_size]; }; + enum { snes_ntsc_burst_size = snes_ntsc_entry_size / snes_ntsc_burst_count }; #define SNES_NTSC_RGB16( ktable, n ) \ @@ -200,7 +205,7 @@ enum { snes_ntsc_burst_size = snes_ntsc_entry_size / snes_ntsc_burst_count }; } #ifdef __cplusplus - } +} #endif #endif diff --git a/Utilities/snes_ntsc_impl.h b/Utilities/snes_ntsc_impl.h index 1d7adc7..c52e72c 100644 --- a/Utilities/snes_ntsc_impl.h +++ b/Utilities/snes_ntsc_impl.h @@ -22,7 +22,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define PI 3.14159265358979323846f #ifndef LUMA_CUTOFF - #define LUMA_CUTOFF 0.20 +#define LUMA_CUTOFF 0.20 #endif #ifndef gamma_size #define gamma_size 1 @@ -31,32 +31,34 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define rgb_bits 8 #endif #ifndef artifacts_max - #define artifacts_max (artifacts_mid * 1.5f) +#define artifacts_max (artifacts_mid * 1.5f) #endif #ifndef fringing_max - #define fringing_max (fringing_mid * 2) +#define fringing_max (fringing_mid * 2) #endif #ifndef STD_HUE_CONDITION - #define STD_HUE_CONDITION( setup ) 1 +#define STD_HUE_CONDITION( setup ) 1 #endif #define ext_decoder_hue (std_decoder_hue + 15) #define rgb_unit (1 << rgb_bits) #define rgb_offset (rgb_unit * 2 + 0.5f) -enum { burst_size = snes_ntsc_entry_size / burst_count }; +enum { burst_size = snes_ntsc_entry_size / burst_count }; + enum { kernel_half = 16 }; + enum { kernel_size = kernel_half * 2 + 1 }; typedef struct init_t { - float to_rgb [burst_count * 6]; - float to_float [gamma_size]; + float to_rgb[burst_count * 6]; + float to_float[gamma_size]; float contrast; float brightness; float artifacts; float fringing; - float kernel [rescale_out * kernel_size * 2]; + float kernel[rescale_out * kernel_size * 2]; } init_t; #define ROTATE_IQ( i, q, sin_b, cos_b ) {\ @@ -66,10 +68,10 @@ typedef struct init_t i = t;\ } -static void init_filters( init_t* impl, snes_ntsc_setup_t const* setup ) +static void init_filters(init_t* impl, snes_ntsc_setup_t const* setup) { #if rescale_out > 1 - float kernels [kernel_size * 2]; + float kernels[kernel_size * 2]; #else float* const kernels = impl->kernel; #endif @@ -77,59 +79,59 @@ static void init_filters( init_t* impl, snes_ntsc_setup_t const* setup ) /* generate luma (y) filter using sinc kernel */ { /* sinc with rolloff (dsf) */ - float const rolloff = 1 + (float) setup->sharpness * (float) 0.032; + float const rolloff = 1 + (float)setup->sharpness * (float)0.032; float const maxh = 32; - float const pow_a_n = (float) pow( rolloff, maxh ); + float const pow_a_n = (float)pow(rolloff, maxh); float sum; int i; /* quadratic mapping to reduce negative (blurring) range */ - float to_angle = (float) setup->resolution + 1; - to_angle = PI / maxh * (float) LUMA_CUTOFF * (to_angle * to_angle + 1); - - kernels [kernel_size * 3 / 2] = maxh; /* default center value */ - for ( i = 0; i < kernel_half * 2 + 1; i++ ) + float to_angle = (float)setup->resolution + 1; + to_angle = PI / maxh * (float)LUMA_CUTOFF * (to_angle * to_angle + 1); + + kernels[kernel_size * 3 / 2] = maxh; /* default center value */ + for (i = 0; i < kernel_half * 2 + 1; i++) { int x = i - kernel_half; float angle = x * to_angle; /* instability occurs at center point with rolloff very close to 1.0 */ - if ( x || pow_a_n > (float) 1.056 || pow_a_n < (float) 0.981 ) + if (x || pow_a_n > (float)1.056 || pow_a_n < (float)0.981) { - float rolloff_cos_a = rolloff * (float) cos( angle ); + float rolloff_cos_a = rolloff * (float)cos(angle); float num = 1 - rolloff_cos_a - - pow_a_n * (float) cos( maxh * angle ) + - pow_a_n * rolloff * (float) cos( (maxh - 1) * angle ); + pow_a_n * (float)cos(maxh * angle) + + pow_a_n * rolloff * (float)cos((maxh - 1) * angle); float den = 1 - rolloff_cos_a - rolloff_cos_a + rolloff * rolloff; float dsf = num / den; - kernels [kernel_size * 3 / 2 - kernel_half + i] = dsf - (float) 0.5; + kernels[kernel_size * 3 / 2 - kernel_half + i] = dsf - (float)0.5; } } - + /* apply blackman window and find sum */ sum = 0; - for ( i = 0; i < kernel_half * 2 + 1; i++ ) + for (i = 0; i < kernel_half * 2 + 1; i++) { float x = PI * 2 / (kernel_half * 2) * i; - float blackman = 0.42f - 0.5f * (float) cos( x ) + 0.08f * (float) cos( x * 2 ); - sum += (kernels [kernel_size * 3 / 2 - kernel_half + i] *= blackman); + float blackman = 0.42f - 0.5f * (float)cos(x) + 0.08f * (float)cos(x * 2); + sum += (kernels[kernel_size * 3 / 2 - kernel_half + i] *= blackman); } - + /* normalize kernel */ sum = 1.0f / sum; - for ( i = 0; i < kernel_half * 2 + 1; i++ ) + for (i = 0; i < kernel_half * 2 + 1; i++) { int x = kernel_size * 3 / 2 - kernel_half + i; - kernels [x] *= sum; - assert( kernels [x] == kernels [x] ); /* catch numerical instability */ + kernels[x] *= sum; + assert(kernels [x] == kernels [x]); /* catch numerical instability */ } } /* generate chroma (iq) filter using gaussian kernel */ { float const cutoff_factor = -0.03125f; - float cutoff = (float) setup->bleed; + float cutoff = (float)setup->bleed; int i; - - if ( cutoff < 0 ) + + if (cutoff < 0) { /* keep extreme value accessible only near upper end of scale (1.0) */ cutoff *= cutoff; @@ -138,27 +140,27 @@ static void init_filters( init_t* impl, snes_ntsc_setup_t const* setup ) cutoff *= -30.0f / 0.65f; } cutoff = cutoff_factor - 0.65f * cutoff_factor * cutoff; - - for ( i = -kernel_half; i <= kernel_half; i++ ) - kernels [kernel_size / 2 + i] = (float) exp( i * i * cutoff ); - + + for (i = -kernel_half; i <= kernel_half; i++) + kernels[kernel_size / 2 + i] = (float)exp(i * i * cutoff); + /* normalize even and odd phases separately */ - for ( i = 0; i < 2; i++ ) + for (i = 0; i < 2; i++) { float sum = 0; int x; - for ( x = i; x < kernel_size; x += 2 ) - sum += kernels [x]; - + for (x = i; x < kernel_size; x += 2) + sum += kernels[x]; + sum = 1.0f / sum; - for ( x = i; x < kernel_size; x += 2 ) + for (x = i; x < kernel_size; x += 2) { - kernels [x] *= sum; - assert( kernels [x] == kernels [x] ); /* catch numerical instability */ + kernels[x] *= sum; + assert(kernels [x] == kernels [x]); /* catch numerical instability */ } } } - + /* printf( "luma:\n" ); for ( i = kernel_size; i < kernel_size * 2; i++ ) @@ -167,9 +169,9 @@ static void init_filters( init_t* impl, snes_ntsc_setup_t const* setup ) for ( i = 0; i < kernel_size; i++ ) printf( "%f\n", kernels [i] ); */ - + /* generate linear rescale kernels */ - #if rescale_out > 1 +#if rescale_out > 1 { float weight = 1.0f; float* out = impl->kernel; @@ -179,73 +181,73 @@ static void init_filters( init_t* impl, snes_ntsc_setup_t const* setup ) float remain = 0; int i; weight -= 1.0f / rescale_in; - for ( i = 0; i < kernel_size * 2; i++ ) + for (i = 0; i < kernel_size * 2; i++) { - float cur = kernels [i]; + float cur = kernels[i]; float m = cur * weight; *out++ = m + remain; remain = cur - m; } } - while ( --n ); + while (--n); } - #endif +#endif } -static float const default_decoder [6] = - { 0.956f, 0.621f, -0.272f, -0.647f, -1.105f, 1.702f }; +static float const default_decoder[6] = + {0.956f, 0.621f, -0.272f, -0.647f, -1.105f, 1.702f}; -static void init( init_t* impl, snes_ntsc_setup_t const* setup ) +static void init(init_t* impl, snes_ntsc_setup_t const* setup) { - impl->brightness = (float) setup->brightness * (0.5f * rgb_unit) + rgb_offset; - impl->contrast = (float) setup->contrast * (0.5f * rgb_unit) + rgb_unit; - #ifdef default_palette_contrast + impl->brightness = (float)setup->brightness * (0.5f * rgb_unit) + rgb_offset; + impl->contrast = (float)setup->contrast * (0.5f * rgb_unit) + rgb_unit; +#ifdef default_palette_contrast if ( !setup->palette ) impl->contrast *= default_palette_contrast; - #endif - - impl->artifacts = (float) setup->artifacts; - if ( impl->artifacts > 0 ) +#endif + + impl->artifacts = (float)setup->artifacts; + if (impl->artifacts > 0) impl->artifacts *= artifacts_max - artifacts_mid; impl->artifacts = impl->artifacts * artifacts_mid + artifacts_mid; - impl->fringing = (float) setup->fringing; - if ( impl->fringing > 0 ) + impl->fringing = (float)setup->fringing; + if (impl->fringing > 0) impl->fringing *= fringing_max - fringing_mid; impl->fringing = impl->fringing * fringing_mid + fringing_mid; - - init_filters( impl, setup ); - + + init_filters(impl, setup); + /* generate gamma table */ - if ( gamma_size > 1 ) + if (gamma_size > 1) { float const to_float = 1.0f / (gamma_size - (gamma_size > 1)); - float const gamma = 1.1333f - (float) setup->gamma * 0.5f; + float const gamma = 1.1333f - (float)setup->gamma * 0.5f; /* match common PC's 2.2 gamma to TV's 2.65 gamma */ int i; - for ( i = 0; i < gamma_size; i++ ) - impl->to_float [i] = - (float) pow( i * to_float, gamma ) * impl->contrast + impl->brightness; + for (i = 0; i < gamma_size; i++) + impl->to_float[i] = + (float)pow(i * to_float, gamma) * impl->contrast + impl->brightness; } - + /* setup decoder matricies */ { - float hue = (float) setup->hue * PI + PI / 180 * ext_decoder_hue; - float sat = (float) setup->saturation + 1; + float hue = (float)setup->hue * PI + PI / 180 * ext_decoder_hue; + float sat = (float)setup->saturation + 1; float const* decoder = setup->decoder_matrix; - if ( !decoder ) + if (!decoder) { decoder = default_decoder; - if ( STD_HUE_CONDITION( setup ) ) + if (STD_HUE_CONDITION(setup)) hue += PI / 180 * (std_decoder_hue - ext_decoder_hue); } - + { - float s = (float) sin( hue ) * sat; - float c = (float) cos( hue ) * sat; + float s = (float)sin(hue) * sat; + float c = (float)cos(hue) * sat; float* out = impl->to_rgb; int n; - + n = burst_count; do { @@ -258,12 +260,12 @@ static void init( init_t* impl, snes_ntsc_setup_t const* setup ) *out++ = i * c - q * s; *out++ = i * s + q * c; } - while ( --n ); - if ( burst_count <= 1 ) + while (--n); + if (burst_count <= 1) break; - ROTATE_IQ( s, c, 0.866025f, -0.5f ); /* +120 degrees */ + ROTATE_IQ(s, c, 0.866025f, -0.5f); /* +120 degrees */ } - while ( --n ); + while (--n); } } } @@ -285,21 +287,22 @@ static void init( init_t* impl, snes_ntsc_setup_t const* setup ) #define PACK_RGB( r, g, b ) ((r) << 21 | (g) << 11 | (b) << 1) enum { rgb_kernel_size = burst_size / alignment_count }; + enum { rgb_bias = rgb_unit * 2 * snes_ntsc_rgb_builder }; typedef struct pixel_info_t { int offset; float negate; - float kernel [4]; + float kernel[4]; } pixel_info_t; #if rescale_in > 1 - #define PIXEL_OFFSET_( ntsc, scaled ) \ +#define PIXEL_OFFSET_( ntsc, scaled ) \ (kernel_size / 2 + ntsc + (scaled != 0) + (rescale_out - scaled) % rescale_out + \ (kernel_size * 2 * scaled)) - #define PIXEL_OFFSET( ntsc, scaled ) \ +#define PIXEL_OFFSET( ntsc, scaled ) \ PIXEL_OFFSET_( ((ntsc) - (scaled) / rescale_out * rescale_in),\ (((scaled) + rescale_out * 10) % rescale_out) ),\ (1.0f - (((ntsc) + 100) & 2)) @@ -309,10 +312,10 @@ typedef struct pixel_info_t (1.0f - (((ntsc) + 100) & 2)) #endif -extern pixel_info_t const snes_ntsc_pixels [alignment_count]; +extern pixel_info_t const snes_ntsc_pixels[alignment_count]; /* Generate pixel at all burst phases and column alignments */ -static void gen_kernel( init_t* impl, float y, float i, float q, snes_ntsc_rgb_t* out ) +static void gen_kernel(init_t* impl, float y, float i, float q, snes_ntsc_rgb_t* out) { /* generate for each scanline burst phase */ float const* to_rgb = impl->to_rgb; @@ -330,61 +333,61 @@ static void gen_kernel( init_t* impl, float y, float i, float q, snes_ntsc_rgb_t { /* negate is -1 when composite starts at odd multiple of 2 */ float const yy = y * impl->fringing * pixel->negate; - float const ic0 = (i + yy) * pixel->kernel [0]; - float const qc1 = (q + yy) * pixel->kernel [1]; - float const ic2 = (i - yy) * pixel->kernel [2]; - float const qc3 = (q - yy) * pixel->kernel [3]; - + float const ic0 = (i + yy) * pixel->kernel[0]; + float const qc1 = (q + yy) * pixel->kernel[1]; + float const ic2 = (i - yy) * pixel->kernel[2]; + float const qc3 = (q - yy) * pixel->kernel[3]; + float const factor = impl->artifacts * pixel->negate; float const ii = i * factor; - float const yc0 = (y + ii) * pixel->kernel [0]; - float const yc2 = (y - ii) * pixel->kernel [2]; - + float const yc0 = (y + ii) * pixel->kernel[0]; + float const yc2 = (y - ii) * pixel->kernel[2]; + float const qq = q * factor; - float const yc1 = (y + qq) * pixel->kernel [1]; - float const yc3 = (y - qq) * pixel->kernel [3]; - - float const* k = &impl->kernel [pixel->offset]; + float const yc1 = (y + qq) * pixel->kernel[1]; + float const yc3 = (y - qq) * pixel->kernel[3]; + + float const* k = &impl->kernel[pixel->offset]; int n; ++pixel; - for ( n = rgb_kernel_size; n; --n ) + for (n = rgb_kernel_size; n; --n) { - float i = k[0]*ic0 + k[2]*ic2; - float q = k[1]*qc1 + k[3]*qc3; - float y = k[kernel_size+0]*yc0 + k[kernel_size+1]*yc1 + - k[kernel_size+2]*yc2 + k[kernel_size+3]*yc3 + rgb_offset; - if ( rescale_out <= 1 ) + float i = k[0] * ic0 + k[2] * ic2; + float q = k[1] * qc1 + k[3] * qc3; + float y = k[kernel_size + 0] * yc0 + k[kernel_size + 1] * yc1 + + k[kernel_size + 2] * yc2 + k[kernel_size + 3] * yc3 + rgb_offset; + if (rescale_out <= 1) k--; - else if ( k < &impl->kernel [kernel_size * 2 * (rescale_out - 1)] ) + else if (k < &impl->kernel[kernel_size * 2 * (rescale_out - 1)]) k += kernel_size * 2 - 1; else k -= kernel_size * 2 * (rescale_out - 1) + 2; { - int r, g, b = YIQ_TO_RGB( y, i, q, to_rgb, int, r, g ); - *out++ = PACK_RGB( r, g, b ) - rgb_bias; + int r, g, b = YIQ_TO_RGB(y, i, q, to_rgb, int, r, g); + *out++ = PACK_RGB(r, g, b) - rgb_bias; } } } - while ( alignment_count > 1 && --alignment_remain ); - - if ( burst_count <= 1 ) + while (alignment_count > 1 && --alignment_remain); + + if (burst_count <= 1) break; - + to_rgb += 6; - - ROTATE_IQ( i, q, -0.866025f, -0.5f ); /* -120 degrees */ + + ROTATE_IQ(i, q, -0.866025f, -0.5f); /* -120 degrees */ } - while ( --burst_remain ); + while (--burst_remain); } -static void correct_errors( snes_ntsc_rgb_t color, snes_ntsc_rgb_t* out ); +static void correct_errors(snes_ntsc_rgb_t color, snes_ntsc_rgb_t* out); #if DISABLE_CORRECTION #define CORRECT_ERROR( a ) { out [i] += rgb_bias; } #define DISTRIBUTE_ERROR( a, b, c ) { out [i] += rgb_bias; } #else - #define CORRECT_ERROR( a ) { out [a] += error; } - #define DISTRIBUTE_ERROR( a, b, c ) {\ +#define CORRECT_ERROR( a ) { out [a] += error; } +#define DISTRIBUTE_ERROR( a, b, c ) {\ snes_ntsc_rgb_t fourth = (error + 2 * snes_ntsc_rgb_builder) >> 2;\ fourth &= (rgb_bias >> 1) - snes_ntsc_rgb_builder;\ fourth -= rgb_bias >> 2;\ @@ -408,32 +411,32 @@ static void correct_errors( snes_ntsc_rgb_t color, snes_ntsc_rgb_t* out ); /* blitter related */ #ifndef restrict - #if defined (__GNUC__) +#if defined (__GNUC__) #define restrict __restrict__ - #elif defined (_MSC_VER) && _MSC_VER > 1300 - #define restrict __restrict - #else +#elif defined (_MSC_VER) && _MSC_VER > 1300 +#define restrict __restrict +#else /* no support for restricted pointers */ #define restrict - #endif +#endif #endif #include #if SNES_NTSC_OUT_DEPTH <= 16 - #if USHRT_MAX == 0xFFFF +#if USHRT_MAX == 0xFFFF typedef unsigned short snes_ntsc_out_t; - #else +#else #error "Need 16-bit int type" - #endif +#endif #else - #if UINT_MAX == 0xFFFFFFFF - typedef unsigned int snes_ntsc_out_t; - #elif ULONG_MAX == 0xFFFFFFFF +#if UINT_MAX == 0xFFFFFFFF +typedef unsigned int snes_ntsc_out_t; +#elif ULONG_MAX == 0xFFFFFFFF typedef unsigned long snes_ntsc_out_t; - #else +#else #error "Need 32-bit int type" - #endif +#endif #endif diff --git a/Utilities/stb_vorbis.cpp b/Utilities/stb_vorbis.cpp index ff35e8f..18c2fec 100644 --- a/Utilities/stb_vorbis.cpp +++ b/Utilities/stb_vorbis.cpp @@ -181,8 +181,6 @@ // #define STB_VORBIS_NO_DEFER_FLOOR - - ////////////////////////////////////////////////////////////////////////////// #ifdef STB_VORBIS_NO_PULLDATA_API @@ -197,14 +195,14 @@ #ifndef STB_VORBIS_NO_INTEGER_CONVERSION #ifndef STB_VORBIS_NO_FAST_SCALED_FLOAT - // only need endianness for fast-float-to-int, which we don't - // use for pushdata +// only need endianness for fast-float-to-int, which we don't +// use for pushdata - #ifndef STB_VORBIS_BIG_ENDIAN - #define STB_VORBIS_ENDIAN 0 - #else +#ifndef STB_VORBIS_BIG_ENDIAN +#define STB_VORBIS_ENDIAN 0 +#else #define STB_VORBIS_ENDIAN 1 - #endif +#endif #endif #endif @@ -215,18 +213,18 @@ #endif #ifndef STB_VORBIS_NO_CRT - #include - #include - #include - #include +#include +#include +#include +#include - // find definition of alloca if it's not in stdlib.h: - #if defined(_MSC_VER) || defined(__MINGW32__) - #include - #endif - #if defined(__linux__) || defined(__linux) || defined(__EMSCRIPTEN__) +// find definition of alloca if it's not in stdlib.h: +#if defined(_MSC_VER) || defined(__MINGW32__) +#include +#endif +#if defined(__linux__) || defined(__linux) || defined(__EMSCRIPTEN__) #include - #endif +#endif #else // STB_VORBIS_NO_CRT #define NULL 0 #define malloc(s) 0 @@ -237,25 +235,25 @@ #include #ifdef __MINGW32__ - // eff you mingw: - // "fixed": - // http://sourceforge.net/p/mingw-w64/mailman/message/32882927/ - // "no that broke the build, reverted, who cares about C": - // http://sourceforge.net/p/mingw-w64/mailman/message/32890381/ - #ifdef __forceinline +// eff you mingw: +// "fixed": +// http://sourceforge.net/p/mingw-w64/mailman/message/32882927/ +// "no that broke the build, reverted, who cares about C": +// http://sourceforge.net/p/mingw-w64/mailman/message/32890381/ +#ifdef __forceinline #undef __forceinline - #endif +#endif #define __forceinline #define alloca __builtin_alloca #elif !defined(_MSC_VER) - #ifdef __forceinline +#ifdef __forceinline #undef __forceinline - #endif - #if __GNUC__ +#endif +#if __GNUC__ #define __forceinline inline - #else +#else #define __forceinline - #endif +#endif #endif #if STB_VORBIS_MAX_CHANNELS > 256 @@ -278,12 +276,12 @@ #define MAX_BLOCKSIZE (1 << MAX_BLOCKSIZE_LOG) -typedef unsigned char uint8; -typedef signed char int8; +typedef unsigned char uint8; +typedef signed char int8; typedef unsigned short uint16; -typedef signed short int16; -typedef unsigned int uint32; -typedef signed int int32; +typedef signed short int16; +typedef unsigned int uint32; +typedef signed int int32; #ifndef TRUE #define TRUE 1 @@ -310,218 +308,218 @@ typedef float codetype; typedef struct { - int dimensions, entries; - uint8 *codeword_lengths; - float minimum_value; - float delta_value; - uint8 value_bits; - uint8 lookup_type; - uint8 sequence_p; - uint8 sparse; - uint32 lookup_values; - codetype *multiplicands; - uint32 *codewords; - #ifdef STB_VORBIS_FAST_HUFFMAN_SHORT - int16 fast_huffman[FAST_HUFFMAN_TABLE_SIZE]; - #else + int dimensions, entries; + uint8* codeword_lengths; + float minimum_value; + float delta_value; + uint8 value_bits; + uint8 lookup_type; + uint8 sequence_p; + uint8 sparse; + uint32 lookup_values; + codetype* multiplicands; + uint32* codewords; +#ifdef STB_VORBIS_FAST_HUFFMAN_SHORT + int16 fast_huffman[FAST_HUFFMAN_TABLE_SIZE]; +#else int32 fast_huffman[FAST_HUFFMAN_TABLE_SIZE]; - #endif - uint32 *sorted_codewords; - int *sorted_values; - int sorted_entries; +#endif + uint32* sorted_codewords; + int* sorted_values; + int sorted_entries; } Codebook; typedef struct { - uint8 order; - uint16 rate; - uint16 bark_map_size; - uint8 amplitude_bits; - uint8 amplitude_offset; - uint8 number_of_books; - uint8 book_list[16]; // varies + uint8 order; + uint16 rate; + uint16 bark_map_size; + uint8 amplitude_bits; + uint8 amplitude_offset; + uint8 number_of_books; + uint8 book_list[16]; // varies } Floor0; typedef struct { - uint8 partitions; - uint8 partition_class_list[32]; // varies - uint8 class_dimensions[16]; // varies - uint8 class_subclasses[16]; // varies - uint8 class_masterbooks[16]; // varies - int16 subclass_books[16][8]; // varies - uint16 Xlist[31*8+2]; // varies - uint8 sorted_order[31*8+2]; - uint8 neighbors[31*8+2][2]; - uint8 floor1_multiplier; - uint8 rangebits; - int values; + uint8 partitions; + uint8 partition_class_list[32]; // varies + uint8 class_dimensions[16]; // varies + uint8 class_subclasses[16]; // varies + uint8 class_masterbooks[16]; // varies + int16 subclass_books[16][8]; // varies + uint16 Xlist[31 * 8 + 2]; // varies + uint8 sorted_order[31 * 8 + 2]; + uint8 neighbors[31 * 8 + 2][2]; + uint8 floor1_multiplier; + uint8 rangebits; + int values; } Floor1; typedef union { - Floor0 floor0; - Floor1 floor1; + Floor0 floor0; + Floor1 floor1; } Floor; typedef struct { - uint32 begin, end; - uint32 part_size; - uint8 classifications; - uint8 classbook; - uint8 **classdata; - int16 (*residue_books)[8]; + uint32 begin, end; + uint32 part_size; + uint8 classifications; + uint8 classbook; + uint8** classdata; + int16 (*residue_books)[8]; } Residue; typedef struct { - uint8 magnitude; - uint8 angle; - uint8 mux; + uint8 magnitude; + uint8 angle; + uint8 mux; } MappingChannel; typedef struct { - uint16 coupling_steps; - MappingChannel *chan; - uint8 submaps; - uint8 submap_floor[15]; // varies - uint8 submap_residue[15]; // varies + uint16 coupling_steps; + MappingChannel* chan; + uint8 submaps; + uint8 submap_floor[15]; // varies + uint8 submap_residue[15]; // varies } Mapping; typedef struct { - uint8 blockflag; - uint8 mapping; - uint16 windowtype; - uint16 transformtype; + uint8 blockflag; + uint8 mapping; + uint16 windowtype; + uint16 transformtype; } Mode; typedef struct { - uint32 goal_crc; // expected crc if match - int bytes_left; // bytes left in packet - uint32 crc_so_far; // running crc - int bytes_done; // bytes processed in _current_ chunk - uint32 sample_loc; // granule pos encoded in page + uint32 goal_crc; // expected crc if match + int bytes_left; // bytes left in packet + uint32 crc_so_far; // running crc + int bytes_done; // bytes processed in _current_ chunk + uint32 sample_loc; // granule pos encoded in page } CRCscan; typedef struct { - uint32 page_start, page_end; - uint32 last_decoded_sample; + uint32 page_start, page_end; + uint32 last_decoded_sample; } ProbedPage; struct stb_vorbis { - // user-accessible info - unsigned int sample_rate; - int channels; + // user-accessible info + unsigned int sample_rate; + int channels; - unsigned int setup_memory_required; - unsigned int temp_memory_required; - unsigned int setup_temp_memory_required; + unsigned int setup_memory_required; + unsigned int temp_memory_required; + unsigned int setup_temp_memory_required; - // input config + // input config #ifndef STB_VORBIS_NO_STDIO - FILE *f; - uint32 f_start; - int close_on_free; + FILE* f; + uint32 f_start; + int close_on_free; #endif - uint8 *stream; - uint8 *stream_start; - uint8 *stream_end; + uint8* stream; + uint8* stream_start; + uint8* stream_end; - uint32 stream_len; + uint32 stream_len; - uint8 push_mode; + uint8 push_mode; - uint32 first_audio_page_offset; + uint32 first_audio_page_offset; - ProbedPage p_first, p_last; + ProbedPage p_first, p_last; - // memory management - stb_vorbis_alloc alloc; - int setup_offset; - int temp_offset; + // memory management + stb_vorbis_alloc alloc; + int setup_offset; + int temp_offset; - // run-time results - int eof; - enum STBVorbisError error; + // run-time results + int eof; + enum STBVorbisError error; - // user-useful data + // user-useful data - // header info - int blocksize[2]; - int blocksize_0, blocksize_1; - int codebook_count; - Codebook *codebooks; - int floor_count; - uint16 floor_types[64]; // varies - Floor *floor_config; - int residue_count; - uint16 residue_types[64]; // varies - Residue *residue_config; - int mapping_count; - Mapping *mapping; - int mode_count; - Mode mode_config[64]; // varies + // header info + int blocksize[2]; + int blocksize_0, blocksize_1; + int codebook_count; + Codebook* codebooks; + int floor_count; + uint16 floor_types[64]; // varies + Floor* floor_config; + int residue_count; + uint16 residue_types[64]; // varies + Residue* residue_config; + int mapping_count; + Mapping* mapping; + int mode_count; + Mode mode_config[64]; // varies - uint32 total_samples; + uint32 total_samples; - // decode buffer - float *channel_buffers[STB_VORBIS_MAX_CHANNELS]; - float *outputs [STB_VORBIS_MAX_CHANNELS]; + // decode buffer + float* channel_buffers[STB_VORBIS_MAX_CHANNELS]; + float* outputs[STB_VORBIS_MAX_CHANNELS]; - float *previous_window[STB_VORBIS_MAX_CHANNELS]; - int previous_length; + float* previous_window[STB_VORBIS_MAX_CHANNELS]; + int previous_length; - #ifndef STB_VORBIS_NO_DEFER_FLOOR - int16 *finalY[STB_VORBIS_MAX_CHANNELS]; - #else +#ifndef STB_VORBIS_NO_DEFER_FLOOR + int16* finalY[STB_VORBIS_MAX_CHANNELS]; +#else float *floor_buffers[STB_VORBIS_MAX_CHANNELS]; - #endif - - uint32 current_loc; // sample location of next frame to decode - int current_loc_valid; - - // per-blocksize precomputed data - - // twiddle factors - float *A[2],*B[2],*C[2]; - float *window[2]; - uint16 *bit_reverse[2]; - - // current page/packet/segment streaming info - uint32 serial; // stream serial number for verification - int last_page; - int segment_count; - uint8 segments[255]; - uint8 page_flag; - uint8 bytes_in_seg; - uint8 first_decode; - int next_seg; - int last_seg; // flag that we're on the last segment - int last_seg_which; // what was the segment number of the last seg? - uint32 acc; - int valid_bits; - int packet_bytes; - int end_seg_with_known_loc; - uint32 known_loc_for_packet; - int discard_samples_deferred; - uint32 samples_output; - - // push mode scanning - int page_crc_tests; // only in push_mode: number of tests active; -1 if not searching -#ifndef STB_VORBIS_NO_PUSHDATA_API - CRCscan scan[STB_VORBIS_PUSHDATA_CRC_COUNT]; #endif - // sample-access - int channel_buffer_start; - int channel_buffer_end; + uint32 current_loc; // sample location of next frame to decode + int current_loc_valid; + + // per-blocksize precomputed data + + // twiddle factors + float *A[2], *B[2], *C[2]; + float* window[2]; + uint16* bit_reverse[2]; + + // current page/packet/segment streaming info + uint32 serial; // stream serial number for verification + int last_page; + int segment_count; + uint8 segments[255]; + uint8 page_flag; + uint8 bytes_in_seg; + uint8 first_decode; + int next_seg; + int last_seg; // flag that we're on the last segment + int last_seg_which; // what was the segment number of the last seg? + uint32 acc; + int valid_bits; + int packet_bytes; + int end_seg_with_known_loc; + uint32 known_loc_for_packet; + int discard_samples_deferred; + uint32 samples_output; + + // push mode scanning + int page_crc_tests; // only in push_mode: number of tests active; -1 if not searching +#ifndef STB_VORBIS_NO_PUSHDATA_API + CRCscan scan[STB_VORBIS_PUSHDATA_CRC_COUNT]; +#endif + + // sample-access + int channel_buffer_start; + int channel_buffer_end; }; #if defined(STB_VORBIS_NO_PUSHDATA_API) @@ -529,18 +527,19 @@ struct stb_vorbis #elif defined(STB_VORBIS_NO_PULLDATA_API) #define IS_PUSH_MODE(f) TRUE #else - #define IS_PUSH_MODE(f) ((f)->push_mode) +#define IS_PUSH_MODE(f) ((f)->push_mode) #endif typedef struct stb_vorbis vorb; -static int error(vorb *f, enum STBVorbisError e) +static int error(vorb* f, enum STBVorbisError e) { - f->error = e; - if (!f->eof && e != VORBIS_need_more_data) { - f->error=e; // breakpoint for debugging - } - return 0; + f->error = e; + if (!f->eof && e != VORBIS_need_more_data) + { + f->error = e; // breakpoint for debugging + } + return 0; } @@ -558,90 +557,96 @@ static int error(vorb *f, enum STBVorbisError e) #define temp_block_array(f,count,size) make_block_array(temp_alloc(f,array_size_required(count,size)), count, size) // given a sufficiently large block of memory, make an array of pointers to subblocks of it -static void *make_block_array(void *mem, int count, int size) +static void* make_block_array(void* mem, int count, int size) { - int i; - void ** p = (void **) mem; - char *q = (char *) (p + count); - for (i=0; i < count; ++i) { - p[i] = q; - q += size; - } - return p; + int i; + void** p = (void**)mem; + char* q = (char*)(p + count); + for (i = 0; i < count; ++i) + { + p[i] = q; + q += size; + } + return p; } -static void *setup_malloc(vorb *f, int sz) +static void* setup_malloc(vorb* f, int sz) { - sz = (sz+3) & ~3; - f->setup_memory_required += sz; - if (f->alloc.alloc_buffer) { - void *p = (char *) f->alloc.alloc_buffer + f->setup_offset; - if (f->setup_offset + sz > f->temp_offset) return NULL; - f->setup_offset += sz; - return p; - } - return sz ? malloc(sz) : NULL; + sz = (sz + 3) & ~3; + f->setup_memory_required += sz; + if (f->alloc.alloc_buffer) + { + void* p = (char*)f->alloc.alloc_buffer + f->setup_offset; + if (f->setup_offset + sz > f->temp_offset) return NULL; + f->setup_offset += sz; + return p; + } + return sz ? malloc(sz) : NULL; } -static void setup_free(vorb *f, void *p) +static void setup_free(vorb* f, void* p) { - if (f->alloc.alloc_buffer) return; // do nothing; setup mem is a stack - free(p); + if (f->alloc.alloc_buffer) return; // do nothing; setup mem is a stack + free(p); } -static void *setup_temp_malloc(vorb *f, int sz) +static void* setup_temp_malloc(vorb* f, int sz) { - sz = (sz+3) & ~3; - if (f->alloc.alloc_buffer) { - if (f->temp_offset - sz < f->setup_offset) return NULL; - f->temp_offset -= sz; - return (char *) f->alloc.alloc_buffer + f->temp_offset; - } - return malloc(sz); + sz = (sz + 3) & ~3; + if (f->alloc.alloc_buffer) + { + if (f->temp_offset - sz < f->setup_offset) return NULL; + f->temp_offset -= sz; + return (char*)f->alloc.alloc_buffer + f->temp_offset; + } + return malloc(sz); } -static void setup_temp_free(vorb *f, void *p, int sz) +static void setup_temp_free(vorb* f, void* p, int sz) { - if (f->alloc.alloc_buffer) { - f->temp_offset += (sz+3)&~3; - return; - } - free(p); + if (f->alloc.alloc_buffer) + { + f->temp_offset += (sz + 3) & ~3; + return; + } + free(p); } #define CRC32_POLY 0x04c11db7 // from spec static uint32 crc_table[256]; + static void crc32_init(void) { - int i,j; - uint32 s; - for(i=0; i < 256; i++) { - for (s=(uint32) i << 24, j=0; j < 8; ++j) - s = (s << 1) ^ (s >= (1U<<31) ? CRC32_POLY : 0); - crc_table[i] = s; - } + int i, j; + uint32 s; + for (i = 0; i < 256; i++) + { + for (s = (uint32)i << 24, j = 0; j < 8; ++j) + s = (s << 1) ^ (s >= (1U << 31) ? CRC32_POLY : 0); + crc_table[i] = s; + } } static __forceinline uint32 crc32_update(uint32 crc, uint8 byte) { - return (crc << 8) ^ crc_table[byte ^ (crc >> 24)]; + return (crc << 8) ^ crc_table[byte ^ (crc >> 24)]; } // used in setup, and for huffman that doesn't go fast path static unsigned int bit_reverse(unsigned int n) { - n = ((n & 0xAAAAAAAA) >> 1) | ((n & 0x55555555) << 1); - n = ((n & 0xCCCCCCCC) >> 2) | ((n & 0x33333333) << 2); - n = ((n & 0xF0F0F0F0) >> 4) | ((n & 0x0F0F0F0F) << 4); - n = ((n & 0xFF00FF00) >> 8) | ((n & 0x00FF00FF) << 8); - return (n >> 16) | (n << 16); + n = ((n & 0xAAAAAAAA) >> 1) | ((n & 0x55555555) << 1); + n = ((n & 0xCCCCCCCC) >> 2) | ((n & 0x33333333) << 2); + n = ((n & 0xF0F0F0F0) >> 4) | ((n & 0x0F0F0F0F) << 4); + n = ((n & 0xFF00FF00) >> 8) | ((n & 0x00FF00FF) << 8); + return (n >> 16) | (n << 16); } static float square(float x) { - return x*x; + return x * x; } // this is a weird definition of log2() for which log2(1) = 1, log2(2) = 2, log2(4) = 3 @@ -649,24 +654,24 @@ static float square(float x) // @OPTIMIZE: called multiple times per-packet with "constants"; move to setup static int ilog(int32 n) { - static signed char log2_4[16] = { 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4 }; + static signed char log2_4[16] = {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4}; - if (n < 0) return 0; // signed n returns 0 + if (n < 0) return 0; // signed n returns 0 - // 2 compares if n < 16, 3 compares otherwise (4 if signed or n > 1<<29) - if (n < (1 << 14)) - if (n < (1 << 4)) return 0 + log2_4[n ]; - else if (n < (1 << 9)) return 5 + log2_4[n >> 5]; - else return 10 + log2_4[n >> 10]; - else if (n < (1 << 24)) - if (n < (1 << 19)) return 15 + log2_4[n >> 15]; - else return 20 + log2_4[n >> 20]; - else if (n < (1 << 29)) return 25 + log2_4[n >> 25]; - else return 30 + log2_4[n >> 30]; + // 2 compares if n < 16, 3 compares otherwise (4 if signed or n > 1<<29) + if (n < (1 << 14)) + if (n < (1 << 4)) return 0 + log2_4[n]; + else if (n < (1 << 9)) return 5 + log2_4[n >> 5]; + else return 10 + log2_4[n >> 10]; + else if (n < (1 << 24)) + if (n < (1 << 19)) return 15 + log2_4[n >> 15]; + else return 20 + log2_4[n >> 20]; + else if (n < (1 << 29)) return 25 + log2_4[n >> 25]; + else return 30 + log2_4[n >> 30]; } #ifndef M_PI - #define M_PI 3.14159265358979323846264f // from CRC +#define M_PI 3.14159265358979323846264f // from CRC #endif // code length assigned to a value with no huffman encoding @@ -679,12 +684,12 @@ static int ilog(int32 n) static float float32_unpack(uint32 x) { - // from the specification - uint32 mantissa = x & 0x1fffff; - uint32 sign = x & 0x80000000; - uint32 exp = (x & 0x7fe00000) >> 21; - double res = sign ? -(double)mantissa : (double)mantissa; - return (float) ldexp((float)res, exp-788); + // from the specification + uint32 mantissa = x & 0x1fffff; + uint32 sign = x & 0x80000000; + uint32 exp = (x & 0x7fe00000) >> 21; + double res = sign ? -(double)mantissa : (double)mantissa; + return (float)ldexp((float)res, exp - 788); } @@ -695,85 +700,98 @@ static float float32_unpack(uint32 x) // vorbis allows a huffman table with non-sorted lengths. This // requires a more sophisticated construction, since symbols in // order do not map to huffman codes "in order". -static void add_entry(Codebook *c, uint32 huff_code, int symbol, int count, int len, uint32 *values) +static void add_entry(Codebook* c, uint32 huff_code, int symbol, int count, int len, uint32* values) { - if (!c->sparse) { - c->codewords [symbol] = huff_code; - } else { - c->codewords [count] = huff_code; - c->codeword_lengths[count] = len; - values [count] = symbol; - } + if (!c->sparse) + { + c->codewords[symbol] = huff_code; + } + else + { + c->codewords[count] = huff_code; + c->codeword_lengths[count] = len; + values[count] = symbol; + } } -static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values) +static int compute_codewords(Codebook* c, uint8* len, int n, uint32* values) { - int i,k,m=0; - uint32 available[32]; + int i, k, m = 0; + uint32 available[32]; - memset(available, 0, sizeof(available)); - // find the first entry - for (k=0; k < n; ++k) if (len[k] < NO_CODE) break; - if (k == n) { assert(c->sorted_entries == 0); return TRUE; } - // add to the list - add_entry(c, 0, k, m++, len[k], values); - // add all available leaves - for (i=1; i <= len[k]; ++i) - available[i] = 1U << (32-i); - // note that the above code treats the first case specially, - // but it's really the same as the following code, so they - // could probably be combined (except the initial code is 0, - // and I use 0 in available[] to mean 'empty') - for (i=k+1; i < n; ++i) { - uint32 res; - int z = len[i], y; - if (z == NO_CODE) continue; - // find lowest available leaf (should always be earliest, - // which is what the specification calls for) - // note that this property, and the fact we can never have - // more than one free leaf at a given level, isn't totally - // trivial to prove, but it seems true and the assert never - // fires, so! - while (z > 0 && !available[z]) --z; - if (z == 0) { return FALSE; } - res = available[z]; - assert(z >= 0 && z < 32); - available[z] = 0; - add_entry(c, bit_reverse(res), i, m++, len[i], values); - // propogate availability up the tree - if (z != len[i]) { - assert(len[i] >= 0 && len[i] < 32); - for (y=len[i]; y > z; --y) { - assert(available[y] == 0); - available[y] = res + (1 << (32-y)); - } - } - } - return TRUE; + memset(available, 0, sizeof(available)); + // find the first entry + for (k = 0; k < n; ++k) if (len[k] < NO_CODE) break; + if (k == n) + { + assert(c->sorted_entries == 0); + return TRUE; + } + // add to the list + add_entry(c, 0, k, m++, len[k], values); + // add all available leaves + for (i = 1; i <= len[k]; ++i) + available[i] = 1U << (32 - i); + // note that the above code treats the first case specially, + // but it's really the same as the following code, so they + // could probably be combined (except the initial code is 0, + // and I use 0 in available[] to mean 'empty') + for (i = k + 1; i < n; ++i) + { + uint32 res; + int z = len[i], y; + if (z == NO_CODE) continue; + // find lowest available leaf (should always be earliest, + // which is what the specification calls for) + // note that this property, and the fact we can never have + // more than one free leaf at a given level, isn't totally + // trivial to prove, but it seems true and the assert never + // fires, so! + while (z > 0 && !available[z]) --z; + if (z == 0) { return FALSE; } + res = available[z]; + assert(z >= 0 && z < 32); + available[z] = 0; + add_entry(c, bit_reverse(res), i, m++, len[i], values); + // propogate availability up the tree + if (z != len[i]) + { + assert(len[i] >= 0 && len[i] < 32); + for (y = len[i]; y > z; --y) + { + assert(available[y] == 0); + available[y] = res + (1 << (32 - y)); + } + } + } + return TRUE; } // accelerated huffman table allows fast O(1) match of all symbols // of length <= STB_VORBIS_FAST_HUFFMAN_LENGTH -static void compute_accelerated_huffman(Codebook *c) +static void compute_accelerated_huffman(Codebook* c) { - int i, len; - for (i=0; i < FAST_HUFFMAN_TABLE_SIZE; ++i) - c->fast_huffman[i] = -1; + int i, len; + for (i = 0; i < FAST_HUFFMAN_TABLE_SIZE; ++i) + c->fast_huffman[i] = -1; - len = c->sparse ? c->sorted_entries : c->entries; - #ifdef STB_VORBIS_FAST_HUFFMAN_SHORT - if (len > 32767) len = 32767; // largest possible value we can encode! - #endif - for (i=0; i < len; ++i) { - if (c->codeword_lengths[i] <= STB_VORBIS_FAST_HUFFMAN_LENGTH) { - uint32 z = c->sparse ? bit_reverse(c->sorted_codewords[i]) : c->codewords[i]; - // set table entries for all bit combinations in the higher bits - while (z < FAST_HUFFMAN_TABLE_SIZE) { - c->fast_huffman[z] = i; - z += 1 << c->codeword_lengths[i]; - } - } - } + len = c->sparse ? c->sorted_entries : c->entries; +#ifdef STB_VORBIS_FAST_HUFFMAN_SHORT + if (len > 32767) len = 32767; // largest possible value we can encode! +#endif + for (i = 0; i < len; ++i) + { + if (c->codeword_lengths[i] <= STB_VORBIS_FAST_HUFFMAN_LENGTH) + { + uint32 z = c->sparse ? bit_reverse(c->sorted_codewords[i]) : c->codewords[i]; + // set table entries for all bit combinations in the higher bits + while (z < FAST_HUFFMAN_TABLE_SIZE) + { + c->fast_huffman[z] = i; + z += 1 << c->codeword_lengths[i]; + } + } + } } #ifdef _MSC_VER @@ -782,167 +800,194 @@ static void compute_accelerated_huffman(Codebook *c) #define STBV_CDECL #endif -static int STBV_CDECL uint32_compare(const void *p, const void *q) +static int STBV_CDECL uint32_compare(const void* p, const void* q) { - uint32 x = * (uint32 *) p; - uint32 y = * (uint32 *) q; - return x < y ? -1 : x > y; + uint32 x = *(uint32*)p; + uint32 y = *(uint32*)q; + return x < y ? -1 : x > y; } -static int include_in_sort(Codebook *c, uint8 len) +static int include_in_sort(Codebook* c, uint8 len) { - if (c->sparse) { assert(len != NO_CODE); return TRUE; } - if (len == NO_CODE) return FALSE; - if (len > STB_VORBIS_FAST_HUFFMAN_LENGTH) return TRUE; - return FALSE; + if (c->sparse) + { + assert(len != NO_CODE); + return TRUE; + } + if (len == NO_CODE) return FALSE; + if (len > STB_VORBIS_FAST_HUFFMAN_LENGTH) return TRUE; + return FALSE; } // if the fast table above doesn't work, we want to binary // search them... need to reverse the bits -static void compute_sorted_huffman(Codebook *c, uint8 *lengths, uint32 *values) +static void compute_sorted_huffman(Codebook* c, uint8* lengths, uint32* values) { - int i, len; - // build a list of all the entries - // OPTIMIZATION: don't include the short ones, since they'll be caught by FAST_HUFFMAN. - // this is kind of a frivolous optimization--I don't see any performance improvement, - // but it's like 4 extra lines of code, so. - if (!c->sparse) { - int k = 0; - for (i=0; i < c->entries; ++i) - if (include_in_sort(c, lengths[i])) - c->sorted_codewords[k++] = bit_reverse(c->codewords[i]); - assert(k == c->sorted_entries); - } else { - for (i=0; i < c->sorted_entries; ++i) - c->sorted_codewords[i] = bit_reverse(c->codewords[i]); - } + int i, len; + // build a list of all the entries + // OPTIMIZATION: don't include the short ones, since they'll be caught by FAST_HUFFMAN. + // this is kind of a frivolous optimization--I don't see any performance improvement, + // but it's like 4 extra lines of code, so. + if (!c->sparse) + { + int k = 0; + for (i = 0; i < c->entries; ++i) + if (include_in_sort(c, lengths[i])) + c->sorted_codewords[k++] = bit_reverse(c->codewords[i]); + assert(k == c->sorted_entries); + } + else + { + for (i = 0; i < c->sorted_entries; ++i) + c->sorted_codewords[i] = bit_reverse(c->codewords[i]); + } - qsort(c->sorted_codewords, c->sorted_entries, sizeof(c->sorted_codewords[0]), uint32_compare); - c->sorted_codewords[c->sorted_entries] = 0xffffffff; + qsort(c->sorted_codewords, c->sorted_entries, sizeof(c->sorted_codewords[0]), uint32_compare); + c->sorted_codewords[c->sorted_entries] = 0xffffffff; - len = c->sparse ? c->sorted_entries : c->entries; - // now we need to indicate how they correspond; we could either - // #1: sort a different data structure that says who they correspond to - // #2: for each sorted entry, search the original list to find who corresponds - // #3: for each original entry, find the sorted entry - // #1 requires extra storage, #2 is slow, #3 can use binary search! - for (i=0; i < len; ++i) { - int huff_len = c->sparse ? lengths[values[i]] : lengths[i]; - if (include_in_sort(c,huff_len)) { - uint32 code = bit_reverse(c->codewords[i]); - int x=0, n=c->sorted_entries; - while (n > 1) { - // invariant: sc[x] <= code < sc[x+n] - int m = x + (n >> 1); - if (c->sorted_codewords[m] <= code) { - x = m; - n -= (n>>1); - } else { - n >>= 1; - } - } - assert(c->sorted_codewords[x] == code); - if (c->sparse) { - c->sorted_values[x] = values[i]; - c->codeword_lengths[x] = huff_len; - } else { - c->sorted_values[x] = i; - } - } - } + len = c->sparse ? c->sorted_entries : c->entries; + // now we need to indicate how they correspond; we could either + // #1: sort a different data structure that says who they correspond to + // #2: for each sorted entry, search the original list to find who corresponds + // #3: for each original entry, find the sorted entry + // #1 requires extra storage, #2 is slow, #3 can use binary search! + for (i = 0; i < len; ++i) + { + int huff_len = c->sparse ? lengths[values[i]] : lengths[i]; + if (include_in_sort(c, huff_len)) + { + uint32 code = bit_reverse(c->codewords[i]); + int x = 0, n = c->sorted_entries; + while (n > 1) + { + // invariant: sc[x] <= code < sc[x+n] + int m = x + (n >> 1); + if (c->sorted_codewords[m] <= code) + { + x = m; + n -= (n >> 1); + } + else + { + n >>= 1; + } + } + assert(c->sorted_codewords[x] == code); + if (c->sparse) + { + c->sorted_values[x] = values[i]; + c->codeword_lengths[x] = huff_len; + } + else + { + c->sorted_values[x] = i; + } + } + } } // only run while parsing the header (3 times) -static int vorbis_validate(uint8 *data) +static int vorbis_validate(uint8* data) { - static uint8 vorbis[6] = { 'v', 'o', 'r', 'b', 'i', 's' }; - return memcmp(data, vorbis, 6) == 0; + static uint8 vorbis[6] = {'v', 'o', 'r', 'b', 'i', 's'}; + return memcmp(data, vorbis, 6) == 0; } // called from setup only, once per code book // (formula implied by specification) static int lookup1_values(int entries, int dim) { - int r = (int) floor(exp((float) log((float) entries) / dim)); - if ((int) floor(pow((float) r+1, dim)) <= entries) // (int) cast for MinGW warning; - ++r; // floor() to avoid _ftol() when non-CRT - assert(pow((float) r+1, dim) > entries); - assert((int) floor(pow((float) r, dim)) <= entries); // (int),floor() as above - return r; + int r = (int)floor(exp((float)log((float)entries) / dim)); + if ((int)floor(pow((float)r + 1, dim)) <= entries) // (int) cast for MinGW warning; + ++r; // floor() to avoid _ftol() when non-CRT + assert(pow((float) r+1, dim) > entries); + assert((int) floor(pow((float) r, dim)) <= entries); // (int),floor() as above + return r; } // called twice per file -static void compute_twiddle_factors(int n, float *A, float *B, float *C) +static void compute_twiddle_factors(int n, float* A, float* B, float* C) { - int n4 = n >> 2, n8 = n >> 3; - int k,k2; + int n4 = n >> 2, n8 = n >> 3; + int k, k2; - for (k=k2=0; k < n4; ++k,k2+=2) { - A[k2 ] = (float) cos(4*k*M_PI/n); - A[k2+1] = (float) -sin(4*k*M_PI/n); - B[k2 ] = (float) cos((k2+1)*M_PI/n/2) * 0.5f; - B[k2+1] = (float) sin((k2+1)*M_PI/n/2) * 0.5f; - } - for (k=k2=0; k < n8; ++k,k2+=2) { - C[k2 ] = (float) cos(2*(k2+1)*M_PI/n); - C[k2+1] = (float) -sin(2*(k2+1)*M_PI/n); - } + for (k = k2 = 0; k < n4; ++k, k2 += 2) + { + A[k2] = (float)cos(4 * k * M_PI / n); + A[k2 + 1] = (float)-sin(4 * k * M_PI / n); + B[k2] = (float)cos((k2 + 1) * M_PI / n / 2) * 0.5f; + B[k2 + 1] = (float)sin((k2 + 1) * M_PI / n / 2) * 0.5f; + } + for (k = k2 = 0; k < n8; ++k, k2 += 2) + { + C[k2] = (float)cos(2 * (k2 + 1) * M_PI / n); + C[k2 + 1] = (float)-sin(2 * (k2 + 1) * M_PI / n); + } } -static void compute_window(int n, float *window) +static void compute_window(int n, float* window) { - int n2 = n >> 1, i; - for (i=0; i < n2; ++i) - window[i] = (float) sin(0.5 * M_PI * square((float) sin((i - 0 + 0.5) / n2 * 0.5 * M_PI))); + int n2 = n >> 1, i; + for (i = 0; i < n2; ++i) + window[i] = (float)sin(0.5 * M_PI * square((float)sin((i - 0 + 0.5) / n2 * 0.5 * M_PI))); } -static void compute_bitreverse(int n, uint16 *rev) +static void compute_bitreverse(int n, uint16* rev) { - int ld = ilog(n) - 1; // ilog is off-by-one from normal definitions - int i, n8 = n >> 3; - for (i=0; i < n8; ++i) - rev[i] = (bit_reverse(i) >> (32-ld+3)) << 2; + int ld = ilog(n) - 1; // ilog is off-by-one from normal definitions + int i, n8 = n >> 3; + for (i = 0; i < n8; ++i) + rev[i] = (bit_reverse(i) >> (32 - ld + 3)) << 2; } -static int init_blocksize(vorb *f, int b, int n) +static int init_blocksize(vorb* f, int b, int n) { - int n2 = n >> 1, n4 = n >> 2, n8 = n >> 3; - f->A[b] = (float *) setup_malloc(f, sizeof(float) * n2); - f->B[b] = (float *) setup_malloc(f, sizeof(float) * n2); - f->C[b] = (float *) setup_malloc(f, sizeof(float) * n4); - if (!f->A[b] || !f->B[b] || !f->C[b]) return error(f, VORBIS_outofmem); - compute_twiddle_factors(n, f->A[b], f->B[b], f->C[b]); - f->window[b] = (float *) setup_malloc(f, sizeof(float) * n2); - if (!f->window[b]) return error(f, VORBIS_outofmem); - compute_window(n, f->window[b]); - f->bit_reverse[b] = (uint16 *) setup_malloc(f, sizeof(uint16) * n8); - if (!f->bit_reverse[b]) return error(f, VORBIS_outofmem); - compute_bitreverse(n, f->bit_reverse[b]); - return TRUE; + int n2 = n >> 1, n4 = n >> 2, n8 = n >> 3; + f->A[b] = (float*)setup_malloc(f, sizeof(float) * n2); + f->B[b] = (float*)setup_malloc(f, sizeof(float) * n2); + f->C[b] = (float*)setup_malloc(f, sizeof(float) * n4); + if (!f->A[b] || !f->B[b] || !f->C[b]) return error(f, VORBIS_outofmem); + compute_twiddle_factors(n, f->A[b], f->B[b], f->C[b]); + f->window[b] = (float*)setup_malloc(f, sizeof(float) * n2); + if (!f->window[b]) return error(f, VORBIS_outofmem); + compute_window(n, f->window[b]); + f->bit_reverse[b] = (uint16*)setup_malloc(f, sizeof(uint16) * n8); + if (!f->bit_reverse[b]) return error(f, VORBIS_outofmem); + compute_bitreverse(n, f->bit_reverse[b]); + return TRUE; } -static void neighbors(uint16 *x, int n, int *plow, int *phigh) +static void neighbors(uint16* x, int n, int* plow, int* phigh) { - int low = -1; - int high = 65536; - int i; - for (i=0; i < n; ++i) { - if (x[i] > low && x[i] < x[n]) { *plow = i; low = x[i]; } - if (x[i] < high && x[i] > x[n]) { *phigh = i; high = x[i]; } - } + int low = -1; + int high = 65536; + int i; + for (i = 0; i < n; ++i) + { + if (x[i] > low && x[i] < x[n]) + { + *plow = i; + low = x[i]; + } + if (x[i] < high && x[i] > x[n]) + { + *phigh = i; + high = x[i]; + } + } } // this has been repurposed so y is now the original index instead of y typedef struct { - uint16 x,id; + uint16 x, id; } stbv__floor_ordering; -static int STBV_CDECL point_compare(const void *p, const void *q) +static int STBV_CDECL point_compare(const void* p, const void* q) { - stbv__floor_ordering *a = (stbv__floor_ordering *) p; - stbv__floor_ordering *b = (stbv__floor_ordering *) q; - return a->x < b->x ? -1 : a->x > b->x; + stbv__floor_ordering* a = (stbv__floor_ordering*)p; + stbv__floor_ordering* b = (stbv__floor_ordering*)q; + return a->x < b->x ? -1 : a->x > b->x; } // @@ -952,374 +997,427 @@ static int STBV_CDECL point_compare(const void *p, const void *q) #if defined(STB_VORBIS_NO_STDIO) #define USE_MEMORY(z) TRUE #else - #define USE_MEMORY(z) ((z)->stream) +#define USE_MEMORY(z) ((z)->stream) #endif -static uint8 get8(vorb *z) +static uint8 get8(vorb* z) { - if (USE_MEMORY(z)) { - if (z->stream >= z->stream_end) { z->eof = TRUE; return 0; } - return *z->stream++; - } + if (USE_MEMORY(z)) + { + if (z->stream >= z->stream_end) + { + z->eof = TRUE; + return 0; + } + return *z->stream++; + } - #ifndef STB_VORBIS_NO_STDIO - { - int c = fgetc(z->f); - if (c == EOF) { z->eof = TRUE; return 0; } - return c; - } - #endif +#ifndef STB_VORBIS_NO_STDIO + { + int c = fgetc(z->f); + if (c == EOF) + { + z->eof = TRUE; + return 0; + } + return c; + } +#endif } -static uint32 get32(vorb *f) +static uint32 get32(vorb* f) { - uint32 x; - x = get8(f); - x += get8(f) << 8; - x += get8(f) << 16; - x += (uint32) get8(f) << 24; - return x; + uint32 x; + x = get8(f); + x += get8(f) << 8; + x += get8(f) << 16; + x += (uint32)get8(f) << 24; + return x; } -static int getn(vorb *z, uint8 *data, int n) +static int getn(vorb* z, uint8* data, int n) { - if (USE_MEMORY(z)) { - if (z->stream+n > z->stream_end) { z->eof = 1; return 0; } - memcpy(data, z->stream, n); - z->stream += n; - return 1; - } + if (USE_MEMORY(z)) + { + if (z->stream + n > z->stream_end) + { + z->eof = 1; + return 0; + } + memcpy(data, z->stream, n); + z->stream += n; + return 1; + } - #ifndef STB_VORBIS_NO_STDIO - if (fread(data, n, 1, z->f) == 1) - return 1; - else { - z->eof = 1; - return 0; - } - #endif +#ifndef STB_VORBIS_NO_STDIO + if (fread(data, n, 1, z->f) == 1) + return 1; + else + { + z->eof = 1; + return 0; + } +#endif } -static void skip(vorb *z, int n) +static void skip(vorb* z, int n) { - if (USE_MEMORY(z)) { - z->stream += n; - if (z->stream >= z->stream_end) z->eof = 1; - return; - } - #ifndef STB_VORBIS_NO_STDIO - { - long x = ftell(z->f); - fseek(z->f, x+n, SEEK_SET); - } - #endif + if (USE_MEMORY(z)) + { + z->stream += n; + if (z->stream >= z->stream_end) z->eof = 1; + return; + } +#ifndef STB_VORBIS_NO_STDIO + { + long x = ftell(z->f); + fseek(z->f, x + n, SEEK_SET); + } +#endif } -static int set_file_offset(stb_vorbis *f, unsigned int loc) +static int set_file_offset(stb_vorbis* f, unsigned int loc) { - #ifndef STB_VORBIS_NO_PUSHDATA_API - if (f->push_mode) return 0; - #endif - f->eof = 0; - if (USE_MEMORY(f)) { - if (f->stream_start + loc >= f->stream_end || f->stream_start + loc < f->stream_start) { - f->stream = f->stream_end; - f->eof = 1; - return 0; - } else { - f->stream = f->stream_start + loc; - return 1; - } - } - #ifndef STB_VORBIS_NO_STDIO - if (loc + f->f_start < loc || loc >= 0x80000000) { - loc = 0x7fffffff; - f->eof = 1; - } else { - loc += f->f_start; - } - if (!fseek(f->f, loc, SEEK_SET)) - return 1; - f->eof = 1; - fseek(f->f, f->f_start, SEEK_END); - return 0; - #endif +#ifndef STB_VORBIS_NO_PUSHDATA_API + if (f->push_mode) return 0; +#endif + f->eof = 0; + if (USE_MEMORY(f)) + { + if (f->stream_start + loc >= f->stream_end || f->stream_start + loc < f->stream_start) + { + f->stream = f->stream_end; + f->eof = 1; + return 0; + } + else + { + f->stream = f->stream_start + loc; + return 1; + } + } +#ifndef STB_VORBIS_NO_STDIO + if (loc + f->f_start < loc || loc >= 0x80000000) + { + loc = 0x7fffffff; + f->eof = 1; + } + else + { + loc += f->f_start; + } + if (!fseek(f->f, loc, SEEK_SET)) + return 1; + f->eof = 1; + fseek(f->f, f->f_start, SEEK_END); + return 0; +#endif } -static uint8 ogg_page_header[4] = { 0x4f, 0x67, 0x67, 0x53 }; +static uint8 ogg_page_header[4] = {0x4f, 0x67, 0x67, 0x53}; -static int capture_pattern(vorb *f) +static int capture_pattern(vorb* f) { - if (0x4f != get8(f)) return FALSE; - if (0x67 != get8(f)) return FALSE; - if (0x67 != get8(f)) return FALSE; - if (0x53 != get8(f)) return FALSE; - return TRUE; + if (0x4f != get8(f)) return FALSE; + if (0x67 != get8(f)) return FALSE; + if (0x67 != get8(f)) return FALSE; + if (0x53 != get8(f)) return FALSE; + return TRUE; } #define PAGEFLAG_continued_packet 1 #define PAGEFLAG_first_page 2 #define PAGEFLAG_last_page 4 -static int start_page_no_capturepattern(vorb *f) +static int start_page_no_capturepattern(vorb* f) { - uint32 loc0,loc1,n; - // stream structure version - if (0 != get8(f)) return error(f, VORBIS_invalid_stream_structure_version); - // header flag - f->page_flag = get8(f); - // absolute granule position - loc0 = get32(f); - loc1 = get32(f); - // @TODO: validate loc0,loc1 as valid positions? - // stream serial number -- vorbis doesn't interleave, so discard - get32(f); - //if (f->serial != get32(f)) return error(f, VORBIS_incorrect_stream_serial_number); - // page sequence number - n = get32(f); - f->last_page = n; - // CRC32 - get32(f); - // page_segments - f->segment_count = get8(f); - if (!getn(f, f->segments, f->segment_count)) - return error(f, VORBIS_unexpected_eof); - // assume we _don't_ know any the sample position of any segments - f->end_seg_with_known_loc = -2; - if (loc0 != ~0U || loc1 != ~0U) { - int i; - // determine which packet is the last one that will complete - for (i=f->segment_count-1; i >= 0; --i) - if (f->segments[i] < 255) - break; - // 'i' is now the index of the _last_ segment of a packet that ends - if (i >= 0) { - f->end_seg_with_known_loc = i; - f->known_loc_for_packet = loc0; - } - } - if (f->first_decode) { - int i,len; - ProbedPage p; - len = 0; - for (i=0; i < f->segment_count; ++i) - len += f->segments[i]; - len += 27 + f->segment_count; - p.page_start = f->first_audio_page_offset; - p.page_end = p.page_start + len; - p.last_decoded_sample = loc0; - f->p_first = p; - } - f->next_seg = 0; - return TRUE; + uint32 loc0, loc1, n; + // stream structure version + if (0 != get8(f)) return error(f, VORBIS_invalid_stream_structure_version); + // header flag + f->page_flag = get8(f); + // absolute granule position + loc0 = get32(f); + loc1 = get32(f); + // @TODO: validate loc0,loc1 as valid positions? + // stream serial number -- vorbis doesn't interleave, so discard + get32(f); + //if (f->serial != get32(f)) return error(f, VORBIS_incorrect_stream_serial_number); + // page sequence number + n = get32(f); + f->last_page = n; + // CRC32 + get32(f); + // page_segments + f->segment_count = get8(f); + if (!getn(f, f->segments, f->segment_count)) + return error(f, VORBIS_unexpected_eof); + // assume we _don't_ know any the sample position of any segments + f->end_seg_with_known_loc = -2; + if (loc0 != ~0U || loc1 != ~0U) + { + int i; + // determine which packet is the last one that will complete + for (i = f->segment_count - 1; i >= 0; --i) + if (f->segments[i] < 255) + break; + // 'i' is now the index of the _last_ segment of a packet that ends + if (i >= 0) + { + f->end_seg_with_known_loc = i; + f->known_loc_for_packet = loc0; + } + } + if (f->first_decode) + { + int i, len; + ProbedPage p; + len = 0; + for (i = 0; i < f->segment_count; ++i) + len += f->segments[i]; + len += 27 + f->segment_count; + p.page_start = f->first_audio_page_offset; + p.page_end = p.page_start + len; + p.last_decoded_sample = loc0; + f->p_first = p; + } + f->next_seg = 0; + return TRUE; } -static int start_page(vorb *f) +static int start_page(vorb* f) { - if (!capture_pattern(f)) return error(f, VORBIS_missing_capture_pattern); - return start_page_no_capturepattern(f); + if (!capture_pattern(f)) return error(f, VORBIS_missing_capture_pattern); + return start_page_no_capturepattern(f); } -static int start_packet(vorb *f) +static int start_packet(vorb* f) { - while (f->next_seg == -1) { - if (!start_page(f)) return FALSE; - if (f->page_flag & PAGEFLAG_continued_packet) - return error(f, VORBIS_continued_packet_flag_invalid); - } - f->last_seg = FALSE; - f->valid_bits = 0; - f->packet_bytes = 0; - f->bytes_in_seg = 0; - // f->next_seg is now valid - return TRUE; + while (f->next_seg == -1) + { + if (!start_page(f)) return FALSE; + if (f->page_flag & PAGEFLAG_continued_packet) + return error(f, VORBIS_continued_packet_flag_invalid); + } + f->last_seg = FALSE; + f->valid_bits = 0; + f->packet_bytes = 0; + f->bytes_in_seg = 0; + // f->next_seg is now valid + return TRUE; } -static int maybe_start_packet(vorb *f) +static int maybe_start_packet(vorb* f) { - if (f->next_seg == -1) { - int x = get8(f); - if (f->eof) return FALSE; // EOF at page boundary is not an error! - if (0x4f != x ) return error(f, VORBIS_missing_capture_pattern); - if (0x67 != get8(f)) return error(f, VORBIS_missing_capture_pattern); - if (0x67 != get8(f)) return error(f, VORBIS_missing_capture_pattern); - if (0x53 != get8(f)) return error(f, VORBIS_missing_capture_pattern); - if (!start_page_no_capturepattern(f)) return FALSE; - if (f->page_flag & PAGEFLAG_continued_packet) { - // set up enough state that we can read this packet if we want, - // e.g. during recovery - f->last_seg = FALSE; - f->bytes_in_seg = 0; - return error(f, VORBIS_continued_packet_flag_invalid); - } - } - return start_packet(f); + if (f->next_seg == -1) + { + int x = get8(f); + if (f->eof) return FALSE; // EOF at page boundary is not an error! + if (0x4f != x) return error(f, VORBIS_missing_capture_pattern); + if (0x67 != get8(f)) return error(f, VORBIS_missing_capture_pattern); + if (0x67 != get8(f)) return error(f, VORBIS_missing_capture_pattern); + if (0x53 != get8(f)) return error(f, VORBIS_missing_capture_pattern); + if (!start_page_no_capturepattern(f)) return FALSE; + if (f->page_flag & PAGEFLAG_continued_packet) + { + // set up enough state that we can read this packet if we want, + // e.g. during recovery + f->last_seg = FALSE; + f->bytes_in_seg = 0; + return error(f, VORBIS_continued_packet_flag_invalid); + } + } + return start_packet(f); } -static int next_segment(vorb *f) +static int next_segment(vorb* f) { - int len; - if (f->last_seg) return 0; - if (f->next_seg == -1) { - f->last_seg_which = f->segment_count-1; // in case start_page fails - if (!start_page(f)) { f->last_seg = 1; return 0; } - if (!(f->page_flag & PAGEFLAG_continued_packet)) return error(f, VORBIS_continued_packet_flag_invalid); - } - len = f->segments[f->next_seg++]; - if (len < 255) { - f->last_seg = TRUE; - f->last_seg_which = f->next_seg-1; - } - if (f->next_seg >= f->segment_count) - f->next_seg = -1; - assert(f->bytes_in_seg == 0); - f->bytes_in_seg = len; - return len; + int len; + if (f->last_seg) return 0; + if (f->next_seg == -1) + { + f->last_seg_which = f->segment_count - 1; // in case start_page fails + if (!start_page(f)) + { + f->last_seg = 1; + return 0; + } + if (!(f->page_flag & PAGEFLAG_continued_packet)) return error(f, VORBIS_continued_packet_flag_invalid); + } + len = f->segments[f->next_seg++]; + if (len < 255) + { + f->last_seg = TRUE; + f->last_seg_which = f->next_seg - 1; + } + if (f->next_seg >= f->segment_count) + f->next_seg = -1; + assert(f->bytes_in_seg == 0); + f->bytes_in_seg = len; + return len; } #define EOP (-1) #define INVALID_BITS (-1) -static int get8_packet_raw(vorb *f) +static int get8_packet_raw(vorb* f) { - if (!f->bytes_in_seg) { // CLANG! - if (f->last_seg) return EOP; - else if (!next_segment(f)) return EOP; - } - assert(f->bytes_in_seg > 0); - --f->bytes_in_seg; - ++f->packet_bytes; - return get8(f); + if (!f->bytes_in_seg) + { + // CLANG! + if (f->last_seg) return EOP; + else if (!next_segment(f)) return EOP; + } + assert(f->bytes_in_seg > 0); + --f->bytes_in_seg; + ++f->packet_bytes; + return get8(f); } -static int get8_packet(vorb *f) +static int get8_packet(vorb* f) { - int x = get8_packet_raw(f); - f->valid_bits = 0; - return x; + int x = get8_packet_raw(f); + f->valid_bits = 0; + return x; } -static void flush_packet(vorb *f) +static void flush_packet(vorb* f) { - while (get8_packet_raw(f) != EOP); + while (get8_packet_raw(f) != EOP); } // @OPTIMIZE: this is the secondary bit decoder, so it's probably not as important // as the huffman decoder? -static uint32 get_bits(vorb *f, int n) +static uint32 get_bits(vorb* f, int n) { - uint32 z; + uint32 z; - if (f->valid_bits < 0) return 0; - if (f->valid_bits < n) { - if (n > 24) { - // the accumulator technique below would not work correctly in this case - z = get_bits(f, 24); - z += get_bits(f, n-24) << 24; - return z; - } - if (f->valid_bits == 0) f->acc = 0; - while (f->valid_bits < n) { - int z = get8_packet_raw(f); - if (z == EOP) { - f->valid_bits = INVALID_BITS; - return 0; - } - f->acc += z << f->valid_bits; - f->valid_bits += 8; - } - } - if (f->valid_bits < 0) return 0; - z = f->acc & ((1 << n)-1); - f->acc >>= n; - f->valid_bits -= n; - return z; + if (f->valid_bits < 0) return 0; + if (f->valid_bits < n) + { + if (n > 24) + { + // the accumulator technique below would not work correctly in this case + z = get_bits(f, 24); + z += get_bits(f, n - 24) << 24; + return z; + } + if (f->valid_bits == 0) f->acc = 0; + while (f->valid_bits < n) + { + int z = get8_packet_raw(f); + if (z == EOP) + { + f->valid_bits = INVALID_BITS; + return 0; + } + f->acc += z << f->valid_bits; + f->valid_bits += 8; + } + } + if (f->valid_bits < 0) return 0; + z = f->acc & ((1 << n) - 1); + f->acc >>= n; + f->valid_bits -= n; + return z; } // @OPTIMIZE: primary accumulator for huffman // expand the buffer to as many bits as possible without reading off end of packet // it might be nice to allow f->valid_bits and f->acc to be stored in registers, // e.g. cache them locally and decode locally -static __forceinline void prep_huffman(vorb *f) +static __forceinline void prep_huffman(vorb* f) { - if (f->valid_bits <= 24) { - if (f->valid_bits == 0) f->acc = 0; - do { - int z; - if (f->last_seg && !f->bytes_in_seg) return; - z = get8_packet_raw(f); - if (z == EOP) return; - f->acc += (unsigned) z << f->valid_bits; - f->valid_bits += 8; - } while (f->valid_bits <= 24); - } + if (f->valid_bits <= 24) + { + if (f->valid_bits == 0) f->acc = 0; + do + { + int z; + if (f->last_seg && !f->bytes_in_seg) return; + z = get8_packet_raw(f); + if (z == EOP) return; + f->acc += (unsigned)z << f->valid_bits; + f->valid_bits += 8; + } + while (f->valid_bits <= 24); + } } enum { - VORBIS_packet_id = 1, - VORBIS_packet_comment = 3, - VORBIS_packet_setup = 5 + VORBIS_packet_id = 1, + VORBIS_packet_comment = 3, + VORBIS_packet_setup = 5 }; -static int codebook_decode_scalar_raw(vorb *f, Codebook *c) +static int codebook_decode_scalar_raw(vorb* f, Codebook* c) { - int i; - prep_huffman(f); + int i; + prep_huffman(f); - if (c->codewords == NULL && c->sorted_codewords == NULL) - return -1; + if (c->codewords == NULL && c->sorted_codewords == NULL) + return -1; - // cases to use binary search: sorted_codewords && !c->codewords - // sorted_codewords && c->entries > 8 - if (c->entries > 8 ? c->sorted_codewords!=NULL : !c->codewords) { - // binary search - uint32 code = bit_reverse(f->acc); - int x=0, n=c->sorted_entries, len; + // cases to use binary search: sorted_codewords && !c->codewords + // sorted_codewords && c->entries > 8 + if (c->entries > 8 ? c->sorted_codewords != NULL : !c->codewords) + { + // binary search + uint32 code = bit_reverse(f->acc); + int x = 0, n = c->sorted_entries, len; - while (n > 1) { - // invariant: sc[x] <= code < sc[x+n] - int m = x + (n >> 1); - if (c->sorted_codewords[m] <= code) { - x = m; - n -= (n>>1); - } else { - n >>= 1; - } - } - // x is now the sorted index - if (!c->sparse) x = c->sorted_values[x]; - // x is now sorted index if sparse, or symbol otherwise - len = c->codeword_lengths[x]; - if (f->valid_bits >= len) { - f->acc >>= len; - f->valid_bits -= len; - return x; - } + while (n > 1) + { + // invariant: sc[x] <= code < sc[x+n] + int m = x + (n >> 1); + if (c->sorted_codewords[m] <= code) + { + x = m; + n -= (n >> 1); + } + else + { + n >>= 1; + } + } + // x is now the sorted index + if (!c->sparse) x = c->sorted_values[x]; + // x is now sorted index if sparse, or symbol otherwise + len = c->codeword_lengths[x]; + if (f->valid_bits >= len) + { + f->acc >>= len; + f->valid_bits -= len; + return x; + } - f->valid_bits = 0; - return -1; - } + f->valid_bits = 0; + return -1; + } - // if small, linear search - assert(!c->sparse); - for (i=0; i < c->entries; ++i) { - if (c->codeword_lengths[i] == NO_CODE) continue; - if (c->codewords[i] == (f->acc & ((1 << c->codeword_lengths[i])-1))) { - if (f->valid_bits >= c->codeword_lengths[i]) { - f->acc >>= c->codeword_lengths[i]; - f->valid_bits -= c->codeword_lengths[i]; - return i; - } - f->valid_bits = 0; - return -1; - } - } + // if small, linear search + assert(!c->sparse); + for (i = 0; i < c->entries; ++i) + { + if (c->codeword_lengths[i] == NO_CODE) continue; + if (c->codewords[i] == (f->acc & ((1 << c->codeword_lengths[i]) - 1))) + { + if (f->valid_bits >= c->codeword_lengths[i]) + { + f->acc >>= c->codeword_lengths[i]; + f->valid_bits -= c->codeword_lengths[i]; + return i; + } + f->valid_bits = 0; + return -1; + } + } - error(f, VORBIS_invalid_stream); - f->valid_bits = 0; - return -1; + error(f, VORBIS_invalid_stream); + f->valid_bits = 0; + return -1; } #ifndef STB_VORBIS_NO_INLINE_DECODE @@ -1366,47 +1464,47 @@ static int codebook_decode_scalar(vorb *f, Codebook *c) if (c->sparse) var = c->sorted_values[var]; #ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK - #define DECODE_VQ(var,f,c) DECODE_RAW(var,f,c) +#define DECODE_VQ(var,f,c) DECODE_RAW(var,f,c) #else #define DECODE_VQ(var,f,c) DECODE(var,f,c) #endif - - - - // CODEBOOK_ELEMENT_FAST is an optimization for the CODEBOOK_FLOATS case // where we avoid one addition #define CODEBOOK_ELEMENT(c,off) (c->multiplicands[off]) #define CODEBOOK_ELEMENT_FAST(c,off) (c->multiplicands[off]) #define CODEBOOK_ELEMENT_BASE(c) (0) -static int codebook_decode_start(vorb *f, Codebook *c) +static int codebook_decode_start(vorb* f, Codebook* c) { - int z = -1; + int z = -1; - // type 0 is only legal in a scalar context - if (c->lookup_type == 0) - error(f, VORBIS_invalid_stream); - else { - DECODE_VQ(z,f,c); - if (c->sparse) assert(z < c->sorted_entries); - if (z < 0) { // check for EOP - if (!f->bytes_in_seg) - if (f->last_seg) - return z; - error(f, VORBIS_invalid_stream); - } - } - return z; + // type 0 is only legal in a scalar context + if (c->lookup_type == 0) + error(f, VORBIS_invalid_stream); + else + { + DECODE_VQ(z, f, c); + if (c->sparse) + assert(z < c->sorted_entries); + if (z < 0) + { + // check for EOP + if (!f->bytes_in_seg) + if (f->last_seg) + return z; + error(f, VORBIS_invalid_stream); + } + } + return z; } -static int codebook_decode(vorb *f, Codebook *c, float *output, int len) +static int codebook_decode(vorb* f, Codebook* c, float* output, int len) { - int i,z = codebook_decode_start(f,c); - if (z < 0) return FALSE; - if (len > c->dimensions) len = c->dimensions; + int i, z = codebook_decode_start(f, c); + if (z < 0) return FALSE; + if (len > c->dimensions) len = c->dimensions; #ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK if (c->lookup_type == 1) { @@ -1423,30 +1521,35 @@ static int codebook_decode(vorb *f, Codebook *c, float *output, int len) } #endif - z *= c->dimensions; - if (c->sequence_p) { - float last = CODEBOOK_ELEMENT_BASE(c); - for (i=0; i < len; ++i) { - float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; - output[i] += val; - last = val + c->minimum_value; - } - } else { - float last = CODEBOOK_ELEMENT_BASE(c); - for (i=0; i < len; ++i) { - output[i] += CODEBOOK_ELEMENT_FAST(c,z+i) + last; - } - } + z *= c->dimensions; + if (c->sequence_p) + { + float last = CODEBOOK_ELEMENT_BASE(c); + for (i = 0; i < len; ++i) + { + float val = CODEBOOK_ELEMENT_FAST(c, z+i) + last; + output[i] += val; + last = val + c->minimum_value; + } + } + else + { + float last = CODEBOOK_ELEMENT_BASE(c); + for (i = 0; i < len; ++i) + { + output[i] += CODEBOOK_ELEMENT_FAST(c, z+i) + last; + } + } - return TRUE; + return TRUE; } -static int codebook_decode_step(vorb *f, Codebook *c, float *output, int len, int step) +static int codebook_decode_step(vorb* f, Codebook* c, float* output, int len, int step) { - int i,z = codebook_decode_start(f,c); - float last = CODEBOOK_ELEMENT_BASE(c); - if (z < 0) return FALSE; - if (len > c->dimensions) len = c->dimensions; + int i, z = codebook_decode_start(f, c); + float last = CODEBOOK_ELEMENT_BASE(c); + if (z < 0) return FALSE; + if (len > c->dimensions) len = c->dimensions; #ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK if (c->lookup_type == 1) { @@ -1462,46 +1565,51 @@ static int codebook_decode_step(vorb *f, Codebook *c, float *output, int len, in } #endif - z *= c->dimensions; - for (i=0; i < len; ++i) { - float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; - output[i*step] += val; - if (c->sequence_p) last = val; - } + z *= c->dimensions; + for (i = 0; i < len; ++i) + { + float val = CODEBOOK_ELEMENT_FAST(c, z+i) + last; + output[i * step] += val; + if (c->sequence_p) last = val; + } - return TRUE; + return TRUE; } -static int codebook_decode_deinterleave_repeat(vorb *f, Codebook *c, float **outputs, int ch, int *c_inter_p, int *p_inter_p, int len, int total_decode) +static int codebook_decode_deinterleave_repeat(vorb* f, Codebook* c, float** outputs, int ch, int* c_inter_p, + int* p_inter_p, int len, int total_decode) { - int c_inter = *c_inter_p; - int p_inter = *p_inter_p; - int i,z, effective = c->dimensions; + int c_inter = *c_inter_p; + int p_inter = *p_inter_p; + int i, z, effective = c->dimensions; - // type 0 is only legal in a scalar context - if (c->lookup_type == 0) return error(f, VORBIS_invalid_stream); + // type 0 is only legal in a scalar context + if (c->lookup_type == 0) return error(f, VORBIS_invalid_stream); - while (total_decode > 0) { - float last = CODEBOOK_ELEMENT_BASE(c); - DECODE_VQ(z,f,c); - #ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK - assert(!c->sparse || z < c->sorted_entries); - #endif - if (z < 0) { - if (!f->bytes_in_seg) - if (f->last_seg) return FALSE; - return error(f, VORBIS_invalid_stream); - } + while (total_decode > 0) + { + float last = CODEBOOK_ELEMENT_BASE(c); + DECODE_VQ(z, f, c); +#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK + assert(!c->sparse || z < c->sorted_entries); +#endif + if (z < 0) + { + if (!f->bytes_in_seg) + if (f->last_seg) return FALSE; + return error(f, VORBIS_invalid_stream); + } - // if this will take us off the end of the buffers, stop short! - // we check by computing the length of the virtual interleaved - // buffer (len*ch), our current offset within it (p_inter*ch)+(c_inter), - // and the length we'll be using (effective) - if (c_inter + p_inter*ch + effective > len * ch) { - effective = len*ch - (p_inter*ch - c_inter); - } + // if this will take us off the end of the buffers, stop short! + // we check by computing the length of the virtual interleaved + // buffer (len*ch), our current offset within it (p_inter*ch)+(c_inter), + // and the length we'll be using (effective) + if (c_inter + p_inter * ch + effective > len * ch) + { + effective = len * ch - (p_inter * ch - c_inter); + } - #ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK +#ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK if (c->lookup_type == 1) { int div = 1; for (i=0; i < effective; ++i) { @@ -1514,111 +1622,124 @@ static int codebook_decode_deinterleave_repeat(vorb *f, Codebook *c, float **out div *= c->lookup_values; } } else - #endif - { - z *= c->dimensions; - if (c->sequence_p) { - for (i=0; i < effective; ++i) { - float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; - if (outputs[c_inter]) - outputs[c_inter][p_inter] += val; - if (++c_inter == ch) { c_inter = 0; ++p_inter; } - last = val; - } - } else { - for (i=0; i < effective; ++i) { - float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; - if (outputs[c_inter]) - outputs[c_inter][p_inter] += val; - if (++c_inter == ch) { c_inter = 0; ++p_inter; } - } - } - } +#endif + { + z *= c->dimensions; + if (c->sequence_p) + { + for (i = 0; i < effective; ++i) + { + float val = CODEBOOK_ELEMENT_FAST(c, z+i) + last; + if (outputs[c_inter]) + outputs[c_inter][p_inter] += val; + if (++c_inter == ch) + { + c_inter = 0; + ++p_inter; + } + last = val; + } + } + else + { + for (i = 0; i < effective; ++i) + { + float val = CODEBOOK_ELEMENT_FAST(c, z+i) + last; + if (outputs[c_inter]) + outputs[c_inter][p_inter] += val; + if (++c_inter == ch) + { + c_inter = 0; + ++p_inter; + } + } + } + } - total_decode -= effective; - } - *c_inter_p = c_inter; - *p_inter_p = p_inter; - return TRUE; + total_decode -= effective; + } + *c_inter_p = c_inter; + *p_inter_p = p_inter; + return TRUE; } static int predict_point(int x, int x0, int x1, int y0, int y1) { - int dy = y1 - y0; - int adx = x1 - x0; - // @OPTIMIZE: force int division to round in the right direction... is this necessary on x86? - int err = abs(dy) * (x - x0); - int off = err / adx; - return dy < 0 ? y0 - off : y0 + off; + int dy = y1 - y0; + int adx = x1 - x0; + // @OPTIMIZE: force int division to round in the right direction... is this necessary on x86? + int err = abs(dy) * (x - x0); + int off = err / adx; + return dy < 0 ? y0 - off : y0 + off; } // the following table is block-copied from the specification static float inverse_db_table[256] = { - 1.0649863e-07f, 1.1341951e-07f, 1.2079015e-07f, 1.2863978e-07f, - 1.3699951e-07f, 1.4590251e-07f, 1.5538408e-07f, 1.6548181e-07f, - 1.7623575e-07f, 1.8768855e-07f, 1.9988561e-07f, 2.1287530e-07f, - 2.2670913e-07f, 2.4144197e-07f, 2.5713223e-07f, 2.7384213e-07f, - 2.9163793e-07f, 3.1059021e-07f, 3.3077411e-07f, 3.5226968e-07f, - 3.7516214e-07f, 3.9954229e-07f, 4.2550680e-07f, 4.5315863e-07f, - 4.8260743e-07f, 5.1396998e-07f, 5.4737065e-07f, 5.8294187e-07f, - 6.2082472e-07f, 6.6116941e-07f, 7.0413592e-07f, 7.4989464e-07f, - 7.9862701e-07f, 8.5052630e-07f, 9.0579828e-07f, 9.6466216e-07f, - 1.0273513e-06f, 1.0941144e-06f, 1.1652161e-06f, 1.2409384e-06f, - 1.3215816e-06f, 1.4074654e-06f, 1.4989305e-06f, 1.5963394e-06f, - 1.7000785e-06f, 1.8105592e-06f, 1.9282195e-06f, 2.0535261e-06f, - 2.1869758e-06f, 2.3290978e-06f, 2.4804557e-06f, 2.6416497e-06f, - 2.8133190e-06f, 2.9961443e-06f, 3.1908506e-06f, 3.3982101e-06f, - 3.6190449e-06f, 3.8542308e-06f, 4.1047004e-06f, 4.3714470e-06f, - 4.6555282e-06f, 4.9580707e-06f, 5.2802740e-06f, 5.6234160e-06f, - 5.9888572e-06f, 6.3780469e-06f, 6.7925283e-06f, 7.2339451e-06f, - 7.7040476e-06f, 8.2047000e-06f, 8.7378876e-06f, 9.3057248e-06f, - 9.9104632e-06f, 1.0554501e-05f, 1.1240392e-05f, 1.1970856e-05f, - 1.2748789e-05f, 1.3577278e-05f, 1.4459606e-05f, 1.5399272e-05f, - 1.6400004e-05f, 1.7465768e-05f, 1.8600792e-05f, 1.9809576e-05f, - 2.1096914e-05f, 2.2467911e-05f, 2.3928002e-05f, 2.5482978e-05f, - 2.7139006e-05f, 2.8902651e-05f, 3.0780908e-05f, 3.2781225e-05f, - 3.4911534e-05f, 3.7180282e-05f, 3.9596466e-05f, 4.2169667e-05f, - 4.4910090e-05f, 4.7828601e-05f, 5.0936773e-05f, 5.4246931e-05f, - 5.7772202e-05f, 6.1526565e-05f, 6.5524908e-05f, 6.9783085e-05f, - 7.4317983e-05f, 7.9147585e-05f, 8.4291040e-05f, 8.9768747e-05f, - 9.5602426e-05f, 0.00010181521f, 0.00010843174f, 0.00011547824f, - 0.00012298267f, 0.00013097477f, 0.00013948625f, 0.00014855085f, - 0.00015820453f, 0.00016848555f, 0.00017943469f, 0.00019109536f, - 0.00020351382f, 0.00021673929f, 0.00023082423f, 0.00024582449f, - 0.00026179955f, 0.00027881276f, 0.00029693158f, 0.00031622787f, - 0.00033677814f, 0.00035866388f, 0.00038197188f, 0.00040679456f, - 0.00043323036f, 0.00046138411f, 0.00049136745f, 0.00052329927f, - 0.00055730621f, 0.00059352311f, 0.00063209358f, 0.00067317058f, - 0.00071691700f, 0.00076350630f, 0.00081312324f, 0.00086596457f, - 0.00092223983f, 0.00098217216f, 0.0010459992f, 0.0011139742f, - 0.0011863665f, 0.0012634633f, 0.0013455702f, 0.0014330129f, - 0.0015261382f, 0.0016253153f, 0.0017309374f, 0.0018434235f, - 0.0019632195f, 0.0020908006f, 0.0022266726f, 0.0023713743f, - 0.0025254795f, 0.0026895994f, 0.0028643847f, 0.0030505286f, - 0.0032487691f, 0.0034598925f, 0.0036847358f, 0.0039241906f, - 0.0041792066f, 0.0044507950f, 0.0047400328f, 0.0050480668f, - 0.0053761186f, 0.0057254891f, 0.0060975636f, 0.0064938176f, - 0.0069158225f, 0.0073652516f, 0.0078438871f, 0.0083536271f, - 0.0088964928f, 0.009474637f, 0.010090352f, 0.010746080f, - 0.011444421f, 0.012188144f, 0.012980198f, 0.013823725f, - 0.014722068f, 0.015678791f, 0.016697687f, 0.017782797f, - 0.018938423f, 0.020169149f, 0.021479854f, 0.022875735f, - 0.024362330f, 0.025945531f, 0.027631618f, 0.029427276f, - 0.031339626f, 0.033376252f, 0.035545228f, 0.037855157f, - 0.040315199f, 0.042935108f, 0.045725273f, 0.048696758f, - 0.051861348f, 0.055231591f, 0.058820850f, 0.062643361f, - 0.066714279f, 0.071049749f, 0.075666962f, 0.080584227f, - 0.085821044f, 0.091398179f, 0.097337747f, 0.10366330f, - 0.11039993f, 0.11757434f, 0.12521498f, 0.13335215f, - 0.14201813f, 0.15124727f, 0.16107617f, 0.17154380f, - 0.18269168f, 0.19456402f, 0.20720788f, 0.22067342f, - 0.23501402f, 0.25028656f, 0.26655159f, 0.28387361f, - 0.30232132f, 0.32196786f, 0.34289114f, 0.36517414f, - 0.38890521f, 0.41417847f, 0.44109412f, 0.46975890f, - 0.50028648f, 0.53279791f, 0.56742212f, 0.60429640f, - 0.64356699f, 0.68538959f, 0.72993007f, 0.77736504f, - 0.82788260f, 0.88168307f, 0.9389798f, 1.0f + 1.0649863e-07f, 1.1341951e-07f, 1.2079015e-07f, 1.2863978e-07f, + 1.3699951e-07f, 1.4590251e-07f, 1.5538408e-07f, 1.6548181e-07f, + 1.7623575e-07f, 1.8768855e-07f, 1.9988561e-07f, 2.1287530e-07f, + 2.2670913e-07f, 2.4144197e-07f, 2.5713223e-07f, 2.7384213e-07f, + 2.9163793e-07f, 3.1059021e-07f, 3.3077411e-07f, 3.5226968e-07f, + 3.7516214e-07f, 3.9954229e-07f, 4.2550680e-07f, 4.5315863e-07f, + 4.8260743e-07f, 5.1396998e-07f, 5.4737065e-07f, 5.8294187e-07f, + 6.2082472e-07f, 6.6116941e-07f, 7.0413592e-07f, 7.4989464e-07f, + 7.9862701e-07f, 8.5052630e-07f, 9.0579828e-07f, 9.6466216e-07f, + 1.0273513e-06f, 1.0941144e-06f, 1.1652161e-06f, 1.2409384e-06f, + 1.3215816e-06f, 1.4074654e-06f, 1.4989305e-06f, 1.5963394e-06f, + 1.7000785e-06f, 1.8105592e-06f, 1.9282195e-06f, 2.0535261e-06f, + 2.1869758e-06f, 2.3290978e-06f, 2.4804557e-06f, 2.6416497e-06f, + 2.8133190e-06f, 2.9961443e-06f, 3.1908506e-06f, 3.3982101e-06f, + 3.6190449e-06f, 3.8542308e-06f, 4.1047004e-06f, 4.3714470e-06f, + 4.6555282e-06f, 4.9580707e-06f, 5.2802740e-06f, 5.6234160e-06f, + 5.9888572e-06f, 6.3780469e-06f, 6.7925283e-06f, 7.2339451e-06f, + 7.7040476e-06f, 8.2047000e-06f, 8.7378876e-06f, 9.3057248e-06f, + 9.9104632e-06f, 1.0554501e-05f, 1.1240392e-05f, 1.1970856e-05f, + 1.2748789e-05f, 1.3577278e-05f, 1.4459606e-05f, 1.5399272e-05f, + 1.6400004e-05f, 1.7465768e-05f, 1.8600792e-05f, 1.9809576e-05f, + 2.1096914e-05f, 2.2467911e-05f, 2.3928002e-05f, 2.5482978e-05f, + 2.7139006e-05f, 2.8902651e-05f, 3.0780908e-05f, 3.2781225e-05f, + 3.4911534e-05f, 3.7180282e-05f, 3.9596466e-05f, 4.2169667e-05f, + 4.4910090e-05f, 4.7828601e-05f, 5.0936773e-05f, 5.4246931e-05f, + 5.7772202e-05f, 6.1526565e-05f, 6.5524908e-05f, 6.9783085e-05f, + 7.4317983e-05f, 7.9147585e-05f, 8.4291040e-05f, 8.9768747e-05f, + 9.5602426e-05f, 0.00010181521f, 0.00010843174f, 0.00011547824f, + 0.00012298267f, 0.00013097477f, 0.00013948625f, 0.00014855085f, + 0.00015820453f, 0.00016848555f, 0.00017943469f, 0.00019109536f, + 0.00020351382f, 0.00021673929f, 0.00023082423f, 0.00024582449f, + 0.00026179955f, 0.00027881276f, 0.00029693158f, 0.00031622787f, + 0.00033677814f, 0.00035866388f, 0.00038197188f, 0.00040679456f, + 0.00043323036f, 0.00046138411f, 0.00049136745f, 0.00052329927f, + 0.00055730621f, 0.00059352311f, 0.00063209358f, 0.00067317058f, + 0.00071691700f, 0.00076350630f, 0.00081312324f, 0.00086596457f, + 0.00092223983f, 0.00098217216f, 0.0010459992f, 0.0011139742f, + 0.0011863665f, 0.0012634633f, 0.0013455702f, 0.0014330129f, + 0.0015261382f, 0.0016253153f, 0.0017309374f, 0.0018434235f, + 0.0019632195f, 0.0020908006f, 0.0022266726f, 0.0023713743f, + 0.0025254795f, 0.0026895994f, 0.0028643847f, 0.0030505286f, + 0.0032487691f, 0.0034598925f, 0.0036847358f, 0.0039241906f, + 0.0041792066f, 0.0044507950f, 0.0047400328f, 0.0050480668f, + 0.0053761186f, 0.0057254891f, 0.0060975636f, 0.0064938176f, + 0.0069158225f, 0.0073652516f, 0.0078438871f, 0.0083536271f, + 0.0088964928f, 0.009474637f, 0.010090352f, 0.010746080f, + 0.011444421f, 0.012188144f, 0.012980198f, 0.013823725f, + 0.014722068f, 0.015678791f, 0.016697687f, 0.017782797f, + 0.018938423f, 0.020169149f, 0.021479854f, 0.022875735f, + 0.024362330f, 0.025945531f, 0.027631618f, 0.029427276f, + 0.031339626f, 0.033376252f, 0.035545228f, 0.037855157f, + 0.040315199f, 0.042935108f, 0.045725273f, 0.048696758f, + 0.051861348f, 0.055231591f, 0.058820850f, 0.062643361f, + 0.066714279f, 0.071049749f, 0.075666962f, 0.080584227f, + 0.085821044f, 0.091398179f, 0.097337747f, 0.10366330f, + 0.11039993f, 0.11757434f, 0.12521498f, 0.13335215f, + 0.14201813f, 0.15124727f, 0.16107617f, 0.17154380f, + 0.18269168f, 0.19456402f, 0.20720788f, 0.22067342f, + 0.23501402f, 0.25028656f, 0.26655159f, 0.28387361f, + 0.30232132f, 0.32196786f, 0.34289114f, 0.36517414f, + 0.38890521f, 0.41417847f, 0.44109412f, 0.46975890f, + 0.50028648f, 0.53279791f, 0.56742212f, 0.60429640f, + 0.64356699f, 0.68538959f, 0.72993007f, 0.77736504f, + 0.82788260f, 0.88168307f, 0.9389798f, 1.0f }; @@ -1641,15 +1762,15 @@ static float inverse_db_table[256] = int8 integer_divide_table[DIVTAB_NUMER][DIVTAB_DENOM]; // 2KB #endif -static __forceinline void draw_line(float *output, int x0, int y0, int x1, int y1, int n) +static __forceinline void draw_line(float* output, int x0, int y0, int x1, int y1, int n) { - int dy = y1 - y0; - int adx = x1 - x0; - int ady = abs(dy); - int base; - int x=x0,y=y0; - int err = 0; - int sy; + int dy = y1 - y0; + int adx = x1 - x0; + int ady = abs(dy); + int base; + int x = x0, y = y0; + int err = 0; + int sy; #ifdef STB_VORBIS_DIVIDE_TABLE if (adx < DIVTAB_DENOM && ady < DIVTAB_NUMER) { @@ -1668,259 +1789,304 @@ static __forceinline void draw_line(float *output, int x0, int y0, int x1, int y sy = base+1; } #else - base = dy / adx; - if (dy < 0) - sy = base - 1; - else - sy = base+1; + base = dy / adx; + if (dy < 0) + sy = base - 1; + else + sy = base + 1; #endif - ady -= abs(base) * adx; - if (x1 > n) x1 = n; - if (x < x1) { - LINE_OP(output[x], inverse_db_table[y]); - for (++x; x < x1; ++x) { - err += ady; - if (err >= adx) { - err -= adx; - y += sy; - } else - y += base; - LINE_OP(output[x], inverse_db_table[y]); - } - } + ady -= abs(base) * adx; + if (x1 > n) x1 = n; + if (x < x1) + { + LINE_OP(output[x], inverse_db_table[y]); + for (++x; x < x1; ++x) + { + err += ady; + if (err >= adx) + { + err -= adx; + y += sy; + } + else + y += base; + LINE_OP(output[x], inverse_db_table[y]); + } + } } -static int residue_decode(vorb *f, Codebook *book, float *target, int offset, int n, int rtype) +static int residue_decode(vorb* f, Codebook* book, float* target, int offset, int n, int rtype) { - int k; - if (rtype == 0) { - int step = n / book->dimensions; - for (k=0; k < step; ++k) - if (!codebook_decode_step(f, book, target+offset+k, n-offset-k, step)) - return FALSE; - } else { - for (k=0; k < n; ) { - if (!codebook_decode(f, book, target+offset, n-k)) - return FALSE; - k += book->dimensions; - offset += book->dimensions; - } - } - return TRUE; + int k; + if (rtype == 0) + { + int step = n / book->dimensions; + for (k = 0; k < step; ++k) + if (!codebook_decode_step(f, book, target + offset + k, n - offset - k, step)) + return FALSE; + } + else + { + for (k = 0; k < n;) + { + if (!codebook_decode(f, book, target + offset, n - k)) + return FALSE; + k += book->dimensions; + offset += book->dimensions; + } + } + return TRUE; } -static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int rn, uint8 *do_not_decode) +static void decode_residue(vorb* f, float* residue_buffers[], int ch, int n, int rn, uint8* do_not_decode) { - int i,j,pass; - Residue *r = f->residue_config + rn; - int rtype = f->residue_types[rn]; - int c = r->classbook; - int classwords = f->codebooks[c].dimensions; - int n_read = r->end - r->begin; - int part_read = n_read / r->part_size; - int temp_alloc_point = temp_alloc_save(f); - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - uint8 ***part_classdata = (uint8 ***) temp_block_array(f,f->channels, part_read * sizeof(**part_classdata)); - #else + int i, j, pass; + Residue* r = f->residue_config + rn; + int rtype = f->residue_types[rn]; + int c = r->classbook; + int classwords = f->codebooks[c].dimensions; + int n_read = r->end - r->begin; + int part_read = n_read / r->part_size; + int temp_alloc_point = temp_alloc_save(f); +#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + uint8*** part_classdata = (uint8***)temp_block_array(f, f->channels, part_read * sizeof(**part_classdata)); +#else int **classifications = (int **) temp_block_array(f,f->channels, part_read * sizeof(**classifications)); - #endif +#endif - CHECK(f); + CHECK(f); - for (i=0; i < ch; ++i) - if (!do_not_decode[i]) - memset(residue_buffers[i], 0, sizeof(float) * n); + for (i = 0; i < ch; ++i) + if (!do_not_decode[i]) + memset(residue_buffers[i], 0, sizeof(float) * n); - if (rtype == 2 && ch != 1) { - for (j=0; j < ch; ++j) - if (!do_not_decode[j]) - break; - if (j == ch) - goto done; + if (rtype == 2 && ch != 1) + { + for (j = 0; j < ch; ++j) + if (!do_not_decode[j]) + break; + if (j == ch) + goto done; - for (pass=0; pass < 8; ++pass) { - int pcount = 0, class_set = 0; - if (ch == 2) { - while (pcount < part_read) { - int z = r->begin + pcount*r->part_size; - int c_inter = (z & 1), p_inter = z>>1; - if (pass == 0) { - Codebook *c = f->codebooks+r->classbook; - int q; - DECODE(q,f,c); - if (q == EOP) goto done; - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - part_classdata[0][class_set] = r->classdata[q]; - #else + for (pass = 0; pass < 8; ++pass) + { + int pcount = 0, class_set = 0; + if (ch == 2) + { + while (pcount < part_read) + { + int z = r->begin + pcount * r->part_size; + int c_inter = (z & 1), p_inter = z >> 1; + if (pass == 0) + { + Codebook* c = f->codebooks + r->classbook; + int q; + DECODE(q, f, c); + if (q == EOP) goto done; +#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + part_classdata[0][class_set] = r->classdata[q]; +#else for (i=classwords-1; i >= 0; --i) { classifications[0][i+pcount] = q % r->classifications; q /= r->classifications; } - #endif - } - for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) { - int z = r->begin + pcount*r->part_size; - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - int c = part_classdata[0][class_set][i]; - #else +#endif + } + for (i = 0; i < classwords && pcount < part_read; ++i, ++pcount) + { + int z = r->begin + pcount * r->part_size; +#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + int c = part_classdata[0][class_set][i]; +#else int c = classifications[0][pcount]; - #endif - int b = r->residue_books[c][pass]; - if (b >= 0) { - Codebook *book = f->codebooks + b; - #ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK +#endif + int b = r->residue_books[c][pass]; + if (b >= 0) + { + Codebook* book = f->codebooks + b; +#ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) goto done; - #else - // saves 1% - if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) - goto done; - #endif - } else { - z += r->part_size; - c_inter = z & 1; - p_inter = z >> 1; - } - } - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - ++class_set; - #endif - } - } else if (ch == 1) { - while (pcount < part_read) { - int z = r->begin + pcount*r->part_size; - int c_inter = 0, p_inter = z; - if (pass == 0) { - Codebook *c = f->codebooks+r->classbook; - int q; - DECODE(q,f,c); - if (q == EOP) goto done; - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - part_classdata[0][class_set] = r->classdata[q]; - #else +#else + // saves 1% + if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, + r->part_size)) + goto done; +#endif + } + else + { + z += r->part_size; + c_inter = z & 1; + p_inter = z >> 1; + } + } +#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + ++class_set; +#endif + } + } + else if (ch == 1) + { + while (pcount < part_read) + { + int z = r->begin + pcount * r->part_size; + int c_inter = 0, p_inter = z; + if (pass == 0) + { + Codebook* c = f->codebooks + r->classbook; + int q; + DECODE(q, f, c); + if (q == EOP) goto done; +#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + part_classdata[0][class_set] = r->classdata[q]; +#else for (i=classwords-1; i >= 0; --i) { classifications[0][i+pcount] = q % r->classifications; q /= r->classifications; } - #endif - } - for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) { - int z = r->begin + pcount*r->part_size; - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - int c = part_classdata[0][class_set][i]; - #else +#endif + } + for (i = 0; i < classwords && pcount < part_read; ++i, ++pcount) + { + int z = r->begin + pcount * r->part_size; +#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + int c = part_classdata[0][class_set][i]; +#else int c = classifications[0][pcount]; - #endif - int b = r->residue_books[c][pass]; - if (b >= 0) { - Codebook *book = f->codebooks + b; - if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) - goto done; - } else { - z += r->part_size; - c_inter = 0; - p_inter = z; - } - } - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - ++class_set; - #endif - } - } else { - while (pcount < part_read) { - int z = r->begin + pcount*r->part_size; - int c_inter = z % ch, p_inter = z/ch; - if (pass == 0) { - Codebook *c = f->codebooks+r->classbook; - int q; - DECODE(q,f,c); - if (q == EOP) goto done; - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - part_classdata[0][class_set] = r->classdata[q]; - #else +#endif + int b = r->residue_books[c][pass]; + if (b >= 0) + { + Codebook* book = f->codebooks + b; + if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, + r->part_size)) + goto done; + } + else + { + z += r->part_size; + c_inter = 0; + p_inter = z; + } + } +#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + ++class_set; +#endif + } + } + else + { + while (pcount < part_read) + { + int z = r->begin + pcount * r->part_size; + int c_inter = z % ch, p_inter = z / ch; + if (pass == 0) + { + Codebook* c = f->codebooks + r->classbook; + int q; + DECODE(q, f, c); + if (q == EOP) goto done; +#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + part_classdata[0][class_set] = r->classdata[q]; +#else for (i=classwords-1; i >= 0; --i) { classifications[0][i+pcount] = q % r->classifications; q /= r->classifications; } - #endif - } - for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) { - int z = r->begin + pcount*r->part_size; - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - int c = part_classdata[0][class_set][i]; - #else +#endif + } + for (i = 0; i < classwords && pcount < part_read; ++i, ++pcount) + { + int z = r->begin + pcount * r->part_size; +#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + int c = part_classdata[0][class_set][i]; +#else int c = classifications[0][pcount]; - #endif - int b = r->residue_books[c][pass]; - if (b >= 0) { - Codebook *book = f->codebooks + b; - if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) - goto done; - } else { - z += r->part_size; - c_inter = z % ch; - p_inter = z / ch; - } - } - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - ++class_set; - #endif - } - } - } - goto done; - } - CHECK(f); +#endif + int b = r->residue_books[c][pass]; + if (b >= 0) + { + Codebook* book = f->codebooks + b; + if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, + r->part_size)) + goto done; + } + else + { + z += r->part_size; + c_inter = z % ch; + p_inter = z / ch; + } + } +#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + ++class_set; +#endif + } + } + } + goto done; + } + CHECK(f); - for (pass=0; pass < 8; ++pass) { - int pcount = 0, class_set=0; - while (pcount < part_read) { - if (pass == 0) { - for (j=0; j < ch; ++j) { - if (!do_not_decode[j]) { - Codebook *c = f->codebooks+r->classbook; - int temp; - DECODE(temp,f,c); - if (temp == EOP) goto done; - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - part_classdata[j][class_set] = r->classdata[temp]; - #else + for (pass = 0; pass < 8; ++pass) + { + int pcount = 0, class_set = 0; + while (pcount < part_read) + { + if (pass == 0) + { + for (j = 0; j < ch; ++j) + { + if (!do_not_decode[j]) + { + Codebook* c = f->codebooks + r->classbook; + int temp; + DECODE(temp, f, c); + if (temp == EOP) goto done; +#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + part_classdata[j][class_set] = r->classdata[temp]; +#else for (i=classwords-1; i >= 0; --i) { classifications[j][i+pcount] = temp % r->classifications; temp /= r->classifications; } - #endif - } - } - } - for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) { - for (j=0; j < ch; ++j) { - if (!do_not_decode[j]) { - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - int c = part_classdata[j][class_set][i]; - #else +#endif + } + } + } + for (i = 0; i < classwords && pcount < part_read; ++i, ++pcount) + { + for (j = 0; j < ch; ++j) + { + if (!do_not_decode[j]) + { +#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + int c = part_classdata[j][class_set][i]; +#else int c = classifications[j][pcount]; - #endif - int b = r->residue_books[c][pass]; - if (b >= 0) { - float *target = residue_buffers[j]; - int offset = r->begin + pcount * r->part_size; - int n = r->part_size; - Codebook *book = f->codebooks + b; - if (!residue_decode(f, book, target, offset, n, rtype)) - goto done; - } - } - } - } - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - ++class_set; - #endif - } - } - done: - CHECK(f); - temp_alloc_restore(f,temp_alloc_point); +#endif + int b = r->residue_books[c][pass]; + if (b >= 0) + { + float* target = residue_buffers[j]; + int offset = r->begin + pcount * r->part_size; + int n = r->part_size; + Codebook* book = f->codebooks + b; + if (!residue_decode(f, book, target, offset, n, rtype)) + goto done; + } + } + } + } +#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + ++class_set; +#endif + } + } +done: + CHECK(f); + temp_alloc_restore(f, temp_alloc_point); } @@ -2045,527 +2211,540 @@ void inverse_mdct(float *buffer, int n, vorb *f, int blocktype) // the following were split out into separate functions while optimizing; // they could be pushed back up but eh. __forceinline showed no change; // they're probably already being inlined. -static void imdct_step3_iter0_loop(int n, float *e, int i_off, int k_off, float *A) +static void imdct_step3_iter0_loop(int n, float* e, int i_off, int k_off, float* A) { - float *ee0 = e + i_off; - float *ee2 = ee0 + k_off; - int i; + float* ee0 = e + i_off; + float* ee2 = ee0 + k_off; + int i; - assert((n & 3) == 0); - for (i=(n>>2); i > 0; --i) { - float k00_20, k01_21; - k00_20 = ee0[ 0] - ee2[ 0]; - k01_21 = ee0[-1] - ee2[-1]; - ee0[ 0] += ee2[ 0];//ee0[ 0] = ee0[ 0] + ee2[ 0]; - ee0[-1] += ee2[-1];//ee0[-1] = ee0[-1] + ee2[-1]; - ee2[ 0] = k00_20 * A[0] - k01_21 * A[1]; - ee2[-1] = k01_21 * A[0] + k00_20 * A[1]; - A += 8; + assert((n & 3) == 0); + for (i = (n >> 2); i > 0; --i) + { + float k00_20, k01_21; + k00_20 = ee0[0] - ee2[0]; + k01_21 = ee0[-1] - ee2[-1]; + ee0[0] += ee2[0]; //ee0[ 0] = ee0[ 0] + ee2[ 0]; + ee0[-1] += ee2[-1]; //ee0[-1] = ee0[-1] + ee2[-1]; + ee2[0] = k00_20 * A[0] - k01_21 * A[1]; + ee2[-1] = k01_21 * A[0] + k00_20 * A[1]; + A += 8; - k00_20 = ee0[-2] - ee2[-2]; - k01_21 = ee0[-3] - ee2[-3]; - ee0[-2] += ee2[-2];//ee0[-2] = ee0[-2] + ee2[-2]; - ee0[-3] += ee2[-3];//ee0[-3] = ee0[-3] + ee2[-3]; - ee2[-2] = k00_20 * A[0] - k01_21 * A[1]; - ee2[-3] = k01_21 * A[0] + k00_20 * A[1]; - A += 8; + k00_20 = ee0[-2] - ee2[-2]; + k01_21 = ee0[-3] - ee2[-3]; + ee0[-2] += ee2[-2]; //ee0[-2] = ee0[-2] + ee2[-2]; + ee0[-3] += ee2[-3]; //ee0[-3] = ee0[-3] + ee2[-3]; + ee2[-2] = k00_20 * A[0] - k01_21 * A[1]; + ee2[-3] = k01_21 * A[0] + k00_20 * A[1]; + A += 8; - k00_20 = ee0[-4] - ee2[-4]; - k01_21 = ee0[-5] - ee2[-5]; - ee0[-4] += ee2[-4];//ee0[-4] = ee0[-4] + ee2[-4]; - ee0[-5] += ee2[-5];//ee0[-5] = ee0[-5] + ee2[-5]; - ee2[-4] = k00_20 * A[0] - k01_21 * A[1]; - ee2[-5] = k01_21 * A[0] + k00_20 * A[1]; - A += 8; + k00_20 = ee0[-4] - ee2[-4]; + k01_21 = ee0[-5] - ee2[-5]; + ee0[-4] += ee2[-4]; //ee0[-4] = ee0[-4] + ee2[-4]; + ee0[-5] += ee2[-5]; //ee0[-5] = ee0[-5] + ee2[-5]; + ee2[-4] = k00_20 * A[0] - k01_21 * A[1]; + ee2[-5] = k01_21 * A[0] + k00_20 * A[1]; + A += 8; - k00_20 = ee0[-6] - ee2[-6]; - k01_21 = ee0[-7] - ee2[-7]; - ee0[-6] += ee2[-6];//ee0[-6] = ee0[-6] + ee2[-6]; - ee0[-7] += ee2[-7];//ee0[-7] = ee0[-7] + ee2[-7]; - ee2[-6] = k00_20 * A[0] - k01_21 * A[1]; - ee2[-7] = k01_21 * A[0] + k00_20 * A[1]; - A += 8; - ee0 -= 8; - ee2 -= 8; - } + k00_20 = ee0[-6] - ee2[-6]; + k01_21 = ee0[-7] - ee2[-7]; + ee0[-6] += ee2[-6]; //ee0[-6] = ee0[-6] + ee2[-6]; + ee0[-7] += ee2[-7]; //ee0[-7] = ee0[-7] + ee2[-7]; + ee2[-6] = k00_20 * A[0] - k01_21 * A[1]; + ee2[-7] = k01_21 * A[0] + k00_20 * A[1]; + A += 8; + ee0 -= 8; + ee2 -= 8; + } } -static void imdct_step3_inner_r_loop(int lim, float *e, int d0, int k_off, float *A, int k1) +static void imdct_step3_inner_r_loop(int lim, float* e, int d0, int k_off, float* A, int k1) { - int i; - float k00_20, k01_21; + int i; + float k00_20, k01_21; - float *e0 = e + d0; - float *e2 = e0 + k_off; + float* e0 = e + d0; + float* e2 = e0 + k_off; - for (i=lim >> 2; i > 0; --i) { - k00_20 = e0[-0] - e2[-0]; - k01_21 = e0[-1] - e2[-1]; - e0[-0] += e2[-0];//e0[-0] = e0[-0] + e2[-0]; - e0[-1] += e2[-1];//e0[-1] = e0[-1] + e2[-1]; - e2[-0] = (k00_20)*A[0] - (k01_21) * A[1]; - e2[-1] = (k01_21)*A[0] + (k00_20) * A[1]; + for (i = lim >> 2; i > 0; --i) + { + k00_20 = e0[-0] - e2[-0]; + k01_21 = e0[-1] - e2[-1]; + e0[-0] += e2[-0]; //e0[-0] = e0[-0] + e2[-0]; + e0[-1] += e2[-1]; //e0[-1] = e0[-1] + e2[-1]; + e2[-0] = (k00_20) * A[0] - (k01_21) * A[1]; + e2[-1] = (k01_21) * A[0] + (k00_20) * A[1]; - A += k1; + A += k1; - k00_20 = e0[-2] - e2[-2]; - k01_21 = e0[-3] - e2[-3]; - e0[-2] += e2[-2];//e0[-2] = e0[-2] + e2[-2]; - e0[-3] += e2[-3];//e0[-3] = e0[-3] + e2[-3]; - e2[-2] = (k00_20)*A[0] - (k01_21) * A[1]; - e2[-3] = (k01_21)*A[0] + (k00_20) * A[1]; + k00_20 = e0[-2] - e2[-2]; + k01_21 = e0[-3] - e2[-3]; + e0[-2] += e2[-2]; //e0[-2] = e0[-2] + e2[-2]; + e0[-3] += e2[-3]; //e0[-3] = e0[-3] + e2[-3]; + e2[-2] = (k00_20) * A[0] - (k01_21) * A[1]; + e2[-3] = (k01_21) * A[0] + (k00_20) * A[1]; - A += k1; + A += k1; - k00_20 = e0[-4] - e2[-4]; - k01_21 = e0[-5] - e2[-5]; - e0[-4] += e2[-4];//e0[-4] = e0[-4] + e2[-4]; - e0[-5] += e2[-5];//e0[-5] = e0[-5] + e2[-5]; - e2[-4] = (k00_20)*A[0] - (k01_21) * A[1]; - e2[-5] = (k01_21)*A[0] + (k00_20) * A[1]; + k00_20 = e0[-4] - e2[-4]; + k01_21 = e0[-5] - e2[-5]; + e0[-4] += e2[-4]; //e0[-4] = e0[-4] + e2[-4]; + e0[-5] += e2[-5]; //e0[-5] = e0[-5] + e2[-5]; + e2[-4] = (k00_20) * A[0] - (k01_21) * A[1]; + e2[-5] = (k01_21) * A[0] + (k00_20) * A[1]; - A += k1; + A += k1; - k00_20 = e0[-6] - e2[-6]; - k01_21 = e0[-7] - e2[-7]; - e0[-6] += e2[-6];//e0[-6] = e0[-6] + e2[-6]; - e0[-7] += e2[-7];//e0[-7] = e0[-7] + e2[-7]; - e2[-6] = (k00_20)*A[0] - (k01_21) * A[1]; - e2[-7] = (k01_21)*A[0] + (k00_20) * A[1]; + k00_20 = e0[-6] - e2[-6]; + k01_21 = e0[-7] - e2[-7]; + e0[-6] += e2[-6]; //e0[-6] = e0[-6] + e2[-6]; + e0[-7] += e2[-7]; //e0[-7] = e0[-7] + e2[-7]; + e2[-6] = (k00_20) * A[0] - (k01_21) * A[1]; + e2[-7] = (k01_21) * A[0] + (k00_20) * A[1]; - e0 -= 8; - e2 -= 8; + e0 -= 8; + e2 -= 8; - A += k1; - } + A += k1; + } } -static void imdct_step3_inner_s_loop(int n, float *e, int i_off, int k_off, float *A, int a_off, int k0) +static void imdct_step3_inner_s_loop(int n, float* e, int i_off, int k_off, float* A, int a_off, int k0) { - int i; - float A0 = A[0]; - float A1 = A[0+1]; - float A2 = A[0+a_off]; - float A3 = A[0+a_off+1]; - float A4 = A[0+a_off*2+0]; - float A5 = A[0+a_off*2+1]; - float A6 = A[0+a_off*3+0]; - float A7 = A[0+a_off*3+1]; + int i; + float A0 = A[0]; + float A1 = A[0 + 1]; + float A2 = A[0 + a_off]; + float A3 = A[0 + a_off + 1]; + float A4 = A[0 + a_off * 2 + 0]; + float A5 = A[0 + a_off * 2 + 1]; + float A6 = A[0 + a_off * 3 + 0]; + float A7 = A[0 + a_off * 3 + 1]; - float k00,k11; + float k00, k11; - float *ee0 = e +i_off; - float *ee2 = ee0+k_off; + float* ee0 = e + i_off; + float* ee2 = ee0 + k_off; - for (i=n; i > 0; --i) { - k00 = ee0[ 0] - ee2[ 0]; - k11 = ee0[-1] - ee2[-1]; - ee0[ 0] = ee0[ 0] + ee2[ 0]; - ee0[-1] = ee0[-1] + ee2[-1]; - ee2[ 0] = (k00) * A0 - (k11) * A1; - ee2[-1] = (k11) * A0 + (k00) * A1; + for (i = n; i > 0; --i) + { + k00 = ee0[0] - ee2[0]; + k11 = ee0[-1] - ee2[-1]; + ee0[0] = ee0[0] + ee2[0]; + ee0[-1] = ee0[-1] + ee2[-1]; + ee2[0] = (k00) * A0 - (k11) * A1; + ee2[-1] = (k11) * A0 + (k00) * A1; - k00 = ee0[-2] - ee2[-2]; - k11 = ee0[-3] - ee2[-3]; - ee0[-2] = ee0[-2] + ee2[-2]; - ee0[-3] = ee0[-3] + ee2[-3]; - ee2[-2] = (k00) * A2 - (k11) * A3; - ee2[-3] = (k11) * A2 + (k00) * A3; + k00 = ee0[-2] - ee2[-2]; + k11 = ee0[-3] - ee2[-3]; + ee0[-2] = ee0[-2] + ee2[-2]; + ee0[-3] = ee0[-3] + ee2[-3]; + ee2[-2] = (k00) * A2 - (k11) * A3; + ee2[-3] = (k11) * A2 + (k00) * A3; - k00 = ee0[-4] - ee2[-4]; - k11 = ee0[-5] - ee2[-5]; - ee0[-4] = ee0[-4] + ee2[-4]; - ee0[-5] = ee0[-5] + ee2[-5]; - ee2[-4] = (k00) * A4 - (k11) * A5; - ee2[-5] = (k11) * A4 + (k00) * A5; + k00 = ee0[-4] - ee2[-4]; + k11 = ee0[-5] - ee2[-5]; + ee0[-4] = ee0[-4] + ee2[-4]; + ee0[-5] = ee0[-5] + ee2[-5]; + ee2[-4] = (k00) * A4 - (k11) * A5; + ee2[-5] = (k11) * A4 + (k00) * A5; - k00 = ee0[-6] - ee2[-6]; - k11 = ee0[-7] - ee2[-7]; - ee0[-6] = ee0[-6] + ee2[-6]; - ee0[-7] = ee0[-7] + ee2[-7]; - ee2[-6] = (k00) * A6 - (k11) * A7; - ee2[-7] = (k11) * A6 + (k00) * A7; + k00 = ee0[-6] - ee2[-6]; + k11 = ee0[-7] - ee2[-7]; + ee0[-6] = ee0[-6] + ee2[-6]; + ee0[-7] = ee0[-7] + ee2[-7]; + ee2[-6] = (k00) * A6 - (k11) * A7; + ee2[-7] = (k11) * A6 + (k00) * A7; - ee0 -= k0; - ee2 -= k0; - } + ee0 -= k0; + ee2 -= k0; + } } -static __forceinline void iter_54(float *z) +static __forceinline void iter_54(float* z) { - float k00,k11,k22,k33; - float y0,y1,y2,y3; + float k00, k11, k22, k33; + float y0, y1, y2, y3; - k00 = z[ 0] - z[-4]; - y0 = z[ 0] + z[-4]; - y2 = z[-2] + z[-6]; - k22 = z[-2] - z[-6]; + k00 = z[0] - z[-4]; + y0 = z[0] + z[-4]; + y2 = z[-2] + z[-6]; + k22 = z[-2] - z[-6]; - z[-0] = y0 + y2; // z0 + z4 + z2 + z6 - z[-2] = y0 - y2; // z0 + z4 - z2 - z6 + z[-0] = y0 + y2; // z0 + z4 + z2 + z6 + z[-2] = y0 - y2; // z0 + z4 - z2 - z6 - // done with y0,y2 + // done with y0,y2 - k33 = z[-3] - z[-7]; + k33 = z[-3] - z[-7]; - z[-4] = k00 + k33; // z0 - z4 + z3 - z7 - z[-6] = k00 - k33; // z0 - z4 - z3 + z7 + z[-4] = k00 + k33; // z0 - z4 + z3 - z7 + z[-6] = k00 - k33; // z0 - z4 - z3 + z7 - // done with k33 + // done with k33 - k11 = z[-1] - z[-5]; - y1 = z[-1] + z[-5]; - y3 = z[-3] + z[-7]; + k11 = z[-1] - z[-5]; + y1 = z[-1] + z[-5]; + y3 = z[-3] + z[-7]; - z[-1] = y1 + y3; // z1 + z5 + z3 + z7 - z[-3] = y1 - y3; // z1 + z5 - z3 - z7 - z[-5] = k11 - k22; // z1 - z5 + z2 - z6 - z[-7] = k11 + k22; // z1 - z5 - z2 + z6 + z[-1] = y1 + y3; // z1 + z5 + z3 + z7 + z[-3] = y1 - y3; // z1 + z5 - z3 - z7 + z[-5] = k11 - k22; // z1 - z5 + z2 - z6 + z[-7] = k11 + k22; // z1 - z5 - z2 + z6 } -static void imdct_step3_inner_s_loop_ld654(int n, float *e, int i_off, float *A, int base_n) +static void imdct_step3_inner_s_loop_ld654(int n, float* e, int i_off, float* A, int base_n) { - int a_off = base_n >> 3; - float A2 = A[0+a_off]; - float *z = e + i_off; - float *base = z - 16 * n; + int a_off = base_n >> 3; + float A2 = A[0 + a_off]; + float* z = e + i_off; + float* base = z - 16 * n; - while (z > base) { - float k00,k11; + while (z > base) + { + float k00, k11; - k00 = z[-0] - z[-8]; - k11 = z[-1] - z[-9]; - z[-0] = z[-0] + z[-8]; - z[-1] = z[-1] + z[-9]; - z[-8] = k00; - z[-9] = k11 ; + k00 = z[-0] - z[-8]; + k11 = z[-1] - z[-9]; + z[-0] = z[-0] + z[-8]; + z[-1] = z[-1] + z[-9]; + z[-8] = k00; + z[-9] = k11; - k00 = z[ -2] - z[-10]; - k11 = z[ -3] - z[-11]; - z[ -2] = z[ -2] + z[-10]; - z[ -3] = z[ -3] + z[-11]; - z[-10] = (k00+k11) * A2; - z[-11] = (k11-k00) * A2; + k00 = z[-2] - z[-10]; + k11 = z[-3] - z[-11]; + z[-2] = z[-2] + z[-10]; + z[-3] = z[-3] + z[-11]; + z[-10] = (k00 + k11) * A2; + z[-11] = (k11 - k00) * A2; - k00 = z[-12] - z[ -4]; // reverse to avoid a unary negation - k11 = z[ -5] - z[-13]; - z[ -4] = z[ -4] + z[-12]; - z[ -5] = z[ -5] + z[-13]; - z[-12] = k11; - z[-13] = k00; + k00 = z[-12] - z[-4]; // reverse to avoid a unary negation + k11 = z[-5] - z[-13]; + z[-4] = z[-4] + z[-12]; + z[-5] = z[-5] + z[-13]; + z[-12] = k11; + z[-13] = k00; - k00 = z[-14] - z[ -6]; // reverse to avoid a unary negation - k11 = z[ -7] - z[-15]; - z[ -6] = z[ -6] + z[-14]; - z[ -7] = z[ -7] + z[-15]; - z[-14] = (k00+k11) * A2; - z[-15] = (k00-k11) * A2; + k00 = z[-14] - z[-6]; // reverse to avoid a unary negation + k11 = z[-7] - z[-15]; + z[-6] = z[-6] + z[-14]; + z[-7] = z[-7] + z[-15]; + z[-14] = (k00 + k11) * A2; + z[-15] = (k00 - k11) * A2; - iter_54(z); - iter_54(z-8); - z -= 16; - } + iter_54(z); + iter_54(z - 8); + z -= 16; + } } -static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype) +static void inverse_mdct(float* buffer, int n, vorb* f, int blocktype) { - int n2 = n >> 1, n4 = n >> 2, n8 = n >> 3, l; - int ld; - // @OPTIMIZE: reduce register pressure by using fewer variables? - int save_point = temp_alloc_save(f); - float *buf2 = (float *) temp_alloc(f, n2 * sizeof(*buf2)); - float *u=NULL,*v=NULL; - // twiddle factors - float *A = f->A[blocktype]; + int n2 = n >> 1, n4 = n >> 2, n8 = n >> 3, l; + int ld; + // @OPTIMIZE: reduce register pressure by using fewer variables? + int save_point = temp_alloc_save(f); + float* buf2 = (float*)temp_alloc(f, n2 * sizeof(*buf2)); + float *u = NULL, *v = NULL; + // twiddle factors + float* A = f->A[blocktype]; - // IMDCT algorithm from "The use of multirate filter banks for coding of high quality digital audio" - // See notes about bugs in that paper in less-optimal implementation 'inverse_mdct_old' after this function. + // IMDCT algorithm from "The use of multirate filter banks for coding of high quality digital audio" + // See notes about bugs in that paper in less-optimal implementation 'inverse_mdct_old' after this function. - // kernel from paper + // kernel from paper - // merged: - // copy and reflect spectral data - // step 0 + // merged: + // copy and reflect spectral data + // step 0 - // note that it turns out that the items added together during - // this step are, in fact, being added to themselves (as reflected - // by step 0). inexplicable inefficiency! this became obvious - // once I combined the passes. + // note that it turns out that the items added together during + // this step are, in fact, being added to themselves (as reflected + // by step 0). inexplicable inefficiency! this became obvious + // once I combined the passes. - // so there's a missing 'times 2' here (for adding X to itself). - // this propogates through linearly to the end, where the numbers - // are 1/2 too small, and need to be compensated for. + // so there's a missing 'times 2' here (for adding X to itself). + // this propogates through linearly to the end, where the numbers + // are 1/2 too small, and need to be compensated for. - { - float *d,*e, *AA, *e_stop; - d = &buf2[n2-2]; - AA = A; - e = &buffer[0]; - e_stop = &buffer[n2]; - while (e != e_stop) { - d[1] = (e[0] * AA[0] - e[2]*AA[1]); - d[0] = (e[0] * AA[1] + e[2]*AA[0]); - d -= 2; - AA += 2; - e += 4; - } + { + float *d, *e, *AA, *e_stop; + d = &buf2[n2 - 2]; + AA = A; + e = &buffer[0]; + e_stop = &buffer[n2]; + while (e != e_stop) + { + d[1] = (e[0] * AA[0] - e[2] * AA[1]); + d[0] = (e[0] * AA[1] + e[2] * AA[0]); + d -= 2; + AA += 2; + e += 4; + } - e = &buffer[n2-3]; - while (d >= buf2) { - d[1] = (-e[2] * AA[0] - -e[0]*AA[1]); - d[0] = (-e[2] * AA[1] + -e[0]*AA[0]); - d -= 2; - AA += 2; - e -= 4; - } - } + e = &buffer[n2 - 3]; + while (d >= buf2) + { + d[1] = (-e[2] * AA[0] - -e[0] * AA[1]); + d[0] = (-e[2] * AA[1] + -e[0] * AA[0]); + d -= 2; + AA += 2; + e -= 4; + } + } - // now we use symbolic names for these, so that we can - // possibly swap their meaning as we change which operations - // are in place + // now we use symbolic names for these, so that we can + // possibly swap their meaning as we change which operations + // are in place - u = buffer; - v = buf2; + u = buffer; + v = buf2; - // step 2 (paper output is w, now u) - // this could be in place, but the data ends up in the wrong - // place... _somebody_'s got to swap it, so this is nominated - { - float *AA = &A[n2-8]; - float *d0,*d1, *e0, *e1; + // step 2 (paper output is w, now u) + // this could be in place, but the data ends up in the wrong + // place... _somebody_'s got to swap it, so this is nominated + { + float* AA = &A[n2 - 8]; + float *d0, *d1, *e0, *e1; - e0 = &v[n4]; - e1 = &v[0]; + e0 = &v[n4]; + e1 = &v[0]; - d0 = &u[n4]; - d1 = &u[0]; + d0 = &u[n4]; + d1 = &u[0]; - while (AA >= A) { - float v40_20, v41_21; + while (AA >= A) + { + float v40_20, v41_21; - v41_21 = e0[1] - e1[1]; - v40_20 = e0[0] - e1[0]; - d0[1] = e0[1] + e1[1]; - d0[0] = e0[0] + e1[0]; - d1[1] = v41_21*AA[4] - v40_20*AA[5]; - d1[0] = v40_20*AA[4] + v41_21*AA[5]; + v41_21 = e0[1] - e1[1]; + v40_20 = e0[0] - e1[0]; + d0[1] = e0[1] + e1[1]; + d0[0] = e0[0] + e1[0]; + d1[1] = v41_21 * AA[4] - v40_20 * AA[5]; + d1[0] = v40_20 * AA[4] + v41_21 * AA[5]; - v41_21 = e0[3] - e1[3]; - v40_20 = e0[2] - e1[2]; - d0[3] = e0[3] + e1[3]; - d0[2] = e0[2] + e1[2]; - d1[3] = v41_21*AA[0] - v40_20*AA[1]; - d1[2] = v40_20*AA[0] + v41_21*AA[1]; + v41_21 = e0[3] - e1[3]; + v40_20 = e0[2] - e1[2]; + d0[3] = e0[3] + e1[3]; + d0[2] = e0[2] + e1[2]; + d1[3] = v41_21 * AA[0] - v40_20 * AA[1]; + d1[2] = v40_20 * AA[0] + v41_21 * AA[1]; - AA -= 8; + AA -= 8; - d0 += 4; - d1 += 4; - e0 += 4; - e1 += 4; - } - } + d0 += 4; + d1 += 4; + e0 += 4; + e1 += 4; + } + } - // step 3 - ld = ilog(n) - 1; // ilog is off-by-one from normal definitions + // step 3 + ld = ilog(n) - 1; // ilog is off-by-one from normal definitions - // optimized step 3: + // optimized step 3: - // the original step3 loop can be nested r inside s or s inside r; - // it's written originally as s inside r, but this is dumb when r - // iterates many times, and s few. So I have two copies of it and - // switch between them halfway. + // the original step3 loop can be nested r inside s or s inside r; + // it's written originally as s inside r, but this is dumb when r + // iterates many times, and s few. So I have two copies of it and + // switch between them halfway. - // this is iteration 0 of step 3 - imdct_step3_iter0_loop(n >> 4, u, n2-1-n4*0, -(n >> 3), A); - imdct_step3_iter0_loop(n >> 4, u, n2-1-n4*1, -(n >> 3), A); + // this is iteration 0 of step 3 + imdct_step3_iter0_loop(n >> 4, u, n2 - 1 - n4 * 0, -(n >> 3), A); + imdct_step3_iter0_loop(n >> 4, u, n2 - 1 - n4 * 1, -(n >> 3), A); - // this is iteration 1 of step 3 - imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*0, -(n >> 4), A, 16); - imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*1, -(n >> 4), A, 16); - imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*2, -(n >> 4), A, 16); - imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*3, -(n >> 4), A, 16); + // this is iteration 1 of step 3 + imdct_step3_inner_r_loop(n >> 5, u, n2 - 1 - n8 * 0, -(n >> 4), A, 16); + imdct_step3_inner_r_loop(n >> 5, u, n2 - 1 - n8 * 1, -(n >> 4), A, 16); + imdct_step3_inner_r_loop(n >> 5, u, n2 - 1 - n8 * 2, -(n >> 4), A, 16); + imdct_step3_inner_r_loop(n >> 5, u, n2 - 1 - n8 * 3, -(n >> 4), A, 16); - l=2; - for (; l < (ld-3)>>1; ++l) { - int k0 = n >> (l+2), k0_2 = k0>>1; - int lim = 1 << (l+1); - int i; - for (i=0; i < lim; ++i) - imdct_step3_inner_r_loop(n >> (l+4), u, n2-1 - k0*i, -k0_2, A, 1 << (l+3)); - } + l = 2; + for (; l < (ld - 3) >> 1; ++l) + { + int k0 = n >> (l + 2), k0_2 = k0 >> 1; + int lim = 1 << (l + 1); + int i; + for (i = 0; i < lim; ++i) + imdct_step3_inner_r_loop(n >> (l + 4), u, n2 - 1 - k0 * i, -k0_2, A, 1 << (l + 3)); + } - for (; l < ld-6; ++l) { - int k0 = n >> (l+2), k1 = 1 << (l+3), k0_2 = k0>>1; - int rlim = n >> (l+6), r; - int lim = 1 << (l+1); - int i_off; - float *A0 = A; - i_off = n2-1; - for (r=rlim; r > 0; --r) { - imdct_step3_inner_s_loop(lim, u, i_off, -k0_2, A0, k1, k0); - A0 += k1*4; - i_off -= 8; - } - } + for (; l < ld - 6; ++l) + { + int k0 = n >> (l + 2), k1 = 1 << (l + 3), k0_2 = k0 >> 1; + int rlim = n >> (l + 6), r; + int lim = 1 << (l + 1); + int i_off; + float* A0 = A; + i_off = n2 - 1; + for (r = rlim; r > 0; --r) + { + imdct_step3_inner_s_loop(lim, u, i_off, -k0_2, A0, k1, k0); + A0 += k1 * 4; + i_off -= 8; + } + } - // iterations with count: - // ld-6,-5,-4 all interleaved together - // the big win comes from getting rid of needless flops - // due to the constants on pass 5 & 4 being all 1 and 0; - // combining them to be simultaneous to improve cache made little difference - imdct_step3_inner_s_loop_ld654(n >> 5, u, n2-1, A, n); + // iterations with count: + // ld-6,-5,-4 all interleaved together + // the big win comes from getting rid of needless flops + // due to the constants on pass 5 & 4 being all 1 and 0; + // combining them to be simultaneous to improve cache made little difference + imdct_step3_inner_s_loop_ld654(n >> 5, u, n2 - 1, A, n); - // output is u + // output is u - // step 4, 5, and 6 - // cannot be in-place because of step 5 - { - uint16 *bitrev = f->bit_reverse[blocktype]; - // weirdly, I'd have thought reading sequentially and writing - // erratically would have been better than vice-versa, but in - // fact that's not what my testing showed. (That is, with - // j = bitreverse(i), do you read i and write j, or read j and write i.) + // step 4, 5, and 6 + // cannot be in-place because of step 5 + { + uint16* bitrev = f->bit_reverse[blocktype]; + // weirdly, I'd have thought reading sequentially and writing + // erratically would have been better than vice-versa, but in + // fact that's not what my testing showed. (That is, with + // j = bitreverse(i), do you read i and write j, or read j and write i.) - float *d0 = &v[n4-4]; - float *d1 = &v[n2-4]; - while (d0 >= v) { - int k4; + float* d0 = &v[n4 - 4]; + float* d1 = &v[n2 - 4]; + while (d0 >= v) + { + int k4; - k4 = bitrev[0]; - d1[3] = u[k4+0]; - d1[2] = u[k4+1]; - d0[3] = u[k4+2]; - d0[2] = u[k4+3]; + k4 = bitrev[0]; + d1[3] = u[k4 + 0]; + d1[2] = u[k4 + 1]; + d0[3] = u[k4 + 2]; + d0[2] = u[k4 + 3]; - k4 = bitrev[1]; - d1[1] = u[k4+0]; - d1[0] = u[k4+1]; - d0[1] = u[k4+2]; - d0[0] = u[k4+3]; - - d0 -= 4; - d1 -= 4; - bitrev += 2; - } - } - // (paper output is u, now v) + k4 = bitrev[1]; + d1[1] = u[k4 + 0]; + d1[0] = u[k4 + 1]; + d0[1] = u[k4 + 2]; + d0[0] = u[k4 + 3]; + + d0 -= 4; + d1 -= 4; + bitrev += 2; + } + } + // (paper output is u, now v) - // data must be in buf2 - assert(v == buf2); + // data must be in buf2 + assert(v == buf2); - // step 7 (paper output is v, now v) - // this is now in place - { - float *C = f->C[blocktype]; - float *d, *e; + // step 7 (paper output is v, now v) + // this is now in place + { + float* C = f->C[blocktype]; + float *d, *e; - d = v; - e = v + n2 - 4; + d = v; + e = v + n2 - 4; - while (d < e) { - float a02,a11,b0,b1,b2,b3; + while (d < e) + { + float a02, a11, b0, b1, b2, b3; - a02 = d[0] - e[2]; - a11 = d[1] + e[3]; + a02 = d[0] - e[2]; + a11 = d[1] + e[3]; - b0 = C[1]*a02 + C[0]*a11; - b1 = C[1]*a11 - C[0]*a02; + b0 = C[1] * a02 + C[0] * a11; + b1 = C[1] * a11 - C[0] * a02; - b2 = d[0] + e[ 2]; - b3 = d[1] - e[ 3]; + b2 = d[0] + e[2]; + b3 = d[1] - e[3]; - d[0] = b2 + b0; - d[1] = b3 + b1; - e[2] = b2 - b0; - e[3] = b1 - b3; + d[0] = b2 + b0; + d[1] = b3 + b1; + e[2] = b2 - b0; + e[3] = b1 - b3; - a02 = d[2] - e[0]; - a11 = d[3] + e[1]; + a02 = d[2] - e[0]; + a11 = d[3] + e[1]; - b0 = C[3]*a02 + C[2]*a11; - b1 = C[3]*a11 - C[2]*a02; + b0 = C[3] * a02 + C[2] * a11; + b1 = C[3] * a11 - C[2] * a02; - b2 = d[2] + e[ 0]; - b3 = d[3] - e[ 1]; + b2 = d[2] + e[0]; + b3 = d[3] - e[1]; - d[2] = b2 + b0; - d[3] = b3 + b1; - e[0] = b2 - b0; - e[1] = b1 - b3; + d[2] = b2 + b0; + d[3] = b3 + b1; + e[0] = b2 - b0; + e[1] = b1 - b3; - C += 4; - d += 4; - e -= 4; - } - } + C += 4; + d += 4; + e -= 4; + } + } - // data must be in buf2 + // data must be in buf2 - // step 8+decode (paper output is X, now buffer) - // this generates pairs of data a la 8 and pushes them directly through - // the decode kernel (pushing rather than pulling) to avoid having - // to make another pass later + // step 8+decode (paper output is X, now buffer) + // this generates pairs of data a la 8 and pushes them directly through + // the decode kernel (pushing rather than pulling) to avoid having + // to make another pass later - // this cannot POSSIBLY be in place, so we refer to the buffers directly + // this cannot POSSIBLY be in place, so we refer to the buffers directly - { - float *d0,*d1,*d2,*d3; + { + float *d0, *d1, *d2, *d3; - float *B = f->B[blocktype] + n2 - 8; - float *e = buf2 + n2 - 8; - d0 = &buffer[0]; - d1 = &buffer[n2-4]; - d2 = &buffer[n2]; - d3 = &buffer[n-4]; - while (e >= v) { - float p0,p1,p2,p3; + float* B = f->B[blocktype] + n2 - 8; + float* e = buf2 + n2 - 8; + d0 = &buffer[0]; + d1 = &buffer[n2 - 4]; + d2 = &buffer[n2]; + d3 = &buffer[n - 4]; + while (e >= v) + { + float p0, p1, p2, p3; - p3 = e[6]*B[7] - e[7]*B[6]; - p2 = -e[6]*B[6] - e[7]*B[7]; + p3 = e[6] * B[7] - e[7] * B[6]; + p2 = -e[6] * B[6] - e[7] * B[7]; - d0[0] = p3; - d1[3] = - p3; - d2[0] = p2; - d3[3] = p2; + d0[0] = p3; + d1[3] = - p3; + d2[0] = p2; + d3[3] = p2; - p1 = e[4]*B[5] - e[5]*B[4]; - p0 = -e[4]*B[4] - e[5]*B[5]; + p1 = e[4] * B[5] - e[5] * B[4]; + p0 = -e[4] * B[4] - e[5] * B[5]; - d0[1] = p1; - d1[2] = - p1; - d2[1] = p0; - d3[2] = p0; + d0[1] = p1; + d1[2] = - p1; + d2[1] = p0; + d3[2] = p0; - p3 = e[2]*B[3] - e[3]*B[2]; - p2 = -e[2]*B[2] - e[3]*B[3]; + p3 = e[2] * B[3] - e[3] * B[2]; + p2 = -e[2] * B[2] - e[3] * B[3]; - d0[2] = p3; - d1[1] = - p3; - d2[2] = p2; - d3[1] = p2; + d0[2] = p3; + d1[1] = - p3; + d2[2] = p2; + d3[1] = p2; - p1 = e[0]*B[1] - e[1]*B[0]; - p0 = -e[0]*B[0] - e[1]*B[1]; + p1 = e[0] * B[1] - e[1] * B[0]; + p0 = -e[0] * B[0] - e[1] * B[1]; - d0[3] = p1; - d1[0] = - p1; - d2[3] = p0; - d3[0] = p0; + d0[3] = p1; + d1[0] = - p1; + d2[3] = p0; + d3[0] = p0; - B -= 8; - e -= 8; - d0 += 4; - d2 += 4; - d1 -= 4; - d3 -= 4; - } - } + B -= 8; + e -= 8; + d0 += 4; + d2 += 4; + d1 -= 4; + d3 -= 4; + } + } - temp_alloc_restore(f,save_point); + temp_alloc_restore(f, save_point); } #if 0 @@ -2696,13 +2875,13 @@ void inverse_mdct_naive(float *buffer, int n) } #endif -static float *get_window(vorb *f, int len) +static float* get_window(vorb* f, int len) { - len <<= 1; - if (len == f->blocksize_0) return f->window[0]; - if (len == f->blocksize_1) return f->window[1]; - assert(0); - return NULL; + len <<= 1; + if (len == f->blocksize_0) return f->window[0]; + if (len == f->blocksize_1) return f->window[1]; + assert(0); + return NULL; } #ifndef STB_VORBIS_NO_DEFER_FLOOR @@ -2710,41 +2889,46 @@ typedef int16 YTYPE; #else typedef int YTYPE; #endif -static int do_floor(vorb *f, Mapping *map, int i, int n, float *target, YTYPE *finalY, uint8 *step2_flag) +static int do_floor(vorb* f, Mapping* map, int i, int n, float* target, YTYPE* finalY, uint8* step2_flag) { - int n2 = n >> 1; - int s = map->chan[i].mux, floor; - floor = map->submap_floor[s]; - if (f->floor_types[floor] == 0) { - return error(f, VORBIS_invalid_stream); - } else { - Floor1 *g = &f->floor_config[floor].floor1; - int j,q; - int lx = 0, ly = finalY[0] * g->floor1_multiplier; - for (q=1; q < g->values; ++q) { - j = g->sorted_order[q]; - #ifndef STB_VORBIS_NO_DEFER_FLOOR - if (finalY[j] >= 0) - #else + int n2 = n >> 1; + int s = map->chan[i].mux, floor; + floor = map->submap_floor[s]; + if (f->floor_types[floor] == 0) + { + return error(f, VORBIS_invalid_stream); + } + else + { + Floor1* g = &f->floor_config[floor].floor1; + int j, q; + int lx = 0, ly = finalY[0] * g->floor1_multiplier; + for (q = 1; q < g->values; ++q) + { + j = g->sorted_order[q]; +#ifndef STB_VORBIS_NO_DEFER_FLOOR + if (finalY[j] >= 0) +#else if (step2_flag[j]) - #endif - { - int hy = finalY[j] * g->floor1_multiplier; - int hx = g->Xlist[j]; - if (lx != hx) - draw_line(target, lx,ly, hx,hy, n2); - CHECK(f); - lx = hx, ly = hy; - } - } - if (lx < n2) { - // optimization of: draw_line(target, lx,ly, n,ly, n2); - for (j=lx; j < n2; ++j) - LINE_OP(target[j], inverse_db_table[ly]); - CHECK(f); - } - } - return TRUE; +#endif + { + int hy = finalY[j] * g->floor1_multiplier; + int hx = g->Xlist[j]; + if (lx != hx) + draw_line(target, lx, ly, hx, hy, n2); + CHECK(f); + lx = hx, ly = hy; + } + } + if (lx < n2) + { + // optimization of: draw_line(target, lx,ly, n,ly, n2); + for (j = lx; j < n2; ++j) + LINE_OP(target[j], inverse_db_table[ly]); + CHECK(f); + } + } + return TRUE; } // The meaning of "left" and "right" @@ -2761,242 +2945,282 @@ static int do_floor(vorb *f, Mapping *map, int i, int n, float *target, YTYPE *f // has to be the same as frame N+1's left_end-left_start (which they are by // construction) -static int vorbis_decode_initial(vorb *f, int *p_left_start, int *p_left_end, int *p_right_start, int *p_right_end, int *mode) +static int vorbis_decode_initial(vorb* f, int* p_left_start, int* p_left_end, int* p_right_start, int* p_right_end, + int* mode) { - Mode *m; - int i, n, prev, next, window_center; - f->channel_buffer_start = f->channel_buffer_end = 0; + Mode* m; + int i, n, prev, next, window_center; + f->channel_buffer_start = f->channel_buffer_end = 0; - retry: - if (f->eof) return FALSE; - if (!maybe_start_packet(f)) - return FALSE; - // check packet type - if (get_bits(f,1) != 0) { - if (IS_PUSH_MODE(f)) - return error(f,VORBIS_bad_packet_type); - while (EOP != get8_packet(f)); - goto retry; - } +retry: + if (f->eof) return FALSE; + if (!maybe_start_packet(f)) + return FALSE; + // check packet type + if (get_bits(f, 1) != 0) + { + if (IS_PUSH_MODE(f)) + return error(f, VORBIS_bad_packet_type); + while (EOP != get8_packet(f)); + goto retry; + } - if (f->alloc.alloc_buffer) - assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); + if (f->alloc.alloc_buffer) + assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); - i = get_bits(f, ilog(f->mode_count-1)); - if (i == EOP) return FALSE; - if (i >= f->mode_count) return FALSE; - *mode = i; - m = f->mode_config + i; - if (m->blockflag) { - n = f->blocksize_1; - prev = get_bits(f,1); - next = get_bits(f,1); - } else { - prev = next = 0; - n = f->blocksize_0; - } + i = get_bits(f, ilog(f->mode_count - 1)); + if (i == EOP) return FALSE; + if (i >= f->mode_count) return FALSE; + *mode = i; + m = f->mode_config + i; + if (m->blockflag) + { + n = f->blocksize_1; + prev = get_bits(f, 1); + next = get_bits(f, 1); + } + else + { + prev = next = 0; + n = f->blocksize_0; + } -// WINDOWING + // WINDOWING - window_center = n >> 1; - if (m->blockflag && !prev) { - *p_left_start = (n - f->blocksize_0) >> 2; - *p_left_end = (n + f->blocksize_0) >> 2; - } else { - *p_left_start = 0; - *p_left_end = window_center; - } - if (m->blockflag && !next) { - *p_right_start = (n*3 - f->blocksize_0) >> 2; - *p_right_end = (n*3 + f->blocksize_0) >> 2; - } else { - *p_right_start = window_center; - *p_right_end = n; - } + window_center = n >> 1; + if (m->blockflag && !prev) + { + *p_left_start = (n - f->blocksize_0) >> 2; + *p_left_end = (n + f->blocksize_0) >> 2; + } + else + { + *p_left_start = 0; + *p_left_end = window_center; + } + if (m->blockflag && !next) + { + *p_right_start = (n * 3 - f->blocksize_0) >> 2; + *p_right_end = (n * 3 + f->blocksize_0) >> 2; + } + else + { + *p_right_start = window_center; + *p_right_end = n; + } - return TRUE; + return TRUE; } -static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, int left_end, int right_start, int right_end, int *p_left) +static int vorbis_decode_packet_rest(vorb* f, int* len, Mode* m, int left_start, int left_end, int right_start, + int right_end, int* p_left) { - Mapping *map; - int i,j,k,n,n2; - int zero_channel[256]; - int really_zero_channel[256]; + Mapping* map; + int i, j, k, n, n2; + int zero_channel[256]; + int really_zero_channel[256]; -// WINDOWING + // WINDOWING - n = f->blocksize[m->blockflag]; - map = &f->mapping[m->mapping]; + n = f->blocksize[m->blockflag]; + map = &f->mapping[m->mapping]; -// FLOORS - n2 = n >> 1; + // FLOORS + n2 = n >> 1; - CHECK(f); + CHECK(f); - for (i=0; i < f->channels; ++i) { - int s = map->chan[i].mux, floor; - zero_channel[i] = FALSE; - floor = map->submap_floor[s]; - if (f->floor_types[floor] == 0) { - return error(f, VORBIS_invalid_stream); - } else { - Floor1 *g = &f->floor_config[floor].floor1; - if (get_bits(f, 1)) { - short *finalY; - uint8 step2_flag[256]; - static int range_list[4] = { 256, 128, 86, 64 }; - int range = range_list[g->floor1_multiplier-1]; - int offset = 2; - finalY = f->finalY[i]; - finalY[0] = get_bits(f, ilog(range)-1); - finalY[1] = get_bits(f, ilog(range)-1); - for (j=0; j < g->partitions; ++j) { - int pclass = g->partition_class_list[j]; - int cdim = g->class_dimensions[pclass]; - int cbits = g->class_subclasses[pclass]; - int csub = (1 << cbits)-1; - int cval = 0; - if (cbits) { - Codebook *c = f->codebooks + g->class_masterbooks[pclass]; - DECODE(cval,f,c); - } - for (k=0; k < cdim; ++k) { - int book = g->subclass_books[pclass][cval & csub]; - cval = cval >> cbits; - if (book >= 0) { - int temp; - Codebook *c = f->codebooks + book; - DECODE(temp,f,c); - finalY[offset++] = temp; - } else - finalY[offset++] = 0; - } - } - if (f->valid_bits == INVALID_BITS) goto error; // behavior according to spec - step2_flag[0] = step2_flag[1] = 1; - for (j=2; j < g->values; ++j) { - int low, high, pred, highroom, lowroom, room, val; - low = g->neighbors[j][0]; - high = g->neighbors[j][1]; - //neighbors(g->Xlist, j, &low, &high); - pred = predict_point(g->Xlist[j], g->Xlist[low], g->Xlist[high], finalY[low], finalY[high]); - val = finalY[j]; - highroom = range - pred; - lowroom = pred; - if (highroom < lowroom) - room = highroom * 2; - else - room = lowroom * 2; - if (val) { - step2_flag[low] = step2_flag[high] = 1; - step2_flag[j] = 1; - if (val >= room) - if (highroom > lowroom) - finalY[j] = val - lowroom + pred; - else - finalY[j] = pred - val + highroom - 1; - else - if (val & 1) - finalY[j] = pred - ((val+1)>>1); - else - finalY[j] = pred + (val>>1); - } else { - step2_flag[j] = 0; - finalY[j] = pred; - } - } + for (i = 0; i < f->channels; ++i) + { + int s = map->chan[i].mux, floor; + zero_channel[i] = FALSE; + floor = map->submap_floor[s]; + if (f->floor_types[floor] == 0) + { + return error(f, VORBIS_invalid_stream); + } + else + { + Floor1* g = &f->floor_config[floor].floor1; + if (get_bits(f, 1)) + { + short* finalY; + uint8 step2_flag[256]; + static int range_list[4] = {256, 128, 86, 64}; + int range = range_list[g->floor1_multiplier - 1]; + int offset = 2; + finalY = f->finalY[i]; + finalY[0] = get_bits(f, ilog(range) - 1); + finalY[1] = get_bits(f, ilog(range) - 1); + for (j = 0; j < g->partitions; ++j) + { + int pclass = g->partition_class_list[j]; + int cdim = g->class_dimensions[pclass]; + int cbits = g->class_subclasses[pclass]; + int csub = (1 << cbits) - 1; + int cval = 0; + if (cbits) + { + Codebook* c = f->codebooks + g->class_masterbooks[pclass]; + DECODE(cval, f, c); + } + for (k = 0; k < cdim; ++k) + { + int book = g->subclass_books[pclass][cval & csub]; + cval = cval >> cbits; + if (book >= 0) + { + int temp; + Codebook* c = f->codebooks + book; + DECODE(temp, f, c); + finalY[offset++] = temp; + } + else + finalY[offset++] = 0; + } + } + if (f->valid_bits == INVALID_BITS) goto error; // behavior according to spec + step2_flag[0] = step2_flag[1] = 1; + for (j = 2; j < g->values; ++j) + { + int low, high, pred, highroom, lowroom, room, val; + low = g->neighbors[j][0]; + high = g->neighbors[j][1]; + //neighbors(g->Xlist, j, &low, &high); + pred = predict_point(g->Xlist[j], g->Xlist[low], g->Xlist[high], finalY[low], finalY[high]); + val = finalY[j]; + highroom = range - pred; + lowroom = pred; + if (highroom < lowroom) + room = highroom * 2; + else + room = lowroom * 2; + if (val) + { + step2_flag[low] = step2_flag[high] = 1; + step2_flag[j] = 1; + if (val >= room) + if (highroom > lowroom) + finalY[j] = val - lowroom + pred; + else + finalY[j] = pred - val + highroom - 1; + else if (val & 1) + finalY[j] = pred - ((val + 1) >> 1); + else + finalY[j] = pred + (val >> 1); + } + else + { + step2_flag[j] = 0; + finalY[j] = pred; + } + } #ifdef STB_VORBIS_NO_DEFER_FLOOR do_floor(f, map, i, n, f->floor_buffers[i], finalY, step2_flag); #else - // defer final floor computation until _after_ residue - for (j=0; j < g->values; ++j) { - if (!step2_flag[j]) - finalY[j] = -1; - } + // defer final floor computation until _after_ residue + for (j = 0; j < g->values; ++j) + { + if (!step2_flag[j]) + finalY[j] = -1; + } #endif - } else { - error: - zero_channel[i] = TRUE; - } - // So we just defer everything else to later + } + else + { + error: + zero_channel[i] = TRUE; + } + // So we just defer everything else to later - // at this point we've decoded the floor into buffer - } - } - CHECK(f); - // at this point we've decoded all floors + // at this point we've decoded the floor into buffer + } + } + CHECK(f); + // at this point we've decoded all floors - if (f->alloc.alloc_buffer) - assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); + if (f->alloc.alloc_buffer) + assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); - // re-enable coupled channels if necessary - memcpy(really_zero_channel, zero_channel, sizeof(really_zero_channel[0]) * f->channels); - for (i=0; i < map->coupling_steps; ++i) - if (!zero_channel[map->chan[i].magnitude] || !zero_channel[map->chan[i].angle]) { - zero_channel[map->chan[i].magnitude] = zero_channel[map->chan[i].angle] = FALSE; - } + // re-enable coupled channels if necessary + memcpy(really_zero_channel, zero_channel, sizeof(really_zero_channel[0]) * f->channels); + for (i = 0; i < map->coupling_steps; ++i) + if (!zero_channel[map->chan[i].magnitude] || !zero_channel[map->chan[i].angle]) + { + zero_channel[map->chan[i].magnitude] = zero_channel[map->chan[i].angle] = FALSE; + } - CHECK(f); -// RESIDUE DECODE - for (i=0; i < map->submaps; ++i) { - float *residue_buffers[STB_VORBIS_MAX_CHANNELS]; - int r; - uint8 do_not_decode[256]; - int ch = 0; - for (j=0; j < f->channels; ++j) { - if (map->chan[j].mux == i) { - if (zero_channel[j]) { - do_not_decode[ch] = TRUE; - residue_buffers[ch] = NULL; - } else { - do_not_decode[ch] = FALSE; - residue_buffers[ch] = f->channel_buffers[j]; - } - ++ch; - } - } - r = map->submap_residue[i]; - decode_residue(f, residue_buffers, ch, n2, r, do_not_decode); - } + CHECK(f); + // RESIDUE DECODE + for (i = 0; i < map->submaps; ++i) + { + float* residue_buffers[STB_VORBIS_MAX_CHANNELS]; + int r; + uint8 do_not_decode[256]; + int ch = 0; + for (j = 0; j < f->channels; ++j) + { + if (map->chan[j].mux == i) + { + if (zero_channel[j]) + { + do_not_decode[ch] = TRUE; + residue_buffers[ch] = NULL; + } + else + { + do_not_decode[ch] = FALSE; + residue_buffers[ch] = f->channel_buffers[j]; + } + ++ch; + } + } + r = map->submap_residue[i]; + decode_residue(f, residue_buffers, ch, n2, r, do_not_decode); + } - if (f->alloc.alloc_buffer) - assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); - CHECK(f); + if (f->alloc.alloc_buffer) + assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); + CHECK(f); -// INVERSE COUPLING - for (i = map->coupling_steps-1; i >= 0; --i) { - int n2 = n >> 1; - float *m = f->channel_buffers[map->chan[i].magnitude]; - float *a = f->channel_buffers[map->chan[i].angle ]; - for (j=0; j < n2; ++j) { - float a2,m2; - if (m[j] > 0) - if (a[j] > 0) - m2 = m[j], a2 = m[j] - a[j]; - else - a2 = m[j], m2 = m[j] + a[j]; - else - if (a[j] > 0) - m2 = m[j], a2 = m[j] + a[j]; - else - a2 = m[j], m2 = m[j] - a[j]; - m[j] = m2; - a[j] = a2; - } - } - CHECK(f); + // INVERSE COUPLING + for (i = map->coupling_steps - 1; i >= 0; --i) + { + int n2 = n >> 1; + float* m = f->channel_buffers[map->chan[i].magnitude]; + float* a = f->channel_buffers[map->chan[i].angle]; + for (j = 0; j < n2; ++j) + { + float a2, m2; + if (m[j] > 0) + if (a[j] > 0) + m2 = m[j], a2 = m[j] - a[j]; + else + a2 = m[j], m2 = m[j] + a[j]; + else if (a[j] > 0) + m2 = m[j], a2 = m[j] + a[j]; + else + a2 = m[j], m2 = m[j] - a[j]; + m[j] = m2; + a[j] = a2; + } + } + CHECK(f); - // finish decoding the floors + // finish decoding the floors #ifndef STB_VORBIS_NO_DEFER_FLOOR - for (i=0; i < f->channels; ++i) { - if (really_zero_channel[i]) { - memset(f->channel_buffers[i], 0, sizeof(*f->channel_buffers[i]) * n2); - } else { - do_floor(f, map, i, n, f->channel_buffers[i], f->finalY[i], NULL); - } - } + for (i = 0; i < f->channels; ++i) + { + if (really_zero_channel[i]) + { + memset(f->channel_buffers[i], 0, sizeof(*f->channel_buffers[i]) * n2); + } + else + { + do_floor(f, map, i, n, f->channel_buffers[i], f->finalY[i], NULL); + } + } #else for (i=0; i < f->channels; ++i) { if (really_zero_channel[i]) { @@ -3008,719 +3232,833 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, } #endif -// INVERSE MDCT - CHECK(f); - for (i=0; i < f->channels; ++i) - inverse_mdct(f->channel_buffers[i], n, f, m->blockflag); - CHECK(f); + // INVERSE MDCT + CHECK(f); + for (i = 0; i < f->channels; ++i) + inverse_mdct(f->channel_buffers[i], n, f, m->blockflag); + CHECK(f); - // this shouldn't be necessary, unless we exited on an error - // and want to flush to get to the next packet - flush_packet(f); + // this shouldn't be necessary, unless we exited on an error + // and want to flush to get to the next packet + flush_packet(f); - if (f->first_decode) { - // assume we start so first non-discarded sample is sample 0 - // this isn't to spec, but spec would require us to read ahead - // and decode the size of all current frames--could be done, - // but presumably it's not a commonly used feature - f->current_loc = -n2; // start of first frame is positioned for discard - // we might have to discard samples "from" the next frame too, - // if we're lapping a large block then a small at the start? - f->discard_samples_deferred = n - right_end; - f->current_loc_valid = TRUE; - f->first_decode = FALSE; - } else if (f->discard_samples_deferred) { - if (f->discard_samples_deferred >= right_start - left_start) { - f->discard_samples_deferred -= (right_start - left_start); - left_start = right_start; - *p_left = left_start; - } else { - left_start += f->discard_samples_deferred; - *p_left = left_start; - f->discard_samples_deferred = 0; - } - } else if (f->previous_length == 0 && f->current_loc_valid) { - // we're recovering from a seek... that means we're going to discard - // the samples from this packet even though we know our position from - // the last page header, so we need to update the position based on - // the discarded samples here - // but wait, the code below is going to add this in itself even - // on a discard, so we don't need to do it here... - } + if (f->first_decode) + { + // assume we start so first non-discarded sample is sample 0 + // this isn't to spec, but spec would require us to read ahead + // and decode the size of all current frames--could be done, + // but presumably it's not a commonly used feature + f->current_loc = -n2; // start of first frame is positioned for discard + // we might have to discard samples "from" the next frame too, + // if we're lapping a large block then a small at the start? + f->discard_samples_deferred = n - right_end; + f->current_loc_valid = TRUE; + f->first_decode = FALSE; + } + else if (f->discard_samples_deferred) + { + if (f->discard_samples_deferred >= right_start - left_start) + { + f->discard_samples_deferred -= (right_start - left_start); + left_start = right_start; + *p_left = left_start; + } + else + { + left_start += f->discard_samples_deferred; + *p_left = left_start; + f->discard_samples_deferred = 0; + } + } + else if (f->previous_length == 0 && f->current_loc_valid) + { + // we're recovering from a seek... that means we're going to discard + // the samples from this packet even though we know our position from + // the last page header, so we need to update the position based on + // the discarded samples here + // but wait, the code below is going to add this in itself even + // on a discard, so we don't need to do it here... + } - // check if we have ogg information about the sample # for this packet - if (f->last_seg_which == f->end_seg_with_known_loc) { - // if we have a valid current loc, and this is final: - if (f->current_loc_valid && (f->page_flag & PAGEFLAG_last_page)) { - uint32 current_end = f->known_loc_for_packet - (n-right_end); - // then let's infer the size of the (probably) short final frame - if (current_end < f->current_loc + (right_end-left_start)) { - if (current_end < f->current_loc) { - // negative truncation, that's impossible! - *len = 0; - } else { - *len = current_end - f->current_loc; - } - *len += left_start; - if (*len > right_end) *len = right_end; // this should never happen - f->current_loc += *len; - return TRUE; - } - } - // otherwise, just set our sample loc - // guess that the ogg granule pos refers to the _middle_ of the - // last frame? - // set f->current_loc to the position of left_start - f->current_loc = f->known_loc_for_packet - (n2-left_start); - f->current_loc_valid = TRUE; - } - if (f->current_loc_valid) - f->current_loc += (right_start - left_start); + // check if we have ogg information about the sample # for this packet + if (f->last_seg_which == f->end_seg_with_known_loc) + { + // if we have a valid current loc, and this is final: + if (f->current_loc_valid && (f->page_flag & PAGEFLAG_last_page)) + { + uint32 current_end = f->known_loc_for_packet - (n - right_end); + // then let's infer the size of the (probably) short final frame + if (current_end < f->current_loc + (right_end - left_start)) + { + if (current_end < f->current_loc) + { + // negative truncation, that's impossible! + *len = 0; + } + else + { + *len = current_end - f->current_loc; + } + *len += left_start; + if (*len > right_end) *len = right_end; // this should never happen + f->current_loc += *len; + return TRUE; + } + } + // otherwise, just set our sample loc + // guess that the ogg granule pos refers to the _middle_ of the + // last frame? + // set f->current_loc to the position of left_start + f->current_loc = f->known_loc_for_packet - (n2 - left_start); + f->current_loc_valid = TRUE; + } + if (f->current_loc_valid) + f->current_loc += (right_start - left_start); - if (f->alloc.alloc_buffer) - assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); - *len = right_end; // ignore samples after the window goes to 0 - CHECK(f); + if (f->alloc.alloc_buffer) + assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); + *len = right_end; // ignore samples after the window goes to 0 + CHECK(f); - return TRUE; + return TRUE; } -static int vorbis_decode_packet(vorb *f, int *len, int *p_left, int *p_right) +static int vorbis_decode_packet(vorb* f, int* len, int* p_left, int* p_right) { - int mode, left_end, right_end; - if (!vorbis_decode_initial(f, p_left, &left_end, p_right, &right_end, &mode)) return 0; - return vorbis_decode_packet_rest(f, len, f->mode_config + mode, *p_left, left_end, *p_right, right_end, p_left); + int mode, left_end, right_end; + if (!vorbis_decode_initial(f, p_left, &left_end, p_right, &right_end, &mode)) return 0; + return vorbis_decode_packet_rest(f, len, f->mode_config + mode, *p_left, left_end, *p_right, right_end, p_left); } -static int vorbis_finish_frame(stb_vorbis *f, int len, int left, int right) +static int vorbis_finish_frame(stb_vorbis* f, int len, int left, int right) { - int prev,i,j; - // we use right&left (the start of the right- and left-window sin()-regions) - // to determine how much to return, rather than inferring from the rules - // (same result, clearer code); 'left' indicates where our sin() window - // starts, therefore where the previous window's right edge starts, and - // therefore where to start mixing from the previous buffer. 'right' - // indicates where our sin() ending-window starts, therefore that's where - // we start saving, and where our returned-data ends. + int prev, i, j; + // we use right&left (the start of the right- and left-window sin()-regions) + // to determine how much to return, rather than inferring from the rules + // (same result, clearer code); 'left' indicates where our sin() window + // starts, therefore where the previous window's right edge starts, and + // therefore where to start mixing from the previous buffer. 'right' + // indicates where our sin() ending-window starts, therefore that's where + // we start saving, and where our returned-data ends. - // mixin from previous window - if (f->previous_length) { - int i,j, n = f->previous_length; - float *w = get_window(f, n); - for (i=0; i < f->channels; ++i) { - for (j=0; j < n; ++j) - f->channel_buffers[i][left+j] = - f->channel_buffers[i][left+j]*w[ j] + - f->previous_window[i][ j]*w[n-1-j]; - } - } + // mixin from previous window + if (f->previous_length) + { + int i, j, n = f->previous_length; + float* w = get_window(f, n); + for (i = 0; i < f->channels; ++i) + { + for (j = 0; j < n; ++j) + f->channel_buffers[i][left + j] = + f->channel_buffers[i][left + j] * w[j] + + f->previous_window[i][j] * w[n - 1 - j]; + } + } - prev = f->previous_length; + prev = f->previous_length; - // last half of this data becomes previous window - f->previous_length = len - right; + // last half of this data becomes previous window + f->previous_length = len - right; - // @OPTIMIZE: could avoid this copy by double-buffering the - // output (flipping previous_window with channel_buffers), but - // then previous_window would have to be 2x as large, and - // channel_buffers couldn't be temp mem (although they're NOT - // currently temp mem, they could be (unless we want to level - // performance by spreading out the computation)) - for (i=0; i < f->channels; ++i) - for (j=0; right+j < len; ++j) - f->previous_window[i][j] = f->channel_buffers[i][right+j]; + // @OPTIMIZE: could avoid this copy by double-buffering the + // output (flipping previous_window with channel_buffers), but + // then previous_window would have to be 2x as large, and + // channel_buffers couldn't be temp mem (although they're NOT + // currently temp mem, they could be (unless we want to level + // performance by spreading out the computation)) + for (i = 0; i < f->channels; ++i) + for (j = 0; right + j < len; ++j) + f->previous_window[i][j] = f->channel_buffers[i][right + j]; - if (!prev) - // there was no previous packet, so this data isn't valid... - // this isn't entirely true, only the would-have-overlapped data - // isn't valid, but this seems to be what the spec requires - return 0; + if (!prev) + // there was no previous packet, so this data isn't valid... + // this isn't entirely true, only the would-have-overlapped data + // isn't valid, but this seems to be what the spec requires + return 0; - // truncate a short frame - if (len < right) right = len; + // truncate a short frame + if (len < right) right = len; - f->samples_output += right-left; + f->samples_output += right - left; - return right - left; + return right - left; } -static int vorbis_pump_first_frame(stb_vorbis *f) +static int vorbis_pump_first_frame(stb_vorbis* f) { - int len, right, left, res; - res = vorbis_decode_packet(f, &len, &left, &right); - if (res) - vorbis_finish_frame(f, len, left, right); - return res; + int len, right, left, res; + res = vorbis_decode_packet(f, &len, &left, &right); + if (res) + vorbis_finish_frame(f, len, left, right); + return res; } #ifndef STB_VORBIS_NO_PUSHDATA_API -static int is_whole_packet_present(stb_vorbis *f, int end_page) +static int is_whole_packet_present(stb_vorbis* f, int end_page) { - // make sure that we have the packet available before continuing... - // this requires a full ogg parse, but we know we can fetch from f->stream + // make sure that we have the packet available before continuing... + // this requires a full ogg parse, but we know we can fetch from f->stream - // instead of coding this out explicitly, we could save the current read state, - // read the next packet with get8() until end-of-packet, check f->eof, then - // reset the state? but that would be slower, esp. since we'd have over 256 bytes - // of state to restore (primarily the page segment table) + // instead of coding this out explicitly, we could save the current read state, + // read the next packet with get8() until end-of-packet, check f->eof, then + // reset the state? but that would be slower, esp. since we'd have over 256 bytes + // of state to restore (primarily the page segment table) - int s = f->next_seg, first = TRUE; - uint8 *p = f->stream; + int s = f->next_seg, first = TRUE; + uint8* p = f->stream; - if (s != -1) { // if we're not starting the packet with a 'continue on next page' flag - for (; s < f->segment_count; ++s) { - p += f->segments[s]; - if (f->segments[s] < 255) // stop at first short segment - break; - } - // either this continues, or it ends it... - if (end_page) - if (s < f->segment_count-1) return error(f, VORBIS_invalid_stream); - if (s == f->segment_count) - s = -1; // set 'crosses page' flag - if (p > f->stream_end) return error(f, VORBIS_need_more_data); - first = FALSE; - } - for (; s == -1;) { - uint8 *q; - int n; + if (s != -1) + { + // if we're not starting the packet with a 'continue on next page' flag + for (; s < f->segment_count; ++s) + { + p += f->segments[s]; + if (f->segments[s] < 255) // stop at first short segment + break; + } + // either this continues, or it ends it... + if (end_page) + if (s < f->segment_count - 1) return error(f, VORBIS_invalid_stream); + if (s == f->segment_count) + s = -1; // set 'crosses page' flag + if (p > f->stream_end) return error(f, VORBIS_need_more_data); + first = FALSE; + } + for (; s == -1;) + { + uint8* q; + int n; - // check that we have the page header ready - if (p + 26 >= f->stream_end) return error(f, VORBIS_need_more_data); - // validate the page - if (memcmp(p, ogg_page_header, 4)) return error(f, VORBIS_invalid_stream); - if (p[4] != 0) return error(f, VORBIS_invalid_stream); - if (first) { // the first segment must NOT have 'continued_packet', later ones MUST - if (f->previous_length) - if ((p[5] & PAGEFLAG_continued_packet)) return error(f, VORBIS_invalid_stream); - // if no previous length, we're resynching, so we can come in on a continued-packet, - // which we'll just drop - } else { - if (!(p[5] & PAGEFLAG_continued_packet)) return error(f, VORBIS_invalid_stream); - } - n = p[26]; // segment counts - q = p+27; // q points to segment table - p = q + n; // advance past header - // make sure we've read the segment table - if (p > f->stream_end) return error(f, VORBIS_need_more_data); - for (s=0; s < n; ++s) { - p += q[s]; - if (q[s] < 255) - break; - } - if (end_page) - if (s < n-1) return error(f, VORBIS_invalid_stream); - if (s == n) - s = -1; // set 'crosses page' flag - if (p > f->stream_end) return error(f, VORBIS_need_more_data); - first = FALSE; - } - return TRUE; + // check that we have the page header ready + if (p + 26 >= f->stream_end) return error(f, VORBIS_need_more_data); + // validate the page + if (memcmp(p, ogg_page_header, 4)) return error(f, VORBIS_invalid_stream); + if (p[4] != 0) return error(f, VORBIS_invalid_stream); + if (first) + { + // the first segment must NOT have 'continued_packet', later ones MUST + if (f->previous_length) + if ((p[5] & PAGEFLAG_continued_packet)) return error(f, VORBIS_invalid_stream); + // if no previous length, we're resynching, so we can come in on a continued-packet, + // which we'll just drop + } + else + { + if (!(p[5] & PAGEFLAG_continued_packet)) return error(f, VORBIS_invalid_stream); + } + n = p[26]; // segment counts + q = p + 27; // q points to segment table + p = q + n; // advance past header + // make sure we've read the segment table + if (p > f->stream_end) return error(f, VORBIS_need_more_data); + for (s = 0; s < n; ++s) + { + p += q[s]; + if (q[s] < 255) + break; + } + if (end_page) + if (s < n - 1) return error(f, VORBIS_invalid_stream); + if (s == n) + s = -1; // set 'crosses page' flag + if (p > f->stream_end) return error(f, VORBIS_need_more_data); + first = FALSE; + } + return TRUE; } #endif // !STB_VORBIS_NO_PUSHDATA_API -static int start_decoder(vorb *f) +static int start_decoder(vorb* f) { - uint8 header[6], x,y; - int len,i,j,k, max_submaps = 0; - int longest_floorlist=0; + uint8 header[6], x, y; + int len, i, j, k, max_submaps = 0; + int longest_floorlist = 0; - // first page, first packet + // first page, first packet - if (!start_page(f)) return FALSE; - // validate page flag - if (!(f->page_flag & PAGEFLAG_first_page)) return error(f, VORBIS_invalid_first_page); - if (f->page_flag & PAGEFLAG_last_page) return error(f, VORBIS_invalid_first_page); - if (f->page_flag & PAGEFLAG_continued_packet) return error(f, VORBIS_invalid_first_page); - // check for expected packet length - if (f->segment_count != 1) return error(f, VORBIS_invalid_first_page); - if (f->segments[0] != 30) return error(f, VORBIS_invalid_first_page); - // read packet - // check packet header - if (get8(f) != VORBIS_packet_id) return error(f, VORBIS_invalid_first_page); - if (!getn(f, header, 6)) return error(f, VORBIS_unexpected_eof); - if (!vorbis_validate(header)) return error(f, VORBIS_invalid_first_page); - // vorbis_version - if (get32(f) != 0) return error(f, VORBIS_invalid_first_page); - f->channels = get8(f); if (!f->channels) return error(f, VORBIS_invalid_first_page); - if (f->channels > STB_VORBIS_MAX_CHANNELS) return error(f, VORBIS_too_many_channels); - f->sample_rate = get32(f); if (!f->sample_rate) return error(f, VORBIS_invalid_first_page); - get32(f); // bitrate_maximum - get32(f); // bitrate_nominal - get32(f); // bitrate_minimum - x = get8(f); - { - int log0,log1; - log0 = x & 15; - log1 = x >> 4; - f->blocksize_0 = 1 << log0; - f->blocksize_1 = 1 << log1; - if (log0 < 6 || log0 > 13) return error(f, VORBIS_invalid_setup); - if (log1 < 6 || log1 > 13) return error(f, VORBIS_invalid_setup); - if (log0 > log1) return error(f, VORBIS_invalid_setup); - } + if (!start_page(f)) return FALSE; + // validate page flag + if (!(f->page_flag & PAGEFLAG_first_page)) return error(f, VORBIS_invalid_first_page); + if (f->page_flag & PAGEFLAG_last_page) return error(f, VORBIS_invalid_first_page); + if (f->page_flag & PAGEFLAG_continued_packet) return error(f, VORBIS_invalid_first_page); + // check for expected packet length + if (f->segment_count != 1) return error(f, VORBIS_invalid_first_page); + if (f->segments[0] != 30) return error(f, VORBIS_invalid_first_page); + // read packet + // check packet header + if (get8(f) != VORBIS_packet_id) return error(f, VORBIS_invalid_first_page); + if (!getn(f, header, 6)) return error(f, VORBIS_unexpected_eof); + if (!vorbis_validate(header)) return error(f, VORBIS_invalid_first_page); + // vorbis_version + if (get32(f) != 0) return error(f, VORBIS_invalid_first_page); + f->channels = get8(f); + if (!f->channels) return error(f, VORBIS_invalid_first_page); + if (f->channels > STB_VORBIS_MAX_CHANNELS) return error(f, VORBIS_too_many_channels); + f->sample_rate = get32(f); + if (!f->sample_rate) return error(f, VORBIS_invalid_first_page); + get32(f); // bitrate_maximum + get32(f); // bitrate_nominal + get32(f); // bitrate_minimum + x = get8(f); + { + int log0, log1; + log0 = x & 15; + log1 = x >> 4; + f->blocksize_0 = 1 << log0; + f->blocksize_1 = 1 << log1; + if (log0 < 6 || log0 > 13) return error(f, VORBIS_invalid_setup); + if (log1 < 6 || log1 > 13) return error(f, VORBIS_invalid_setup); + if (log0 > log1) return error(f, VORBIS_invalid_setup); + } - // framing_flag - x = get8(f); - if (!(x & 1)) return error(f, VORBIS_invalid_first_page); + // framing_flag + x = get8(f); + if (!(x & 1)) return error(f, VORBIS_invalid_first_page); - // second packet! - if (!start_page(f)) return FALSE; + // second packet! + if (!start_page(f)) return FALSE; - if (!start_packet(f)) return FALSE; - do { - len = next_segment(f); - skip(f, len); - f->bytes_in_seg = 0; - } while (len); + if (!start_packet(f)) return FALSE; + do + { + len = next_segment(f); + skip(f, len); + f->bytes_in_seg = 0; + } + while (len); - // third packet! - if (!start_packet(f)) return FALSE; + // third packet! + if (!start_packet(f)) return FALSE; - #ifndef STB_VORBIS_NO_PUSHDATA_API - if (IS_PUSH_MODE(f)) { - if (!is_whole_packet_present(f, TRUE)) { - // convert error in ogg header to write type - if (f->error == VORBIS_invalid_stream) - f->error = VORBIS_invalid_setup; - return FALSE; - } - } - #endif +#ifndef STB_VORBIS_NO_PUSHDATA_API + if (IS_PUSH_MODE(f)) + { + if (!is_whole_packet_present(f, TRUE)) + { + // convert error in ogg header to write type + if (f->error == VORBIS_invalid_stream) + f->error = VORBIS_invalid_setup; + return FALSE; + } + } +#endif - crc32_init(); // always init it, to avoid multithread race conditions + crc32_init(); // always init it, to avoid multithread race conditions - if (get8_packet(f) != VORBIS_packet_setup) return error(f, VORBIS_invalid_setup); - for (i=0; i < 6; ++i) header[i] = get8_packet(f); - if (!vorbis_validate(header)) return error(f, VORBIS_invalid_setup); + if (get8_packet(f) != VORBIS_packet_setup) return error(f, VORBIS_invalid_setup); + for (i = 0; i < 6; ++i) header[i] = get8_packet(f); + if (!vorbis_validate(header)) return error(f, VORBIS_invalid_setup); - // codebooks + // codebooks - f->codebook_count = get_bits(f,8) + 1; - f->codebooks = (Codebook *) setup_malloc(f, sizeof(*f->codebooks) * f->codebook_count); - if (f->codebooks == NULL) return error(f, VORBIS_outofmem); - memset(f->codebooks, 0, sizeof(*f->codebooks) * f->codebook_count); - for (i=0; i < f->codebook_count; ++i) { - uint32 *values; - int ordered, sorted_count; - int total=0; - uint8 *lengths; - Codebook *c = f->codebooks+i; - CHECK(f); - x = get_bits(f, 8); if (x != 0x42) return error(f, VORBIS_invalid_setup); - x = get_bits(f, 8); if (x != 0x43) return error(f, VORBIS_invalid_setup); - x = get_bits(f, 8); if (x != 0x56) return error(f, VORBIS_invalid_setup); - x = get_bits(f, 8); - c->dimensions = (get_bits(f, 8)<<8) + x; - x = get_bits(f, 8); - y = get_bits(f, 8); - c->entries = (get_bits(f, 8)<<16) + (y<<8) + x; - ordered = get_bits(f,1); - c->sparse = ordered ? 0 : get_bits(f,1); + f->codebook_count = get_bits(f, 8) + 1; + f->codebooks = (Codebook*)setup_malloc(f, sizeof(*f->codebooks) * f->codebook_count); + if (f->codebooks == NULL) return error(f, VORBIS_outofmem); + memset(f->codebooks, 0, sizeof(*f->codebooks) * f->codebook_count); + for (i = 0; i < f->codebook_count; ++i) + { + uint32* values; + int ordered, sorted_count; + int total = 0; + uint8* lengths; + Codebook* c = f->codebooks + i; + CHECK(f); + x = get_bits(f, 8); + if (x != 0x42) return error(f, VORBIS_invalid_setup); + x = get_bits(f, 8); + if (x != 0x43) return error(f, VORBIS_invalid_setup); + x = get_bits(f, 8); + if (x != 0x56) return error(f, VORBIS_invalid_setup); + x = get_bits(f, 8); + c->dimensions = (get_bits(f, 8) << 8) + x; + x = get_bits(f, 8); + y = get_bits(f, 8); + c->entries = (get_bits(f, 8) << 16) + (y << 8) + x; + ordered = get_bits(f, 1); + c->sparse = ordered ? 0 : get_bits(f, 1); - if (c->dimensions == 0 && c->entries != 0) return error(f, VORBIS_invalid_setup); + if (c->dimensions == 0 && c->entries != 0) return error(f, VORBIS_invalid_setup); - if (c->sparse) - lengths = (uint8 *) setup_temp_malloc(f, c->entries); - else - lengths = c->codeword_lengths = (uint8 *) setup_malloc(f, c->entries); + if (c->sparse) + lengths = (uint8*)setup_temp_malloc(f, c->entries); + else + lengths = c->codeword_lengths = (uint8*)setup_malloc(f, c->entries); - if (!lengths) return error(f, VORBIS_outofmem); + if (!lengths) return error(f, VORBIS_outofmem); - if (ordered) { - int current_entry = 0; - int current_length = get_bits(f,5) + 1; - while (current_entry < c->entries) { - int limit = c->entries - current_entry; - int n = get_bits(f, ilog(limit)); - if (current_entry + n > (int) c->entries) { return error(f, VORBIS_invalid_setup); } - memset(lengths + current_entry, current_length, n); - current_entry += n; - ++current_length; - } - } else { - for (j=0; j < c->entries; ++j) { - int present = c->sparse ? get_bits(f,1) : 1; - if (present) { - lengths[j] = get_bits(f, 5) + 1; - ++total; - if (lengths[j] == 32) - return error(f, VORBIS_invalid_setup); - } else { - lengths[j] = NO_CODE; - } - } - } + if (ordered) + { + int current_entry = 0; + int current_length = get_bits(f, 5) + 1; + while (current_entry < c->entries) + { + int limit = c->entries - current_entry; + int n = get_bits(f, ilog(limit)); + if (current_entry + n > (int)c->entries) { return error(f, VORBIS_invalid_setup); } + memset(lengths + current_entry, current_length, n); + current_entry += n; + ++current_length; + } + } + else + { + for (j = 0; j < c->entries; ++j) + { + int present = c->sparse ? get_bits(f, 1) : 1; + if (present) + { + lengths[j] = get_bits(f, 5) + 1; + ++total; + if (lengths[j] == 32) + return error(f, VORBIS_invalid_setup); + } + else + { + lengths[j] = NO_CODE; + } + } + } - if (c->sparse && total >= c->entries >> 2) { - // convert sparse items to non-sparse! - if (c->entries > (int) f->setup_temp_memory_required) - f->setup_temp_memory_required = c->entries; + if (c->sparse && total >= c->entries >> 2) + { + // convert sparse items to non-sparse! + if (c->entries > (int)f->setup_temp_memory_required) + f->setup_temp_memory_required = c->entries; - c->codeword_lengths = (uint8 *) setup_malloc(f, c->entries); - if (c->codeword_lengths == NULL) return error(f, VORBIS_outofmem); - memcpy(c->codeword_lengths, lengths, c->entries); - setup_temp_free(f, lengths, c->entries); // note this is only safe if there have been no intervening temp mallocs! - lengths = c->codeword_lengths; - c->sparse = 0; - } + c->codeword_lengths = (uint8*)setup_malloc(f, c->entries); + if (c->codeword_lengths == NULL) return error(f, VORBIS_outofmem); + memcpy(c->codeword_lengths, lengths, c->entries); + setup_temp_free(f, lengths, c->entries); + // note this is only safe if there have been no intervening temp mallocs! + lengths = c->codeword_lengths; + c->sparse = 0; + } - // compute the size of the sorted tables - if (c->sparse) { - sorted_count = total; - } else { - sorted_count = 0; - #ifndef STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH - for (j=0; j < c->entries; ++j) - if (lengths[j] > STB_VORBIS_FAST_HUFFMAN_LENGTH && lengths[j] != NO_CODE) - ++sorted_count; - #endif - } + // compute the size of the sorted tables + if (c->sparse) + { + sorted_count = total; + } + else + { + sorted_count = 0; +#ifndef STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH + for (j = 0; j < c->entries; ++j) + if (lengths[j] > STB_VORBIS_FAST_HUFFMAN_LENGTH && lengths[j] != NO_CODE) + ++sorted_count; +#endif + } - c->sorted_entries = sorted_count; - values = NULL; + c->sorted_entries = sorted_count; + values = NULL; - CHECK(f); - if (!c->sparse) { - c->codewords = (uint32 *) setup_malloc(f, sizeof(c->codewords[0]) * c->entries); - if (!c->codewords) return error(f, VORBIS_outofmem); - } else { - unsigned int size; - if (c->sorted_entries) { - c->codeword_lengths = (uint8 *) setup_malloc(f, c->sorted_entries); - if (!c->codeword_lengths) return error(f, VORBIS_outofmem); - c->codewords = (uint32 *) setup_temp_malloc(f, sizeof(*c->codewords) * c->sorted_entries); - if (!c->codewords) return error(f, VORBIS_outofmem); - values = (uint32 *) setup_temp_malloc(f, sizeof(*values) * c->sorted_entries); - if (!values) return error(f, VORBIS_outofmem); - } - size = c->entries + (sizeof(*c->codewords) + sizeof(*values)) * c->sorted_entries; - if (size > f->setup_temp_memory_required) - f->setup_temp_memory_required = size; - } + CHECK(f); + if (!c->sparse) + { + c->codewords = (uint32*)setup_malloc(f, sizeof(c->codewords[0]) * c->entries); + if (!c->codewords) return error(f, VORBIS_outofmem); + } + else + { + unsigned int size; + if (c->sorted_entries) + { + c->codeword_lengths = (uint8*)setup_malloc(f, c->sorted_entries); + if (!c->codeword_lengths) return error(f, VORBIS_outofmem); + c->codewords = (uint32*)setup_temp_malloc(f, sizeof(*c->codewords) * c->sorted_entries); + if (!c->codewords) return error(f, VORBIS_outofmem); + values = (uint32*)setup_temp_malloc(f, sizeof(*values) * c->sorted_entries); + if (!values) return error(f, VORBIS_outofmem); + } + size = c->entries + (sizeof(*c->codewords) + sizeof(*values)) * c->sorted_entries; + if (size > f->setup_temp_memory_required) + f->setup_temp_memory_required = size; + } - if (!compute_codewords(c, lengths, c->entries, values)) { - if (c->sparse) setup_temp_free(f, values, 0); - return error(f, VORBIS_invalid_setup); - } + if (!compute_codewords(c, lengths, c->entries, values)) + { + if (c->sparse) setup_temp_free(f, values, 0); + return error(f, VORBIS_invalid_setup); + } - if (c->sorted_entries) { - // allocate an extra slot for sentinels - c->sorted_codewords = (uint32 *) setup_malloc(f, sizeof(*c->sorted_codewords) * (c->sorted_entries+1)); - if (c->sorted_codewords == NULL) return error(f, VORBIS_outofmem); - // allocate an extra slot at the front so that c->sorted_values[-1] is defined - // so that we can catch that case without an extra if - c->sorted_values = ( int *) setup_malloc(f, sizeof(*c->sorted_values ) * (c->sorted_entries+1)); - if (c->sorted_values == NULL) return error(f, VORBIS_outofmem); - ++c->sorted_values; - c->sorted_values[-1] = -1; - compute_sorted_huffman(c, lengths, values); - } + if (c->sorted_entries) + { + // allocate an extra slot for sentinels + c->sorted_codewords = (uint32*)setup_malloc(f, sizeof(*c->sorted_codewords) * (c->sorted_entries + 1)); + if (c->sorted_codewords == NULL) return error(f, VORBIS_outofmem); + // allocate an extra slot at the front so that c->sorted_values[-1] is defined + // so that we can catch that case without an extra if + c->sorted_values = (int*)setup_malloc(f, sizeof(*c->sorted_values) * (c->sorted_entries + 1)); + if (c->sorted_values == NULL) return error(f, VORBIS_outofmem); + ++c->sorted_values; + c->sorted_values[-1] = -1; + compute_sorted_huffman(c, lengths, values); + } - if (c->sparse) { - setup_temp_free(f, values, sizeof(*values)*c->sorted_entries); - setup_temp_free(f, c->codewords, sizeof(*c->codewords)*c->sorted_entries); - setup_temp_free(f, lengths, c->entries); - c->codewords = NULL; - } + if (c->sparse) + { + setup_temp_free(f, values, sizeof(*values) * c->sorted_entries); + setup_temp_free(f, c->codewords, sizeof(*c->codewords) * c->sorted_entries); + setup_temp_free(f, lengths, c->entries); + c->codewords = NULL; + } - compute_accelerated_huffman(c); + compute_accelerated_huffman(c); - CHECK(f); - c->lookup_type = get_bits(f, 4); - if (c->lookup_type > 2) return error(f, VORBIS_invalid_setup); - if (c->lookup_type > 0) { - uint16 *mults; - c->minimum_value = float32_unpack(get_bits(f, 32)); - c->delta_value = float32_unpack(get_bits(f, 32)); - c->value_bits = get_bits(f, 4)+1; - c->sequence_p = get_bits(f,1); - if (c->lookup_type == 1) { - c->lookup_values = lookup1_values(c->entries, c->dimensions); - } else { - c->lookup_values = c->entries * c->dimensions; - } - if (c->lookup_values == 0) return error(f, VORBIS_invalid_setup); - mults = (uint16 *) setup_temp_malloc(f, sizeof(mults[0]) * c->lookup_values); - if (mults == NULL) return error(f, VORBIS_outofmem); - for (j=0; j < (int) c->lookup_values; ++j) { - int q = get_bits(f, c->value_bits); - if (q == EOP) { setup_temp_free(f,mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_invalid_setup); } - mults[j] = q; - } + CHECK(f); + c->lookup_type = get_bits(f, 4); + if (c->lookup_type > 2) return error(f, VORBIS_invalid_setup); + if (c->lookup_type > 0) + { + uint16* mults; + c->minimum_value = float32_unpack(get_bits(f, 32)); + c->delta_value = float32_unpack(get_bits(f, 32)); + c->value_bits = get_bits(f, 4) + 1; + c->sequence_p = get_bits(f, 1); + if (c->lookup_type == 1) + { + c->lookup_values = lookup1_values(c->entries, c->dimensions); + } + else + { + c->lookup_values = c->entries * c->dimensions; + } + if (c->lookup_values == 0) return error(f, VORBIS_invalid_setup); + mults = (uint16*)setup_temp_malloc(f, sizeof(mults[0]) * c->lookup_values); + if (mults == NULL) return error(f, VORBIS_outofmem); + for (j = 0; j < (int)c->lookup_values; ++j) + { + int q = get_bits(f, c->value_bits); + if (q == EOP) + { + setup_temp_free(f, mults, sizeof(mults[0]) * c->lookup_values); + return error(f, VORBIS_invalid_setup); + } + mults[j] = q; + } #ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK - if (c->lookup_type == 1) { - int len, sparse = c->sparse; - float last=0; - // pre-expand the lookup1-style multiplicands, to avoid a divide in the inner loop - if (sparse) { - if (c->sorted_entries == 0) goto skip; - c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->sorted_entries * c->dimensions); - } else - c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->entries * c->dimensions); - if (c->multiplicands == NULL) { setup_temp_free(f,mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); } - len = sparse ? c->sorted_entries : c->entries; - for (j=0; j < len; ++j) { - unsigned int z = sparse ? c->sorted_values[j] : j; - unsigned int div=1; - for (k=0; k < c->dimensions; ++k) { - int off = (z / div) % c->lookup_values; - float val = mults[off]; - val = mults[off]*c->delta_value + c->minimum_value + last; - c->multiplicands[j*c->dimensions + k] = val; - if (c->sequence_p) - last = val; - if (k+1 < c->dimensions) { - if (div > UINT_MAX / (unsigned int) c->lookup_values) { - setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); - return error(f, VORBIS_invalid_setup); - } - div *= c->lookup_values; - } - } - } - c->lookup_type = 2; - } - else + if (c->lookup_type == 1) + { + int len, sparse = c->sparse; + float last = 0; + // pre-expand the lookup1-style multiplicands, to avoid a divide in the inner loop + if (sparse) + { + if (c->sorted_entries == 0) goto skip; + c->multiplicands = (codetype*)setup_malloc( + f, sizeof(c->multiplicands[0]) * c->sorted_entries * c->dimensions); + } + else + c->multiplicands = (codetype*)setup_malloc(f, sizeof(c->multiplicands[0]) * c->entries * c->dimensions); + if (c->multiplicands == NULL) + { + setup_temp_free(f, mults, sizeof(mults[0]) * c->lookup_values); + return error(f, VORBIS_outofmem); + } + len = sparse ? c->sorted_entries : c->entries; + for (j = 0; j < len; ++j) + { + unsigned int z = sparse ? c->sorted_values[j] : j; + unsigned int div = 1; + for (k = 0; k < c->dimensions; ++k) + { + int off = (z / div) % c->lookup_values; + float val = mults[off]; + val = mults[off] * c->delta_value + c->minimum_value + last; + c->multiplicands[j * c->dimensions + k] = val; + if (c->sequence_p) + last = val; + if (k + 1 < c->dimensions) + { + if (div > UINT_MAX / (unsigned int)c->lookup_values) + { + setup_temp_free(f, mults, sizeof(mults[0]) * c->lookup_values); + return error(f, VORBIS_invalid_setup); + } + div *= c->lookup_values; + } + } + } + c->lookup_type = 2; + } + else #endif - { - float last=0; - CHECK(f); - c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->lookup_values); - if (c->multiplicands == NULL) { setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); } - for (j=0; j < (int) c->lookup_values; ++j) { - float val = mults[j] * c->delta_value + c->minimum_value + last; - c->multiplicands[j] = val; - if (c->sequence_p) - last = val; - } - } + { + float last = 0; + CHECK(f); + c->multiplicands = (codetype*)setup_malloc(f, sizeof(c->multiplicands[0]) * c->lookup_values); + if (c->multiplicands == NULL) + { + setup_temp_free(f, mults, sizeof(mults[0]) * c->lookup_values); + return error(f, VORBIS_outofmem); + } + for (j = 0; j < (int)c->lookup_values; ++j) + { + float val = mults[j] * c->delta_value + c->minimum_value + last; + c->multiplicands[j] = val; + if (c->sequence_p) + last = val; + } + } #ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK - skip:; + skip:; #endif - setup_temp_free(f, mults, sizeof(mults[0])*c->lookup_values); + setup_temp_free(f, mults, sizeof(mults[0]) * c->lookup_values); - CHECK(f); - } - CHECK(f); - } + CHECK(f); + } + CHECK(f); + } - // time domain transfers (notused) + // time domain transfers (notused) - x = get_bits(f, 6) + 1; - for (i=0; i < x; ++i) { - uint32 z = get_bits(f, 16); - if (z != 0) return error(f, VORBIS_invalid_setup); - } + x = get_bits(f, 6) + 1; + for (i = 0; i < x; ++i) + { + uint32 z = get_bits(f, 16); + if (z != 0) return error(f, VORBIS_invalid_setup); + } - // Floors - f->floor_count = get_bits(f, 6)+1; - f->floor_config = (Floor *) setup_malloc(f, f->floor_count * sizeof(*f->floor_config)); - if (f->floor_config == NULL) return error(f, VORBIS_outofmem); - for (i=0; i < f->floor_count; ++i) { - f->floor_types[i] = get_bits(f, 16); - if (f->floor_types[i] > 1) return error(f, VORBIS_invalid_setup); - if (f->floor_types[i] == 0) { - Floor0 *g = &f->floor_config[i].floor0; - g->order = get_bits(f,8); - g->rate = get_bits(f,16); - g->bark_map_size = get_bits(f,16); - g->amplitude_bits = get_bits(f,6); - g->amplitude_offset = get_bits(f,8); - g->number_of_books = get_bits(f,4) + 1; - for (j=0; j < g->number_of_books; ++j) - g->book_list[j] = get_bits(f,8); - return error(f, VORBIS_feature_not_supported); - } else { - stbv__floor_ordering p[31*8+2]; - Floor1 *g = &f->floor_config[i].floor1; - int max_class = -1; - g->partitions = get_bits(f, 5); - for (j=0; j < g->partitions; ++j) { - g->partition_class_list[j] = get_bits(f, 4); - if (g->partition_class_list[j] > max_class) - max_class = g->partition_class_list[j]; - } - for (j=0; j <= max_class; ++j) { - g->class_dimensions[j] = get_bits(f, 3)+1; - g->class_subclasses[j] = get_bits(f, 2); - if (g->class_subclasses[j]) { - g->class_masterbooks[j] = get_bits(f, 8); - if (g->class_masterbooks[j] >= f->codebook_count) return error(f, VORBIS_invalid_setup); - } - for (k=0; k < 1 << g->class_subclasses[j]; ++k) { - g->subclass_books[j][k] = get_bits(f,8)-1; - if (g->subclass_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup); - } - } - g->floor1_multiplier = get_bits(f,2)+1; - g->rangebits = get_bits(f,4); - g->Xlist[0] = 0; - g->Xlist[1] = 1 << g->rangebits; - g->values = 2; - for (j=0; j < g->partitions; ++j) { - int c = g->partition_class_list[j]; - for (k=0; k < g->class_dimensions[c]; ++k) { - g->Xlist[g->values] = get_bits(f, g->rangebits); - ++g->values; - } - } - // precompute the sorting - for (j=0; j < g->values; ++j) { - p[j].x = g->Xlist[j]; - p[j].id = j; - } - qsort(p, g->values, sizeof(p[0]), point_compare); - for (j=0; j < g->values; ++j) - g->sorted_order[j] = (uint8) p[j].id; - // precompute the neighbors - for (j=2; j < g->values; ++j) { - int low=0,hi=0; - neighbors(g->Xlist, j, &low,&hi); - g->neighbors[j][0] = low; - g->neighbors[j][1] = hi; - } + // Floors + f->floor_count = get_bits(f, 6) + 1; + f->floor_config = (Floor*)setup_malloc(f, f->floor_count * sizeof(*f->floor_config)); + if (f->floor_config == NULL) return error(f, VORBIS_outofmem); + for (i = 0; i < f->floor_count; ++i) + { + f->floor_types[i] = get_bits(f, 16); + if (f->floor_types[i] > 1) return error(f, VORBIS_invalid_setup); + if (f->floor_types[i] == 0) + { + Floor0* g = &f->floor_config[i].floor0; + g->order = get_bits(f, 8); + g->rate = get_bits(f, 16); + g->bark_map_size = get_bits(f, 16); + g->amplitude_bits = get_bits(f, 6); + g->amplitude_offset = get_bits(f, 8); + g->number_of_books = get_bits(f, 4) + 1; + for (j = 0; j < g->number_of_books; ++j) + g->book_list[j] = get_bits(f, 8); + return error(f, VORBIS_feature_not_supported); + } + else + { + stbv__floor_ordering p[31 * 8 + 2]; + Floor1* g = &f->floor_config[i].floor1; + int max_class = -1; + g->partitions = get_bits(f, 5); + for (j = 0; j < g->partitions; ++j) + { + g->partition_class_list[j] = get_bits(f, 4); + if (g->partition_class_list[j] > max_class) + max_class = g->partition_class_list[j]; + } + for (j = 0; j <= max_class; ++j) + { + g->class_dimensions[j] = get_bits(f, 3) + 1; + g->class_subclasses[j] = get_bits(f, 2); + if (g->class_subclasses[j]) + { + g->class_masterbooks[j] = get_bits(f, 8); + if (g->class_masterbooks[j] >= f->codebook_count) return error(f, VORBIS_invalid_setup); + } + for (k = 0; k < 1 << g->class_subclasses[j]; ++k) + { + g->subclass_books[j][k] = get_bits(f, 8) - 1; + if (g->subclass_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup); + } + } + g->floor1_multiplier = get_bits(f, 2) + 1; + g->rangebits = get_bits(f, 4); + g->Xlist[0] = 0; + g->Xlist[1] = 1 << g->rangebits; + g->values = 2; + for (j = 0; j < g->partitions; ++j) + { + int c = g->partition_class_list[j]; + for (k = 0; k < g->class_dimensions[c]; ++k) + { + g->Xlist[g->values] = get_bits(f, g->rangebits); + ++g->values; + } + } + // precompute the sorting + for (j = 0; j < g->values; ++j) + { + p[j].x = g->Xlist[j]; + p[j].id = j; + } + qsort(p, g->values, sizeof(p[0]), point_compare); + for (j = 0; j < g->values; ++j) + g->sorted_order[j] = (uint8)p[j].id; + // precompute the neighbors + for (j = 2; j < g->values; ++j) + { + int low = 0, hi = 0; + neighbors(g->Xlist, j, &low, &hi); + g->neighbors[j][0] = low; + g->neighbors[j][1] = hi; + } - if (g->values > longest_floorlist) - longest_floorlist = g->values; - } - } + if (g->values > longest_floorlist) + longest_floorlist = g->values; + } + } - // Residue - f->residue_count = get_bits(f, 6)+1; - f->residue_config = (Residue *) setup_malloc(f, f->residue_count * sizeof(f->residue_config[0])); - if (f->residue_config == NULL) return error(f, VORBIS_outofmem); - memset(f->residue_config, 0, f->residue_count * sizeof(f->residue_config[0])); - for (i=0; i < f->residue_count; ++i) { - uint8 residue_cascade[64]; - Residue *r = f->residue_config+i; - f->residue_types[i] = get_bits(f, 16); - if (f->residue_types[i] > 2) return error(f, VORBIS_invalid_setup); - r->begin = get_bits(f, 24); - r->end = get_bits(f, 24); - if (r->end < r->begin) return error(f, VORBIS_invalid_setup); - r->part_size = get_bits(f,24)+1; - r->classifications = get_bits(f,6)+1; - r->classbook = get_bits(f,8); - if (r->classbook >= f->codebook_count) return error(f, VORBIS_invalid_setup); - for (j=0; j < r->classifications; ++j) { - uint8 high_bits=0; - uint8 low_bits=get_bits(f,3); - if (get_bits(f,1)) - high_bits = get_bits(f,5); - residue_cascade[j] = high_bits*8 + low_bits; - } - r->residue_books = (short (*)[8]) setup_malloc(f, sizeof(r->residue_books[0]) * r->classifications); - if (r->residue_books == NULL) return error(f, VORBIS_outofmem); - for (j=0; j < r->classifications; ++j) { - for (k=0; k < 8; ++k) { - if (residue_cascade[j] & (1 << k)) { - r->residue_books[j][k] = get_bits(f, 8); - if (r->residue_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup); - } else { - r->residue_books[j][k] = -1; - } - } - } - // precompute the classifications[] array to avoid inner-loop mod/divide - // call it 'classdata' since we already have r->classifications - r->classdata = (uint8 **) setup_malloc(f, sizeof(*r->classdata) * f->codebooks[r->classbook].entries); - if (!r->classdata) return error(f, VORBIS_outofmem); - memset(r->classdata, 0, sizeof(*r->classdata) * f->codebooks[r->classbook].entries); - for (j=0; j < f->codebooks[r->classbook].entries; ++j) { - int classwords = f->codebooks[r->classbook].dimensions; - int temp = j; - r->classdata[j] = (uint8 *) setup_malloc(f, sizeof(r->classdata[j][0]) * classwords); - if (r->classdata[j] == NULL) return error(f, VORBIS_outofmem); - for (k=classwords-1; k >= 0; --k) { - r->classdata[j][k] = temp % r->classifications; - temp /= r->classifications; - } - } - } + // Residue + f->residue_count = get_bits(f, 6) + 1; + f->residue_config = (Residue*)setup_malloc(f, f->residue_count * sizeof(f->residue_config[0])); + if (f->residue_config == NULL) return error(f, VORBIS_outofmem); + memset(f->residue_config, 0, f->residue_count * sizeof(f->residue_config[0])); + for (i = 0; i < f->residue_count; ++i) + { + uint8 residue_cascade[64]; + Residue* r = f->residue_config + i; + f->residue_types[i] = get_bits(f, 16); + if (f->residue_types[i] > 2) return error(f, VORBIS_invalid_setup); + r->begin = get_bits(f, 24); + r->end = get_bits(f, 24); + if (r->end < r->begin) return error(f, VORBIS_invalid_setup); + r->part_size = get_bits(f, 24) + 1; + r->classifications = get_bits(f, 6) + 1; + r->classbook = get_bits(f, 8); + if (r->classbook >= f->codebook_count) return error(f, VORBIS_invalid_setup); + for (j = 0; j < r->classifications; ++j) + { + uint8 high_bits = 0; + uint8 low_bits = get_bits(f, 3); + if (get_bits(f, 1)) + high_bits = get_bits(f, 5); + residue_cascade[j] = high_bits * 8 + low_bits; + } + r->residue_books = (short (*)[8])setup_malloc(f, sizeof(r->residue_books[0]) * r->classifications); + if (r->residue_books == NULL) return error(f, VORBIS_outofmem); + for (j = 0; j < r->classifications; ++j) + { + for (k = 0; k < 8; ++k) + { + if (residue_cascade[j] & (1 << k)) + { + r->residue_books[j][k] = get_bits(f, 8); + if (r->residue_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup); + } + else + { + r->residue_books[j][k] = -1; + } + } + } + // precompute the classifications[] array to avoid inner-loop mod/divide + // call it 'classdata' since we already have r->classifications + r->classdata = (uint8**)setup_malloc(f, sizeof(*r->classdata) * f->codebooks[r->classbook].entries); + if (!r->classdata) return error(f, VORBIS_outofmem); + memset(r->classdata, 0, sizeof(*r->classdata) * f->codebooks[r->classbook].entries); + for (j = 0; j < f->codebooks[r->classbook].entries; ++j) + { + int classwords = f->codebooks[r->classbook].dimensions; + int temp = j; + r->classdata[j] = (uint8*)setup_malloc(f, sizeof(r->classdata[j][0]) * classwords); + if (r->classdata[j] == NULL) return error(f, VORBIS_outofmem); + for (k = classwords - 1; k >= 0; --k) + { + r->classdata[j][k] = temp % r->classifications; + temp /= r->classifications; + } + } + } - f->mapping_count = get_bits(f,6)+1; - f->mapping = (Mapping *) setup_malloc(f, f->mapping_count * sizeof(*f->mapping)); - if (f->mapping == NULL) return error(f, VORBIS_outofmem); - memset(f->mapping, 0, f->mapping_count * sizeof(*f->mapping)); - for (i=0; i < f->mapping_count; ++i) { - Mapping *m = f->mapping + i; - int mapping_type = get_bits(f,16); - if (mapping_type != 0) return error(f, VORBIS_invalid_setup); - m->chan = (MappingChannel *) setup_malloc(f, f->channels * sizeof(*m->chan)); - if (m->chan == NULL) return error(f, VORBIS_outofmem); - if (get_bits(f,1)) - m->submaps = get_bits(f,4)+1; - else - m->submaps = 1; - if (m->submaps > max_submaps) - max_submaps = m->submaps; - if (get_bits(f,1)) { - m->coupling_steps = get_bits(f,8)+1; - for (k=0; k < m->coupling_steps; ++k) { - m->chan[k].magnitude = get_bits(f, ilog(f->channels-1)); - m->chan[k].angle = get_bits(f, ilog(f->channels-1)); - if (m->chan[k].magnitude >= f->channels) return error(f, VORBIS_invalid_setup); - if (m->chan[k].angle >= f->channels) return error(f, VORBIS_invalid_setup); - if (m->chan[k].magnitude == m->chan[k].angle) return error(f, VORBIS_invalid_setup); - } - } else - m->coupling_steps = 0; + f->mapping_count = get_bits(f, 6) + 1; + f->mapping = (Mapping*)setup_malloc(f, f->mapping_count * sizeof(*f->mapping)); + if (f->mapping == NULL) return error(f, VORBIS_outofmem); + memset(f->mapping, 0, f->mapping_count * sizeof(*f->mapping)); + for (i = 0; i < f->mapping_count; ++i) + { + Mapping* m = f->mapping + i; + int mapping_type = get_bits(f, 16); + if (mapping_type != 0) return error(f, VORBIS_invalid_setup); + m->chan = (MappingChannel*)setup_malloc(f, f->channels * sizeof(*m->chan)); + if (m->chan == NULL) return error(f, VORBIS_outofmem); + if (get_bits(f, 1)) + m->submaps = get_bits(f, 4) + 1; + else + m->submaps = 1; + if (m->submaps > max_submaps) + max_submaps = m->submaps; + if (get_bits(f, 1)) + { + m->coupling_steps = get_bits(f, 8) + 1; + for (k = 0; k < m->coupling_steps; ++k) + { + m->chan[k].magnitude = get_bits(f, ilog(f->channels - 1)); + m->chan[k].angle = get_bits(f, ilog(f->channels - 1)); + if (m->chan[k].magnitude >= f->channels) return error(f, VORBIS_invalid_setup); + if (m->chan[k].angle >= f->channels) return error(f, VORBIS_invalid_setup); + if (m->chan[k].magnitude == m->chan[k].angle) return error(f, VORBIS_invalid_setup); + } + } + else + m->coupling_steps = 0; - // reserved field - if (get_bits(f,2)) return error(f, VORBIS_invalid_setup); - if (m->submaps > 1) { - for (j=0; j < f->channels; ++j) { - m->chan[j].mux = get_bits(f, 4); - if (m->chan[j].mux >= m->submaps) return error(f, VORBIS_invalid_setup); - } - } else - // @SPECIFICATION: this case is missing from the spec - for (j=0; j < f->channels; ++j) - m->chan[j].mux = 0; + // reserved field + if (get_bits(f, 2)) return error(f, VORBIS_invalid_setup); + if (m->submaps > 1) + { + for (j = 0; j < f->channels; ++j) + { + m->chan[j].mux = get_bits(f, 4); + if (m->chan[j].mux >= m->submaps) return error(f, VORBIS_invalid_setup); + } + } + else + // @SPECIFICATION: this case is missing from the spec + for (j = 0; j < f->channels; ++j) + m->chan[j].mux = 0; - for (j=0; j < m->submaps; ++j) { - get_bits(f,8); // discard - m->submap_floor[j] = get_bits(f,8); - m->submap_residue[j] = get_bits(f,8); - if (m->submap_floor[j] >= f->floor_count) return error(f, VORBIS_invalid_setup); - if (m->submap_residue[j] >= f->residue_count) return error(f, VORBIS_invalid_setup); - } - } + for (j = 0; j < m->submaps; ++j) + { + get_bits(f, 8); // discard + m->submap_floor[j] = get_bits(f, 8); + m->submap_residue[j] = get_bits(f, 8); + if (m->submap_floor[j] >= f->floor_count) return error(f, VORBIS_invalid_setup); + if (m->submap_residue[j] >= f->residue_count) return error(f, VORBIS_invalid_setup); + } + } - // Modes - f->mode_count = get_bits(f, 6)+1; - for (i=0; i < f->mode_count; ++i) { - Mode *m = f->mode_config+i; - m->blockflag = get_bits(f,1); - m->windowtype = get_bits(f,16); - m->transformtype = get_bits(f,16); - m->mapping = get_bits(f,8); - if (m->windowtype != 0) return error(f, VORBIS_invalid_setup); - if (m->transformtype != 0) return error(f, VORBIS_invalid_setup); - if (m->mapping >= f->mapping_count) return error(f, VORBIS_invalid_setup); - } + // Modes + f->mode_count = get_bits(f, 6) + 1; + for (i = 0; i < f->mode_count; ++i) + { + Mode* m = f->mode_config + i; + m->blockflag = get_bits(f, 1); + m->windowtype = get_bits(f, 16); + m->transformtype = get_bits(f, 16); + m->mapping = get_bits(f, 8); + if (m->windowtype != 0) return error(f, VORBIS_invalid_setup); + if (m->transformtype != 0) return error(f, VORBIS_invalid_setup); + if (m->mapping >= f->mapping_count) return error(f, VORBIS_invalid_setup); + } - flush_packet(f); + flush_packet(f); - f->previous_length = 0; + f->previous_length = 0; - for (i=0; i < f->channels; ++i) { - f->channel_buffers[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1); - f->previous_window[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2); - f->finalY[i] = (int16 *) setup_malloc(f, sizeof(int16) * longest_floorlist); - if (f->channel_buffers[i] == NULL || f->previous_window[i] == NULL || f->finalY[i] == NULL) return error(f, VORBIS_outofmem); - #ifdef STB_VORBIS_NO_DEFER_FLOOR + for (i = 0; i < f->channels; ++i) + { + f->channel_buffers[i] = (float*)setup_malloc(f, sizeof(float) * f->blocksize_1); + f->previous_window[i] = (float*)setup_malloc(f, sizeof(float) * f->blocksize_1 / 2); + f->finalY[i] = (int16*)setup_malloc(f, sizeof(int16) * longest_floorlist); + if (f->channel_buffers[i] == NULL || f->previous_window[i] == NULL || f->finalY[i] == NULL) return error( + f, VORBIS_outofmem); +#ifdef STB_VORBIS_NO_DEFER_FLOOR f->floor_buffers[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2); if (f->floor_buffers[i] == NULL) return error(f, VORBIS_outofmem); - #endif - } +#endif + } - if (!init_blocksize(f, 0, f->blocksize_0)) return FALSE; - if (!init_blocksize(f, 1, f->blocksize_1)) return FALSE; - f->blocksize[0] = f->blocksize_0; - f->blocksize[1] = f->blocksize_1; + if (!init_blocksize(f, 0, f->blocksize_0)) return FALSE; + if (!init_blocksize(f, 1, f->blocksize_1)) return FALSE; + f->blocksize[0] = f->blocksize_0; + f->blocksize[1] = f->blocksize_1; #ifdef STB_VORBIS_DIVIDE_TABLE if (integer_divide_table[1][1]==0) @@ -3729,374 +4067,405 @@ static int start_decoder(vorb *f) integer_divide_table[i][j] = i / j; #endif - // compute how much temporary memory is needed + // compute how much temporary memory is needed - // 1. - { - uint32 imdct_mem = (f->blocksize_1 * sizeof(float) >> 1); - uint32 classify_mem; - int i,max_part_read=0; - for (i=0; i < f->residue_count; ++i) { - Residue *r = f->residue_config + i; - int n_read = r->end - r->begin; - int part_read = n_read / r->part_size; - if (part_read > max_part_read) - max_part_read = part_read; - } - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(uint8 *)); - #else + // 1. + { + uint32 imdct_mem = (f->blocksize_1 * sizeof(float) >> 1); + uint32 classify_mem; + int i, max_part_read = 0; + for (i = 0; i < f->residue_count; ++i) + { + Residue* r = f->residue_config + i; + int n_read = r->end - r->begin; + int part_read = n_read / r->part_size; + if (part_read > max_part_read) + max_part_read = part_read; + } +#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(uint8*)); +#else classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(int *)); - #endif +#endif - f->temp_memory_required = classify_mem; - if (imdct_mem > f->temp_memory_required) - f->temp_memory_required = imdct_mem; - } + f->temp_memory_required = classify_mem; + if (imdct_mem > f->temp_memory_required) + f->temp_memory_required = imdct_mem; + } - f->first_decode = TRUE; + f->first_decode = TRUE; - if (f->alloc.alloc_buffer) { - assert(f->temp_offset == f->alloc.alloc_buffer_length_in_bytes); - // check if there's enough temp memory so we don't error later - if (f->setup_offset + sizeof(*f) + f->temp_memory_required > (unsigned) f->temp_offset) - return error(f, VORBIS_outofmem); - } + if (f->alloc.alloc_buffer) + { + assert(f->temp_offset == f->alloc.alloc_buffer_length_in_bytes); + // check if there's enough temp memory so we don't error later + if (f->setup_offset + sizeof(*f) + f->temp_memory_required > (unsigned)f->temp_offset) + return error(f, VORBIS_outofmem); + } - f->first_audio_page_offset = stb_vorbis_get_file_offset(f); + f->first_audio_page_offset = stb_vorbis_get_file_offset(f); - return TRUE; + return TRUE; } -static void vorbis_deinit(stb_vorbis *p) +static void vorbis_deinit(stb_vorbis* p) { - int i,j; - if (p->residue_config) { - for (i=0; i < p->residue_count; ++i) { - Residue *r = p->residue_config+i; - if (r->classdata) { - for (j=0; j < p->codebooks[r->classbook].entries; ++j) - setup_free(p, r->classdata[j]); - setup_free(p, r->classdata); - } - setup_free(p, r->residue_books); - } - } + int i, j; + if (p->residue_config) + { + for (i = 0; i < p->residue_count; ++i) + { + Residue* r = p->residue_config + i; + if (r->classdata) + { + for (j = 0; j < p->codebooks[r->classbook].entries; ++j) + setup_free(p, r->classdata[j]); + setup_free(p, r->classdata); + } + setup_free(p, r->residue_books); + } + } - if (p->codebooks) { - CHECK(p); - for (i=0; i < p->codebook_count; ++i) { - Codebook *c = p->codebooks + i; - setup_free(p, c->codeword_lengths); - setup_free(p, c->multiplicands); - setup_free(p, c->codewords); - setup_free(p, c->sorted_codewords); - // c->sorted_values[-1] is the first entry in the array - setup_free(p, c->sorted_values ? c->sorted_values-1 : NULL); - } - setup_free(p, p->codebooks); - } - setup_free(p, p->floor_config); - setup_free(p, p->residue_config); - if (p->mapping) { - for (i=0; i < p->mapping_count; ++i) - setup_free(p, p->mapping[i].chan); - setup_free(p, p->mapping); - } - CHECK(p); - for (i=0; i < p->channels && i < STB_VORBIS_MAX_CHANNELS; ++i) { - setup_free(p, p->channel_buffers[i]); - setup_free(p, p->previous_window[i]); - #ifdef STB_VORBIS_NO_DEFER_FLOOR + if (p->codebooks) + { + CHECK(p); + for (i = 0; i < p->codebook_count; ++i) + { + Codebook* c = p->codebooks + i; + setup_free(p, c->codeword_lengths); + setup_free(p, c->multiplicands); + setup_free(p, c->codewords); + setup_free(p, c->sorted_codewords); + // c->sorted_values[-1] is the first entry in the array + setup_free(p, c->sorted_values ? c->sorted_values - 1 : NULL); + } + setup_free(p, p->codebooks); + } + setup_free(p, p->floor_config); + setup_free(p, p->residue_config); + if (p->mapping) + { + for (i = 0; i < p->mapping_count; ++i) + setup_free(p, p->mapping[i].chan); + setup_free(p, p->mapping); + } + CHECK(p); + for (i = 0; i < p->channels && i < STB_VORBIS_MAX_CHANNELS; ++i) + { + setup_free(p, p->channel_buffers[i]); + setup_free(p, p->previous_window[i]); +#ifdef STB_VORBIS_NO_DEFER_FLOOR setup_free(p, p->floor_buffers[i]); - #endif - setup_free(p, p->finalY[i]); - } - for (i=0; i < 2; ++i) { - setup_free(p, p->A[i]); - setup_free(p, p->B[i]); - setup_free(p, p->C[i]); - setup_free(p, p->window[i]); - setup_free(p, p->bit_reverse[i]); - } - #ifndef STB_VORBIS_NO_STDIO - if (p->close_on_free) fclose(p->f); - #endif +#endif + setup_free(p, p->finalY[i]); + } + for (i = 0; i < 2; ++i) + { + setup_free(p, p->A[i]); + setup_free(p, p->B[i]); + setup_free(p, p->C[i]); + setup_free(p, p->window[i]); + setup_free(p, p->bit_reverse[i]); + } +#ifndef STB_VORBIS_NO_STDIO + if (p->close_on_free) fclose(p->f); +#endif } -void stb_vorbis_close(stb_vorbis *p) +void stb_vorbis_close(stb_vorbis* p) { - if (p == NULL) return; - vorbis_deinit(p); - setup_free(p,p); + if (p == NULL) return; + vorbis_deinit(p); + setup_free(p, p); } -static void vorbis_init(stb_vorbis *p, const stb_vorbis_alloc *z) +static void vorbis_init(stb_vorbis* p, const stb_vorbis_alloc* z) { - memset(p, 0, sizeof(*p)); // NULL out all malloc'd pointers to start - if (z) { - p->alloc = *z; - p->alloc.alloc_buffer_length_in_bytes = (p->alloc.alloc_buffer_length_in_bytes+3) & ~3; - p->temp_offset = p->alloc.alloc_buffer_length_in_bytes; - } - p->eof = 0; - p->error = VORBIS__no_error; - p->stream = NULL; - p->codebooks = NULL; - p->page_crc_tests = -1; - #ifndef STB_VORBIS_NO_STDIO - p->close_on_free = FALSE; - p->f = NULL; - #endif + memset(p, 0, sizeof(*p)); // NULL out all malloc'd pointers to start + if (z) + { + p->alloc = *z; + p->alloc.alloc_buffer_length_in_bytes = (p->alloc.alloc_buffer_length_in_bytes + 3) & ~3; + p->temp_offset = p->alloc.alloc_buffer_length_in_bytes; + } + p->eof = 0; + p->error = VORBIS__no_error; + p->stream = NULL; + p->codebooks = NULL; + p->page_crc_tests = -1; +#ifndef STB_VORBIS_NO_STDIO + p->close_on_free = FALSE; + p->f = NULL; +#endif } -int stb_vorbis_get_sample_offset(stb_vorbis *f) +int stb_vorbis_get_sample_offset(stb_vorbis* f) { - if (f->current_loc_valid) - return f->current_loc; - else - return -1; + if (f->current_loc_valid) + return f->current_loc; + else + return -1; } -stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f) +stb_vorbis_info stb_vorbis_get_info(stb_vorbis* f) { - stb_vorbis_info d; - d.channels = f->channels; - d.sample_rate = f->sample_rate; - d.setup_memory_required = f->setup_memory_required; - d.setup_temp_memory_required = f->setup_temp_memory_required; - d.temp_memory_required = f->temp_memory_required; - d.max_frame_size = f->blocksize_1 >> 1; - return d; + stb_vorbis_info d; + d.channels = f->channels; + d.sample_rate = f->sample_rate; + d.setup_memory_required = f->setup_memory_required; + d.setup_temp_memory_required = f->setup_temp_memory_required; + d.temp_memory_required = f->temp_memory_required; + d.max_frame_size = f->blocksize_1 >> 1; + return d; } -int stb_vorbis_get_error(stb_vorbis *f) +int stb_vorbis_get_error(stb_vorbis* f) { - int e = f->error; - f->error = VORBIS__no_error; - return e; + int e = f->error; + f->error = VORBIS__no_error; + return e; } -static stb_vorbis * vorbis_alloc(stb_vorbis *f) +static stb_vorbis* vorbis_alloc(stb_vorbis* f) { - stb_vorbis *p = (stb_vorbis *) setup_malloc(f, sizeof(*p)); - return p; + stb_vorbis* p = (stb_vorbis*)setup_malloc(f, sizeof(*p)); + return p; } #ifndef STB_VORBIS_NO_PUSHDATA_API -void stb_vorbis_flush_pushdata(stb_vorbis *f) +void stb_vorbis_flush_pushdata(stb_vorbis* f) { - f->previous_length = 0; - f->page_crc_tests = 0; - f->discard_samples_deferred = 0; - f->current_loc_valid = FALSE; - f->first_decode = FALSE; - f->samples_output = 0; - f->channel_buffer_start = 0; - f->channel_buffer_end = 0; + f->previous_length = 0; + f->page_crc_tests = 0; + f->discard_samples_deferred = 0; + f->current_loc_valid = FALSE; + f->first_decode = FALSE; + f->samples_output = 0; + f->channel_buffer_start = 0; + f->channel_buffer_end = 0; } -static int vorbis_search_for_page_pushdata(vorb *f, uint8 *data, int data_len) +static int vorbis_search_for_page_pushdata(vorb* f, uint8* data, int data_len) { - int i,n; - for (i=0; i < f->page_crc_tests; ++i) - f->scan[i].bytes_done = 0; + int i, n; + for (i = 0; i < f->page_crc_tests; ++i) + f->scan[i].bytes_done = 0; - // if we have room for more scans, search for them first, because - // they may cause us to stop early if their header is incomplete - if (f->page_crc_tests < STB_VORBIS_PUSHDATA_CRC_COUNT) { - if (data_len < 4) return 0; - data_len -= 3; // need to look for 4-byte sequence, so don't miss - // one that straddles a boundary - for (i=0; i < data_len; ++i) { - if (data[i] == 0x4f) { - if (0==memcmp(data+i, ogg_page_header, 4)) { - int j,len; - uint32 crc; - // make sure we have the whole page header - if (i+26 >= data_len || i+27+data[i+26] >= data_len) { - // only read up to this page start, so hopefully we'll - // have the whole page header start next time - data_len = i; - break; - } - // ok, we have it all; compute the length of the page - len = 27 + data[i+26]; - for (j=0; j < data[i+26]; ++j) - len += data[i+27+j]; - // scan everything up to the embedded crc (which we must 0) - crc = 0; - for (j=0; j < 22; ++j) - crc = crc32_update(crc, data[i+j]); - // now process 4 0-bytes - for ( ; j < 26; ++j) - crc = crc32_update(crc, 0); - // len is the total number of bytes we need to scan - n = f->page_crc_tests++; - f->scan[n].bytes_left = len-j; - f->scan[n].crc_so_far = crc; - f->scan[n].goal_crc = data[i+22] + (data[i+23] << 8) + (data[i+24]<<16) + (data[i+25]<<24); - // if the last frame on a page is continued to the next, then - // we can't recover the sample_loc immediately - if (data[i+27+data[i+26]-1] == 255) - f->scan[n].sample_loc = ~0; - else - f->scan[n].sample_loc = data[i+6] + (data[i+7] << 8) + (data[i+ 8]<<16) + (data[i+ 9]<<24); - f->scan[n].bytes_done = i+j; - if (f->page_crc_tests == STB_VORBIS_PUSHDATA_CRC_COUNT) - break; - // keep going if we still have room for more - } - } - } - } + // if we have room for more scans, search for them first, because + // they may cause us to stop early if their header is incomplete + if (f->page_crc_tests < STB_VORBIS_PUSHDATA_CRC_COUNT) + { + if (data_len < 4) return 0; + data_len -= 3; // need to look for 4-byte sequence, so don't miss + // one that straddles a boundary + for (i = 0; i < data_len; ++i) + { + if (data[i] == 0x4f) + { + if (0 == memcmp(data + i, ogg_page_header, 4)) + { + int j, len; + uint32 crc; + // make sure we have the whole page header + if (i + 26 >= data_len || i + 27 + data[i + 26] >= data_len) + { + // only read up to this page start, so hopefully we'll + // have the whole page header start next time + data_len = i; + break; + } + // ok, we have it all; compute the length of the page + len = 27 + data[i + 26]; + for (j = 0; j < data[i + 26]; ++j) + len += data[i + 27 + j]; + // scan everything up to the embedded crc (which we must 0) + crc = 0; + for (j = 0; j < 22; ++j) + crc = crc32_update(crc, data[i + j]); + // now process 4 0-bytes + for (; j < 26; ++j) + crc = crc32_update(crc, 0); + // len is the total number of bytes we need to scan + n = f->page_crc_tests++; + f->scan[n].bytes_left = len - j; + f->scan[n].crc_so_far = crc; + f->scan[n].goal_crc = data[i + 22] + (data[i + 23] << 8) + (data[i + 24] << 16) + (data[i + 25] << 24); + // if the last frame on a page is continued to the next, then + // we can't recover the sample_loc immediately + if (data[i + 27 + data[i + 26] - 1] == 255) + f->scan[n].sample_loc = ~0; + else + f->scan[n].sample_loc = data[i + 6] + (data[i + 7] << 8) + (data[i + 8] << 16) + (data[i + 9] << 24); + f->scan[n].bytes_done = i + j; + if (f->page_crc_tests == STB_VORBIS_PUSHDATA_CRC_COUNT) + break; + // keep going if we still have room for more + } + } + } + } - for (i=0; i < f->page_crc_tests;) { - uint32 crc; - int j; - int n = f->scan[i].bytes_done; - int m = f->scan[i].bytes_left; - if (m > data_len - n) m = data_len - n; - // m is the bytes to scan in the current chunk - crc = f->scan[i].crc_so_far; - for (j=0; j < m; ++j) - crc = crc32_update(crc, data[n+j]); - f->scan[i].bytes_left -= m; - f->scan[i].crc_so_far = crc; - if (f->scan[i].bytes_left == 0) { - // does it match? - if (f->scan[i].crc_so_far == f->scan[i].goal_crc) { - // Houston, we have page - data_len = n+m; // consumption amount is wherever that scan ended - f->page_crc_tests = -1; // drop out of page scan mode - f->previous_length = 0; // decode-but-don't-output one frame - f->next_seg = -1; // start a new page - f->current_loc = f->scan[i].sample_loc; // set the current sample location - // to the amount we'd have decoded had we decoded this page - f->current_loc_valid = f->current_loc != ~0U; - return data_len; - } - // delete entry - f->scan[i] = f->scan[--f->page_crc_tests]; - } else { - ++i; - } - } + for (i = 0; i < f->page_crc_tests;) + { + uint32 crc; + int j; + int n = f->scan[i].bytes_done; + int m = f->scan[i].bytes_left; + if (m > data_len - n) m = data_len - n; + // m is the bytes to scan in the current chunk + crc = f->scan[i].crc_so_far; + for (j = 0; j < m; ++j) + crc = crc32_update(crc, data[n + j]); + f->scan[i].bytes_left -= m; + f->scan[i].crc_so_far = crc; + if (f->scan[i].bytes_left == 0) + { + // does it match? + if (f->scan[i].crc_so_far == f->scan[i].goal_crc) + { + // Houston, we have page + data_len = n + m; // consumption amount is wherever that scan ended + f->page_crc_tests = -1; // drop out of page scan mode + f->previous_length = 0; // decode-but-don't-output one frame + f->next_seg = -1; // start a new page + f->current_loc = f->scan[i].sample_loc; // set the current sample location + // to the amount we'd have decoded had we decoded this page + f->current_loc_valid = f->current_loc != ~0U; + return data_len; + } + // delete entry + f->scan[i] = f->scan[--f->page_crc_tests]; + } + else + { + ++i; + } + } - return data_len; + return data_len; } // return value: number of bytes we used int stb_vorbis_decode_frame_pushdata( - stb_vorbis *f, // the file we're decoding - const uint8 *data, int data_len, // the memory available for decoding - int *channels, // place to write number of float * buffers - float ***output, // place to write float ** array of float * buffers - int *samples // place to write number of output samples - ) + stb_vorbis* f, // the file we're decoding + const uint8* data, int data_len, // the memory available for decoding + int* channels, // place to write number of float * buffers + float*** output, // place to write float ** array of float * buffers + int* samples // place to write number of output samples +) { - int i; - int len,right,left; + int i; + int len, right, left; - if (!IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); + if (!IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); - if (f->page_crc_tests >= 0) { - *samples = 0; - return vorbis_search_for_page_pushdata(f, (uint8 *) data, data_len); - } + if (f->page_crc_tests >= 0) + { + *samples = 0; + return vorbis_search_for_page_pushdata(f, (uint8*)data, data_len); + } - f->stream = (uint8 *) data; - f->stream_end = (uint8 *) data + data_len; - f->error = VORBIS__no_error; + f->stream = (uint8*)data; + f->stream_end = (uint8*)data + data_len; + f->error = VORBIS__no_error; - // check that we have the entire packet in memory - if (!is_whole_packet_present(f, FALSE)) { - *samples = 0; - return 0; - } + // check that we have the entire packet in memory + if (!is_whole_packet_present(f, FALSE)) + { + *samples = 0; + return 0; + } - if (!vorbis_decode_packet(f, &len, &left, &right)) { - // save the actual error we encountered - enum STBVorbisError error = f->error; - if (error == VORBIS_bad_packet_type) { - // flush and resynch - f->error = VORBIS__no_error; - while (get8_packet(f) != EOP) - if (f->eof) break; - *samples = 0; - return (int) (f->stream - data); - } - if (error == VORBIS_continued_packet_flag_invalid) { - if (f->previous_length == 0) { - // we may be resynching, in which case it's ok to hit one - // of these; just discard the packet - f->error = VORBIS__no_error; - while (get8_packet(f) != EOP) - if (f->eof) break; - *samples = 0; - return (int) (f->stream - data); - } - } - // if we get an error while parsing, what to do? - // well, it DEFINITELY won't work to continue from where we are! - stb_vorbis_flush_pushdata(f); - // restore the error that actually made us bail - f->error = error; - *samples = 0; - return 1; - } + if (!vorbis_decode_packet(f, &len, &left, &right)) + { + // save the actual error we encountered + enum STBVorbisError error = f->error; + if (error == VORBIS_bad_packet_type) + { + // flush and resynch + f->error = VORBIS__no_error; + while (get8_packet(f) != EOP) + if (f->eof) break; + *samples = 0; + return (int)(f->stream - data); + } + if (error == VORBIS_continued_packet_flag_invalid) + { + if (f->previous_length == 0) + { + // we may be resynching, in which case it's ok to hit one + // of these; just discard the packet + f->error = VORBIS__no_error; + while (get8_packet(f) != EOP) + if (f->eof) break; + *samples = 0; + return (int)(f->stream - data); + } + } + // if we get an error while parsing, what to do? + // well, it DEFINITELY won't work to continue from where we are! + stb_vorbis_flush_pushdata(f); + // restore the error that actually made us bail + f->error = error; + *samples = 0; + return 1; + } - // success! - len = vorbis_finish_frame(f, len, left, right); - for (i=0; i < f->channels; ++i) - f->outputs[i] = f->channel_buffers[i] + left; + // success! + len = vorbis_finish_frame(f, len, left, right); + for (i = 0; i < f->channels; ++i) + f->outputs[i] = f->channel_buffers[i] + left; - if (channels) *channels = f->channels; - *samples = len; - *output = f->outputs; - return (int) (f->stream - data); + if (channels) *channels = f->channels; + *samples = len; + *output = f->outputs; + return (int)(f->stream - data); } -stb_vorbis *stb_vorbis_open_pushdata( - const unsigned char *data, int data_len, // the memory available for decoding - int *data_used, // only defined if result is not NULL - int *error, const stb_vorbis_alloc *alloc) +stb_vorbis* stb_vorbis_open_pushdata( + const unsigned char* data, int data_len, // the memory available for decoding + int* data_used, // only defined if result is not NULL + int* error, const stb_vorbis_alloc* alloc) { - stb_vorbis *f, p; - vorbis_init(&p, alloc); - p.stream = (uint8 *) data; - p.stream_end = (uint8 *) data + data_len; - p.push_mode = TRUE; - if (!start_decoder(&p)) { - if (p.eof) - *error = VORBIS_need_more_data; - else - *error = p.error; - return NULL; - } - f = vorbis_alloc(&p); - if (f) { - *f = p; - *data_used = (int) (f->stream - data); - *error = 0; - return f; - } else { - vorbis_deinit(&p); - return NULL; - } + stb_vorbis *f, p; + vorbis_init(&p, alloc); + p.stream = (uint8*)data; + p.stream_end = (uint8*)data + data_len; + p.push_mode = TRUE; + if (!start_decoder(&p)) + { + if (p.eof) + *error = VORBIS_need_more_data; + else + *error = p.error; + return NULL; + } + f = vorbis_alloc(&p); + if (f) + { + *f = p; + *data_used = (int)(f->stream - data); + *error = 0; + return f; + } + else + { + vorbis_deinit(&p); + return NULL; + } } #endif // STB_VORBIS_NO_PUSHDATA_API -unsigned int stb_vorbis_get_file_offset(stb_vorbis *f) +unsigned int stb_vorbis_get_file_offset(stb_vorbis* f) { - #ifndef STB_VORBIS_NO_PUSHDATA_API - if (f->push_mode) return 0; - #endif - if (USE_MEMORY(f)) return (unsigned int) (f->stream - f->stream_start); - #ifndef STB_VORBIS_NO_STDIO - return (unsigned int) (ftell(f->f) - f->f_start); - #endif +#ifndef STB_VORBIS_NO_PUSHDATA_API + if (f->push_mode) return 0; +#endif + if (USE_MEMORY(f)) return (unsigned int)(f->stream - f->stream_start); +#ifndef STB_VORBIS_NO_STDIO + return (unsigned int)(ftell(f->f) - f->f_start); +#endif } #ifndef STB_VORBIS_NO_PULLDATA_API @@ -4104,74 +4473,81 @@ unsigned int stb_vorbis_get_file_offset(stb_vorbis *f) // DATA-PULLING API // -static uint32 vorbis_find_page(stb_vorbis *f, uint32 *end, uint32 *last) +static uint32 vorbis_find_page(stb_vorbis* f, uint32* end, uint32* last) { - for(;;) { - int n; - if (f->eof) return 0; - n = get8(f); - if (n == 0x4f) { // page header candidate - unsigned int retry_loc = stb_vorbis_get_file_offset(f); - int i; - // check if we're off the end of a file_section stream - if (retry_loc - 25 > f->stream_len) - return 0; - // check the rest of the header - for (i=1; i < 4; ++i) - if (get8(f) != ogg_page_header[i]) - break; - if (f->eof) return 0; - if (i == 4) { - uint8 header[27]; - uint32 i, crc, goal, len; - for (i=0; i < 4; ++i) - header[i] = ogg_page_header[i]; - for (; i < 27; ++i) - header[i] = get8(f); - if (f->eof) return 0; - if (header[4] != 0) goto invalid; - goal = header[22] + (header[23] << 8) + (header[24]<<16) + (header[25]<<24); - for (i=22; i < 26; ++i) - header[i] = 0; - crc = 0; - for (i=0; i < 27; ++i) - crc = crc32_update(crc, header[i]); - len = 0; - for (i=0; i < header[26]; ++i) { - int s = get8(f); - crc = crc32_update(crc, s); - len += s; - } - if (len && f->eof) return 0; - for (i=0; i < len; ++i) - crc = crc32_update(crc, get8(f)); - // finished parsing probable page - if (crc == goal) { - // we could now check that it's either got the last - // page flag set, OR it's followed by the capture - // pattern, but I guess TECHNICALLY you could have - // a file with garbage between each ogg page and recover - // from it automatically? So even though that paranoia - // might decrease the chance of an invalid decode by - // another 2^32, not worth it since it would hose those - // invalid-but-useful files? - if (end) - *end = stb_vorbis_get_file_offset(f); - if (last) { - if (header[5] & 0x04) - *last = 1; - else - *last = 0; - } - set_file_offset(f, retry_loc-1); - return 1; - } - } - invalid: - // not a valid page, so rewind and look for next one - set_file_offset(f, retry_loc); - } - } + for (;;) + { + int n; + if (f->eof) return 0; + n = get8(f); + if (n == 0x4f) + { + // page header candidate + unsigned int retry_loc = stb_vorbis_get_file_offset(f); + int i; + // check if we're off the end of a file_section stream + if (retry_loc - 25 > f->stream_len) + return 0; + // check the rest of the header + for (i = 1; i < 4; ++i) + if (get8(f) != ogg_page_header[i]) + break; + if (f->eof) return 0; + if (i == 4) + { + uint8 header[27]; + uint32 i, crc, goal, len; + for (i = 0; i < 4; ++i) + header[i] = ogg_page_header[i]; + for (; i < 27; ++i) + header[i] = get8(f); + if (f->eof) return 0; + if (header[4] != 0) goto invalid; + goal = header[22] + (header[23] << 8) + (header[24] << 16) + (header[25] << 24); + for (i = 22; i < 26; ++i) + header[i] = 0; + crc = 0; + for (i = 0; i < 27; ++i) + crc = crc32_update(crc, header[i]); + len = 0; + for (i = 0; i < header[26]; ++i) + { + int s = get8(f); + crc = crc32_update(crc, s); + len += s; + } + if (len && f->eof) return 0; + for (i = 0; i < len; ++i) + crc = crc32_update(crc, get8(f)); + // finished parsing probable page + if (crc == goal) + { + // we could now check that it's either got the last + // page flag set, OR it's followed by the capture + // pattern, but I guess TECHNICALLY you could have + // a file with garbage between each ogg page and recover + // from it automatically? So even though that paranoia + // might decrease the chance of an invalid decode by + // another 2^32, not worth it since it would hose those + // invalid-but-useful files? + if (end) + *end = stb_vorbis_get_file_offset(f); + if (last) + { + if (header[5] & 0x04) + *last = 1; + else + *last = 0; + } + set_file_offset(f, retry_loc - 1); + return 1; + } + } + invalid: + // not a valid page, so rewind and look for next one + set_file_offset(f, retry_loc); + } + } } @@ -4186,478 +4562,511 @@ static uint32 vorbis_find_page(stb_vorbis *f, uint32 *end, uint32 *last) // to try to bound either side of the binary search sensibly, while still // working in O(log n) time if they fail. -static int get_seek_page_info(stb_vorbis *f, ProbedPage *z) +static int get_seek_page_info(stb_vorbis* f, ProbedPage* z) { - uint8 header[27], lacing[255]; - int i,len; + uint8 header[27], lacing[255]; + int i, len; - // record where the page starts - z->page_start = stb_vorbis_get_file_offset(f); + // record where the page starts + z->page_start = stb_vorbis_get_file_offset(f); - // parse the header - getn(f, header, 27); - if (header[0] != 'O' || header[1] != 'g' || header[2] != 'g' || header[3] != 'S') - return 0; - getn(f, lacing, header[26]); + // parse the header + getn(f, header, 27); + if (header[0] != 'O' || header[1] != 'g' || header[2] != 'g' || header[3] != 'S') + return 0; + getn(f, lacing, header[26]); - // determine the length of the payload - len = 0; - for (i=0; i < header[26]; ++i) - len += lacing[i]; + // determine the length of the payload + len = 0; + for (i = 0; i < header[26]; ++i) + len += lacing[i]; - // this implies where the page ends - z->page_end = z->page_start + 27 + header[26] + len; + // this implies where the page ends + z->page_end = z->page_start + 27 + header[26] + len; - // read the last-decoded sample out of the data - z->last_decoded_sample = header[6] + (header[7] << 8) + (header[8] << 16) + (header[9] << 24); + // read the last-decoded sample out of the data + z->last_decoded_sample = header[6] + (header[7] << 8) + (header[8] << 16) + (header[9] << 24); - // restore file state to where we were - set_file_offset(f, z->page_start); - return 1; + // restore file state to where we were + set_file_offset(f, z->page_start); + return 1; } // rarely used function to seek back to the preceeding page while finding the // start of a packet -static int go_to_page_before(stb_vorbis *f, unsigned int limit_offset) +static int go_to_page_before(stb_vorbis* f, unsigned int limit_offset) { - unsigned int previous_safe, end; + unsigned int previous_safe, end; - // now we want to seek back 64K from the limit - if (limit_offset >= 65536 && limit_offset-65536 >= f->first_audio_page_offset) - previous_safe = limit_offset - 65536; - else - previous_safe = f->first_audio_page_offset; + // now we want to seek back 64K from the limit + if (limit_offset >= 65536 && limit_offset - 65536 >= f->first_audio_page_offset) + previous_safe = limit_offset - 65536; + else + previous_safe = f->first_audio_page_offset; - set_file_offset(f, previous_safe); + set_file_offset(f, previous_safe); - while (vorbis_find_page(f, &end, NULL)) { - if (end >= limit_offset && stb_vorbis_get_file_offset(f) < limit_offset) - return 1; - set_file_offset(f, end); - } + while (vorbis_find_page(f, &end, NULL)) + { + if (end >= limit_offset && stb_vorbis_get_file_offset(f) < limit_offset) + return 1; + set_file_offset(f, end); + } - return 0; + return 0; } // implements the search logic for finding a page and starting decoding. if // the function succeeds, current_loc_valid will be true and current_loc will // be less than or equal to the provided sample number (the closer the // better). -static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number) +static int seek_to_sample_coarse(stb_vorbis* f, uint32 sample_number) { - ProbedPage left, right, mid; - int i, start_seg_with_known_loc, end_pos, page_start; - uint32 delta, stream_length, padding; - double offset = 0, bytes_per_sample = 0; - int probe = 0; + ProbedPage left, right, mid; + int i, start_seg_with_known_loc, end_pos, page_start; + uint32 delta, stream_length, padding; + double offset = 0, bytes_per_sample = 0; + int probe = 0; - // find the last page and validate the target sample - stream_length = stb_vorbis_stream_length_in_samples(f); - if (stream_length == 0) return error(f, VORBIS_seek_without_length); - if (sample_number > stream_length) return error(f, VORBIS_seek_invalid); + // find the last page and validate the target sample + stream_length = stb_vorbis_stream_length_in_samples(f); + if (stream_length == 0) return error(f, VORBIS_seek_without_length); + if (sample_number > stream_length) return error(f, VORBIS_seek_invalid); - // this is the maximum difference between the window-center (which is the - // actual granule position value), and the right-start (which the spec - // indicates should be the granule position (give or take one)). - padding = ((f->blocksize_1 - f->blocksize_0) >> 2); - if (sample_number < padding) - sample_number = 0; - else - sample_number -= padding; + // this is the maximum difference between the window-center (which is the + // actual granule position value), and the right-start (which the spec + // indicates should be the granule position (give or take one)). + padding = ((f->blocksize_1 - f->blocksize_0) >> 2); + if (sample_number < padding) + sample_number = 0; + else + sample_number -= padding; - left = f->p_first; - while (left.last_decoded_sample == ~0U) { - // (untested) the first page does not have a 'last_decoded_sample' - set_file_offset(f, left.page_end); - if (!get_seek_page_info(f, &left)) goto error; - } + left = f->p_first; + while (left.last_decoded_sample == ~0U) + { + // (untested) the first page does not have a 'last_decoded_sample' + set_file_offset(f, left.page_end); + if (!get_seek_page_info(f, &left)) goto error; + } - right = f->p_last; - assert(right.last_decoded_sample != ~0U); + right = f->p_last; + assert(right.last_decoded_sample != ~0U); - // starting from the start is handled differently - if (sample_number <= left.last_decoded_sample) { - if (stb_vorbis_seek_start(f)) - return 1; - return 0; - } + // starting from the start is handled differently + if (sample_number <= left.last_decoded_sample) + { + if (stb_vorbis_seek_start(f)) + return 1; + return 0; + } - while (left.page_end != right.page_start) { - assert(left.page_end < right.page_start); - // search range in bytes - delta = right.page_start - left.page_end; - if (delta <= 65536) { - // there's only 64K left to search - handle it linearly - set_file_offset(f, left.page_end); - } else { - if (probe < 2) { - if (probe == 0) { - // first probe (interpolate) - double data_bytes = right.page_end - left.page_start; - bytes_per_sample = data_bytes / right.last_decoded_sample; - offset = left.page_start + bytes_per_sample * (sample_number - left.last_decoded_sample); - } else { - // second probe (try to bound the other side) - double error = ((double) sample_number - mid.last_decoded_sample) * bytes_per_sample; - if (error >= 0 && error < 8000) error = 8000; - if (error < 0 && error > -8000) error = -8000; - offset += error * 2; - } + while (left.page_end != right.page_start) + { + assert(left.page_end < right.page_start); + // search range in bytes + delta = right.page_start - left.page_end; + if (delta <= 65536) + { + // there's only 64K left to search - handle it linearly + set_file_offset(f, left.page_end); + } + else + { + if (probe < 2) + { + if (probe == 0) + { + // first probe (interpolate) + double data_bytes = right.page_end - left.page_start; + bytes_per_sample = data_bytes / right.last_decoded_sample; + offset = left.page_start + bytes_per_sample * (sample_number - left.last_decoded_sample); + } + else + { + // second probe (try to bound the other side) + double error = ((double)sample_number - mid.last_decoded_sample) * bytes_per_sample; + if (error >= 0 && error < 8000) error = 8000; + if (error < 0 && error > -8000) error = -8000; + offset += error * 2; + } - // ensure the offset is valid - if (offset < left.page_end) - offset = left.page_end; - if (offset > right.page_start - 65536) - offset = right.page_start - 65536; + // ensure the offset is valid + if (offset < left.page_end) + offset = left.page_end; + if (offset > right.page_start - 65536) + offset = right.page_start - 65536; - set_file_offset(f, (unsigned int) offset); - } else { - // binary search for large ranges (offset by 32K to ensure - // we don't hit the right page) - set_file_offset(f, left.page_end + (delta / 2) - 32768); - } + set_file_offset(f, (unsigned int)offset); + } + else + { + // binary search for large ranges (offset by 32K to ensure + // we don't hit the right page) + set_file_offset(f, left.page_end + (delta / 2) - 32768); + } - if (!vorbis_find_page(f, NULL, NULL)) goto error; - } + if (!vorbis_find_page(f, NULL, NULL)) goto error; + } - for (;;) { - if (!get_seek_page_info(f, &mid)) goto error; - if (mid.last_decoded_sample != ~0U) break; - // (untested) no frames end on this page - set_file_offset(f, mid.page_end); - assert(mid.page_start < right.page_start); - } + for (;;) + { + if (!get_seek_page_info(f, &mid)) goto error; + if (mid.last_decoded_sample != ~0U) break; + // (untested) no frames end on this page + set_file_offset(f, mid.page_end); + assert(mid.page_start < right.page_start); + } - // if we've just found the last page again then we're in a tricky file, - // and we're close enough. - if (mid.page_start == right.page_start) - break; + // if we've just found the last page again then we're in a tricky file, + // and we're close enough. + if (mid.page_start == right.page_start) + break; - if (sample_number < mid.last_decoded_sample) - right = mid; - else - left = mid; + if (sample_number < mid.last_decoded_sample) + right = mid; + else + left = mid; - ++probe; - } + ++probe; + } - // seek back to start of the last packet - page_start = left.page_start; - set_file_offset(f, page_start); - if (!start_page(f)) return error(f, VORBIS_seek_failed); - end_pos = f->end_seg_with_known_loc; - assert(end_pos >= 0); + // seek back to start of the last packet + page_start = left.page_start; + set_file_offset(f, page_start); + if (!start_page(f)) return error(f, VORBIS_seek_failed); + end_pos = f->end_seg_with_known_loc; + assert(end_pos >= 0); - for (;;) { - for (i = end_pos; i > 0; --i) - if (f->segments[i-1] != 255) - break; + for (;;) + { + for (i = end_pos; i > 0; --i) + if (f->segments[i - 1] != 255) + break; - start_seg_with_known_loc = i; + start_seg_with_known_loc = i; - if (start_seg_with_known_loc > 0 || !(f->page_flag & PAGEFLAG_continued_packet)) - break; + if (start_seg_with_known_loc > 0 || !(f->page_flag & PAGEFLAG_continued_packet)) + break; - // (untested) the final packet begins on an earlier page - if (!go_to_page_before(f, page_start)) - goto error; + // (untested) the final packet begins on an earlier page + if (!go_to_page_before(f, page_start)) + goto error; - page_start = stb_vorbis_get_file_offset(f); - if (!start_page(f)) goto error; - end_pos = f->segment_count - 1; - } + page_start = stb_vorbis_get_file_offset(f); + if (!start_page(f)) goto error; + end_pos = f->segment_count - 1; + } - // prepare to start decoding - f->current_loc_valid = FALSE; - f->last_seg = FALSE; - f->valid_bits = 0; - f->packet_bytes = 0; - f->bytes_in_seg = 0; - f->previous_length = 0; - f->next_seg = start_seg_with_known_loc; + // prepare to start decoding + f->current_loc_valid = FALSE; + f->last_seg = FALSE; + f->valid_bits = 0; + f->packet_bytes = 0; + f->bytes_in_seg = 0; + f->previous_length = 0; + f->next_seg = start_seg_with_known_loc; - for (i = 0; i < start_seg_with_known_loc; i++) - skip(f, f->segments[i]); + for (i = 0; i < start_seg_with_known_loc; i++) + skip(f, f->segments[i]); - // start decoding (optimizable - this frame is generally discarded) - if (!vorbis_pump_first_frame(f)) - return 0; - if (f->current_loc > sample_number) - return error(f, VORBIS_seek_failed); - return 1; + // start decoding (optimizable - this frame is generally discarded) + if (!vorbis_pump_first_frame(f)) + return 0; + if (f->current_loc > sample_number) + return error(f, VORBIS_seek_failed); + return 1; error: - // try to restore the file to a valid state - stb_vorbis_seek_start(f); - return error(f, VORBIS_seek_failed); + // try to restore the file to a valid state + stb_vorbis_seek_start(f); + return error(f, VORBIS_seek_failed); } // the same as vorbis_decode_initial, but without advancing -static int peek_decode_initial(vorb *f, int *p_left_start, int *p_left_end, int *p_right_start, int *p_right_end, int *mode) +static int peek_decode_initial(vorb* f, int* p_left_start, int* p_left_end, int* p_right_start, int* p_right_end, + int* mode) { - int bits_read, bytes_read; + int bits_read, bytes_read; - if (!vorbis_decode_initial(f, p_left_start, p_left_end, p_right_start, p_right_end, mode)) - return 0; + if (!vorbis_decode_initial(f, p_left_start, p_left_end, p_right_start, p_right_end, mode)) + return 0; - // either 1 or 2 bytes were read, figure out which so we can rewind - bits_read = 1 + ilog(f->mode_count-1); - if (f->mode_config[*mode].blockflag) - bits_read += 2; - bytes_read = (bits_read + 7) / 8; + // either 1 or 2 bytes were read, figure out which so we can rewind + bits_read = 1 + ilog(f->mode_count - 1); + if (f->mode_config[*mode].blockflag) + bits_read += 2; + bytes_read = (bits_read + 7) / 8; - f->bytes_in_seg += bytes_read; - f->packet_bytes -= bytes_read; - skip(f, -bytes_read); - if (f->next_seg == -1) - f->next_seg = f->segment_count - 1; - else - f->next_seg--; - f->valid_bits = 0; + f->bytes_in_seg += bytes_read; + f->packet_bytes -= bytes_read; + skip(f, -bytes_read); + if (f->next_seg == -1) + f->next_seg = f->segment_count - 1; + else + f->next_seg--; + f->valid_bits = 0; - return 1; + return 1; } -int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number) +int stb_vorbis_seek_frame(stb_vorbis* f, unsigned int sample_number) { - uint32 max_frame_samples; + uint32 max_frame_samples; - if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); + if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); - // fast page-level search - if (!seek_to_sample_coarse(f, sample_number)) - return 0; + // fast page-level search + if (!seek_to_sample_coarse(f, sample_number)) + return 0; - assert(f->current_loc_valid); - assert(f->current_loc <= sample_number); + assert(f->current_loc_valid); + assert(f->current_loc <= sample_number); - // linear search for the relevant packet - max_frame_samples = (f->blocksize_1*3 - f->blocksize_0) >> 2; - while (f->current_loc < sample_number) { - int left_start, left_end, right_start, right_end, mode, frame_samples; - if (!peek_decode_initial(f, &left_start, &left_end, &right_start, &right_end, &mode)) - return error(f, VORBIS_seek_failed); - // calculate the number of samples returned by the next frame - frame_samples = right_start - left_start; - if (f->current_loc + frame_samples > sample_number) { - return 1; // the next frame will contain the sample - } else if (f->current_loc + frame_samples + max_frame_samples > sample_number) { - // there's a chance the frame after this could contain the sample - vorbis_pump_first_frame(f); - } else { - // this frame is too early to be relevant - f->current_loc += frame_samples; - f->previous_length = 0; - maybe_start_packet(f); - flush_packet(f); - } - } - // the next frame will start with the sample - assert(f->current_loc == sample_number); - return 1; + // linear search for the relevant packet + max_frame_samples = (f->blocksize_1 * 3 - f->blocksize_0) >> 2; + while (f->current_loc < sample_number) + { + int left_start, left_end, right_start, right_end, mode, frame_samples; + if (!peek_decode_initial(f, &left_start, &left_end, &right_start, &right_end, &mode)) + return error(f, VORBIS_seek_failed); + // calculate the number of samples returned by the next frame + frame_samples = right_start - left_start; + if (f->current_loc + frame_samples > sample_number) + { + return 1; // the next frame will contain the sample + } + else if (f->current_loc + frame_samples + max_frame_samples > sample_number) + { + // there's a chance the frame after this could contain the sample + vorbis_pump_first_frame(f); + } + else + { + // this frame is too early to be relevant + f->current_loc += frame_samples; + f->previous_length = 0; + maybe_start_packet(f); + flush_packet(f); + } + } + // the next frame will start with the sample + assert(f->current_loc == sample_number); + return 1; } -int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number) +int stb_vorbis_seek(stb_vorbis* f, unsigned int sample_number) { - if (!stb_vorbis_seek_frame(f, sample_number)) - return 0; + if (!stb_vorbis_seek_frame(f, sample_number)) + return 0; - if (sample_number != f->current_loc) { - int n; - uint32 frame_start = f->current_loc; - stb_vorbis_get_frame_float(f, &n, NULL); - assert(sample_number > frame_start); - assert(f->channel_buffer_start + (int) (sample_number-frame_start) <= f->channel_buffer_end); - f->channel_buffer_start += (sample_number - frame_start); - } + if (sample_number != f->current_loc) + { + int n; + uint32 frame_start = f->current_loc; + stb_vorbis_get_frame_float(f, &n, NULL); + assert(sample_number > frame_start); + assert(f->channel_buffer_start + (int) (sample_number-frame_start) <= f->channel_buffer_end); + f->channel_buffer_start += (sample_number - frame_start); + } - return 1; + return 1; } -int stb_vorbis_seek_start(stb_vorbis *f) +int stb_vorbis_seek_start(stb_vorbis* f) { - if (IS_PUSH_MODE(f)) { return error(f, VORBIS_invalid_api_mixing); } - set_file_offset(f, f->first_audio_page_offset); - f->previous_length = 0; - f->first_decode = TRUE; - f->next_seg = -1; - return vorbis_pump_first_frame(f); + if (IS_PUSH_MODE(f)) { return error(f, VORBIS_invalid_api_mixing); } + set_file_offset(f, f->first_audio_page_offset); + f->previous_length = 0; + f->first_decode = TRUE; + f->next_seg = -1; + return vorbis_pump_first_frame(f); } -unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f) +unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis* f) { - unsigned int restore_offset, previous_safe; - unsigned int end, last_page_loc; + unsigned int restore_offset, previous_safe; + unsigned int end, last_page_loc; - if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); - if (!f->total_samples) { - unsigned int last; - uint32 lo,hi; - char header[6]; + if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); + if (!f->total_samples) + { + unsigned int last; + uint32 lo, hi; + char header[6]; - // first, store the current decode position so we can restore it - restore_offset = stb_vorbis_get_file_offset(f); + // first, store the current decode position so we can restore it + restore_offset = stb_vorbis_get_file_offset(f); - // now we want to seek back 64K from the end (the last page must - // be at most a little less than 64K, but let's allow a little slop) - if (f->stream_len >= 65536 && f->stream_len-65536 >= f->first_audio_page_offset) - previous_safe = f->stream_len - 65536; - else - previous_safe = f->first_audio_page_offset; + // now we want to seek back 64K from the end (the last page must + // be at most a little less than 64K, but let's allow a little slop) + if (f->stream_len >= 65536 && f->stream_len - 65536 >= f->first_audio_page_offset) + previous_safe = f->stream_len - 65536; + else + previous_safe = f->first_audio_page_offset; - set_file_offset(f, previous_safe); - // previous_safe is now our candidate 'earliest known place that seeking - // to will lead to the final page' + set_file_offset(f, previous_safe); + // previous_safe is now our candidate 'earliest known place that seeking + // to will lead to the final page' - if (!vorbis_find_page(f, &end, &last)) { - // if we can't find a page, we're hosed! - f->error = VORBIS_cant_find_last_page; - f->total_samples = 0xffffffff; - goto done; - } + if (!vorbis_find_page(f, &end, &last)) + { + // if we can't find a page, we're hosed! + f->error = VORBIS_cant_find_last_page; + f->total_samples = 0xffffffff; + goto done; + } - // check if there are more pages - last_page_loc = stb_vorbis_get_file_offset(f); + // check if there are more pages + last_page_loc = stb_vorbis_get_file_offset(f); - // stop when the last_page flag is set, not when we reach eof; - // this allows us to stop short of a 'file_section' end without - // explicitly checking the length of the section - while (!last) { - set_file_offset(f, end); - if (!vorbis_find_page(f, &end, &last)) { - // the last page we found didn't have the 'last page' flag - // set. whoops! - break; - } - previous_safe = last_page_loc+1; - last_page_loc = stb_vorbis_get_file_offset(f); - } + // stop when the last_page flag is set, not when we reach eof; + // this allows us to stop short of a 'file_section' end without + // explicitly checking the length of the section + while (!last) + { + set_file_offset(f, end); + if (!vorbis_find_page(f, &end, &last)) + { + // the last page we found didn't have the 'last page' flag + // set. whoops! + break; + } + previous_safe = last_page_loc + 1; + last_page_loc = stb_vorbis_get_file_offset(f); + } - set_file_offset(f, last_page_loc); + set_file_offset(f, last_page_loc); - // parse the header - getn(f, (unsigned char *)header, 6); - // extract the absolute granule position - lo = get32(f); - hi = get32(f); - if (lo == 0xffffffff && hi == 0xffffffff) { - f->error = VORBIS_cant_find_last_page; - f->total_samples = SAMPLE_unknown; - goto done; - } - if (hi) - lo = 0xfffffffe; // saturate - f->total_samples = lo; + // parse the header + getn(f, (unsigned char*)header, 6); + // extract the absolute granule position + lo = get32(f); + hi = get32(f); + if (lo == 0xffffffff && hi == 0xffffffff) + { + f->error = VORBIS_cant_find_last_page; + f->total_samples = SAMPLE_unknown; + goto done; + } + if (hi) + lo = 0xfffffffe; // saturate + f->total_samples = lo; - f->p_last.page_start = last_page_loc; - f->p_last.page_end = end; - f->p_last.last_decoded_sample = lo; + f->p_last.page_start = last_page_loc; + f->p_last.page_end = end; + f->p_last.last_decoded_sample = lo; - done: - set_file_offset(f, restore_offset); - } - return f->total_samples == SAMPLE_unknown ? 0 : f->total_samples; + done: + set_file_offset(f, restore_offset); + } + return f->total_samples == SAMPLE_unknown ? 0 : f->total_samples; } -float stb_vorbis_stream_length_in_seconds(stb_vorbis *f) +float stb_vorbis_stream_length_in_seconds(stb_vorbis* f) { - return stb_vorbis_stream_length_in_samples(f) / (float) f->sample_rate; + return stb_vorbis_stream_length_in_samples(f) / (float)f->sample_rate; } - -int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output) +int stb_vorbis_get_frame_float(stb_vorbis* f, int* channels, float*** output) { - int len, right,left,i; - if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); + int len, right, left, i; + if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); - if (!vorbis_decode_packet(f, &len, &left, &right)) { - f->channel_buffer_start = f->channel_buffer_end = 0; - return 0; - } + if (!vorbis_decode_packet(f, &len, &left, &right)) + { + f->channel_buffer_start = f->channel_buffer_end = 0; + return 0; + } - len = vorbis_finish_frame(f, len, left, right); - for (i=0; i < f->channels; ++i) - f->outputs[i] = f->channel_buffers[i] + left; + len = vorbis_finish_frame(f, len, left, right); + for (i = 0; i < f->channels; ++i) + f->outputs[i] = f->channel_buffers[i] + left; - f->channel_buffer_start = left; - f->channel_buffer_end = left+len; + f->channel_buffer_start = left; + f->channel_buffer_end = left + len; - if (channels) *channels = f->channels; - if (output) *output = f->outputs; - return len; + if (channels) *channels = f->channels; + if (output) *output = f->outputs; + return len; } #ifndef STB_VORBIS_NO_STDIO -stb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *error, const stb_vorbis_alloc *alloc, unsigned int length) +stb_vorbis* stb_vorbis_open_file_section(FILE* file, int close_on_free, int* error, const stb_vorbis_alloc* alloc, + unsigned int length) { - stb_vorbis *f, p; - vorbis_init(&p, alloc); - p.f = file; - p.f_start = (uint32) ftell(file); - p.stream_len = length; - p.close_on_free = close_on_free; - if (start_decoder(&p)) { - f = vorbis_alloc(&p); - if (f) { - *f = p; - vorbis_pump_first_frame(f); - return f; - } - } - if (error) *error = p.error; - vorbis_deinit(&p); - return NULL; + stb_vorbis *f, p; + vorbis_init(&p, alloc); + p.f = file; + p.f_start = (uint32)ftell(file); + p.stream_len = length; + p.close_on_free = close_on_free; + if (start_decoder(&p)) + { + f = vorbis_alloc(&p); + if (f) + { + *f = p; + vorbis_pump_first_frame(f); + return f; + } + } + if (error) *error = p.error; + vorbis_deinit(&p); + return NULL; } -stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, const stb_vorbis_alloc *alloc) +stb_vorbis* stb_vorbis_open_file(FILE* file, int close_on_free, int* error, const stb_vorbis_alloc* alloc) { - unsigned int len, start; - start = (unsigned int) ftell(file); - fseek(file, 0, SEEK_END); - len = (unsigned int) (ftell(file) - start); - fseek(file, start, SEEK_SET); - return stb_vorbis_open_file_section(file, close_on_free, error, alloc, len); + unsigned int len, start; + start = (unsigned int)ftell(file); + fseek(file, 0, SEEK_END); + len = (unsigned int)(ftell(file) - start); + fseek(file, start, SEEK_SET); + return stb_vorbis_open_file_section(file, close_on_free, error, alloc, len); } -stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, const stb_vorbis_alloc *alloc) +stb_vorbis* stb_vorbis_open_filename(const char* filename, int* error, const stb_vorbis_alloc* alloc) { - FILE *f; + FILE* f; #if defined(_MSC_VER) || defined(__MINGW64__) - fopen_s(&f, filename, "rb"); + fopen_s(&f, filename, "rb"); #else f = fopen(filename, "rb"); #endif - if (f) - return stb_vorbis_open_file(f, TRUE, error, alloc); - if (error) *error = VORBIS_file_open_failure; - return NULL; + if (f) + return stb_vorbis_open_file(f, TRUE, error, alloc); + if (error) *error = VORBIS_file_open_failure; + return NULL; } #endif // STB_VORBIS_NO_STDIO -stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, int *error, const stb_vorbis_alloc *alloc) +stb_vorbis* stb_vorbis_open_memory(const unsigned char* data, int len, int* error, const stb_vorbis_alloc* alloc) { - stb_vorbis *f, p; - if (data == NULL) return NULL; - vorbis_init(&p, alloc); - p.stream = (uint8 *) data; - p.stream_end = (uint8 *) data + len; - p.stream_start = (uint8 *) p.stream; - p.stream_len = len; - p.push_mode = FALSE; - if (start_decoder(&p)) { - f = vorbis_alloc(&p); - if (f) { - *f = p; - vorbis_pump_first_frame(f); - if (error) *error = VORBIS__no_error; - return f; - } - } - if (error) *error = p.error; - vorbis_deinit(&p); - return NULL; + stb_vorbis *f, p; + if (data == NULL) return NULL; + vorbis_init(&p, alloc); + p.stream = (uint8*)data; + p.stream_end = (uint8*)data + len; + p.stream_start = (uint8*)p.stream; + p.stream_len = len; + p.push_mode = FALSE; + if (start_decoder(&p)) + { + f = vorbis_alloc(&p); + if (f) + { + *f = p; + vorbis_pump_first_frame(f); + if (error) *error = VORBIS__no_error; + return f; + } + } + if (error) *error = p.error; + vorbis_deinit(&p); + return NULL; } #ifndef STB_VORBIS_NO_INTEGER_CONVERSION @@ -4671,348 +5080,392 @@ stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, int *err static int8 channel_position[7][6] = { - { 0 }, - { C }, - { L, R }, - { L, C, R }, - { L, R, L, R }, - { L, C, R, L, R }, - { L, C, R, L, R, C }, + {0}, + {C}, + {L, R}, + {L, C, R}, + {L, R, L, R}, + {L, C, R, L, R}, + {L, C, R, L, R, C}, }; #ifndef STB_VORBIS_NO_FAST_SCALED_FLOAT - typedef union { - float f; - int i; - } float_conv; - typedef char stb_vorbis_float_size_test[sizeof(float)==4 && sizeof(int) == 4]; - #define FASTDEF(x) float_conv x - // add (1<<23) to convert to int, then divide by 2^SHIFT, then add 0.5/2^SHIFT to round - #define MAGIC(SHIFT) (1.5f * (1 << (23-SHIFT)) + 0.5f/(1 << SHIFT)) - #define ADDEND(SHIFT) (((150-SHIFT) << 23) + (1 << 22)) - #define FAST_SCALED_FLOAT_TO_INT(temp,x,s) (temp.f = (x) + MAGIC(s), temp.i - ADDEND(s)) - #define check_endianness() +typedef union +{ + float f; + int i; +} float_conv; + +typedef char stb_vorbis_float_size_test[sizeof(float) == 4 && sizeof(int) == 4]; +#define FASTDEF(x) float_conv x +// add (1<<23) to convert to int, then divide by 2^SHIFT, then add 0.5/2^SHIFT to round +#define MAGIC(SHIFT) (1.5f * (1 << (23-SHIFT)) + 0.5f/(1 << SHIFT)) +#define ADDEND(SHIFT) (((150-SHIFT) << 23) + (1 << 22)) +#define FAST_SCALED_FLOAT_TO_INT(temp,x,s) (temp.f = (x) + MAGIC(s), temp.i - ADDEND(s)) +#define check_endianness() #else #define FAST_SCALED_FLOAT_TO_INT(temp,x,s) ((int) ((x) * (1 << (s)))) #define check_endianness() #define FASTDEF(x) #endif -static void copy_samples(short *dest, float *src, int len) +static void copy_samples(short* dest, float* src, int len) { - int i; - check_endianness(); - for (i=0; i < len; ++i) { - FASTDEF(temp); - int v = FAST_SCALED_FLOAT_TO_INT(temp, src[i],15); - if ((unsigned int) (v + 32768) > 65535) - v = v < 0 ? -32768 : 32767; - dest[i] = v; - } + int i; + check_endianness(); + for (i = 0; i < len; ++i) + { + FASTDEF(temp); + int v = FAST_SCALED_FLOAT_TO_INT(temp, src[i], 15); + if ((unsigned int)(v + 32768) > 65535) + v = v < 0 ? -32768 : 32767; + dest[i] = v; + } } -static void compute_samples(int mask, short *output, int num_c, float **data, int d_offset, int len) +static void compute_samples(int mask, short* output, int num_c, float** data, int d_offset, int len) { - #define BUFFER_SIZE 32 - float buffer[BUFFER_SIZE]; - int i,j,o,n = BUFFER_SIZE; - check_endianness(); - for (o = 0; o < len; o += BUFFER_SIZE) { - memset(buffer, 0, sizeof(buffer)); - if (o + n > len) n = len - o; - for (j=0; j < num_c; ++j) { - if (channel_position[num_c][j] & mask) { - for (i=0; i < n; ++i) - buffer[i] += data[j][d_offset+o+i]; - } - } - for (i=0; i < n; ++i) { - FASTDEF(temp); - int v = FAST_SCALED_FLOAT_TO_INT(temp,buffer[i],15); - if ((unsigned int) (v + 32768) > 65535) - v = v < 0 ? -32768 : 32767; - output[o+i] = v; - } - } +#define BUFFER_SIZE 32 + float buffer[BUFFER_SIZE]; + int i, j, o, n = BUFFER_SIZE; + check_endianness(); + for (o = 0; o < len; o += BUFFER_SIZE) + { + memset(buffer, 0, sizeof(buffer)); + if (o + n > len) n = len - o; + for (j = 0; j < num_c; ++j) + { + if (channel_position[num_c][j] & mask) + { + for (i = 0; i < n; ++i) + buffer[i] += data[j][d_offset + o + i]; + } + } + for (i = 0; i < n; ++i) + { + FASTDEF(temp); + int v = FAST_SCALED_FLOAT_TO_INT(temp, buffer[i], 15); + if ((unsigned int)(v + 32768) > 65535) + v = v < 0 ? -32768 : 32767; + output[o + i] = v; + } + } } -static void compute_stereo_samples(short *output, int num_c, float **data, int d_offset, int len) +static void compute_stereo_samples(short* output, int num_c, float** data, int d_offset, int len) { - #define BUFFER_SIZE 32 - float buffer[BUFFER_SIZE]; - int i,j,o,n = BUFFER_SIZE >> 1; - // o is the offset in the source data - check_endianness(); - for (o = 0; o < len; o += BUFFER_SIZE >> 1) { - // o2 is the offset in the output data - int o2 = o << 1; - memset(buffer, 0, sizeof(buffer)); - if (o + n > len) n = len - o; - for (j=0; j < num_c; ++j) { - int m = channel_position[num_c][j] & (PLAYBACK_LEFT | PLAYBACK_RIGHT); - if (m == (PLAYBACK_LEFT | PLAYBACK_RIGHT)) { - for (i=0; i < n; ++i) { - buffer[i*2+0] += data[j][d_offset+o+i]; - buffer[i*2+1] += data[j][d_offset+o+i]; - } - } else if (m == PLAYBACK_LEFT) { - for (i=0; i < n; ++i) { - buffer[i*2+0] += data[j][d_offset+o+i]; - } - } else if (m == PLAYBACK_RIGHT) { - for (i=0; i < n; ++i) { - buffer[i*2+1] += data[j][d_offset+o+i]; - } - } - } - for (i=0; i < (n<<1); ++i) { - FASTDEF(temp); - int v = FAST_SCALED_FLOAT_TO_INT(temp,buffer[i],15); - if ((unsigned int) (v + 32768) > 65535) - v = v < 0 ? -32768 : 32767; - output[o2+i] = v; - } - } +#define BUFFER_SIZE 32 + float buffer[BUFFER_SIZE]; + int i, j, o, n = BUFFER_SIZE >> 1; + // o is the offset in the source data + check_endianness(); + for (o = 0; o < len; o += BUFFER_SIZE >> 1) + { + // o2 is the offset in the output data + int o2 = o << 1; + memset(buffer, 0, sizeof(buffer)); + if (o + n > len) n = len - o; + for (j = 0; j < num_c; ++j) + { + int m = channel_position[num_c][j] & (PLAYBACK_LEFT | PLAYBACK_RIGHT); + if (m == (PLAYBACK_LEFT | PLAYBACK_RIGHT)) + { + for (i = 0; i < n; ++i) + { + buffer[i * 2 + 0] += data[j][d_offset + o + i]; + buffer[i * 2 + 1] += data[j][d_offset + o + i]; + } + } + else if (m == PLAYBACK_LEFT) + { + for (i = 0; i < n; ++i) + { + buffer[i * 2 + 0] += data[j][d_offset + o + i]; + } + } + else if (m == PLAYBACK_RIGHT) + { + for (i = 0; i < n; ++i) + { + buffer[i * 2 + 1] += data[j][d_offset + o + i]; + } + } + } + for (i = 0; i < (n << 1); ++i) + { + FASTDEF(temp); + int v = FAST_SCALED_FLOAT_TO_INT(temp, buffer[i], 15); + if ((unsigned int)(v + 32768) > 65535) + v = v < 0 ? -32768 : 32767; + output[o2 + i] = v; + } + } } -static void convert_samples_short(int buf_c, short **buffer, int b_offset, int data_c, float **data, int d_offset, int samples) +static void convert_samples_short(int buf_c, short** buffer, int b_offset, int data_c, float** data, int d_offset, + int samples) { - int i; - if (buf_c != data_c && buf_c <= 2 && data_c <= 6) { - static int channel_selector[3][2] = { {0}, {PLAYBACK_MONO}, {PLAYBACK_LEFT, PLAYBACK_RIGHT} }; - for (i=0; i < buf_c; ++i) - compute_samples(channel_selector[buf_c][i], buffer[i]+b_offset, data_c, data, d_offset, samples); - } else { - int limit = buf_c < data_c ? buf_c : data_c; - for (i=0; i < limit; ++i) - copy_samples(buffer[i]+b_offset, data[i]+d_offset, samples); - for ( ; i < buf_c; ++i) - memset(buffer[i]+b_offset, 0, sizeof(short) * samples); - } + int i; + if (buf_c != data_c && buf_c <= 2 && data_c <= 6) + { + static int channel_selector[3][2] = {{0}, {PLAYBACK_MONO}, {PLAYBACK_LEFT, PLAYBACK_RIGHT}}; + for (i = 0; i < buf_c; ++i) + compute_samples(channel_selector[buf_c][i], buffer[i] + b_offset, data_c, data, d_offset, samples); + } + else + { + int limit = buf_c < data_c ? buf_c : data_c; + for (i = 0; i < limit; ++i) + copy_samples(buffer[i] + b_offset, data[i] + d_offset, samples); + for (; i < buf_c; ++i) + memset(buffer[i] + b_offset, 0, sizeof(short) * samples); + } } -int stb_vorbis_get_frame_short(stb_vorbis *f, int num_c, short **buffer, int num_samples) +int stb_vorbis_get_frame_short(stb_vorbis* f, int num_c, short** buffer, int num_samples) { - float **output = nullptr; - int len = stb_vorbis_get_frame_float(f, NULL, &output); - if (len > num_samples) len = num_samples; - if (len) - convert_samples_short(num_c, buffer, 0, f->channels, output, 0, len); - return len; + float** output = nullptr; + int len = stb_vorbis_get_frame_float(f, NULL, &output); + if (len > num_samples) len = num_samples; + if (len) + convert_samples_short(num_c, buffer, 0, f->channels, output, 0, len); + return len; } -static void convert_channels_short_interleaved(int buf_c, short *buffer, int data_c, float **data, int d_offset, int len) +static void convert_channels_short_interleaved(int buf_c, short* buffer, int data_c, float** data, int d_offset, + int len) { - int i; - check_endianness(); - if (buf_c != data_c && buf_c <= 2 && data_c <= 6) { - assert(buf_c == 2); - for (i=0; i < buf_c; ++i) - compute_stereo_samples(buffer, data_c, data, d_offset, len); - } else { - int limit = buf_c < data_c ? buf_c : data_c; - int j; - for (j=0; j < len; ++j) { - for (i=0; i < limit; ++i) { - FASTDEF(temp); - float f = data[i][d_offset+j]; - int v = FAST_SCALED_FLOAT_TO_INT(temp, f,15);//data[i][d_offset+j],15); - if ((unsigned int) (v + 32768) > 65535) - v = v < 0 ? -32768 : 32767; - *buffer++ = v; - } - for ( ; i < buf_c; ++i) - *buffer++ = 0; - } - } + int i; + check_endianness(); + if (buf_c != data_c && buf_c <= 2 && data_c <= 6) + { + assert(buf_c == 2); + for (i = 0; i < buf_c; ++i) + compute_stereo_samples(buffer, data_c, data, d_offset, len); + } + else + { + int limit = buf_c < data_c ? buf_c : data_c; + int j; + for (j = 0; j < len; ++j) + { + for (i = 0; i < limit; ++i) + { + FASTDEF(temp); + float f = data[i][d_offset + j]; + int v = FAST_SCALED_FLOAT_TO_INT(temp, f, 15); //data[i][d_offset+j],15); + if ((unsigned int)(v + 32768) > 65535) + v = v < 0 ? -32768 : 32767; + *buffer++ = v; + } + for (; i < buf_c; ++i) + *buffer++ = 0; + } + } } -int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts) +int stb_vorbis_get_frame_short_interleaved(stb_vorbis* f, int num_c, short* buffer, int num_shorts) { - float **output; - int len; - if (num_c == 1) return stb_vorbis_get_frame_short(f,num_c,&buffer, num_shorts); - len = stb_vorbis_get_frame_float(f, NULL, &output); - if (len) { - if (len*num_c > num_shorts) len = num_shorts / num_c; - convert_channels_short_interleaved(num_c, buffer, f->channels, output, 0, len); - } - return len; + float** output; + int len; + if (num_c == 1) return stb_vorbis_get_frame_short(f, num_c, &buffer, num_shorts); + len = stb_vorbis_get_frame_float(f, NULL, &output); + if (len) + { + if (len * num_c > num_shorts) len = num_shorts / num_c; + convert_channels_short_interleaved(num_c, buffer, f->channels, output, 0, len); + } + return len; } -int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short *buffer, int num_shorts) +int stb_vorbis_get_samples_short_interleaved(stb_vorbis* f, int channels, short* buffer, int num_shorts) { - float **outputs; - int len = num_shorts / channels; - int n=0; - int z = f->channels; - if (z > channels) z = channels; - while (n < len) { - int k = f->channel_buffer_end - f->channel_buffer_start; - if (n+k >= len) k = len - n; - if (k) - convert_channels_short_interleaved(channels, buffer, f->channels, f->channel_buffers, f->channel_buffer_start, k); - buffer += k*channels; - n += k; - f->channel_buffer_start += k; - if (n == len) break; - if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break; - } - return n; + float** outputs; + int len = num_shorts / channels; + int n = 0; + int z = f->channels; + if (z > channels) z = channels; + while (n < len) + { + int k = f->channel_buffer_end - f->channel_buffer_start; + if (n + k >= len) k = len - n; + if (k) + convert_channels_short_interleaved(channels, buffer, f->channels, f->channel_buffers, f->channel_buffer_start, + k); + buffer += k * channels; + n += k; + f->channel_buffer_start += k; + if (n == len) break; + if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break; + } + return n; } -int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, int len) +int stb_vorbis_get_samples_short(stb_vorbis* f, int channels, short** buffer, int len) { - float **outputs; - int n=0; - int z = f->channels; - if (z > channels) z = channels; - while (n < len) { - int k = f->channel_buffer_end - f->channel_buffer_start; - if (n+k >= len) k = len - n; - if (k) - convert_samples_short(channels, buffer, n, f->channels, f->channel_buffers, f->channel_buffer_start, k); - n += k; - f->channel_buffer_start += k; - if (n == len) break; - if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break; - } - return n; + float** outputs; + int n = 0; + int z = f->channels; + if (z > channels) z = channels; + while (n < len) + { + int k = f->channel_buffer_end - f->channel_buffer_start; + if (n + k >= len) k = len - n; + if (k) + convert_samples_short(channels, buffer, n, f->channels, f->channel_buffers, f->channel_buffer_start, k); + n += k; + f->channel_buffer_start += k; + if (n == len) break; + if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break; + } + return n; } #ifndef STB_VORBIS_NO_STDIO -int stb_vorbis_decode_filename(const char *filename, int *channels, int *sample_rate, short **output) +int stb_vorbis_decode_filename(const char* filename, int* channels, int* sample_rate, short** output) { - int data_len, offset, total, limit, error; - short *data; - stb_vorbis *v = stb_vorbis_open_filename(filename, &error, NULL); - if (v == NULL) return -1; - limit = v->channels * 4096; - *channels = v->channels; - if (sample_rate) - *sample_rate = v->sample_rate; - offset = data_len = 0; - total = limit; - data = (short *) malloc(total * sizeof(*data)); - if (data == NULL) { - stb_vorbis_close(v); - return -2; - } - for (;;) { - int n = stb_vorbis_get_frame_short_interleaved(v, v->channels, data+offset, total-offset); - if (n == 0) break; - data_len += n; - offset += n * v->channels; - if (offset + limit > total) { - short *data2; - total *= 2; - data2 = (short *) realloc(data, total * sizeof(*data)); - if (data2 == NULL) { - free(data); - stb_vorbis_close(v); - return -2; - } - data = data2; - } - } - *output = data; - stb_vorbis_close(v); - return data_len; + int data_len, offset, total, limit, error; + short* data; + stb_vorbis* v = stb_vorbis_open_filename(filename, &error, NULL); + if (v == NULL) return -1; + limit = v->channels * 4096; + *channels = v->channels; + if (sample_rate) + *sample_rate = v->sample_rate; + offset = data_len = 0; + total = limit; + data = (short*)malloc(total * sizeof(*data)); + if (data == NULL) + { + stb_vorbis_close(v); + return -2; + } + for (;;) + { + int n = stb_vorbis_get_frame_short_interleaved(v, v->channels, data + offset, total - offset); + if (n == 0) break; + data_len += n; + offset += n * v->channels; + if (offset + limit > total) + { + short* data2; + total *= 2; + data2 = (short*)realloc(data, total * sizeof(*data)); + if (data2 == NULL) + { + free(data); + stb_vorbis_close(v); + return -2; + } + data = data2; + } + } + *output = data; + stb_vorbis_close(v); + return data_len; } #endif // NO_STDIO -int stb_vorbis_decode_memory(const uint8 *mem, int len, int *channels, int *sample_rate, short **output) +int stb_vorbis_decode_memory(const uint8* mem, int len, int* channels, int* sample_rate, short** output) { - int data_len, offset, total, limit, error; - short *data; - stb_vorbis *v = stb_vorbis_open_memory(mem, len, &error, NULL); - if (v == NULL) return -1; - limit = v->channels * 4096; - *channels = v->channels; - if (sample_rate) - *sample_rate = v->sample_rate; - offset = data_len = 0; - total = limit; - data = (short *) malloc(total * sizeof(*data)); - if (data == NULL) { - stb_vorbis_close(v); - return -2; - } - for (;;) { - int n = stb_vorbis_get_frame_short_interleaved(v, v->channels, data+offset, total-offset); - if (n == 0) break; - data_len += n; - offset += n * v->channels; - if (offset + limit > total) { - short *data2; - total *= 2; - data2 = (short *) realloc(data, total * sizeof(*data)); - if (data2 == NULL) { - free(data); - stb_vorbis_close(v); - return -2; - } - data = data2; - } - } - *output = data; - stb_vorbis_close(v); - return data_len; + int data_len, offset, total, limit, error; + short* data; + stb_vorbis* v = stb_vorbis_open_memory(mem, len, &error, NULL); + if (v == NULL) return -1; + limit = v->channels * 4096; + *channels = v->channels; + if (sample_rate) + *sample_rate = v->sample_rate; + offset = data_len = 0; + total = limit; + data = (short*)malloc(total * sizeof(*data)); + if (data == NULL) + { + stb_vorbis_close(v); + return -2; + } + for (;;) + { + int n = stb_vorbis_get_frame_short_interleaved(v, v->channels, data + offset, total - offset); + if (n == 0) break; + data_len += n; + offset += n * v->channels; + if (offset + limit > total) + { + short* data2; + total *= 2; + data2 = (short*)realloc(data, total * sizeof(*data)); + if (data2 == NULL) + { + free(data); + stb_vorbis_close(v); + return -2; + } + data = data2; + } + } + *output = data; + stb_vorbis_close(v); + return data_len; } #endif // STB_VORBIS_NO_INTEGER_CONVERSION -int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float *buffer, int num_floats) +int stb_vorbis_get_samples_float_interleaved(stb_vorbis* f, int channels, float* buffer, int num_floats) { - float **outputs; - int len = num_floats / channels; - int n=0; - int z = f->channels; - if (z > channels) z = channels; - while (n < len) { - int i,j; - int k = f->channel_buffer_end - f->channel_buffer_start; - if (n+k >= len) k = len - n; - for (j=0; j < k; ++j) { - for (i=0; i < z; ++i) - *buffer++ = f->channel_buffers[i][f->channel_buffer_start+j]; - for ( ; i < channels; ++i) - *buffer++ = 0; - } - n += k; - f->channel_buffer_start += k; - if (n == len) - break; - if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) - break; - } - return n; + float** outputs; + int len = num_floats / channels; + int n = 0; + int z = f->channels; + if (z > channels) z = channels; + while (n < len) + { + int i, j; + int k = f->channel_buffer_end - f->channel_buffer_start; + if (n + k >= len) k = len - n; + for (j = 0; j < k; ++j) + { + for (i = 0; i < z; ++i) + *buffer++ = f->channel_buffers[i][f->channel_buffer_start + j]; + for (; i < channels; ++i) + *buffer++ = 0; + } + n += k; + f->channel_buffer_start += k; + if (n == len) + break; + if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) + break; + } + return n; } -int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, int num_samples) +int stb_vorbis_get_samples_float(stb_vorbis* f, int channels, float** buffer, int num_samples) { - float **outputs; - int n=0; - int z = f->channels; - if (z > channels) z = channels; - while (n < num_samples) { - int i; - int k = f->channel_buffer_end - f->channel_buffer_start; - if (n+k >= num_samples) k = num_samples - n; - if (k) { - for (i=0; i < z; ++i) - memcpy(buffer[i]+n, f->channel_buffers[i]+f->channel_buffer_start, sizeof(float)*k); - for ( ; i < channels; ++i) - memset(buffer[i]+n, 0, sizeof(float) * k); - } - n += k; - f->channel_buffer_start += k; - if (n == num_samples) - break; - if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) - break; - } - return n; + float** outputs; + int n = 0; + int z = f->channels; + if (z > channels) z = channels; + while (n < num_samples) + { + int i; + int k = f->channel_buffer_end - f->channel_buffer_start; + if (n + k >= num_samples) k = num_samples - n; + if (k) + { + for (i = 0; i < z; ++i) + memcpy(buffer[i] + n, f->channel_buffers[i] + f->channel_buffer_start, sizeof(float) * k); + for (; i < channels; ++i) + memset(buffer[i] + n, 0, sizeof(float) * k); + } + n += k; + f->channel_buffer_start += k; + if (n == num_samples) + break; + if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) + break; + } + return n; } #endif // STB_VORBIS_NO_PULLDATA_API diff --git a/Utilities/stb_vorbis.h b/Utilities/stb_vorbis.h index a7dcb07..c3c0085 100644 --- a/Utilities/stb_vorbis.h +++ b/Utilities/stb_vorbis.h @@ -18,307 +18,316 @@ extern "C" { #endif - /////////// THREAD SAFETY +/////////// THREAD SAFETY - // Individual stb_vorbis* handles are not thread-safe; you cannot decode from - // them from multiple threads at the same time. However, you can have multiple - // stb_vorbis* handles and decode from them independently in multiple thrads. +// Individual stb_vorbis* handles are not thread-safe; you cannot decode from +// them from multiple threads at the same time. However, you can have multiple +// stb_vorbis* handles and decode from them independently in multiple thrads. - /////////// MEMORY ALLOCATION +/////////// MEMORY ALLOCATION - // normally stb_vorbis uses malloc() to allocate memory at startup, - // and alloca() to allocate temporary memory during a frame on the - // stack. (Memory consumption will depend on the amount of setup - // data in the file and how you set the compile flags for speed - // vs. size. In my test files the maximal-size usage is ~150KB.) - // - // You can modify the wrapper functions in the source (setup_malloc, - // setup_temp_malloc, temp_malloc) to change this behavior, or you - // can use a simpler allocation model: you pass in a buffer from - // which stb_vorbis will allocate _all_ its memory (including the - // temp memory). "open" may fail with a VORBIS_outofmem if you - // do not pass in enough data; there is no way to determine how - // much you do need except to succeed (at which point you can - // query get_info to find the exact amount required. yes I know - // this is lame). - // - // If you pass in a non-NULL buffer of the type below, allocation - // will occur from it as described above. Otherwise just pass NULL - // to use malloc()/alloca() +// normally stb_vorbis uses malloc() to allocate memory at startup, +// and alloca() to allocate temporary memory during a frame on the +// stack. (Memory consumption will depend on the amount of setup +// data in the file and how you set the compile flags for speed +// vs. size. In my test files the maximal-size usage is ~150KB.) +// +// You can modify the wrapper functions in the source (setup_malloc, +// setup_temp_malloc, temp_malloc) to change this behavior, or you +// can use a simpler allocation model: you pass in a buffer from +// which stb_vorbis will allocate _all_ its memory (including the +// temp memory). "open" may fail with a VORBIS_outofmem if you +// do not pass in enough data; there is no way to determine how +// much you do need except to succeed (at which point you can +// query get_info to find the exact amount required. yes I know +// this is lame). +// +// If you pass in a non-NULL buffer of the type below, allocation +// will occur from it as described above. Otherwise just pass NULL +// to use malloc()/alloca() - typedef struct - { - char *alloc_buffer; - int alloc_buffer_length_in_bytes; - } stb_vorbis_alloc; +typedef struct +{ + char* alloc_buffer; + int alloc_buffer_length_in_bytes; +} stb_vorbis_alloc; - /////////// FUNCTIONS USEABLE WITH ALL INPUT MODES +/////////// FUNCTIONS USEABLE WITH ALL INPUT MODES - typedef struct stb_vorbis stb_vorbis; +typedef struct stb_vorbis stb_vorbis; - typedef struct - { - unsigned int sample_rate; - int channels; +typedef struct +{ + unsigned int sample_rate; + int channels; - unsigned int setup_memory_required; - unsigned int setup_temp_memory_required; - unsigned int temp_memory_required; + unsigned int setup_memory_required; + unsigned int setup_temp_memory_required; + unsigned int temp_memory_required; - int max_frame_size; - } stb_vorbis_info; + int max_frame_size; +} stb_vorbis_info; - // get general information about the file - extern stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f); +// get general information about the file +extern stb_vorbis_info stb_vorbis_get_info(stb_vorbis* f); - // get the last error detected (clears it, too) - extern int stb_vorbis_get_error(stb_vorbis *f); +// get the last error detected (clears it, too) +extern int stb_vorbis_get_error(stb_vorbis* f); - // close an ogg vorbis file and free all memory in use - extern void stb_vorbis_close(stb_vorbis *f); +// close an ogg vorbis file and free all memory in use +extern void stb_vorbis_close(stb_vorbis* f); - // this function returns the offset (in samples) from the beginning of the - // file that will be returned by the next decode, if it is known, or -1 - // otherwise. after a flush_pushdata() call, this may take a while before - // it becomes valid again. - // NOT WORKING YET after a seek with PULLDATA API - extern int stb_vorbis_get_sample_offset(stb_vorbis *f); +// this function returns the offset (in samples) from the beginning of the +// file that will be returned by the next decode, if it is known, or -1 +// otherwise. after a flush_pushdata() call, this may take a while before +// it becomes valid again. +// NOT WORKING YET after a seek with PULLDATA API +extern int stb_vorbis_get_sample_offset(stb_vorbis* f); - // returns the current seek point within the file, or offset from the beginning - // of the memory buffer. In pushdata mode it returns 0. - extern unsigned int stb_vorbis_get_file_offset(stb_vorbis *f); +// returns the current seek point within the file, or offset from the beginning +// of the memory buffer. In pushdata mode it returns 0. +extern unsigned int stb_vorbis_get_file_offset(stb_vorbis* f); - /////////// PUSHDATA API +/////////// PUSHDATA API #ifndef STB_VORBIS_NO_PUSHDATA_API - // this API allows you to get blocks of data from any source and hand - // them to stb_vorbis. you have to buffer them; stb_vorbis will tell - // you how much it used, and you have to give it the rest next time; - // and stb_vorbis may not have enough data to work with and you will - // need to give it the same data again PLUS more. Note that the Vorbis - // specification does not bound the size of an individual frame. +// this API allows you to get blocks of data from any source and hand +// them to stb_vorbis. you have to buffer them; stb_vorbis will tell +// you how much it used, and you have to give it the rest next time; +// and stb_vorbis may not have enough data to work with and you will +// need to give it the same data again PLUS more. Note that the Vorbis +// specification does not bound the size of an individual frame. - extern stb_vorbis *stb_vorbis_open_pushdata( - const unsigned char * datablock, int datablock_length_in_bytes, - int *datablock_memory_consumed_in_bytes, - int *error, - const stb_vorbis_alloc *alloc_buffer); - // create a vorbis decoder by passing in the initial data block containing - // the ogg&vorbis headers (you don't need to do parse them, just provide - // the first N bytes of the file--you're told if it's not enough, see below) - // on success, returns an stb_vorbis *, does not set error, returns the amount of - // data parsed/consumed on this call in *datablock_memory_consumed_in_bytes; - // on failure, returns NULL on error and sets *error, does not change *datablock_memory_consumed - // if returns NULL and *error is VORBIS_need_more_data, then the input block was - // incomplete and you need to pass in a larger block from the start of the file +extern stb_vorbis* stb_vorbis_open_pushdata( + const unsigned char* datablock, int datablock_length_in_bytes, + int* datablock_memory_consumed_in_bytes, + int* error, + const stb_vorbis_alloc* alloc_buffer); +// create a vorbis decoder by passing in the initial data block containing +// the ogg&vorbis headers (you don't need to do parse them, just provide +// the first N bytes of the file--you're told if it's not enough, see below) +// on success, returns an stb_vorbis *, does not set error, returns the amount of +// data parsed/consumed on this call in *datablock_memory_consumed_in_bytes; +// on failure, returns NULL on error and sets *error, does not change *datablock_memory_consumed +// if returns NULL and *error is VORBIS_need_more_data, then the input block was +// incomplete and you need to pass in a larger block from the start of the file - extern int stb_vorbis_decode_frame_pushdata( - stb_vorbis *f, - const unsigned char *datablock, int datablock_length_in_bytes, - int *channels, // place to write number of float * buffers - float ***output, // place to write float ** array of float * buffers - int *samples // place to write number of output samples - ); - // decode a frame of audio sample data if possible from the passed-in data block - // - // return value: number of bytes we used from datablock - // - // possible cases: - // 0 bytes used, 0 samples output (need more data) - // N bytes used, 0 samples output (resynching the stream, keep going) - // N bytes used, M samples output (one frame of data) - // note that after opening a file, you will ALWAYS get one N-bytes,0-sample - // frame, because Vorbis always "discards" the first frame. - // - // Note that on resynch, stb_vorbis will rarely consume all of the buffer, - // instead only datablock_length_in_bytes-3 or less. This is because it wants - // to avoid missing parts of a page header if they cross a datablock boundary, - // without writing state-machiney code to record a partial detection. - // - // The number of channels returned are stored in *channels (which can be - // NULL--it is always the same as the number of channels reported by - // get_info). *output will contain an array of float* buffers, one per - // channel. In other words, (*output)[0][0] contains the first sample from - // the first channel, and (*output)[1][0] contains the first sample from - // the second channel. +extern int stb_vorbis_decode_frame_pushdata( + stb_vorbis* f, + const unsigned char* datablock, int datablock_length_in_bytes, + int* channels, // place to write number of float * buffers + float*** output, // place to write float ** array of float * buffers + int* samples // place to write number of output samples +); +// decode a frame of audio sample data if possible from the passed-in data block +// +// return value: number of bytes we used from datablock +// +// possible cases: +// 0 bytes used, 0 samples output (need more data) +// N bytes used, 0 samples output (resynching the stream, keep going) +// N bytes used, M samples output (one frame of data) +// note that after opening a file, you will ALWAYS get one N-bytes,0-sample +// frame, because Vorbis always "discards" the first frame. +// +// Note that on resynch, stb_vorbis will rarely consume all of the buffer, +// instead only datablock_length_in_bytes-3 or less. This is because it wants +// to avoid missing parts of a page header if they cross a datablock boundary, +// without writing state-machiney code to record a partial detection. +// +// The number of channels returned are stored in *channels (which can be +// NULL--it is always the same as the number of channels reported by +// get_info). *output will contain an array of float* buffers, one per +// channel. In other words, (*output)[0][0] contains the first sample from +// the first channel, and (*output)[1][0] contains the first sample from +// the second channel. - extern void stb_vorbis_flush_pushdata(stb_vorbis *f); - // inform stb_vorbis that your next datablock will not be contiguous with - // previous ones (e.g. you've seeked in the data); future attempts to decode - // frames will cause stb_vorbis to resynchronize (as noted above), and - // once it sees a valid Ogg page (typically 4-8KB, as large as 64KB), it - // will begin decoding the _next_ frame. - // - // if you want to seek using pushdata, you need to seek in your file, then - // call stb_vorbis_flush_pushdata(), then start calling decoding, then once - // decoding is returning you data, call stb_vorbis_get_sample_offset, and - // if you don't like the result, seek your file again and repeat. +extern void stb_vorbis_flush_pushdata(stb_vorbis* f); +// inform stb_vorbis that your next datablock will not be contiguous with +// previous ones (e.g. you've seeked in the data); future attempts to decode +// frames will cause stb_vorbis to resynchronize (as noted above), and +// once it sees a valid Ogg page (typically 4-8KB, as large as 64KB), it +// will begin decoding the _next_ frame. +// +// if you want to seek using pushdata, you need to seek in your file, then +// call stb_vorbis_flush_pushdata(), then start calling decoding, then once +// decoding is returning you data, call stb_vorbis_get_sample_offset, and +// if you don't like the result, seek your file again and repeat. #endif - ////////// PULLING INPUT API +////////// PULLING INPUT API #ifndef STB_VORBIS_NO_PULLDATA_API - // This API assumes stb_vorbis is allowed to pull data from a source-- - // either a block of memory containing the _entire_ vorbis stream, or a - // FILE * that you or it create, or possibly some other reading mechanism - // if you go modify the source to replace the FILE * case with some kind - // of callback to your code. (But if you don't support seeking, you may - // just want to go ahead and use pushdata.) +// This API assumes stb_vorbis is allowed to pull data from a source-- +// either a block of memory containing the _entire_ vorbis stream, or a +// FILE * that you or it create, or possibly some other reading mechanism +// if you go modify the source to replace the FILE * case with some kind +// of callback to your code. (But if you don't support seeking, you may +// just want to go ahead and use pushdata.) #if !defined(STB_VORBIS_NO_STDIO) && !defined(STB_VORBIS_NO_INTEGER_CONVERSION) - extern int stb_vorbis_decode_filename(const char *filename, int *channels, int *sample_rate, short **output); +extern int stb_vorbis_decode_filename(const char* filename, int* channels, int* sample_rate, short** output); #endif #if !defined(STB_VORBIS_NO_INTEGER_CONVERSION) - extern int stb_vorbis_decode_memory(const unsigned char *mem, int len, int *channels, int *sample_rate, short **output); +extern int stb_vorbis_decode_memory(const unsigned char* mem, int len, int* channels, int* sample_rate, short** output); #endif - // decode an entire file and output the data interleaved into a malloc()ed - // buffer stored in *output. The return value is the number of samples - // decoded, or -1 if the file could not be opened or was not an ogg vorbis file. - // When you're done with it, just free() the pointer returned in *output. +// decode an entire file and output the data interleaved into a malloc()ed +// buffer stored in *output. The return value is the number of samples +// decoded, or -1 if the file could not be opened or was not an ogg vorbis file. +// When you're done with it, just free() the pointer returned in *output. - extern stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, - int *error, const stb_vorbis_alloc *alloc_buffer); - // create an ogg vorbis decoder from an ogg vorbis stream in memory (note - // this must be the entire stream!). on failure, returns NULL and sets *error +extern stb_vorbis* stb_vorbis_open_memory(const unsigned char* data, int len, + int* error, const stb_vorbis_alloc* alloc_buffer); +// create an ogg vorbis decoder from an ogg vorbis stream in memory (note +// this must be the entire stream!). on failure, returns NULL and sets *error #ifndef STB_VORBIS_NO_STDIO - extern stb_vorbis * stb_vorbis_open_filename(const char *filename, - int *error, const stb_vorbis_alloc *alloc_buffer); - // create an ogg vorbis decoder from a filename via fopen(). on failure, - // returns NULL and sets *error (possibly to VORBIS_file_open_failure). +extern stb_vorbis* stb_vorbis_open_filename(const char* filename, + int* error, const stb_vorbis_alloc* alloc_buffer); +// create an ogg vorbis decoder from a filename via fopen(). on failure, +// returns NULL and sets *error (possibly to VORBIS_file_open_failure). - extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close, - int *error, const stb_vorbis_alloc *alloc_buffer); - // create an ogg vorbis decoder from an open FILE *, looking for a stream at - // the _current_ seek point (ftell). on failure, returns NULL and sets *error. - // note that stb_vorbis must "own" this stream; if you seek it in between - // calls to stb_vorbis, it will become confused. Morever, if you attempt to - // perform stb_vorbis_seek_*() operations on this file, it will assume it - // owns the _entire_ rest of the file after the start point. Use the next - // function, stb_vorbis_open_file_section(), to limit it. +extern stb_vorbis* stb_vorbis_open_file(FILE* f, int close_handle_on_close, + int* error, const stb_vorbis_alloc* alloc_buffer); +// create an ogg vorbis decoder from an open FILE *, looking for a stream at +// the _current_ seek point (ftell). on failure, returns NULL and sets *error. +// note that stb_vorbis must "own" this stream; if you seek it in between +// calls to stb_vorbis, it will become confused. Morever, if you attempt to +// perform stb_vorbis_seek_*() operations on this file, it will assume it +// owns the _entire_ rest of the file after the start point. Use the next +// function, stb_vorbis_open_file_section(), to limit it. - extern stb_vorbis * stb_vorbis_open_file_section(FILE *f, int close_handle_on_close, - int *error, const stb_vorbis_alloc *alloc_buffer, unsigned int len); - // create an ogg vorbis decoder from an open FILE *, looking for a stream at - // the _current_ seek point (ftell); the stream will be of length 'len' bytes. - // on failure, returns NULL and sets *error. note that stb_vorbis must "own" - // this stream; if you seek it in between calls to stb_vorbis, it will become - // confused. +extern stb_vorbis* stb_vorbis_open_file_section(FILE* f, int close_handle_on_close, + int* error, const stb_vorbis_alloc* alloc_buffer, unsigned int len); +// create an ogg vorbis decoder from an open FILE *, looking for a stream at +// the _current_ seek point (ftell); the stream will be of length 'len' bytes. +// on failure, returns NULL and sets *error. note that stb_vorbis must "own" +// this stream; if you seek it in between calls to stb_vorbis, it will become +// confused. #endif - extern int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number); - extern int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number); - // these functions seek in the Vorbis file to (approximately) 'sample_number'. - // after calling seek_frame(), the next call to get_frame_*() will include - // the specified sample. after calling stb_vorbis_seek(), the next call to - // stb_vorbis_get_samples_* will start with the specified sample. If you - // do not need to seek to EXACTLY the target sample when using get_samples_*, - // you can also use seek_frame(). +extern int stb_vorbis_seek_frame(stb_vorbis* f, unsigned int sample_number); +extern int stb_vorbis_seek(stb_vorbis* f, unsigned int sample_number); +// these functions seek in the Vorbis file to (approximately) 'sample_number'. +// after calling seek_frame(), the next call to get_frame_*() will include +// the specified sample. after calling stb_vorbis_seek(), the next call to +// stb_vorbis_get_samples_* will start with the specified sample. If you +// do not need to seek to EXACTLY the target sample when using get_samples_*, +// you can also use seek_frame(). - extern int stb_vorbis_seek_start(stb_vorbis *f); - // this function is equivalent to stb_vorbis_seek(f,0) +extern int stb_vorbis_seek_start(stb_vorbis* f); +// this function is equivalent to stb_vorbis_seek(f,0) - extern unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f); - extern float stb_vorbis_stream_length_in_seconds(stb_vorbis *f); - // these functions return the total length of the vorbis stream +extern unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis* f); +extern float stb_vorbis_stream_length_in_seconds(stb_vorbis* f); +// these functions return the total length of the vorbis stream - extern int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output); - // decode the next frame and return the number of samples. the number of - // channels returned are stored in *channels (which can be NULL--it is always - // the same as the number of channels reported by get_info). *output will - // contain an array of float* buffers, one per channel. These outputs will - // be overwritten on the next call to stb_vorbis_get_frame_*. - // - // You generally should not intermix calls to stb_vorbis_get_frame_*() - // and stb_vorbis_get_samples_*(), since the latter calls the former. +extern int stb_vorbis_get_frame_float(stb_vorbis* f, int* channels, float*** output); +// decode the next frame and return the number of samples. the number of +// channels returned are stored in *channels (which can be NULL--it is always +// the same as the number of channels reported by get_info). *output will +// contain an array of float* buffers, one per channel. These outputs will +// be overwritten on the next call to stb_vorbis_get_frame_*. +// +// You generally should not intermix calls to stb_vorbis_get_frame_*() +// and stb_vorbis_get_samples_*(), since the latter calls the former. #ifndef STB_VORBIS_NO_INTEGER_CONVERSION - extern int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts); - extern int stb_vorbis_get_frame_short(stb_vorbis *f, int num_c, short **buffer, int num_samples); +extern int stb_vorbis_get_frame_short_interleaved(stb_vorbis* f, int num_c, short* buffer, int num_shorts); +extern int stb_vorbis_get_frame_short(stb_vorbis* f, int num_c, short** buffer, int num_samples); #endif - // decode the next frame and return the number of *samples* per channel. - // Note that for interleaved data, you pass in the number of shorts (the - // size of your array), but the return value is the number of samples per - // channel, not the total number of samples. - // - // The data is coerced to the number of channels you request according to the - // channel coercion rules (see below). You must pass in the size of your - // buffer(s) so that stb_vorbis will not overwrite the end of the buffer. - // The maximum buffer size needed can be gotten from get_info(); however, - // the Vorbis I specification implies an absolute maximum of 4096 samples - // per channel. +// decode the next frame and return the number of *samples* per channel. +// Note that for interleaved data, you pass in the number of shorts (the +// size of your array), but the return value is the number of samples per +// channel, not the total number of samples. +// +// The data is coerced to the number of channels you request according to the +// channel coercion rules (see below). You must pass in the size of your +// buffer(s) so that stb_vorbis will not overwrite the end of the buffer. +// The maximum buffer size needed can be gotten from get_info(); however, +// the Vorbis I specification implies an absolute maximum of 4096 samples +// per channel. - // Channel coercion rules: - // Let M be the number of channels requested, and N the number of channels present, - // and Cn be the nth channel; let stereo L be the sum of all L and center channels, - // and stereo R be the sum of all R and center channels (channel assignment from the - // vorbis spec). - // M N output - // 1 k sum(Ck) for all k - // 2 * stereo L, stereo R - // k l k > l, the first l channels, then 0s - // k l k <= l, the first k channels - // Note that this is not _good_ surround etc. mixing at all! It's just so - // you get something useful. +// Channel coercion rules: +// Let M be the number of channels requested, and N the number of channels present, +// and Cn be the nth channel; let stereo L be the sum of all L and center channels, +// and stereo R be the sum of all R and center channels (channel assignment from the +// vorbis spec). +// M N output +// 1 k sum(Ck) for all k +// 2 * stereo L, stereo R +// k l k > l, the first l channels, then 0s +// k l k <= l, the first k channels +// Note that this is not _good_ surround etc. mixing at all! It's just so +// you get something useful. - extern int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float *buffer, int num_floats); - extern int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, int num_samples); - // gets num_samples samples, not necessarily on a frame boundary--this requires - // buffering so you have to supply the buffers. DOES NOT APPLY THE COERCION RULES. - // Returns the number of samples stored per channel; it may be less than requested - // at the end of the file. If there are no more samples in the file, returns 0. +extern int stb_vorbis_get_samples_float_interleaved(stb_vorbis* f, int channels, float* buffer, int num_floats); +extern int stb_vorbis_get_samples_float(stb_vorbis* f, int channels, float** buffer, int num_samples); +// gets num_samples samples, not necessarily on a frame boundary--this requires +// buffering so you have to supply the buffers. DOES NOT APPLY THE COERCION RULES. +// Returns the number of samples stored per channel; it may be less than requested +// at the end of the file. If there are no more samples in the file, returns 0. #ifndef STB_VORBIS_NO_INTEGER_CONVERSION - extern int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short *buffer, int num_shorts); - extern int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, int num_samples); +extern int stb_vorbis_get_samples_short_interleaved(stb_vorbis* f, int channels, short* buffer, int num_shorts); +extern int stb_vorbis_get_samples_short(stb_vorbis* f, int channels, short** buffer, int num_samples); #endif - // gets num_samples samples, not necessarily on a frame boundary--this requires - // buffering so you have to supply the buffers. Applies the coercion rules above - // to produce 'channels' channels. Returns the number of samples stored per channel; - // it may be less than requested at the end of the file. If there are no more - // samples in the file, returns 0. +// gets num_samples samples, not necessarily on a frame boundary--this requires +// buffering so you have to supply the buffers. Applies the coercion rules above +// to produce 'channels' channels. Returns the number of samples stored per channel; +// it may be less than requested at the end of the file. If there are no more +// samples in the file, returns 0. #endif - //////// ERROR CODES +//////// ERROR CODES - enum STBVorbisError - { - VORBIS__no_error, +enum STBVorbisError +{ + VORBIS__no_error, - VORBIS_need_more_data = 1, // not a real error + VORBIS_need_more_data = 1, + // not a real error - VORBIS_invalid_api_mixing, // can't mix API modes - VORBIS_outofmem, // not enough memory - VORBIS_feature_not_supported, // uses floor 0 - VORBIS_too_many_channels, // STB_VORBIS_MAX_CHANNELS is too small - VORBIS_file_open_failure, // fopen() failed - VORBIS_seek_without_length, // can't seek in unknown-length file + VORBIS_invalid_api_mixing, + // can't mix API modes + VORBIS_outofmem, + // not enough memory + VORBIS_feature_not_supported, + // uses floor 0 + VORBIS_too_many_channels, + // STB_VORBIS_MAX_CHANNELS is too small + VORBIS_file_open_failure, + // fopen() failed + VORBIS_seek_without_length, + // can't seek in unknown-length file - VORBIS_unexpected_eof = 10, // file is truncated? - VORBIS_seek_invalid, // seek past EOF + VORBIS_unexpected_eof = 10, + // file is truncated? + VORBIS_seek_invalid, + // seek past EOF - // decoding errors (corrupt/invalid stream) -- you probably - // don't care about the exact details of these + // decoding errors (corrupt/invalid stream) -- you probably + // don't care about the exact details of these - // vorbis errors: - VORBIS_invalid_setup = 20, - VORBIS_invalid_stream, + // vorbis errors: + VORBIS_invalid_setup = 20, + VORBIS_invalid_stream, - // ogg errors: - VORBIS_missing_capture_pattern = 30, - VORBIS_invalid_stream_structure_version, - VORBIS_continued_packet_flag_invalid, - VORBIS_incorrect_stream_serial_number, - VORBIS_invalid_first_page, - VORBIS_bad_packet_type, - VORBIS_cant_find_last_page, - VORBIS_seek_failed - }; + // ogg errors: + VORBIS_missing_capture_pattern = 30, + VORBIS_invalid_stream_structure_version, + VORBIS_continued_packet_flag_invalid, + VORBIS_incorrect_stream_serial_number, + VORBIS_invalid_first_page, + VORBIS_bad_packet_type, + VORBIS_cant_find_last_page, + VORBIS_seek_failed +}; #ifdef __cplusplus @@ -330,4 +339,3 @@ extern "C" { // HEADER ENDS HERE // ////////////////////////////////////////////////////////////////////////////// - diff --git a/Utilities/stdafx.h b/Utilities/stdafx.h index fcaaeee..749020f 100644 --- a/Utilities/stdafx.h +++ b/Utilities/stdafx.h @@ -24,11 +24,11 @@ using std::atomic; using std::atomic_flag; #ifndef __MINGW32__ - #ifdef __clang__ +#ifdef __clang__ #define __forceinline __attribute__((always_inline)) inline - #else - #ifdef __GNUC__ +#else +#ifdef __GNUC__ #define __forceinline __attribute__((always_inline)) inline - #endif - #endif -#endif \ No newline at end of file +#endif +#endif +#endif diff --git a/Utilities/xBRZ/config.h b/Utilities/xBRZ/config.h index 49a6790..64e18c6 100644 --- a/Utilities/xBRZ/config.h +++ b/Utilities/xBRZ/config.h @@ -20,14 +20,14 @@ namespace xbrz { -struct ScalerCfg -{ - double luminanceWeight = 1; - double equalColorTolerance = 30; - double dominantDirectionThreshold = 3.6; - double steepDirectionThreshold = 2.2; - double newTestAttribute = 0; //unused; test new parameters -}; + struct ScalerCfg + { + double luminanceWeight = 1; + double equalColorTolerance = 30; + double dominantDirectionThreshold = 3.6; + double steepDirectionThreshold = 2.2; + double newTestAttribute = 0; //unused; test new parameters + }; } #endif diff --git a/Utilities/xBRZ/xbrz.cpp b/Utilities/xBRZ/xbrz.cpp index c8f4f47..036e7a5 100644 --- a/Utilities/xBRZ/xbrz.cpp +++ b/Utilities/xBRZ/xbrz.cpp @@ -22,88 +22,107 @@ namespace { -template inline -unsigned char getByte(uint32_t val) { return static_cast((val >> (8 * N)) & 0xff); } + template + inline + unsigned char getByte(uint32_t val) { return static_cast((val >> (8 * N)) & 0xff); } -inline unsigned char getAlpha(uint32_t pix) { return getByte<3>(pix); } -inline unsigned char getRed (uint32_t pix) { return getByte<2>(pix); } -inline unsigned char getGreen(uint32_t pix) { return getByte<1>(pix); } -inline unsigned char getBlue (uint32_t pix) { return getByte<0>(pix); } + inline unsigned char getAlpha(uint32_t pix) { return getByte<3>(pix); } + inline unsigned char getRed(uint32_t pix) { return getByte<2>(pix); } + inline unsigned char getGreen(uint32_t pix) { return getByte<1>(pix); } + inline unsigned char getBlue(uint32_t pix) { return getByte<0>(pix); } -inline uint32_t makePixel( unsigned char r, unsigned char g, unsigned char b) { return (r << 16) | (g << 8) | b; } -inline uint32_t makePixel(unsigned char a, unsigned char r, unsigned char g, unsigned char b) { return (a << 24) | (r << 16) | (g << 8) | b; } + inline uint32_t makePixel(unsigned char r, unsigned char g, unsigned char b) { return (r << 16) | (g << 8) | b; } + + inline uint32_t makePixel(unsigned char a, unsigned char r, unsigned char g, unsigned char b) + { + return (a << 24) | (r << 16) | (g << 8) | b; + } -template inline -uint32_t gradientRGB(uint32_t pixFront, uint32_t pixBack) //blend front color with opacity M / N over opaque background: http://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending -{ - static_assert(0 < M && M < N && N <= 1000, ""); + template + inline + uint32_t gradientRGB(uint32_t pixFront, uint32_t pixBack) + //blend front color with opacity M / N over opaque background: http://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending + { + static_assert(0 < M && M < N && N <= 1000, ""); - auto calcColor = [](unsigned char colFront, unsigned char colBack) -> unsigned char { return (colFront * M + colBack * (N - M)) / N; }; + auto calcColor = [](unsigned char colFront, unsigned char colBack) -> unsigned char + { + return (colFront * M + colBack * (N - M)) / N; + }; - return makePixel(calcColor(getRed (pixFront), getRed (pixBack)), - calcColor(getGreen(pixFront), getGreen(pixBack)), - calcColor(getBlue (pixFront), getBlue (pixBack))); -} + return makePixel(calcColor(getRed(pixFront), getRed(pixBack)), + calcColor(getGreen(pixFront), getGreen(pixBack)), + calcColor(getBlue(pixFront), getBlue(pixBack))); + } -template inline -uint32_t gradientARGB(uint32_t pixFront, uint32_t pixBack) //find intermediate color between two colors with alpha channels (=> NO alpha blending!!!) -{ - static_assert(0 < M && M < N && N <= 1000, ""); + template + inline + uint32_t gradientARGB(uint32_t pixFront, uint32_t pixBack) + //find intermediate color between two colors with alpha channels (=> NO alpha blending!!!) + { + static_assert(0 < M && M < N && N <= 1000, ""); - const unsigned int weightFront = getAlpha(pixFront) * M; - const unsigned int weightBack = getAlpha(pixBack) * (N - M); - const unsigned int weightSum = weightFront + weightBack; - if (weightSum == 0) - return 0; + const unsigned int weightFront = getAlpha(pixFront) * M; + const unsigned int weightBack = getAlpha(pixBack) * (N - M); + const unsigned int weightSum = weightFront + weightBack; + if (weightSum == 0) + return 0; - auto calcColor = [=](unsigned char colFront, unsigned char colBack) - { - return static_cast((colFront * weightFront + colBack * weightBack) / weightSum); - }; + auto calcColor = [=](unsigned char colFront, unsigned char colBack) + { + return static_cast((colFront * weightFront + colBack * weightBack) / weightSum); + }; - return makePixel(static_cast(weightSum / N), - calcColor(getRed (pixFront), getRed (pixBack)), - calcColor(getGreen(pixFront), getGreen(pixBack)), - calcColor(getBlue (pixFront), getBlue (pixBack))); -} + return makePixel(static_cast(weightSum / N), + calcColor(getRed(pixFront), getRed(pixBack)), + calcColor(getGreen(pixFront), getGreen(pixBack)), + calcColor(getBlue(pixFront), getBlue(pixBack))); + } -//inline -//double fastSqrt(double n) -//{ -// __asm //speeds up xBRZ by about 9% compared to std::sqrt which internally uses the same assembler instructions but adds some "fluff" -// { -// fld n -// fsqrt -// } -//} -// + //inline + //double fastSqrt(double n) + //{ + // __asm //speeds up xBRZ by about 9% compared to std::sqrt which internally uses the same assembler instructions but adds some "fluff" + // { + // fld n + // fsqrt + // } + //} + // -uint32_t* byteAdvance( uint32_t* ptr, int bytes) { return reinterpret_cast< uint32_t*>(reinterpret_cast< char*>(ptr) + bytes); } -const uint32_t* byteAdvance(const uint32_t* ptr, int bytes) { return reinterpret_cast(reinterpret_cast(ptr) + bytes); } + uint32_t* byteAdvance(uint32_t* ptr, int bytes) + { + return reinterpret_cast(reinterpret_cast(ptr) + bytes); + } + + const uint32_t* byteAdvance(const uint32_t* ptr, int bytes) + { + return reinterpret_cast(reinterpret_cast(ptr) + bytes); + } -//fill block with the given color -inline -void fillBlock(uint32_t* trg, int pitch, uint32_t col, int blockWidth, int blockHeight) -{ - //for (int y = 0; y < blockHeight; ++y, trg = byteAdvance(trg, pitch)) - // std::fill(trg, trg + blockWidth, col); + //fill block with the given color + inline + void fillBlock(uint32_t* trg, int pitch, uint32_t col, int blockWidth, int blockHeight) + { + //for (int y = 0; y < blockHeight; ++y, trg = byteAdvance(trg, pitch)) + // std::fill(trg, trg + blockWidth, col); - for (int y = 0; y < blockHeight; ++y, trg = byteAdvance(trg, pitch)) - for (int x = 0; x < blockWidth; ++x) - trg[x] = col; -} + for (int y = 0; y < blockHeight; ++y, trg = byteAdvance(trg, pitch)) + for (int x = 0; x < blockWidth; ++x) + trg[x] = col; + } -inline -void fillBlock(uint32_t* trg, int pitch, uint32_t col, int n) { fillBlock(trg, pitch, col, n, n); } + inline + void fillBlock(uint32_t* trg, int pitch, uint32_t col, int n) { fillBlock(trg, pitch, col, n, n); } #ifdef _MSC_VER - #define FORCE_INLINE __forceinline +#define FORCE_INLINE __forceinline #elif defined __GNUC__ #define FORCE_INLINE __attribute__((always_inline)) inline #else @@ -111,260 +130,301 @@ void fillBlock(uint32_t* trg, int pitch, uint32_t col, int n) { fillBlock(trg, p #endif -enum RotationDegree //clock-wise -{ - ROT_0, - ROT_90, - ROT_180, - ROT_270 -}; + enum RotationDegree //clock-wise + { + ROT_0, + ROT_90, + ROT_180, + ROT_270 + }; -//calculate input matrix coordinates after rotation at compile time -template -struct MatrixRotation; + //calculate input matrix coordinates after rotation at compile time + template + struct MatrixRotation; -template -struct MatrixRotation -{ - static const size_t I_old = I; - static const size_t J_old = J; -}; + template + struct MatrixRotation + { + static const size_t I_old = I; + static const size_t J_old = J; + }; -template //(i, j) = (row, col) indices, N = size of (square) matrix -struct MatrixRotation -{ - static const size_t I_old = N - 1 - MatrixRotation(rotDeg - 1), I, J, N>::J_old; //old coordinates before rotation! - static const size_t J_old = MatrixRotation(rotDeg - 1), I, J, N>::I_old; // -}; + template + //(i, j) = (row, col) indices, N = size of (square) matrix + struct MatrixRotation + { + static const size_t I_old = N - 1 - MatrixRotation(rotDeg - 1), I, J, N>::J_old; + //old coordinates before rotation! + static const size_t J_old = MatrixRotation(rotDeg - 1), I, J, N>::I_old; // + }; -template -class OutputMatrix -{ -public: - OutputMatrix(uint32_t* out, int outWidth) : //access matrix area, top-left at position "out" for image with given width - out_(out), - outWidth_(outWidth) {} + template + class OutputMatrix + { + public: + OutputMatrix(uint32_t* out, int outWidth) : + //access matrix area, top-left at position "out" for image with given width + out_(out), + outWidth_(outWidth) + { + } - template - uint32_t& ref() const - { - static const size_t I_old = MatrixRotation::I_old; - static const size_t J_old = MatrixRotation::J_old; - return *(out_ + J_old + I_old * outWidth_); - } + template + uint32_t& ref() const + { + static const size_t I_old = MatrixRotation::I_old; + static const size_t J_old = MatrixRotation::J_old; + return *(out_ + J_old + I_old * outWidth_); + } -private: - uint32_t* out_; - const int outWidth_; -}; + private: + uint32_t* out_; + const int outWidth_; + }; -template inline -T square(T value) { return value * value; } + template + inline + T square(T value) { return value * value; } -struct DistYCbCrBuffer //30% perf boost compared to distYCbCr()! -{ -public: - static double dist(uint32_t pix1, uint32_t pix2) - { + struct DistYCbCrBuffer //30% perf boost compared to distYCbCr()! + { + public: + static double dist(uint32_t pix1, uint32_t pix2) + { #if defined _MSC_VER && _MSC_VER < 1900 #error function scope static initialization is not yet thread-safe! #endif - static const DistYCbCrBuffer inst; - return inst.distImpl(pix1, pix2); - } + static const DistYCbCrBuffer inst; + return inst.distImpl(pix1, pix2); + } -private: - DistYCbCrBuffer() : buffer(256 * 256 * 256) - { - for (uint32_t i = 0; i < 256 * 256 * 256; ++i) //startup time: 114 ms on Intel Core i5 (four cores) - { - const int r_diff = getByte<2>(i) * 2 - 255; - const int g_diff = getByte<1>(i) * 2 - 255; - const int b_diff = getByte<0>(i) * 2 - 255; + private: + DistYCbCrBuffer() : buffer(256 * 256 * 256) + { + for (uint32_t i = 0; i < 256 * 256 * 256; ++i) //startup time: 114 ms on Intel Core i5 (four cores) + { + const int r_diff = getByte<2>(i) * 2 - 255; + const int g_diff = getByte<1>(i) * 2 - 255; + const int b_diff = getByte<0>(i) * 2 - 255; - const double k_b = 0.0593; //ITU-R BT.2020 conversion - const double k_r = 0.2627; // - const double k_g = 1 - k_b - k_r; + const double k_b = 0.0593; //ITU-R BT.2020 conversion + const double k_r = 0.2627; // + const double k_g = 1 - k_b - k_r; - const double scale_b = 0.5 / (1 - k_b); - const double scale_r = 0.5 / (1 - k_r); + const double scale_b = 0.5 / (1 - k_b); + const double scale_r = 0.5 / (1 - k_r); - const double y = k_r * r_diff + k_g * g_diff + k_b * b_diff; //[!], analog YCbCr! - const double c_b = scale_b * (b_diff - y); - const double c_r = scale_r * (r_diff - y); + const double y = k_r * r_diff + k_g * g_diff + k_b * b_diff; //[!], analog YCbCr! + const double c_b = scale_b * (b_diff - y); + const double c_r = scale_r * (r_diff - y); - buffer[i] = static_cast(std::sqrt(square(y) + square(c_b) + square(c_r))); - } - } + buffer[i] = static_cast(std::sqrt(square(y) + square(c_b) + square(c_r))); + } + } - double distImpl(uint32_t pix1, uint32_t pix2) const - { - //if (pix1 == pix2) -> 8% perf degradation! - // return 0; - //if (pix1 > pix2) - // std::swap(pix1, pix2); -> 30% perf degradation!!! + double distImpl(uint32_t pix1, uint32_t pix2) const + { + //if (pix1 == pix2) -> 8% perf degradation! + // return 0; + //if (pix1 > pix2) + // std::swap(pix1, pix2); -> 30% perf degradation!!! - const int r_diff = static_cast(getRed (pix1)) - getRed (pix2); - const int g_diff = static_cast(getGreen(pix1)) - getGreen(pix2); - const int b_diff = static_cast(getBlue (pix1)) - getBlue (pix2); + const int r_diff = static_cast(getRed(pix1)) - getRed(pix2); + const int g_diff = static_cast(getGreen(pix1)) - getGreen(pix2); + const int b_diff = static_cast(getBlue(pix1)) - getBlue(pix2); - return buffer[(((r_diff + 255) / 2) << 16) | //slightly reduce precision (division by 2) to squeeze value into single byte - (((g_diff + 255) / 2) << 8) | - (( b_diff + 255) / 2)]; - } + return buffer[(((r_diff + 255) / 2) << 16) | + //slightly reduce precision (division by 2) to squeeze value into single byte + (((g_diff + 255) / 2) << 8) | + ((b_diff + 255) / 2)]; + } - std::vector buffer; //consumes 64 MB memory; using double is only 2% faster, but takes 128 MB -}; + std::vector buffer; //consumes 64 MB memory; using double is only 2% faster, but takes 128 MB + }; -enum BlendType -{ - BLEND_NONE = 0, - BLEND_NORMAL, //a normal indication to blend - BLEND_DOMINANT, //a strong indication to blend - //attention: BlendType must fit into the value range of 2 bit!!! -}; + enum BlendType + { + BLEND_NONE = 0, + BLEND_NORMAL, + //a normal indication to blend + BLEND_DOMINANT, + //a strong indication to blend + //attention: BlendType must fit into the value range of 2 bit!!! + }; -struct BlendResult -{ - BlendType - /**/blend_f, blend_g, - /**/blend_j, blend_k; -}; + struct BlendResult + { + BlendType + /**/blend_f, blend_g, + /**/blend_j, blend_k; + }; -struct Kernel_4x4 //kernel for preprocessing step -{ - uint32_t - /**/a, b, c, d, - /**/e, f, g, h, - /**/i, j, k, l, - /**/m, n, o, p; -}; + struct Kernel_4x4 //kernel for preprocessing step + { + uint32_t + /**/a, b, c, d, + /**/e, f, g, h, + /**/i, j, k, l, + /**/m, n, o, p; + }; -/* -input kernel area naming convention: ------------------ -| A | B | C | D | -----|---|---|---| -| E | F | G | H | //evaluate the four corners between F, G, J, K -----|---|---|---| //input pixel is at position F -| I | J | K | L | -----|---|---|---| -| M | N | O | P | ------------------ -*/ -template -FORCE_INLINE //detect blend direction -BlendResult preProcessCorners(const Kernel_4x4& ker, const xbrz::ScalerCfg& cfg) //result: F, G, J, K corners of "GradientType" -{ - BlendResult result = {}; + /* + input kernel area naming convention: + ----------------- + | A | B | C | D | + ----|---|---|---| + | E | F | G | H | //evaluate the four corners between F, G, J, K + ----|---|---|---| //input pixel is at position F + | I | J | K | L | + ----|---|---|---| + | M | N | O | P | + ----------------- + */ + template + FORCE_INLINE //detect blend direction + BlendResult preProcessCorners(const Kernel_4x4& ker, const xbrz::ScalerCfg& cfg) + //result: F, G, J, K corners of "GradientType" + { + BlendResult result = {}; - if ((ker.f == ker.g && - ker.j == ker.k) || - (ker.f == ker.j && - ker.g == ker.k)) - return result; + if ((ker.f == ker.g && + ker.j == ker.k) || + (ker.f == ker.j && + ker.g == ker.k)) + return result; - auto dist = [&](uint32_t pix1, uint32_t pix2) { return ColorDistance::dist(pix1, pix2, cfg.luminanceWeight); }; + auto dist = [&](uint32_t pix1, uint32_t pix2) { return ColorDistance::dist(pix1, pix2, cfg.luminanceWeight); }; - const int weight = 4; - double jg = dist(ker.i, ker.f) + dist(ker.f, ker.c) + dist(ker.n, ker.k) + dist(ker.k, ker.h) + weight * dist(ker.j, ker.g); - double fk = dist(ker.e, ker.j) + dist(ker.j, ker.o) + dist(ker.b, ker.g) + dist(ker.g, ker.l) + weight * dist(ker.f, ker.k); + const int weight = 4; + double jg = dist(ker.i, ker.f) + dist(ker.f, ker.c) + dist(ker.n, ker.k) + dist(ker.k, ker.h) + weight * + dist(ker.j, ker.g); + double fk = dist(ker.e, ker.j) + dist(ker.j, ker.o) + dist(ker.b, ker.g) + dist(ker.g, ker.l) + weight * + dist(ker.f, ker.k); - if (jg < fk) //test sample: 70% of values max(jg, fk) / min(jg, fk) are between 1.1 and 3.7 with median being 1.8 - { - const bool dominantGradient = cfg.dominantDirectionThreshold * jg < fk; - if (ker.f != ker.g && ker.f != ker.j) - result.blend_f = dominantGradient ? BLEND_DOMINANT : BLEND_NORMAL; + if (jg < fk) //test sample: 70% of values max(jg, fk) / min(jg, fk) are between 1.1 and 3.7 with median being 1.8 + { + const bool dominantGradient = cfg.dominantDirectionThreshold * jg < fk; + if (ker.f != ker.g && ker.f != ker.j) + result.blend_f = dominantGradient ? BLEND_DOMINANT : BLEND_NORMAL; - if (ker.k != ker.j && ker.k != ker.g) - result.blend_k = dominantGradient ? BLEND_DOMINANT : BLEND_NORMAL; - } - else if (fk < jg) - { - const bool dominantGradient = cfg.dominantDirectionThreshold * fk < jg; - if (ker.j != ker.f && ker.j != ker.k) - result.blend_j = dominantGradient ? BLEND_DOMINANT : BLEND_NORMAL; + if (ker.k != ker.j && ker.k != ker.g) + result.blend_k = dominantGradient ? BLEND_DOMINANT : BLEND_NORMAL; + } + else if (fk < jg) + { + const bool dominantGradient = cfg.dominantDirectionThreshold * fk < jg; + if (ker.j != ker.f && ker.j != ker.k) + result.blend_j = dominantGradient ? BLEND_DOMINANT : BLEND_NORMAL; - if (ker.g != ker.f && ker.g != ker.k) - result.blend_g = dominantGradient ? BLEND_DOMINANT : BLEND_NORMAL; - } - return result; -} + if (ker.g != ker.f && ker.g != ker.k) + result.blend_g = dominantGradient ? BLEND_DOMINANT : BLEND_NORMAL; + } + return result; + } -struct Kernel_3x3 -{ - uint32_t - /**/a, b, c, - /**/d, e, f, - /**/g, h, i; -}; + struct Kernel_3x3 + { + uint32_t + /**/a, b, c, + /**/d, e, f, + /**/g, h, i; + }; #define DEF_GETTER(x) template uint32_t inline get_##x(const Kernel_3x3& ker) { return ker.x; } -//we cannot and NEED NOT write "ker.##x" since ## concatenates preprocessor tokens but "." is not a token -DEF_GETTER(a) DEF_GETTER(b) DEF_GETTER(c) -DEF_GETTER(d) DEF_GETTER(e) DEF_GETTER(f) -DEF_GETTER(g) DEF_GETTER(h) DEF_GETTER(i) + //we cannot and NEED NOT write "ker.##x" since ## concatenates preprocessor tokens but "." is not a token + DEF_GETTER(a) + DEF_GETTER(b) + DEF_GETTER(c) + DEF_GETTER(d) + DEF_GETTER(e) + DEF_GETTER(f) + DEF_GETTER(g) + DEF_GETTER(h) + DEF_GETTER(i) #undef DEF_GETTER #define DEF_GETTER(x, y) template <> inline uint32_t get_##x(const Kernel_3x3& ker) { return ker.y; } -DEF_GETTER(b, d) DEF_GETTER(c, a) -DEF_GETTER(d, h) DEF_GETTER(e, e) DEF_GETTER(f, b) -DEF_GETTER(g, i) DEF_GETTER(h, f) DEF_GETTER(i, c) + DEF_GETTER(b, d) + DEF_GETTER(c, a) + DEF_GETTER(d, h) + DEF_GETTER(e, e) + DEF_GETTER(f, b) + DEF_GETTER(g, i) + DEF_GETTER(h, f) + DEF_GETTER(i, c) #undef DEF_GETTER #define DEF_GETTER(x, y) template <> inline uint32_t get_##x(const Kernel_3x3& ker) { return ker.y; } -DEF_GETTER(b, h) DEF_GETTER(c, g) -DEF_GETTER(d, f) DEF_GETTER(e, e) DEF_GETTER(f, d) -DEF_GETTER(g, c) DEF_GETTER(h, b) DEF_GETTER(i, a) + DEF_GETTER(b, h) + DEF_GETTER(c, g) + DEF_GETTER(d, f) + DEF_GETTER(e, e) + DEF_GETTER(f, d) + DEF_GETTER(g, c) + DEF_GETTER(h, b) + DEF_GETTER(i, a) #undef DEF_GETTER #define DEF_GETTER(x, y) template <> inline uint32_t get_##x(const Kernel_3x3& ker) { return ker.y; } -DEF_GETTER(b, f) DEF_GETTER(c, i) -DEF_GETTER(d, b) DEF_GETTER(e, e) DEF_GETTER(f, h) -DEF_GETTER(g, a) DEF_GETTER(h, d) DEF_GETTER(i, g) + DEF_GETTER(b, f) + DEF_GETTER(c, i) + DEF_GETTER(d, b) + DEF_GETTER(e, e) + DEF_GETTER(f, h) + DEF_GETTER(g, a) + DEF_GETTER(h, d) + DEF_GETTER(i, g) #undef DEF_GETTER -//compress four blend types into a single byte -inline BlendType getTopR (unsigned char b) { return static_cast(0x3 & (b >> 2)); } -inline BlendType getBottomR(unsigned char b) { return static_cast(0x3 & (b >> 4)); } -inline BlendType getBottomL(unsigned char b) { return static_cast(0x3 & (b >> 6)); } + //compress four blend types into a single byte + inline BlendType getTopR(unsigned char b) { return static_cast(0x3 & (b >> 2)); } + inline BlendType getBottomR(unsigned char b) { return static_cast(0x3 & (b >> 4)); } + inline BlendType getBottomL(unsigned char b) { return static_cast(0x3 & (b >> 6)); } -inline void setTopL (unsigned char& b, BlendType bt) { b |= bt; } //buffer is assumed to be initialized before preprocessing! -inline void setTopR (unsigned char& b, BlendType bt) { b |= (bt << 2); } -inline void setBottomR(unsigned char& b, BlendType bt) { b |= (bt << 4); } -inline void setBottomL(unsigned char& b, BlendType bt) { b |= (bt << 6); } + inline void setTopL(unsigned char& b, BlendType bt) { b |= bt; } + //buffer is assumed to be initialized before preprocessing! + inline void setTopR(unsigned char& b, BlendType bt) { b |= (bt << 2); } + inline void setBottomR(unsigned char& b, BlendType bt) { b |= (bt << 4); } + inline void setBottomL(unsigned char& b, BlendType bt) { b |= (bt << 6); } -inline bool blendingNeeded(unsigned char b) { return b != 0; } + inline bool blendingNeeded(unsigned char b) { return b != 0; } -template inline -unsigned char rotateBlendInfo(unsigned char b) { return b; } -template <> inline unsigned char rotateBlendInfo(unsigned char b) { return ((b << 2) | (b >> 6)) & 0xff; } -template <> inline unsigned char rotateBlendInfo(unsigned char b) { return ((b << 4) | (b >> 4)) & 0xff; } -template <> inline unsigned char rotateBlendInfo(unsigned char b) { return ((b << 6) | (b >> 2)) & 0xff; } + template + inline + unsigned char rotateBlendInfo(unsigned char b) { return b; } + + template <> + inline unsigned char rotateBlendInfo(unsigned char b) { return ((b << 2) | (b >> 6)) & 0xff; } + + template <> + inline unsigned char rotateBlendInfo(unsigned char b) { return ((b << 4) | (b >> 4)) & 0xff; } + + template <> + inline unsigned char rotateBlendInfo(unsigned char b) { return ((b << 6) | (b >> 2)) & 0xff; } -/* -input kernel area naming convention: -------------- -| A | B | C | -----|---|---| -| D | E | F | //input pixel is at position E -----|---|---| -| G | H | I | -------------- -*/ -template -FORCE_INLINE //perf: quite worth it! -void blendPixel(const Kernel_3x3& ker, - uint32_t* target, int trgWidth, - unsigned char blendInfo, //result of preprocessing all four corners of pixel "e" - const xbrz::ScalerCfg& cfg) -{ + /* + input kernel area naming convention: + ------------- + | A | B | C | + ----|---|---| + | D | E | F | //input pixel is at position E + ----|---|---| + | G | H | I | + ------------- + */ + template + FORCE_INLINE //perf: quite worth it! + void blendPixel(const Kernel_3x3& ker, + uint32_t* target, int trgWidth, + unsigned char blendInfo, //result of preprocessing all four corners of pixel "e" + const xbrz::ScalerCfg& cfg) + { #define a get_a(ker) #define b get_b(ker) #define c get_c(ker) @@ -376,61 +436,65 @@ void blendPixel(const Kernel_3x3& ker, #define i get_i(ker) - const unsigned char blend = rotateBlendInfo(blendInfo); + const unsigned char blend = rotateBlendInfo(blendInfo); - if (getBottomR(blend) >= BLEND_NORMAL) - { - auto eq = [&](uint32_t pix1, uint32_t pix2) { return ColorDistance::dist(pix1, pix2, cfg.luminanceWeight) < cfg.equalColorTolerance; }; - auto dist = [&](uint32_t pix1, uint32_t pix2) { return ColorDistance::dist(pix1, pix2, cfg.luminanceWeight); }; + if (getBottomR(blend) >= BLEND_NORMAL) + { + auto eq = [&](uint32_t pix1, uint32_t pix2) + { + return ColorDistance::dist(pix1, pix2, cfg.luminanceWeight) < cfg.equalColorTolerance; + }; + auto dist = [&](uint32_t pix1, uint32_t pix2) { return ColorDistance::dist(pix1, pix2, cfg.luminanceWeight); }; - const bool doLineBlend = [&]() -> bool - { - if (getBottomR(blend) >= BLEND_DOMINANT) - return true; + const bool doLineBlend = [&]() -> bool + { + if (getBottomR(blend) >= BLEND_DOMINANT) + return true; - //make sure there is no second blending in an adjacent rotation for this pixel: handles insular pixels, mario eyes - if (getTopR(blend) != BLEND_NONE && !eq(e, g)) //but support double-blending for 90 corners - return false; - if (getBottomL(blend) != BLEND_NONE && !eq(e, c)) - return false; + //make sure there is no second blending in an adjacent rotation for this pixel: handles insular pixels, mario eyes + if (getTopR(blend) != BLEND_NONE && !eq(e, g)) //but support double-blending for 90 corners + return false; + if (getBottomL(blend) != BLEND_NONE && !eq(e, c)) + return false; - //no full blending for L-shapes; blend corner only (handles "mario mushroom eyes") - if (!eq(e, i) && eq(g, h) && eq(h , i) && eq(i, f) && eq(f, c)) - return false; + //no full blending for L-shapes; blend corner only (handles "mario mushroom eyes") + if (!eq(e, i) && eq(g, h) && eq(h, i) && eq(i, f) && eq(f, c)) + return false; - return true; - }(); + return true; + }(); - const uint32_t px = dist(e, f) <= dist(e, h) ? f : h; //choose most similar color + const uint32_t px = dist(e, f) <= dist(e, h) ? f : h; //choose most similar color - OutputMatrix out(target, trgWidth); + OutputMatrix out(target, trgWidth); - if (doLineBlend) - { - const double fg = dist(f, g); //test sample: 70% of values max(fg, hc) / min(fg, hc) are between 1.1 and 3.7 with median being 1.9 - const double hc = dist(h, c); // + if (doLineBlend) + { + const double fg = dist(f, g); + //test sample: 70% of values max(fg, hc) / min(fg, hc) are between 1.1 and 3.7 with median being 1.9 + const double hc = dist(h, c); // - const bool haveShallowLine = cfg.steepDirectionThreshold * fg <= hc && e != g && d != g; - const bool haveSteepLine = cfg.steepDirectionThreshold * hc <= fg && e != c && b != c; + const bool haveShallowLine = cfg.steepDirectionThreshold * fg <= hc && e != g && d != g; + const bool haveSteepLine = cfg.steepDirectionThreshold * hc <= fg && e != c && b != c; - if (haveShallowLine) - { - if (haveSteepLine) - Scaler::blendLineSteepAndShallow(px, out); - else - Scaler::blendLineShallow(px, out); - } - else - { - if (haveSteepLine) - Scaler::blendLineSteep(px, out); - else - Scaler::blendLineDiagonal(px,out); - } - } - else - Scaler::blendCorner(px, out); - } + if (haveShallowLine) + { + if (haveSteepLine) + Scaler::blendLineSteepAndShallow(px, out); + else + Scaler::blendLineShallow(px, out); + } + else + { + if (haveSteepLine) + Scaler::blendLineSteep(px, out); + else + Scaler::blendLineDiagonal(px, out); + } + } + else + Scaler::blendCorner(px, out); + } #undef a #undef b @@ -441,649 +505,682 @@ void blendPixel(const Kernel_3x3& ker, #undef g #undef h #undef i + } + + + template //scaler policy: see "Scaler2x" reference implementation + void scaleImage(const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight, const xbrz::ScalerCfg& cfg, + int yFirst, int yLast) + { + yFirst = std::max(yFirst, 0); + yLast = std::min(yLast, srcHeight); + if (yFirst >= yLast || srcWidth <= 0) + return; + + const int trgWidth = srcWidth * Scaler::scale; + + //"use" space at the end of the image as temporary buffer for "on the fly preprocessing": we even could use larger area of + //"sizeof(uint32_t) * srcWidth * (yLast - yFirst)" bytes without risk of accidental overwriting before accessing + const int bufferSize = srcWidth; + unsigned char* preProcBuffer = reinterpret_cast(trg + yLast * Scaler::scale * trgWidth) - + bufferSize; + std::fill(preProcBuffer, preProcBuffer + bufferSize, 0); + static_assert(BLEND_NONE == 0, ""); + + //initialize preprocessing buffer for first row of current stripe: detect upper left and right corner blending + //this cannot be optimized for adjacent processing stripes; we must not allow for a memory race condition! + if (yFirst > 0) + { + const int y = yFirst - 1; + + const uint32_t* s_m1 = src + srcWidth * std::max(y - 1, 0); + const uint32_t* s_0 = src + srcWidth * y; //center line + const uint32_t* s_p1 = src + srcWidth * std::min(y + 1, srcHeight - 1); + const uint32_t* s_p2 = src + srcWidth * std::min(y + 2, srcHeight - 1); + + for (int x = 0; x < srcWidth; ++x) + { + const int x_m1 = std::max(x - 1, 0); + const int x_p1 = std::min(x + 1, srcWidth - 1); + const int x_p2 = std::min(x + 2, srcWidth - 1); + + Kernel_4x4 ker = {}; //perf: initialization is negligible + ker.a = s_m1[x_m1]; //read sequentially from memory as far as possible + ker.b = s_m1[x]; + ker.c = s_m1[x_p1]; + ker.d = s_m1[x_p2]; + + ker.e = s_0[x_m1]; + ker.f = s_0[x]; + ker.g = s_0[x_p1]; + ker.h = s_0[x_p2]; + + ker.i = s_p1[x_m1]; + ker.j = s_p1[x]; + ker.k = s_p1[x_p1]; + ker.l = s_p1[x_p2]; + + ker.m = s_p2[x_m1]; + ker.n = s_p2[x]; + ker.o = s_p2[x_p1]; + ker.p = s_p2[x_p2]; + + const BlendResult res = preProcessCorners(ker, cfg); + /* + preprocessing blend result: + --------- + | F | G | //evalute corner between F, G, J, K + ----|---| //input pixel is at position F + | J | K | + --------- + */ + setTopR(preProcBuffer[x], res.blend_j); + + if (x + 1 < bufferSize) + setTopL(preProcBuffer[x + 1], res.blend_k); + } + } + //------------------------------------------------------------------------------------ + + for (int y = yFirst; y < yLast; ++y) + { + uint32_t* out = trg + Scaler::scale * y * trgWidth; //consider MT "striped" access + + const uint32_t* s_m1 = src + srcWidth * std::max(y - 1, 0); + const uint32_t* s_0 = src + srcWidth * y; //center line + const uint32_t* s_p1 = src + srcWidth * std::min(y + 1, srcHeight - 1); + const uint32_t* s_p2 = src + srcWidth * std::min(y + 2, srcHeight - 1); + + unsigned char blend_xy1 = 0; //corner blending for current (x, y + 1) position + + for (int x = 0; x < srcWidth; ++x, out += Scaler::scale) + { + //all those bounds checks have only insignificant impact on performance! + const int x_m1 = std::max(x - 1, 0); //perf: prefer array indexing to additional pointers! + const int x_p1 = std::min(x + 1, srcWidth - 1); + const int x_p2 = std::min(x + 2, srcWidth - 1); + + Kernel_4x4 ker4 = {}; //perf: initialization is negligible + + ker4.a = s_m1[x_m1]; //read sequentially from memory as far as possible + ker4.b = s_m1[x]; + ker4.c = s_m1[x_p1]; + ker4.d = s_m1[x_p2]; + + ker4.e = s_0[x_m1]; + ker4.f = s_0[x]; + ker4.g = s_0[x_p1]; + ker4.h = s_0[x_p2]; + + ker4.i = s_p1[x_m1]; + ker4.j = s_p1[x]; + ker4.k = s_p1[x_p1]; + ker4.l = s_p1[x_p2]; + + ker4.m = s_p2[x_m1]; + ker4.n = s_p2[x]; + ker4.o = s_p2[x_p1]; + ker4.p = s_p2[x_p2]; + + //evaluate the four corners on bottom-right of current pixel + unsigned char blend_xy = 0; //for current (x, y) position + { + const BlendResult res = preProcessCorners(ker4, cfg); + /* + preprocessing blend result: + --------- + | F | G | //evalute corner between F, G, J, K + ----|---| //current input pixel is at position F + | J | K | + --------- + */ + blend_xy = preProcBuffer[x]; + setBottomR(blend_xy, res.blend_f); + //all four corners of (x, y) have been determined at this point due to processing sequence! + + setTopR(blend_xy1, res.blend_j); //set 2nd known corner for (x, y + 1) + preProcBuffer[x] = blend_xy1; //store on current buffer position for use on next row + + blend_xy1 = 0; + setTopL(blend_xy1, res.blend_k); + //set 1st known corner for (x + 1, y + 1) and buffer for use on next column + + if (x + 1 < bufferSize) //set 3rd known corner for (x + 1, y) + setBottomL(preProcBuffer[x + 1], res.blend_g); + } + + //fill block of size scale * scale with the given color + fillBlock(out, trgWidth * sizeof(uint32_t), ker4.f, Scaler::scale); + //place *after* preprocessing step, to not overwrite the results while processing the the last pixel! + + //blend four corners of current pixel + if (blendingNeeded(blend_xy)) //good 5% perf-improvement + { + Kernel_3x3 ker3 = {}; //perf: initialization is negligible + + ker3.a = ker4.a; + ker3.b = ker4.b; + ker3.c = ker4.c; + + ker3.d = ker4.e; + ker3.e = ker4.f; + ker3.f = ker4.g; + + ker3.g = ker4.i; + ker3.h = ker4.j; + ker3.i = ker4.k; + + blendPixel(ker3, out, trgWidth, blend_xy, cfg); + blendPixel(ker3, out, trgWidth, blend_xy, cfg); + blendPixel(ker3, out, trgWidth, blend_xy, cfg); + blendPixel(ker3, out, trgWidth, blend_xy, cfg); + } + } + } + } + + //------------------------------------------------------------------------------------ + + template + struct Scaler2x : public ColorGradient + { + static const int scale = 2; + + template //bring template function into scope for GCC + static void alphaGrad(uint32_t& pixBack, uint32_t pixFront) + { + ColorGradient::template alphaGrad(pixBack, pixFront); + } + + + template + static void blendLineShallow(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref(), col); + alphaGrad<3, 4>(out.template ref(), col); + } + + template + static void blendLineSteep(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col); + alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col); + } + + template + static void blendLineSteepAndShallow(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref<1, 0>(), col); + alphaGrad<1, 4>(out.template ref<0, 1>(), col); + alphaGrad<5, 6>(out.template ref<1, 1>(), col); //[!] fixes 7/8 used in xBR + } + + template + static void blendLineDiagonal(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 2>(out.template ref<1, 1>(), col); + } + + template + static void blendCorner(uint32_t col, OutputMatrix& out) + { + //model a round corner + alphaGrad<21, 100>(out.template ref<1, 1>(), col); //exact: 1 - pi/4 = 0.2146018366 + } + }; + + + template + struct Scaler3x : public ColorGradient + { + static const int scale = 3; + + template //bring template function into scope for GCC + static void alphaGrad(uint32_t& pixBack, uint32_t pixFront) + { + ColorGradient::template alphaGrad(pixBack, pixFront); + } + + + template + static void blendLineShallow(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref(), col); + alphaGrad<1, 4>(out.template ref(), col); + + alphaGrad<3, 4>(out.template ref(), col); + out.template ref() = col; + } + + template + static void blendLineSteep(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col); + alphaGrad<1, 4>(out.template ref<2, scale - 2>(), col); + + alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col); + out.template ref<2, scale - 1>() = col; + } + + template + static void blendLineSteepAndShallow(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref<2, 0>(), col); + alphaGrad<1, 4>(out.template ref<0, 2>(), col); + alphaGrad<3, 4>(out.template ref<2, 1>(), col); + alphaGrad<3, 4>(out.template ref<1, 2>(), col); + out.template ref<2, 2>() = col; + } + + template + static void blendLineDiagonal(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 8>(out.template ref<1, 2>(), col); //conflict with other rotations for this odd scale + alphaGrad<1, 8>(out.template ref<2, 1>(), col); + alphaGrad<7, 8>(out.template ref<2, 2>(), col); // + } + + template + static void blendCorner(uint32_t col, OutputMatrix& out) + { + //model a round corner + alphaGrad<45, 100>(out.template ref<2, 2>(), col); //exact: 0.4545939598 + //alphaGrad<7, 256>(out.template ref<2, 1>(), col); //0.02826017254 -> negligible + avoid conflicts with other rotations for this odd scale + //alphaGrad<7, 256>(out.template ref<1, 2>(), col); //0.02826017254 + } + }; + + + template + struct Scaler4x : public ColorGradient + { + static const int scale = 4; + + template //bring template function into scope for GCC + static void alphaGrad(uint32_t& pixBack, uint32_t pixFront) + { + ColorGradient::template alphaGrad(pixBack, pixFront); + } + + + template + static void blendLineShallow(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref(), col); + alphaGrad<1, 4>(out.template ref(), col); + + alphaGrad<3, 4>(out.template ref(), col); + alphaGrad<3, 4>(out.template ref(), col); + + out.template ref() = col; + out.template ref() = col; + } + + template + static void blendLineSteep(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col); + alphaGrad<1, 4>(out.template ref<2, scale - 2>(), col); + + alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col); + alphaGrad<3, 4>(out.template ref<3, scale - 2>(), col); + + out.template ref<2, scale - 1>() = col; + out.template ref<3, scale - 1>() = col; + } + + template + static void blendLineSteepAndShallow(uint32_t col, OutputMatrix& out) + { + alphaGrad<3, 4>(out.template ref<3, 1>(), col); + alphaGrad<3, 4>(out.template ref<1, 3>(), col); + alphaGrad<1, 4>(out.template ref<3, 0>(), col); + alphaGrad<1, 4>(out.template ref<0, 3>(), col); + + alphaGrad<1, 3>(out.template ref<2, 2>(), col); //[!] fixes 1/4 used in xBR + + out.template ref<3, 3>() = col; + out.template ref<3, 2>() = col; + out.template ref<2, 3>() = col; + } + + template + static void blendLineDiagonal(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 2>(out.template ref(), col); + alphaGrad<1, 2>(out.template ref(), col); + out.template ref() = col; + } + + template + static void blendCorner(uint32_t col, OutputMatrix& out) + { + //model a round corner + alphaGrad<68, 100>(out.template ref<3, 3>(), col); //exact: 0.6848532563 + alphaGrad<9, 100>(out.template ref<3, 2>(), col); //0.08677704501 + alphaGrad<9, 100>(out.template ref<2, 3>(), col); //0.08677704501 + } + }; + + + template + struct Scaler5x : public ColorGradient + { + static const int scale = 5; + + template //bring template function into scope for GCC + static void alphaGrad(uint32_t& pixBack, uint32_t pixFront) + { + ColorGradient::template alphaGrad(pixBack, pixFront); + } + + + template + static void blendLineShallow(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref(), col); + alphaGrad<1, 4>(out.template ref(), col); + alphaGrad<1, 4>(out.template ref(), col); + + alphaGrad<3, 4>(out.template ref(), col); + alphaGrad<3, 4>(out.template ref(), col); + + out.template ref() = col; + out.template ref() = col; + out.template ref() = col; + out.template ref() = col; + } + + template + static void blendLineSteep(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col); + alphaGrad<1, 4>(out.template ref<2, scale - 2>(), col); + alphaGrad<1, 4>(out.template ref<4, scale - 3>(), col); + + alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col); + alphaGrad<3, 4>(out.template ref<3, scale - 2>(), col); + + out.template ref<2, scale - 1>() = col; + out.template ref<3, scale - 1>() = col; + out.template ref<4, scale - 1>() = col; + out.template ref<4, scale - 2>() = col; + } + + template + static void blendLineSteepAndShallow(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col); + alphaGrad<1, 4>(out.template ref<2, scale - 2>(), col); + alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col); + + alphaGrad<1, 4>(out.template ref(), col); + alphaGrad<1, 4>(out.template ref(), col); + alphaGrad<3, 4>(out.template ref(), col); + + alphaGrad<2, 3>(out.template ref<3, 3>(), col); + + out.template ref<2, scale - 1>() = col; + out.template ref<3, scale - 1>() = col; + out.template ref<4, scale - 1>() = col; + + out.template ref() = col; + out.template ref() = col; + } + + template + static void blendLineDiagonal(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 8>(out.template ref(), col); + //conflict with other rotations for this odd scale + alphaGrad<1, 8>(out.template ref(), col); + alphaGrad<1, 8>(out.template ref(), col); // + + alphaGrad<7, 8>(out.template ref<4, 3>(), col); + alphaGrad<7, 8>(out.template ref<3, 4>(), col); + + out.template ref<4, 4>() = col; + } + + template + static void blendCorner(uint32_t col, OutputMatrix& out) + { + //model a round corner + alphaGrad<86, 100>(out.template ref<4, 4>(), col); //exact: 0.8631434088 + alphaGrad<23, 100>(out.template ref<4, 3>(), col); //0.2306749731 + alphaGrad<23, 100>(out.template ref<3, 4>(), col); //0.2306749731 + //alphaGrad<1, 64>(out.template ref<4, 2>(), col); //0.01676812367 -> negligible + avoid conflicts with other rotations for this odd scale + //alphaGrad<1, 64>(out.template ref<2, 4>(), col); //0.01676812367 + } + }; + + + template + struct Scaler6x : public ColorGradient + { + static const int scale = 6; + + template //bring template function into scope for GCC + static void alphaGrad(uint32_t& pixBack, uint32_t pixFront) + { + ColorGradient::template alphaGrad(pixBack, pixFront); + } + + + template + static void blendLineShallow(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref(), col); + alphaGrad<1, 4>(out.template ref(), col); + alphaGrad<1, 4>(out.template ref(), col); + + alphaGrad<3, 4>(out.template ref(), col); + alphaGrad<3, 4>(out.template ref(), col); + alphaGrad<3, 4>(out.template ref(), col); + + out.template ref() = col; + out.template ref() = col; + out.template ref() = col; + out.template ref() = col; + + out.template ref() = col; + out.template ref() = col; + } + + template + static void blendLineSteep(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col); + alphaGrad<1, 4>(out.template ref<2, scale - 2>(), col); + alphaGrad<1, 4>(out.template ref<4, scale - 3>(), col); + + alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col); + alphaGrad<3, 4>(out.template ref<3, scale - 2>(), col); + alphaGrad<3, 4>(out.template ref<5, scale - 3>(), col); + + out.template ref<2, scale - 1>() = col; + out.template ref<3, scale - 1>() = col; + out.template ref<4, scale - 1>() = col; + out.template ref<5, scale - 1>() = col; + + out.template ref<4, scale - 2>() = col; + out.template ref<5, scale - 2>() = col; + } + + template + static void blendLineSteepAndShallow(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col); + alphaGrad<1, 4>(out.template ref<2, scale - 2>(), col); + alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col); + alphaGrad<3, 4>(out.template ref<3, scale - 2>(), col); + + alphaGrad<1, 4>(out.template ref(), col); + alphaGrad<1, 4>(out.template ref(), col); + alphaGrad<3, 4>(out.template ref(), col); + alphaGrad<3, 4>(out.template ref(), col); + + out.template ref<2, scale - 1>() = col; + out.template ref<3, scale - 1>() = col; + out.template ref<4, scale - 1>() = col; + out.template ref<5, scale - 1>() = col; + + out.template ref<4, scale - 2>() = col; + out.template ref<5, scale - 2>() = col; + + out.template ref() = col; + out.template ref() = col; + } + + template + static void blendLineDiagonal(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 2>(out.template ref(), col); + alphaGrad<1, 2>(out.template ref(), col); + alphaGrad<1, 2>(out.template ref(), col); + + out.template ref() = col; + out.template ref() = col; + out.template ref() = col; + } + + template + static void blendCorner(uint32_t col, OutputMatrix& out) + { + //model a round corner + alphaGrad<97, 100>(out.template ref<5, 5>(), col); //exact: 0.9711013910 + alphaGrad<42, 100>(out.template ref<4, 5>(), col); //0.4236372243 + alphaGrad<42, 100>(out.template ref<5, 4>(), col); //0.4236372243 + alphaGrad<6, 100>(out.template ref<5, 3>(), col); //0.05652034508 + alphaGrad<6, 100>(out.template ref<3, 5>(), col); //0.05652034508 + } + }; + + //------------------------------------------------------------------------------------ + + struct ColorDistanceRGB + { + static double dist(uint32_t pix1, uint32_t pix2, double luminanceWeight) + { + return DistYCbCrBuffer::dist(pix1, pix2); + + //if (pix1 == pix2) //about 4% perf boost + // return 0; + //return distYCbCr(pix1, pix2, luminanceWeight); + } + }; + + struct ColorDistanceARGB + { + static double dist(uint32_t pix1, uint32_t pix2, double luminanceWeight) + { + const double a1 = getAlpha(pix1) / 255.0; + const double a2 = getAlpha(pix2) / 255.0; + /* + Requirements for a color distance handling alpha channel: with a1, a2 in [0, 1] + + 1. if a1 = a2, distance should be: a1 * distYCbCr() + 2. if a1 = 0, distance should be: a2 * distYCbCr(black, white) = a2 * 255 + 3. if a1 = 1, ??? maybe: 255 * (1 - a2) + a2 * distYCbCr() + */ + + //return std::min(a1, a2) * DistYCbCrBuffer::dist(pix1, pix2) + 255 * abs(a1 - a2); + //=> following code is 15% faster: + const double d = DistYCbCrBuffer::dist(pix1, pix2); + if (a1 < a2) + return a1 * d + 255 * (a2 - a1); + else + return a2 * d + 255 * (a1 - a2); + + //alternative? return std::sqrt(a1 * a2 * square(DistYCbCrBuffer::dist(pix1, pix2)) + square(255 * (a1 - a2))); + } + }; + + + struct ColorGradientRGB + { + template + static void alphaGrad(uint32_t& pixBack, uint32_t pixFront) + { + pixBack = gradientRGB(pixFront, pixBack); + } + }; + + struct ColorGradientARGB + { + template + static void alphaGrad(uint32_t& pixBack, uint32_t pixFront) + { + pixBack = gradientARGB(pixFront, pixBack); + } + }; } -template //scaler policy: see "Scaler2x" reference implementation -void scaleImage(const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight, const xbrz::ScalerCfg& cfg, int yFirst, int yLast) +void xbrz::scale(size_t factor, const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight, ColorFormat colFmt, + const xbrz::ScalerCfg& cfg, int yFirst, int yLast) { - yFirst = std::max(yFirst, 0); - yLast = std::min(yLast, srcHeight); - if (yFirst >= yLast || srcWidth <= 0) - return; - - const int trgWidth = srcWidth * Scaler::scale; - - //"use" space at the end of the image as temporary buffer for "on the fly preprocessing": we even could use larger area of - //"sizeof(uint32_t) * srcWidth * (yLast - yFirst)" bytes without risk of accidental overwriting before accessing - const int bufferSize = srcWidth; - unsigned char* preProcBuffer = reinterpret_cast(trg + yLast * Scaler::scale * trgWidth) - bufferSize; - std::fill(preProcBuffer, preProcBuffer + bufferSize, 0); - static_assert(BLEND_NONE == 0, ""); - - //initialize preprocessing buffer for first row of current stripe: detect upper left and right corner blending - //this cannot be optimized for adjacent processing stripes; we must not allow for a memory race condition! - if (yFirst > 0) - { - const int y = yFirst - 1; - - const uint32_t* s_m1 = src + srcWidth * std::max(y - 1, 0); - const uint32_t* s_0 = src + srcWidth * y; //center line - const uint32_t* s_p1 = src + srcWidth * std::min(y + 1, srcHeight - 1); - const uint32_t* s_p2 = src + srcWidth * std::min(y + 2, srcHeight - 1); - - for (int x = 0; x < srcWidth; ++x) - { - const int x_m1 = std::max(x - 1, 0); - const int x_p1 = std::min(x + 1, srcWidth - 1); - const int x_p2 = std::min(x + 2, srcWidth - 1); - - Kernel_4x4 ker = {}; //perf: initialization is negligible - ker.a = s_m1[x_m1]; //read sequentially from memory as far as possible - ker.b = s_m1[x]; - ker.c = s_m1[x_p1]; - ker.d = s_m1[x_p2]; - - ker.e = s_0[x_m1]; - ker.f = s_0[x]; - ker.g = s_0[x_p1]; - ker.h = s_0[x_p2]; - - ker.i = s_p1[x_m1]; - ker.j = s_p1[x]; - ker.k = s_p1[x_p1]; - ker.l = s_p1[x_p2]; - - ker.m = s_p2[x_m1]; - ker.n = s_p2[x]; - ker.o = s_p2[x_p1]; - ker.p = s_p2[x_p2]; - - const BlendResult res = preProcessCorners(ker, cfg); - /* - preprocessing blend result: - --------- - | F | G | //evalute corner between F, G, J, K - ----|---| //input pixel is at position F - | J | K | - --------- - */ - setTopR(preProcBuffer[x], res.blend_j); - - if (x + 1 < bufferSize) - setTopL(preProcBuffer[x + 1], res.blend_k); - } - } - //------------------------------------------------------------------------------------ - - for (int y = yFirst; y < yLast; ++y) - { - uint32_t* out = trg + Scaler::scale * y * trgWidth; //consider MT "striped" access - - const uint32_t* s_m1 = src + srcWidth * std::max(y - 1, 0); - const uint32_t* s_0 = src + srcWidth * y; //center line - const uint32_t* s_p1 = src + srcWidth * std::min(y + 1, srcHeight - 1); - const uint32_t* s_p2 = src + srcWidth * std::min(y + 2, srcHeight - 1); - - unsigned char blend_xy1 = 0; //corner blending for current (x, y + 1) position - - for (int x = 0; x < srcWidth; ++x, out += Scaler::scale) - { - //all those bounds checks have only insignificant impact on performance! - const int x_m1 = std::max(x - 1, 0); //perf: prefer array indexing to additional pointers! - const int x_p1 = std::min(x + 1, srcWidth - 1); - const int x_p2 = std::min(x + 2, srcWidth - 1); - - Kernel_4x4 ker4 = {}; //perf: initialization is negligible - - ker4.a = s_m1[x_m1]; //read sequentially from memory as far as possible - ker4.b = s_m1[x]; - ker4.c = s_m1[x_p1]; - ker4.d = s_m1[x_p2]; - - ker4.e = s_0[x_m1]; - ker4.f = s_0[x]; - ker4.g = s_0[x_p1]; - ker4.h = s_0[x_p2]; - - ker4.i = s_p1[x_m1]; - ker4.j = s_p1[x]; - ker4.k = s_p1[x_p1]; - ker4.l = s_p1[x_p2]; - - ker4.m = s_p2[x_m1]; - ker4.n = s_p2[x]; - ker4.o = s_p2[x_p1]; - ker4.p = s_p2[x_p2]; - - //evaluate the four corners on bottom-right of current pixel - unsigned char blend_xy = 0; //for current (x, y) position - { - const BlendResult res = preProcessCorners(ker4, cfg); - /* - preprocessing blend result: - --------- - | F | G | //evalute corner between F, G, J, K - ----|---| //current input pixel is at position F - | J | K | - --------- - */ - blend_xy = preProcBuffer[x]; - setBottomR(blend_xy, res.blend_f); //all four corners of (x, y) have been determined at this point due to processing sequence! - - setTopR(blend_xy1, res.blend_j); //set 2nd known corner for (x, y + 1) - preProcBuffer[x] = blend_xy1; //store on current buffer position for use on next row - - blend_xy1 = 0; - setTopL(blend_xy1, res.blend_k); //set 1st known corner for (x + 1, y + 1) and buffer for use on next column - - if (x + 1 < bufferSize) //set 3rd known corner for (x + 1, y) - setBottomL(preProcBuffer[x + 1], res.blend_g); - } - - //fill block of size scale * scale with the given color - fillBlock(out, trgWidth * sizeof(uint32_t), ker4.f, Scaler::scale); //place *after* preprocessing step, to not overwrite the results while processing the the last pixel! - - //blend four corners of current pixel - if (blendingNeeded(blend_xy)) //good 5% perf-improvement - { - Kernel_3x3 ker3 = {}; //perf: initialization is negligible - - ker3.a = ker4.a; - ker3.b = ker4.b; - ker3.c = ker4.c; - - ker3.d = ker4.e; - ker3.e = ker4.f; - ker3.f = ker4.g; - - ker3.g = ker4.i; - ker3.h = ker4.j; - ker3.i = ker4.k; - - blendPixel(ker3, out, trgWidth, blend_xy, cfg); - blendPixel(ker3, out, trgWidth, blend_xy, cfg); - blendPixel(ker3, out, trgWidth, blend_xy, cfg); - blendPixel(ker3, out, trgWidth, blend_xy, cfg); - } - } - } -} - -//------------------------------------------------------------------------------------ - -template -struct Scaler2x : public ColorGradient -{ - static const int scale = 2; - - template //bring template function into scope for GCC - static void alphaGrad(uint32_t& pixBack, uint32_t pixFront) { ColorGradient::template alphaGrad(pixBack, pixFront); } - - - template - static void blendLineShallow(uint32_t col, OutputMatrix& out) - { - alphaGrad<1, 4>(out.template ref(), col); - alphaGrad<3, 4>(out.template ref(), col); - } - - template - static void blendLineSteep(uint32_t col, OutputMatrix& out) - { - alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col); - alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col); - } - - template - static void blendLineSteepAndShallow(uint32_t col, OutputMatrix& out) - { - alphaGrad<1, 4>(out.template ref<1, 0>(), col); - alphaGrad<1, 4>(out.template ref<0, 1>(), col); - alphaGrad<5, 6>(out.template ref<1, 1>(), col); //[!] fixes 7/8 used in xBR - } - - template - static void blendLineDiagonal(uint32_t col, OutputMatrix& out) - { - alphaGrad<1, 2>(out.template ref<1, 1>(), col); - } - - template - static void blendCorner(uint32_t col, OutputMatrix& out) - { - //model a round corner - alphaGrad<21, 100>(out.template ref<1, 1>(), col); //exact: 1 - pi/4 = 0.2146018366 - } -}; - - -template -struct Scaler3x : public ColorGradient -{ - static const int scale = 3; - - template //bring template function into scope for GCC - static void alphaGrad(uint32_t& pixBack, uint32_t pixFront) { ColorGradient::template alphaGrad(pixBack, pixFront); } - - - template - static void blendLineShallow(uint32_t col, OutputMatrix& out) - { - alphaGrad<1, 4>(out.template ref(), col); - alphaGrad<1, 4>(out.template ref(), col); - - alphaGrad<3, 4>(out.template ref(), col); - out.template ref() = col; - } - - template - static void blendLineSteep(uint32_t col, OutputMatrix& out) - { - alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col); - alphaGrad<1, 4>(out.template ref<2, scale - 2>(), col); - - alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col); - out.template ref<2, scale - 1>() = col; - } - - template - static void blendLineSteepAndShallow(uint32_t col, OutputMatrix& out) - { - alphaGrad<1, 4>(out.template ref<2, 0>(), col); - alphaGrad<1, 4>(out.template ref<0, 2>(), col); - alphaGrad<3, 4>(out.template ref<2, 1>(), col); - alphaGrad<3, 4>(out.template ref<1, 2>(), col); - out.template ref<2, 2>() = col; - } - - template - static void blendLineDiagonal(uint32_t col, OutputMatrix& out) - { - alphaGrad<1, 8>(out.template ref<1, 2>(), col); //conflict with other rotations for this odd scale - alphaGrad<1, 8>(out.template ref<2, 1>(), col); - alphaGrad<7, 8>(out.template ref<2, 2>(), col); // - } - - template - static void blendCorner(uint32_t col, OutputMatrix& out) - { - //model a round corner - alphaGrad<45, 100>(out.template ref<2, 2>(), col); //exact: 0.4545939598 - //alphaGrad<7, 256>(out.template ref<2, 1>(), col); //0.02826017254 -> negligible + avoid conflicts with other rotations for this odd scale - //alphaGrad<7, 256>(out.template ref<1, 2>(), col); //0.02826017254 - } -}; - - -template -struct Scaler4x : public ColorGradient -{ - static const int scale = 4; - - template //bring template function into scope for GCC - static void alphaGrad(uint32_t& pixBack, uint32_t pixFront) { ColorGradient::template alphaGrad(pixBack, pixFront); } - - - template - static void blendLineShallow(uint32_t col, OutputMatrix& out) - { - alphaGrad<1, 4>(out.template ref(), col); - alphaGrad<1, 4>(out.template ref(), col); - - alphaGrad<3, 4>(out.template ref(), col); - alphaGrad<3, 4>(out.template ref(), col); - - out.template ref() = col; - out.template ref() = col; - } - - template - static void blendLineSteep(uint32_t col, OutputMatrix& out) - { - alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col); - alphaGrad<1, 4>(out.template ref<2, scale - 2>(), col); - - alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col); - alphaGrad<3, 4>(out.template ref<3, scale - 2>(), col); - - out.template ref<2, scale - 1>() = col; - out.template ref<3, scale - 1>() = col; - } - - template - static void blendLineSteepAndShallow(uint32_t col, OutputMatrix& out) - { - alphaGrad<3, 4>(out.template ref<3, 1>(), col); - alphaGrad<3, 4>(out.template ref<1, 3>(), col); - alphaGrad<1, 4>(out.template ref<3, 0>(), col); - alphaGrad<1, 4>(out.template ref<0, 3>(), col); - - alphaGrad<1, 3>(out.template ref<2, 2>(), col); //[!] fixes 1/4 used in xBR - - out.template ref<3, 3>() = col; - out.template ref<3, 2>() = col; - out.template ref<2, 3>() = col; - } - - template - static void blendLineDiagonal(uint32_t col, OutputMatrix& out) - { - alphaGrad<1, 2>(out.template ref(), col); - alphaGrad<1, 2>(out.template ref(), col); - out.template ref() = col; - } - - template - static void blendCorner(uint32_t col, OutputMatrix& out) - { - //model a round corner - alphaGrad<68, 100>(out.template ref<3, 3>(), col); //exact: 0.6848532563 - alphaGrad< 9, 100>(out.template ref<3, 2>(), col); //0.08677704501 - alphaGrad< 9, 100>(out.template ref<2, 3>(), col); //0.08677704501 - } -}; - - -template -struct Scaler5x : public ColorGradient -{ - static const int scale = 5; - - template //bring template function into scope for GCC - static void alphaGrad(uint32_t& pixBack, uint32_t pixFront) { ColorGradient::template alphaGrad(pixBack, pixFront); } - - - template - static void blendLineShallow(uint32_t col, OutputMatrix& out) - { - alphaGrad<1, 4>(out.template ref(), col); - alphaGrad<1, 4>(out.template ref(), col); - alphaGrad<1, 4>(out.template ref(), col); - - alphaGrad<3, 4>(out.template ref(), col); - alphaGrad<3, 4>(out.template ref(), col); - - out.template ref() = col; - out.template ref() = col; - out.template ref() = col; - out.template ref() = col; - } - - template - static void blendLineSteep(uint32_t col, OutputMatrix& out) - { - alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col); - alphaGrad<1, 4>(out.template ref<2, scale - 2>(), col); - alphaGrad<1, 4>(out.template ref<4, scale - 3>(), col); - - alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col); - alphaGrad<3, 4>(out.template ref<3, scale - 2>(), col); - - out.template ref<2, scale - 1>() = col; - out.template ref<3, scale - 1>() = col; - out.template ref<4, scale - 1>() = col; - out.template ref<4, scale - 2>() = col; - } - - template - static void blendLineSteepAndShallow(uint32_t col, OutputMatrix& out) - { - alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col); - alphaGrad<1, 4>(out.template ref<2, scale - 2>(), col); - alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col); - - alphaGrad<1, 4>(out.template ref(), col); - alphaGrad<1, 4>(out.template ref(), col); - alphaGrad<3, 4>(out.template ref(), col); - - alphaGrad<2, 3>(out.template ref<3, 3>(), col); - - out.template ref<2, scale - 1>() = col; - out.template ref<3, scale - 1>() = col; - out.template ref<4, scale - 1>() = col; - - out.template ref() = col; - out.template ref() = col; - } - - template - static void blendLineDiagonal(uint32_t col, OutputMatrix& out) - { - alphaGrad<1, 8>(out.template ref(), col); //conflict with other rotations for this odd scale - alphaGrad<1, 8>(out.template ref(), col); - alphaGrad<1, 8>(out.template ref(), col); // - - alphaGrad<7, 8>(out.template ref<4, 3>(), col); - alphaGrad<7, 8>(out.template ref<3, 4>(), col); - - out.template ref<4, 4>() = col; - } - - template - static void blendCorner(uint32_t col, OutputMatrix& out) - { - //model a round corner - alphaGrad<86, 100>(out.template ref<4, 4>(), col); //exact: 0.8631434088 - alphaGrad<23, 100>(out.template ref<4, 3>(), col); //0.2306749731 - alphaGrad<23, 100>(out.template ref<3, 4>(), col); //0.2306749731 - //alphaGrad<1, 64>(out.template ref<4, 2>(), col); //0.01676812367 -> negligible + avoid conflicts with other rotations for this odd scale - //alphaGrad<1, 64>(out.template ref<2, 4>(), col); //0.01676812367 - } -}; - - -template -struct Scaler6x : public ColorGradient -{ - static const int scale = 6; - - template //bring template function into scope for GCC - static void alphaGrad(uint32_t& pixBack, uint32_t pixFront) { ColorGradient::template alphaGrad(pixBack, pixFront); } - - - template - static void blendLineShallow(uint32_t col, OutputMatrix& out) - { - alphaGrad<1, 4>(out.template ref(), col); - alphaGrad<1, 4>(out.template ref(), col); - alphaGrad<1, 4>(out.template ref(), col); - - alphaGrad<3, 4>(out.template ref(), col); - alphaGrad<3, 4>(out.template ref(), col); - alphaGrad<3, 4>(out.template ref(), col); - - out.template ref() = col; - out.template ref() = col; - out.template ref() = col; - out.template ref() = col; - - out.template ref() = col; - out.template ref() = col; - } - - template - static void blendLineSteep(uint32_t col, OutputMatrix& out) - { - alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col); - alphaGrad<1, 4>(out.template ref<2, scale - 2>(), col); - alphaGrad<1, 4>(out.template ref<4, scale - 3>(), col); - - alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col); - alphaGrad<3, 4>(out.template ref<3, scale - 2>(), col); - alphaGrad<3, 4>(out.template ref<5, scale - 3>(), col); - - out.template ref<2, scale - 1>() = col; - out.template ref<3, scale - 1>() = col; - out.template ref<4, scale - 1>() = col; - out.template ref<5, scale - 1>() = col; - - out.template ref<4, scale - 2>() = col; - out.template ref<5, scale - 2>() = col; - } - - template - static void blendLineSteepAndShallow(uint32_t col, OutputMatrix& out) - { - alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col); - alphaGrad<1, 4>(out.template ref<2, scale - 2>(), col); - alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col); - alphaGrad<3, 4>(out.template ref<3, scale - 2>(), col); - - alphaGrad<1, 4>(out.template ref(), col); - alphaGrad<1, 4>(out.template ref(), col); - alphaGrad<3, 4>(out.template ref(), col); - alphaGrad<3, 4>(out.template ref(), col); - - out.template ref<2, scale - 1>() = col; - out.template ref<3, scale - 1>() = col; - out.template ref<4, scale - 1>() = col; - out.template ref<5, scale - 1>() = col; - - out.template ref<4, scale - 2>() = col; - out.template ref<5, scale - 2>() = col; - - out.template ref() = col; - out.template ref() = col; - } - - template - static void blendLineDiagonal(uint32_t col, OutputMatrix& out) - { - alphaGrad<1, 2>(out.template ref(), col); - alphaGrad<1, 2>(out.template ref(), col); - alphaGrad<1, 2>(out.template ref(), col); - - out.template ref() = col; - out.template ref() = col; - out.template ref() = col; - } - - template - static void blendCorner(uint32_t col, OutputMatrix& out) - { - //model a round corner - alphaGrad<97, 100>(out.template ref<5, 5>(), col); //exact: 0.9711013910 - alphaGrad<42, 100>(out.template ref<4, 5>(), col); //0.4236372243 - alphaGrad<42, 100>(out.template ref<5, 4>(), col); //0.4236372243 - alphaGrad< 6, 100>(out.template ref<5, 3>(), col); //0.05652034508 - alphaGrad< 6, 100>(out.template ref<3, 5>(), col); //0.05652034508 - } -}; - -//------------------------------------------------------------------------------------ - -struct ColorDistanceRGB -{ - static double dist(uint32_t pix1, uint32_t pix2, double luminanceWeight) - { - return DistYCbCrBuffer::dist(pix1, pix2); - - //if (pix1 == pix2) //about 4% perf boost - // return 0; - //return distYCbCr(pix1, pix2, luminanceWeight); - } -}; - -struct ColorDistanceARGB -{ - static double dist(uint32_t pix1, uint32_t pix2, double luminanceWeight) - { - const double a1 = getAlpha(pix1) / 255.0 ; - const double a2 = getAlpha(pix2) / 255.0 ; - /* - Requirements for a color distance handling alpha channel: with a1, a2 in [0, 1] - - 1. if a1 = a2, distance should be: a1 * distYCbCr() - 2. if a1 = 0, distance should be: a2 * distYCbCr(black, white) = a2 * 255 - 3. if a1 = 1, ??? maybe: 255 * (1 - a2) + a2 * distYCbCr() - */ - - //return std::min(a1, a2) * DistYCbCrBuffer::dist(pix1, pix2) + 255 * abs(a1 - a2); - //=> following code is 15% faster: - const double d = DistYCbCrBuffer::dist(pix1, pix2); - if (a1 < a2) - return a1 * d + 255 * (a2 - a1); - else - return a2 * d + 255 * (a1 - a2); - - //alternative? return std::sqrt(a1 * a2 * square(DistYCbCrBuffer::dist(pix1, pix2)) + square(255 * (a1 - a2))); - } -}; - - -struct ColorGradientRGB -{ - template - static void alphaGrad(uint32_t& pixBack, uint32_t pixFront) - { - pixBack = gradientRGB(pixFront, pixBack); - } -}; - -struct ColorGradientARGB -{ - template - static void alphaGrad(uint32_t& pixBack, uint32_t pixFront) - { - pixBack = gradientARGB(pixFront, pixBack); - } -}; + switch (colFmt) + { + case ColorFormat::ARGB: + switch (factor) + { + case 2: + return scaleImage, ColorDistanceARGB>( + src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); + case 3: + return scaleImage, ColorDistanceARGB>( + src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); + case 4: + return scaleImage, ColorDistanceARGB>( + src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); + case 5: + return scaleImage, ColorDistanceARGB>( + src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); + case 6: + return scaleImage, ColorDistanceARGB>( + src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); + } + break; + + case ColorFormat::RGB: + switch (factor) + { + case 2: + return scaleImage, ColorDistanceRGB>( + src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); + case 3: + return scaleImage, ColorDistanceRGB>( + src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); + case 4: + return scaleImage, ColorDistanceRGB>( + src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); + case 5: + return scaleImage, ColorDistanceRGB>( + src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); + case 6: + return scaleImage, ColorDistanceRGB>( + src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); + } + break; + } + assert(false); } -void xbrz::scale(size_t factor, const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight, ColorFormat colFmt, const xbrz::ScalerCfg& cfg, int yFirst, int yLast) +bool xbrz::equalColorTest(uint32_t col1, uint32_t col2, ColorFormat colFmt, double luminanceWeight, + double equalColorTolerance) { - switch (colFmt) - { - case ColorFormat::ARGB: - switch (factor) - { - case 2: - return scaleImage, ColorDistanceARGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); - case 3: - return scaleImage, ColorDistanceARGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); - case 4: - return scaleImage, ColorDistanceARGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); - case 5: - return scaleImage, ColorDistanceARGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); - case 6: - return scaleImage, ColorDistanceARGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); - } - break; + switch (colFmt) + { + case ColorFormat::ARGB: + return ColorDistanceARGB::dist(col1, col2, luminanceWeight) < equalColorTolerance; - case ColorFormat::RGB: - switch (factor) - { - case 2: - return scaleImage, ColorDistanceRGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); - case 3: - return scaleImage, ColorDistanceRGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); - case 4: - return scaleImage, ColorDistanceRGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); - case 5: - return scaleImage, ColorDistanceRGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); - case 6: - return scaleImage, ColorDistanceRGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); - } - break; - } - assert(false); -} - - -bool xbrz::equalColorTest(uint32_t col1, uint32_t col2, ColorFormat colFmt, double luminanceWeight, double equalColorTolerance) -{ - switch (colFmt) - { - case ColorFormat::ARGB: - return ColorDistanceARGB::dist(col1, col2, luminanceWeight) < equalColorTolerance; - - case ColorFormat::RGB: - return ColorDistanceRGB::dist(col1, col2, luminanceWeight) < equalColorTolerance; - } - assert(false); - return false; + case ColorFormat::RGB: + return ColorDistanceRGB::dist(col1, col2, luminanceWeight) < equalColorTolerance; + } + assert(false); + return false; } @@ -1091,69 +1188,70 @@ void xbrz::nearestNeighborScale(const uint32_t* src, int srcWidth, int srcHeight uint32_t* trg, int trgWidth, int trgHeight, int trgPitch, SliceType st, int yFirst, int yLast) { - if (srcPitch < srcWidth * static_cast(sizeof(uint32_t)) || - trgPitch < trgWidth * static_cast(sizeof(uint32_t))) - { - assert(false); - return; - } + if (srcPitch < srcWidth * static_cast(sizeof(uint32_t)) || + trgPitch < trgWidth * static_cast(sizeof(uint32_t))) + { + assert(false); + return; + } - switch (st) - { - case NN_SCALE_SLICE_SOURCE: - //nearest-neighbor (going over source image - fast for upscaling, since source is read only once - yFirst = std::max(yFirst, 0); - yLast = std::min(yLast, srcHeight); - if (yFirst >= yLast || trgWidth <= 0 || trgHeight <= 0) return; + switch (st) + { + case NN_SCALE_SLICE_SOURCE: + //nearest-neighbor (going over source image - fast for upscaling, since source is read only once + yFirst = std::max(yFirst, 0); + yLast = std::min(yLast, srcHeight); + if (yFirst >= yLast || trgWidth <= 0 || trgHeight <= 0) return; - for (int y = yFirst; y < yLast; ++y) - { - //mathematically: ySrc = floor(srcHeight * yTrg / trgHeight) - // => search for integers in: [ySrc, ySrc + 1) * trgHeight / srcHeight + for (int y = yFirst; y < yLast; ++y) + { + //mathematically: ySrc = floor(srcHeight * yTrg / trgHeight) + // => search for integers in: [ySrc, ySrc + 1) * trgHeight / srcHeight - //keep within for loop to support MT input slices! - const int yTrg_first = ( y * trgHeight + srcHeight - 1) / srcHeight; //=ceil(y * trgHeight / srcHeight) - const int yTrg_last = ((y + 1) * trgHeight + srcHeight - 1) / srcHeight; //=ceil(((y + 1) * trgHeight) / srcHeight) - const int blockHeight = yTrg_last - yTrg_first; + //keep within for loop to support MT input slices! + const int yTrg_first = (y * trgHeight + srcHeight - 1) / srcHeight; //=ceil(y * trgHeight / srcHeight) + const int yTrg_last = ((y + 1) * trgHeight + srcHeight - 1) / srcHeight; + //=ceil(((y + 1) * trgHeight) / srcHeight) + const int blockHeight = yTrg_last - yTrg_first; - if (blockHeight > 0) - { - const uint32_t* srcLine = byteAdvance(src, y * srcPitch); - uint32_t* trgLine = byteAdvance(trg, yTrg_first * trgPitch); - int xTrg_first = 0; + if (blockHeight > 0) + { + const uint32_t* srcLine = byteAdvance(src, y * srcPitch); + uint32_t* trgLine = byteAdvance(trg, yTrg_first * trgPitch); + int xTrg_first = 0; - for (int x = 0; x < srcWidth; ++x) - { - int xTrg_last = ((x + 1) * trgWidth + srcWidth - 1) / srcWidth; - const int blockWidth = xTrg_last - xTrg_first; - if (blockWidth > 0) - { - xTrg_first = xTrg_last; - fillBlock(trgLine, trgPitch, srcLine[x], blockWidth, blockHeight); - trgLine += blockWidth; - } - } - } - } - break; + for (int x = 0; x < srcWidth; ++x) + { + int xTrg_last = ((x + 1) * trgWidth + srcWidth - 1) / srcWidth; + const int blockWidth = xTrg_last - xTrg_first; + if (blockWidth > 0) + { + xTrg_first = xTrg_last; + fillBlock(trgLine, trgPitch, srcLine[x], blockWidth, blockHeight); + trgLine += blockWidth; + } + } + } + } + break; - case NN_SCALE_SLICE_TARGET: - //nearest-neighbor (going over target image - slow for upscaling, since source is read multiple times missing out on cache! Fast for similar image sizes!) - yFirst = std::max(yFirst, 0); - yLast = std::min(yLast, trgHeight); - if (yFirst >= yLast || srcHeight <= 0 || srcWidth <= 0) return; + case NN_SCALE_SLICE_TARGET: + //nearest-neighbor (going over target image - slow for upscaling, since source is read multiple times missing out on cache! Fast for similar image sizes!) + yFirst = std::max(yFirst, 0); + yLast = std::min(yLast, trgHeight); + if (yFirst >= yLast || srcHeight <= 0 || srcWidth <= 0) return; - for (int y = yFirst; y < yLast; ++y) - { - uint32_t* trgLine = byteAdvance(trg, y * trgPitch); - const int ySrc = srcHeight * y / trgHeight; - const uint32_t* srcLine = byteAdvance(src, ySrc * srcPitch); - for (int x = 0; x < trgWidth; ++x) - { - const int xSrc = srcWidth * x / trgWidth; - trgLine[x] = srcLine[xSrc]; - } - } - break; - } + for (int y = yFirst; y < yLast; ++y) + { + uint32_t* trgLine = byteAdvance(trg, y * trgPitch); + const int ySrc = srcHeight * y / trgHeight; + const uint32_t* srcLine = byteAdvance(src, ySrc * srcPitch); + for (int x = 0; x < trgWidth; ++x) + { + const int xSrc = srcWidth * x / trgWidth; + trgLine[x] = srcLine[xSrc]; + } + } + break; + } } diff --git a/Utilities/xBRZ/xbrz.h b/Utilities/xBRZ/xbrz.h index 40dd410..bb86fe0 100644 --- a/Utilities/xBRZ/xbrz.h +++ b/Utilities/xBRZ/xbrz.h @@ -23,72 +23,73 @@ namespace xbrz { -/* -------------------------------------------------------------------------- -| xBRZ: "Scale by rules" - high quality image upscaling filter by Zenju | -------------------------------------------------------------------------- -using a modified approach of xBR: -http://board.byuu.org/viewtopic.php?f=10&t=2248 -- new rule set preserving small image features -- highly optimized for performance -- support alpha channel -- support multithreading -- support 64-bit architectures -- support processing image slices -- support scaling up to 6xBRZ -*/ + /* + ------------------------------------------------------------------------- + | xBRZ: "Scale by rules" - high quality image upscaling filter by Zenju | + ------------------------------------------------------------------------- + using a modified approach of xBR: + http://board.byuu.org/viewtopic.php?f=10&t=2248 + - new rule set preserving small image features + - highly optimized for performance + - support alpha channel + - support multithreading + - support 64-bit architectures + - support processing image slices + - support scaling up to 6xBRZ + */ -enum class ColorFormat //from high bits -> low bits, 8 bit per channel -{ - RGB, //8 bit for each red, green, blue, upper 8 bits unused - ARGB, //including alpha channel, BGRA byte order on little-endian machines -}; + enum class ColorFormat //from high bits -> low bits, 8 bit per channel + { + RGB, + //8 bit for each red, green, blue, upper 8 bits unused + ARGB, + //including alpha channel, BGRA byte order on little-endian machines + }; -/* --> map source (srcWidth * srcHeight) to target (scale * width x scale * height) image, optionally processing a half-open slice of rows [yFirst, yLast) only --> support for source/target pitch in bytes! --> if your emulator changes only a few image slices during each cycle (e.g. DOSBox) then there's no need to run xBRZ on the complete image: - Just make sure you enlarge the source image slice by 2 rows on top and 2 on bottom (this is the additional range the xBRZ algorithm is using during analysis) - Caveat: If there are multiple changed slices, make sure they do not overlap after adding these additional rows in order to avoid a memory race condition - in the target image data if you are using multiple threads for processing each enlarged slice! + /* + -> map source (srcWidth * srcHeight) to target (scale * width x scale * height) image, optionally processing a half-open slice of rows [yFirst, yLast) only + -> support for source/target pitch in bytes! + -> if your emulator changes only a few image slices during each cycle (e.g. DOSBox) then there's no need to run xBRZ on the complete image: + Just make sure you enlarge the source image slice by 2 rows on top and 2 on bottom (this is the additional range the xBRZ algorithm is using during analysis) + Caveat: If there are multiple changed slices, make sure they do not overlap after adding these additional rows in order to avoid a memory race condition + in the target image data if you are using multiple threads for processing each enlarged slice! + + THREAD-SAFETY: - parts of the same image may be scaled by multiple threads as long as the [yFirst, yLast) ranges do not overlap! + - there is a minor inefficiency for the first row of a slice, so avoid processing single rows only; suggestion: process 8-16 rows at least + */ + void scale(size_t factor, //valid range: 2 - 6 + const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight, + ColorFormat colFmt, + const ScalerCfg& cfg = ScalerCfg(), + int yFirst = 0, int yLast = std::numeric_limits::max()); //slice of source image -THREAD-SAFETY: - parts of the same image may be scaled by multiple threads as long as the [yFirst, yLast) ranges do not overlap! - - there is a minor inefficiency for the first row of a slice, so avoid processing single rows only; suggestion: process 8-16 rows at least -*/ -void scale(size_t factor, //valid range: 2 - 6 - const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight, - ColorFormat colFmt, - const ScalerCfg& cfg = ScalerCfg(), - int yFirst = 0, int yLast = std::numeric_limits::max()); //slice of source image + void nearestNeighborScale(const uint32_t* src, int srcWidth, int srcHeight, + uint32_t* trg, int trgWidth, int trgHeight); -void nearestNeighborScale(const uint32_t* src, int srcWidth, int srcHeight, - uint32_t* trg, int trgWidth, int trgHeight); + enum SliceType + { + NN_SCALE_SLICE_SOURCE, + NN_SCALE_SLICE_TARGET, + }; -enum SliceType -{ - NN_SCALE_SLICE_SOURCE, - NN_SCALE_SLICE_TARGET, -}; -void nearestNeighborScale(const uint32_t* src, int srcWidth, int srcHeight, int srcPitch, //pitch in bytes! - uint32_t* trg, int trgWidth, int trgHeight, int trgPitch, - SliceType st, int yFirst, int yLast); + void nearestNeighborScale(const uint32_t* src, int srcWidth, int srcHeight, int srcPitch, //pitch in bytes! + uint32_t* trg, int trgWidth, int trgHeight, int trgPitch, + SliceType st, int yFirst, int yLast); -//parameter tuning -bool equalColorTest(uint32_t col1, uint32_t col2, ColorFormat colFmt, double luminanceWeight, double equalColorTolerance); + //parameter tuning + bool equalColorTest(uint32_t col1, uint32_t col2, ColorFormat colFmt, double luminanceWeight, + double equalColorTolerance); - - - -//########################### implementation ########################### -inline -void nearestNeighborScale(const uint32_t* src, int srcWidth, int srcHeight, - uint32_t* trg, int trgWidth, int trgHeight) -{ - nearestNeighborScale(src, srcWidth, srcHeight, srcWidth * sizeof(uint32_t), - trg, trgWidth, trgHeight, trgWidth * sizeof(uint32_t), - NN_SCALE_SLICE_TARGET, 0, trgHeight); -} + //########################### implementation ########################### + inline + void nearestNeighborScale(const uint32_t* src, int srcWidth, int srcHeight, + uint32_t* trg, int trgWidth, int trgHeight) + { + nearestNeighborScale(src, srcWidth, srcHeight, srcWidth * sizeof(uint32_t), + trg, trgWidth, trgHeight, trgWidth * sizeof(uint32_t), + NN_SCALE_SLICE_TARGET, 0, trgHeight); + } } #endif