Reformat Utilities (Resharper)

This commit is contained in:
Vladimir Kononovich 2020-12-19 23:32:47 +03:00
parent 68c88a6b7c
commit c0aabf20a1
97 changed files with 25869 additions and 23038 deletions

View file

@ -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<uint8_t> 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<string> ArchiveReader::GetFileList(std::initializer_list<string> extensions)
{
if(extensions.size() == 0) {
if (extensions.size() == 0)
{
return InternalGetFileList();
}
vector<string> 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<uint8_t> &data)
bool ArchiveReader::LoadArchive(vector<uint8_t>& 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> ArchiveReader::GetReader(std::istream &in)
shared_ptr<ArchiveReader> ArchiveReader::GetReader(std::istream& in)
{
uint8_t header[2] = { 0,0 };
uint8_t header[2] = {0, 0};
in.read((char*)header, 2);
shared_ptr<ArchiveReader> 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,7 +124,8 @@ shared_ptr<ArchiveReader> ArchiveReader::GetReader(std::istream &in)
shared_ptr<ArchiveReader> ArchiveReader::GetReader(string filepath)
{
ifstream in(filepath, std::ios::in | std::ios::binary);
if(in) {
if (in)
{
return GetReader(in);
}
return nullptr;

View file

@ -14,15 +14,15 @@ public:
bool LoadArchive(void* buffer, size_t size);
bool LoadArchive(vector<uint8_t>& 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<string> GetFileList(std::initializer_list<string> extensions = {});
bool CheckFile(string filename);
virtual bool ExtractFile(string filename, vector<uint8_t> &output) = 0;
virtual bool ExtractFile(string filename, vector<uint8_t>& output) = 0;
static shared_ptr<ArchiveReader> GetReader(std::istream &in);
static shared_ptr<ArchiveReader> GetReader(std::istream& in);
static shared_ptr<ArchiveReader> GetReader(string filepath);
};

View file

@ -15,10 +15,13 @@ AutoResetEvent::~AutoResetEvent()
void AutoResetEvent::Wait(int timeoutDelay)
{
std::unique_lock<std::mutex> 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<int, std::milli>(timeoutDelay);
_signal.wait_until(lock, timeoutTime, [this] { return _signaled; });

View file

@ -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);
}
}

View file

@ -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;

View file

@ -28,13 +28,13 @@
#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;
@ -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) {
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;
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 (!_codec->SetupCompress(width, height, compressionLevel))
{
return false;
}
_frameBuffer = new uint8_t[width*height*bpp];
_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 */
@ -233,9 +241,10 @@ void AviWriter::EndWrite()
_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;
}

View file

@ -46,12 +46,13 @@ private:
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();
};

View file

@ -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<uint8_t> out;
vector<int> 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;
}

View file

@ -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() { }
virtual ~BaseCodec()
{
}
};

View file

@ -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<uint8_t> &input, vector<uint8_t> &output)
bool BpsPatcher::PatchBuffer(string bpsFilepath, vector<uint8_t>& input, vector<uint8_t>& 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<uint8_t> &input, vector<uint8_t> &output)
bool BpsPatcher::PatchBuffer(std::istream& bpsFile, vector<uint8_t>& input, vector<uint8_t>& 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<uint8_t> &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,49 +68,58 @@ bool BpsPatcher::PatchBuffer(std::istream &bpsFile, vector<uint8_t> &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;
@ -116,12 +131,15 @@ bool BpsPatcher::PatchBuffer(std::istream &bpsFile, vector<uint8_t> &input, vect
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;

View file

@ -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<uint8_t> &input, vector<uint8_t> &output);
static bool PatchBuffer(string bpsFilepath, vector<uint8_t> &input, vector<uint8_t> &output);
static bool PatchBuffer(std::istream& bpsFile, vector<uint8_t>& input, vector<uint8_t>& output);
static bool PatchBuffer(string bpsFilepath, vector<uint8_t>& input, vector<uint8_t>& output);
};

File diff suppressed because it is too large Load diff

View file

@ -19,18 +19,21 @@ 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);
@ -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,21 +69,26 @@ 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);

View file

@ -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;
};

View file

@ -2,10 +2,11 @@
#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];
@ -19,13 +20,18 @@ void Equalizer::ApplyEqualizer(uint32_t sampleCount, int16_t *samples)
void Equalizer::UpdateEqualizers(vector<double> bandGains, uint32_t sampleRate)
{
if(_prevSampleRate != sampleRate || memcmp(bandGains.data(), _prevEqualizerGains.data(), bandGains.size() * sizeof(double)) != 0) {
vector<double> 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<double> 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<double> 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]);
}

View file

@ -13,6 +13,6 @@ private:
vector<double> _prevEqualizerGains;
public:
void ApplyEqualizer(uint32_t sampleCount, int16_t *samples);
void ApplyEqualizer(uint32_t sampleCount, int16_t* samples);
void UpdateEqualizers(vector<double> bandGains, uint32_t sampleRate);
};

View file

@ -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<typename T, typename... Args>
void WriteAll(T first, Args... args)
template <typename T, typename... Args>
void WriteAll(T first, Args ... args)
{
Write(first);
WriteAll(args...);

View file

@ -2,8 +2,8 @@
#ifndef LIBRETRO
#if __has_include(<filesystem>)
#include <filesystem>
namespace fs = std::filesystem;
#include <filesystem>
namespace fs = std::filesystem;
#elif __has_include(<experimental/filesystem>)
#include <experimental/filesystem>
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<string> 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<string> FolderUtilities::GetFolders(string rootFolder)
vector<string> 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<string> FolderUtilities::GetFolders(string rootFolder)
return folders;
}
vector<string> FolderUtilities::GetFilesInFolder(string rootFolder, std::unordered_set<string> extensions, bool recursive)
vector<string> FolderUtilities::GetFilesInFolder(string rootFolder, std::unordered_set<string> extensions,
bool recursive)
{
vector<string> files;
vector<string> folders = { { rootFolder } };
vector<string> 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<string> 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;
}
}

View file

@ -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<string> GetKnownGameFolders();

View file

@ -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());
}
}
@ -31,7 +33,8 @@ void GifRecorder::AddFrame(void* frameBuffer, uint32_t width, uint32_t height, d
{
_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);
}

View file

@ -16,7 +16,8 @@ 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;

View file

@ -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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -24,34 +24,37 @@
#include <stdint.h>
#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

View file

@ -20,29 +20,34 @@
#include <stdint.h>
#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;
}
}
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;
/* 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)
{
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;
}
}

View file

@ -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);

View file

@ -1,26 +1,8 @@
#include "stdafx.h"
#include "HexUtilities.h"
const vector<string> 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<string> 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,22 +91,31 @@ 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<uint8_t> &data)
string HexUtilities::ToHex(vector<uint8_t>& data)
{
string result;
result.reserve(data.size() * 2);
for(uint8_t value : data) {
for (uint8_t value : data)
{
result += HexUtilities::ToHex(value);
}
return result;

View file

@ -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<uint8_t> &data);
static string ToHex(vector<uint8_t>& data);
static int FromHex(string hex);
};

View file

@ -5,6 +5,5 @@ class Serializer;
class ISerializable
{
public:
virtual void Serialize(Serializer &s) = 0;
virtual void Serialize(Serializer& s) = 0;
};

View file

@ -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;

View file

@ -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<uint8_t> &output)
void WriteRecord(vector<uint8_t>& 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<uint8_t> &input, vector<uint8_t> &output)
bool IpsPatcher::PatchBuffer(string ipsFilepath, vector<uint8_t>& input, vector<uint8_t>& 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<uint8_t> &ipsData, vector<uint8_t> &input, vector<uint8_t> &output)
bool IpsPatcher::PatchBuffer(vector<uint8_t>& ipsData, vector<uint8_t>& input, vector<uint8_t>& output)
{
std::stringstream ss;
ss.write((char*)ipsData.data(), ipsData.size());
return PatchBuffer(ss, input, output);
}
bool IpsPatcher::PatchBuffer(std::istream &ipsFile, vector<uint8_t> &input, vector<uint8_t> &output)
bool IpsPatcher::PatchBuffer(std::istream& ipsFile, vector<uint8_t>& input, vector<uint8_t>& 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<uint8_t> &input, vect
vector<IpsRecord> 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<uint8_t> &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<uint8_t> &input, vect
vector<uint8_t> IpsPatcher::CreatePatch(vector<uint8_t> originalData, vector<uint8_t> newData)
{
vector<uint8_t> 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,30 +192,38 @@ vector<uint8_t> IpsPatcher::CreatePatch(vector<uint8_t> originalData, vector<uin
patchRecord.Length++;
i++;
if((patchRecord.Length == rleCount && rleCount > 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<uint8_t>(&newData[patchRecord.Address], &newData[patchRecord.Address + patchRecord.Length]);
}
else
{
patchRecord.Replacement = vector<uint8_t>(&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;

View file

@ -5,8 +5,8 @@
class IpsPatcher
{
public:
static bool PatchBuffer(string ipsFilepath, vector<uint8_t> &input, vector<uint8_t> &output);
static bool PatchBuffer(string ipsFilepath, vector<uint8_t>& input, vector<uint8_t>& output);
static bool PatchBuffer(vector<uint8_t>& ipsData, vector<uint8_t>& input, vector<uint8_t>& output);
static bool PatchBuffer(std::istream &ipsFile, vector<uint8_t> &input, vector<uint8_t> &output);
static bool PatchBuffer(std::istream& ipsFile, vector<uint8_t>& input, vector<uint8_t>& output);
static vector<uint8_t> CreatePatch(vector<uint8_t> originalData, vector<uint8_t> newData);
};

View file

@ -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);

View file

@ -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);

View file

@ -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++;
}

View file

@ -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);

View file

@ -7,29 +7,34 @@ 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;
}
}

File diff suppressed because it is too large Load diff

View file

@ -4,11 +4,13 @@
class PNGHelper
{
private:
static int DecodePNG(vector<unsigned char>& 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<unsigned char>& 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<uint8_t> &pngData, uint32_t &pngWidth, uint32_t &pngHeight);
static bool ReadPNG(vector<uint8_t> input, vector<uint8_t> &output, uint32_t &pngWidth, uint32_t &pngHeight);
static bool ReadPNG(string filename, vector<uint8_t>& pngData, uint32_t& pngWidth, uint32_t& pngHeight);
static bool ReadPNG(vector<uint8_t> input, vector<uint8_t>& output, uint32_t& pngWidth, uint32_t& pngHeight);
};

View file

@ -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
#endif
}

View file

@ -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];

View file

@ -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<uint8_t> &output)
bool SZReader::ExtractFile(string filename, vector<uint8_t>& 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<uint8_t>(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<uint8_t>(outBuffer + offset, outBuffer + offset + outSizeProcessed);
result = true;
}
IAlloc_Free(&_allocImp, outBuffer);
@ -70,12 +77,15 @@ bool SZReader::ExtractFile(string filename, vector<uint8_t> &output)
vector<string> SZReader::InternalGetFileList()
{
vector<string> 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;
}

View file

@ -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<uint8_t> &output);
bool ExtractFile(string filename, vector<uint8_t>& output);
};

View file

@ -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);

View file

@ -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

View file

@ -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
}

View file

@ -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

View file

@ -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;
}
}

View file

@ -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

View file

@ -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<BlockData> block(new BlockData());
block->Position = 0;
if(!_saving) {
VectorInfo<uint8_t> vectorInfo = { &block->Data };
if (!_saving)
{
VectorInfo<uint8_t> vectorInfo = {&block->Data};
InternalStream(vectorInfo);
} else {
}
else
{
block->Data = vector<uint8_t>(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<uint8_t> arrayInfo { block->Data.data(), block->Position };
if (_saving)
{
ArrayInfo<uint8_t> 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<uint8_t> stringData;
stringData.resize(str.size());
memcpy(stringData.data(), str.data(), str.size());
StreamVector(stringData);
} else {
}
else
{
vector<uint8_t> stringData;
StreamVector(stringData);
str = string(stringData.begin(), stringData.end());

View file

@ -5,20 +5,20 @@
class Serializer;
class ISerializable;
template<typename T>
template <typename T>
struct ArrayInfo
{
T* Array;
uint32_t ElementCount;
};
template<typename T>
template <typename T>
struct VectorInfo
{
vector<T>* Vector;
};
template<typename T>
template <typename T>
struct ValueInfo
{
T* Value;
@ -43,69 +43,86 @@ private:
private:
void EnsureCapacity(uint32_t typeSize);
template<typename T> void StreamElement(T &value, T defaultValue = T());
template <typename T>
void StreamElement(T& value, T defaultValue = T());
template<typename T> void InternalStream(ArrayInfo<T> &info);
template<typename T> void InternalStream(VectorInfo<T> &info);
template<typename T> void InternalStream(ValueInfo<T> &info);
template<typename T> void InternalStream(T &value);
void InternalStream(string &str);
template <typename T>
void InternalStream(ArrayInfo<T>& info);
template <typename T>
void InternalStream(VectorInfo<T>& info);
template <typename T>
void InternalStream(ValueInfo<T>& info);
template <typename T>
void InternalStream(T& value);
void InternalStream(string& str);
void RecursiveStream();
template<typename T, typename... T2> void RecursiveStream(T &value, T2&... args);
template <typename T, typename... T2>
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<typename... T> void Stream(T&... args);
template<typename T> void StreamArray(T *array, uint32_t size);
template<typename T> void StreamVector(vector<T> &list);
template <typename... T>
void Stream(T&... args);
template <typename T>
void StreamArray(T* array, uint32_t size);
template <typename T>
void StreamVector(vector<T>& 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<typename T>
void Serializer::StreamElement(T &value, T defaultValue)
template <typename T>
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<typename T>
void Serializer::InternalStream(ArrayInfo<T> &info)
template <typename T>
void Serializer::InternalStream(ArrayInfo<T>& info)
{
uint32_t count = info.ElementCount;
StreamElement<uint32_t>(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<T> &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<typename T>
void Serializer::InternalStream(VectorInfo<T> &info)
template <typename T>
void Serializer::InternalStream(VectorInfo<T>& info)
{
vector<T> *vector = info.Vector;
vector<T>* vector = info.Vector;
uint32_t count = (uint32_t)vector->size();
StreamElement<uint32_t>(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<T>(*pointer);
pointer++;
}
}
template<typename T>
void Serializer::InternalStream(ValueInfo<T> &info)
template <typename T>
void Serializer::InternalStream(ValueInfo<T>& info)
{
StreamElement<T>(*info.Value, info.DefaultValue);
}
template<typename T>
void Serializer::InternalStream(T &value)
template <typename T>
void Serializer::InternalStream(T& value)
{
StreamElement<T>(value);
}
template<typename T, typename... T2>
void Serializer::RecursiveStream(T &value, T2&... args)
template <typename T, typename... T2>
void Serializer::RecursiveStream(T& value, T2&... args)
{
InternalStream(value);
RecursiveStream(args...);
}
template<typename... T>
template <typename... T>
void Serializer::Stream(T&... args)
{
StreamStartBlock();
@ -172,8 +195,8 @@ void Serializer::Stream(T&... args)
StreamEndBlock();
}
template<typename T>
void Serializer::StreamArray(T *array, uint32_t size)
template <typename T>
void Serializer::StreamArray(T* array, uint32_t size)
{
ArrayInfo<T> info;
info.Array = array;
@ -181,8 +204,8 @@ void Serializer::StreamArray(T *array, uint32_t size)
InternalStream(info);
}
template<typename T>
void Serializer::StreamVector(vector<T> &list)
template <typename T>
void Serializer::StreamVector(vector<T>& list)
{
VectorInfo<T> info;
info.Vector = &list;

View file

@ -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();

View file

@ -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();
};

View file

@ -8,11 +8,11 @@
using namespace std;
#ifdef _WIN32
#pragma comment(lib,"ws2_32.lib") //Winsock Library
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <Windows.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <Windows.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
@ -38,21 +38,25 @@ 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();
}
}
@ -61,28 +65,34 @@ 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()
@ -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,12 +188,16 @@ 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;
}
@ -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,27 +230,36 @@ 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();
@ -241,22 +270,28 @@ int Socket::Send(char *buf, int len, int flags)
}
}
}
} 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();

View file

@ -6,9 +6,9 @@ class Socket
{
private:
#ifndef LIBRETRO
#ifdef _WIN32
#ifdef _WIN32
bool _cleanupWSA = false;
#endif
#endif
uintptr_t _socket = ~0;
bool _connectionError = false;
@ -31,8 +31,8 @@ public:
void Listen(int backlog);
shared_ptr<Socket> 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);
};

View file

@ -9,7 +9,8 @@ public:
vector<string> 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;

View file

@ -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, std::milli>((int)(targetMillisecond - elapsedTime)));
}
}

View file

@ -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);
Timer();
void Reset();
double GetElapsedMS();
void WaitUntil(double targetMillisecond);
};

View file

@ -12,52 +12,66 @@ bool UPnPPortMapper::AddNATPortMapping(uint16_t internalPort, uint16_t externalP
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<wstring> 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();
@ -74,8 +88,8 @@ bool UPnPPortMapper::AddNATPortMapping(uint16_t internalPort, uint16_t externalP
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<wstring> UPnPPortMapper::GetLocalIPs()
{
vector<wstring> localIPs;
ADDRINFOW *result = nullptr;
ADDRINFOW *current = nullptr;
ADDRINFOW* result = nullptr;
ADDRINFOW* current = nullptr;
ADDRINFOW hints;
ZeroMemory(&hints, sizeof(hints));
@ -117,14 +133,18 @@ vector<wstring> 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);
}
}

View file

@ -5,27 +5,27 @@
namespace utf8
{
std::wstring utf8::decode(const std::string &str)
std::wstring utf8::decode(const std::string& str)
{
std::wstring_convert<std::codecvt_utf8<wchar_t>> 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<std::codecvt_utf8<wchar_t>> 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<std::codecvt_utf8_utf16<int16_t>, int16_t> conv;
auto p = reinterpret_cast<const int16_t *>(wstr.data());
return conv.to_bytes(p, p + wstr.size());
#else
#ifdef _MSC_VER
std::wstring_convert<std::codecvt_utf8_utf16<int16_t>, int16_t> conv;
auto p = reinterpret_cast<const int16_t*>(wstr.data());
return conv.to_bytes(p, p + wstr.size());
#else
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> conv;
return conv.to_bytes(wstr);
#endif
#endif
}
}

View file

@ -2,30 +2,51 @@
#include <fstream>
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;

View file

@ -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<uint8_t> &input, vector<uint8_t> &output)
bool UpsPatcher::PatchBuffer(string upsFilepath, vector<uint8_t>& input, vector<uint8_t>& 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<uint8_t> &input, vector<uint8_t> &output)
bool UpsPatcher::PatchBuffer(std::istream& upsFile, vector<uint8_t>& input, vector<uint8_t>& 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<uint8_t> &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<uint8_t> &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<uint8_t> &input, vect
output[pos] ^= xorValue;
pos++;
if(!xorValue) {
if (!xorValue)
{
break;
}
}
@ -88,12 +99,15 @@ bool UpsPatcher::PatchBuffer(std::istream &upsFile, vector<uint8_t> &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;

View file

@ -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<uint8_t> &input, vector<uint8_t> &output);
static bool PatchBuffer(string upsFilepath, vector<uint8_t> &input, vector<uint8_t> &output);
static bool PatchBuffer(std::istream& upsFile, vector<uint8_t>& input, vector<uint8_t>& output);
static bool PatchBuffer(string upsFilepath, vector<uint8_t>& input, vector<uint8_t>& output);
};

View file

@ -10,7 +10,7 @@
#include "../Utilities/IpsPatcher.h"
#include "../Utilities/UpsPatcher.h"
const std::initializer_list<string> VirtualFile::RomExtensions = { ".sfc", ".smc", ".swc", ".fig", ".bs", ".gb", ".gbc" };
const std::initializer_list<string> VirtualFile::RomExtensions = {".sfc", ".smc", ".swc", ".fig", ".bs", ".gb", ".gbc"};
VirtualFile::VirtualFile()
{
@ -26,12 +26,18 @@ VirtualFile::VirtualFile(const string& file)
{
vector<string> 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<uint8_t>& output)
void VirtualFile::LoadFile()
{
if(_data.size() == 0) {
if(!_innerFile.empty()) {
if (_data.size() == 0)
{
if (!_innerFile.empty())
{
shared_ptr<ArchiveReader> reader = ArchiveReader::GetReader(_path);
if(reader) {
if(_innerFileIndex >= 0) {
if (reader)
{
if (_innerFileIndex >= 0)
{
vector<string> 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<ArchiveReader> reader = ArchiveReader::GetReader(_path);
if(reader) {
if (reader)
{
vector<string> 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<uint8_t>& 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<uint8_t>& 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,22 +225,30 @@ 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<uint8_t> 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;
}
}

View file

@ -10,7 +10,7 @@ private:
int32_t _innerFileIndex = -1;
vector<uint8_t> _data;
void FromStream(std::istream &input, vector<uint8_t> &output);
void FromStream(std::istream& input, vector<uint8_t>& output);
void LoadFile();
@ -18,10 +18,10 @@ public:
static const std::initializer_list<string> 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;
@ -33,9 +33,9 @@ public:
size_t GetSize();
bool ReadFile(vector<uint8_t> &out);
bool ReadFile(std::stringstream &out);
bool ReadFile(vector<uint8_t>& out);
bool ReadFile(std::stringstream& out);
bool ReadFile(uint8_t* out, uint32_t expectedSize);
bool ApplyPatch(VirtualFile &patch);
bool ApplyPatch(VirtualFile& patch);
};

View file

@ -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<string> ZipReader::InternalGetFileList()
{
vector<string> 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<string> ZipReader::InternalGetFileList()
return fileList;
}
bool ZipReader::ExtractFile(string filename, vector<uint8_t> &output)
bool ZipReader::ExtractFile(string filename, vector<uint8_t>& 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

View file

@ -16,5 +16,5 @@ public:
ZipReader();
virtual ~ZipReader();
bool ExtractFile(string filename, vector<uint8_t> &output);
bool ExtractFile(string filename, vector<uint8_t>& output);
};

View file

@ -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<uint8_t> &fileData, string zipFilename)
void ZipWriter::AddFile(vector<uint8_t>& 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();

View file

@ -16,6 +16,6 @@ public:
bool Save();
void AddFile(string filepath, string zipFilename);
void AddFile(vector<uint8_t> &fileData, string zipFilename);
void AddFile(std::stringstream &filestream, string zipFilename);
void AddFile(vector<uint8_t>& fileData, string zipFilename);
void AddFile(std::stringstream& filestream, string zipFilename);
};

View file

@ -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<yblocks;y++) {
for (x=0;x<xblocks;x++) {
blocks[i].start=((y*blockheight)+MAX_VECTOR)*pitch+
(x*blockwidth)+MAX_VECTOR;
if (xleft && x==(xblocks-1)) {
blocks[i].dx=xleft;
} else {
blocks[i].dx=blockwidth;
int y, x, i;
i = 0;
for (y = 0; y < yblocks; y++)
{
for (x = 0; x < xblocks; x++)
{
blocks[i].start = ((y * blockheight) + MAX_VECTOR) * pitch +
(x * blockwidth) + MAX_VECTOR;
if (xleft && x == (xblocks - 1))
{
blocks[i].dx = xleft;
}
if (yleft && y==(yblocks-1)) {
blocks[i].dy=yleft;
} else {
blocks[i].dy=blockheight;
else
{
blocks[i].dx = blockwidth;
}
if (yleft && y == (yblocks - 1))
{
blocks[i].dy = yleft;
}
else
{
blocks[i].dy = blockheight;
}
i++;
}
}
memset(buf1,0,bufsize);
memset(buf2,0,bufsize);
memset(work,0,bufsize);
oldframe=buf1;
newframe=buf2;
memset(buf1, 0, bufsize);
memset(buf2, 0, bufsize);
memset(work, 0, bufsize);
oldframe = buf1;
newframe = buf2;
format = _format;
_bufSize = NeededSize(width, height, format);
@ -125,141 +142,165 @@ bool ZmbvCodec::SetupBuffers(zmbv_format_t _format, int blockwidth, int blockhei
return true;
}
void ZmbvCodec::CreateVectorTable(void) {
int x,y,s;
VectorCount=1;
void ZmbvCodec::CreateVectorTable(void)
{
int x, y, s;
VectorCount = 1;
VectorTable[0].x=VectorTable[0].y=0;
for (s=1;s<=10;s++) {
for (y=0-s;y<=0+s;y++) for (x=0-s;x<=0+s;x++) {
if (abs(x)==s || abs(y)==s) {
VectorTable[VectorCount].x=x;
VectorTable[VectorCount].y=y;
VectorCount++;
VectorTable[0].x = VectorTable[0].y = 0;
for (s = 1; s <= 10; s++)
{
for (y = 0 - s; y <= 0 + s; y++)
for (x = 0 - s; x <= 0 + s; x++)
{
if (abs(x) == s || abs(y) == s)
{
VectorTable[VectorCount].x = x;
VectorTable[VectorCount].y = y;
VectorCount++;
}
}
}
}
}
template<class P>
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);
template <class P>
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<class P>
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);
template <class P>
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<class P>
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);
template <class P>
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<class P>
void ZmbvCodec::AddXorFrame(void) {
signed char * vectors=(signed char*)&work[workUsed];
template <class P>
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<blockcount;b++) {
FrameBlock * block=&blocks[b];
workUsed = (workUsed + blockcount * 2 + 3) & ~3;
for (int b = 0; b < blockcount; b++)
{
FrameBlock* block = &blocks[b];
int bestvx = 0;
int bestvy = 0;
int bestchange=CompareBlock<P>(0,0, block);
int possibles=64;
for (int v=0;v<VectorCount && possibles;v++) {
if (bestchange<4) break;
int bestchange = CompareBlock<P>(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<P>(vx, vy, block) < 4) {
if (PossibleBlock<P>(vx, vy, block) < 4)
{
possibles--;
int testchange=CompareBlock<P>(vx,vy, block);
if (testchange<bestchange) {
bestchange=testchange;
int testchange = CompareBlock<P>(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<P>(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,82 +309,95 @@ 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));
memset(&palette, 0, sizeof(palette));
/* keyframes get the full palette */
for (i=0;i<palsize;i++) {
work[workUsed++] = palette[i*4+0];
work[workUsed++] = palette[i*4+1];
work[workUsed++] = palette[i*4+2];
for (i = 0; i < palsize; i++)
{
work[workUsed++] = palette[i * 4 + 0];
work[workUsed++] = palette[i * 4 + 1];
work[workUsed++] = palette[i * 4 + 2];
}
}
/* Restart deflate */
deflateReset(&zstream);
} else {
if (palsize && pal && memcmp(pal, palette, palsize * 4)) {
}
else
{
if (palsize && pal && memcmp(pal, palette, palsize * 4))
{
*firstByte |= Mask_DeltaPalette;
for(i=0;i<palsize;i++) {
work[workUsed++]=palette[i*4+0] ^ pal[i*4+0];
work[workUsed++]=palette[i*4+1] ^ pal[i*4+1];
work[workUsed++]=palette[i*4+2] ^ pal[i*4+2];
for (i = 0; i < palsize; i++)
{
work[workUsed++] = palette[i * 4 + 0] ^ pal[i * 4 + 0];
work[workUsed++] = palette[i * 4 + 1] ^ pal[i * 4 + 1];
work[workUsed++] = palette[i * 4 + 2] ^ pal[i * 4 + 2];
}
memcpy(&palette,pal, palsize * 4);
memcpy(&palette, pal, palsize * 4);
}
}
return true;
}
void ZmbvCodec::CompressLines(int lineCount, void *lineData[])
void ZmbvCodec::CompressLines(int lineCount, void* lineData[])
{
int linePitch = pitch * pixelsize;
int lineWidth = width * pixelsize;
int i = 0;
unsigned char *destStart = newframe + pixelsize*(MAX_VECTOR+(compressInfo.linesDone+MAX_VECTOR)*pitch);
while ( i < lineCount && (compressInfo.linesDone < height)) {
memcpy(destStart, lineData[i], lineWidth );
unsigned char* destStart = newframe + pixelsize * (MAX_VECTOR + (compressInfo.linesDone + MAX_VECTOR) * pitch);
while (i < lineCount && (compressInfo.linesDone < height))
{
memcpy(destStart, lineData[i], lineWidth);
destStart += linePitch;
i++; compressInfo.linesDone++;
i++;
compressInfo.linesDone++;
}
}
int ZmbvCodec::FinishCompressFrame(uint8_t** compressedData)
{
unsigned char firstByte = *compressInfo.writeBuf;
if (firstByte & Mask_KeyFrame) {
if (firstByte & Mask_KeyFrame)
{
int i;
/* Add the full frame data */
unsigned char * readFrame = newframe + pixelsize*(MAX_VECTOR+MAX_VECTOR*pitch);
for (i=0;i<height;i++) {
memcpy(&work[workUsed], readFrame, width*pixelsize);
readFrame += pitch*pixelsize;
workUsed += width*pixelsize;
unsigned char* readFrame = newframe + pixelsize * (MAX_VECTOR + MAX_VECTOR * pitch);
for (i = 0; i < height; i++)
{
memcpy(&work[workUsed], readFrame, width * pixelsize);
readFrame += pitch * pixelsize;
workUsed += width * pixelsize;
}
} else {
}
else
{
/* Add the delta frame data */
switch (format) {
case ZMBV_FORMAT_8BPP:
AddXorFrame<int8_t>();
break;
case ZMBV_FORMAT_15BPP:
case ZMBV_FORMAT_16BPP:
AddXorFrame<int16_t>();
break;
switch (format)
{
case ZMBV_FORMAT_8BPP:
AddXorFrame<int8_t>();
break;
case ZMBV_FORMAT_15BPP:
case ZMBV_FORMAT_16BPP:
AddXorFrame<int16_t>();
break;
default:
case ZMBV_FORMAT_32BPP:
AddXorFrame<int32_t>();
break;
default:
case ZMBV_FORMAT_32BPP:
AddXorFrame<int32_t>();
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;
@ -375,17 +429,19 @@ ZmbvCodec::ZmbvCodec()
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);
}

View file

@ -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;
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<class P> void AddXorFrame(void);
template<class P> INLINE int PossibleBlock(int vx,int vy,FrameBlock * block);
template<class P> INLINE int CompareBlock(int vx,int vy,FrameBlock * block);
template<class P> INLINE void AddXorBlock(int vx,int vy,FrameBlock * block);
template <class P>
void AddXorFrame(void);
template <class P>
INLINE int PossibleBlock(int vx, int vy, FrameBlock* block);
template <class P>
INLINE int CompareBlock(int vx, int vy, FrameBlock* block);
template <class P>
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;
};

View file

@ -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,72 +96,72 @@ 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
#endif
assert( (-3 >> 1) == -2 ); /* right shift must preserve sign */
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 );
CLAMP(n);
assert(n == min_sample);
assert( blip_max_ratio <= time_unit );
assert( blip_max_frame <= (fixed_t) -1 >> time_bits );
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 );
assert(size >= 0);
m = (blip_t*) malloc( sizeof *m + (size + buf_extra) * sizeof (buf_t) );
if ( m )
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.
@ -161,72 +169,72 @@ void blip_clear( blip_t* m )
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 );
assert(samples >= 0 && m->avail + samples <= m->size);
needed = (fixed_t) samples * time_unit;
if ( needed < m->offset )
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 );
assert(count >= 0);
if ( count > m->avail )
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;
@ -234,10 +242,10 @@ int blip_read_samples( blip_t* m, short out [], int count, int stereo )
/* 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] );
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;
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] );
assert(out <= &SAMPLES( m ) [m->size + end_frame_extra]);
out [7] += delta * delta_unit - delta2;
out [8] += delta2;
out[7] += delta * delta_unit - delta2;
out[8] += delta2;
}

View file

@ -9,13 +9,13 @@ Sample buffer that resamples from input clock rate to output sample rate */
#define BLIP_BUF_H
#if defined(_MSC_VER)
#define EXPORT __declspec(dllexport)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#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

File diff suppressed because it is too large Load diff

View file

@ -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,7 +314,8 @@ 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();

View file

@ -28,15 +28,16 @@
/* 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);

File diff suppressed because it is too large Load diff

View file

@ -199,7 +199,7 @@
#endif
#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS)
#include <time.h>
#include <time.h>
#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

File diff suppressed because it is too large Load diff

View file

@ -24,11 +24,11 @@
#include <fstream>
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,7 +305,7 @@ std::string SHA1::final()
return result.str();
}
std::string SHA1::GetHash(vector<uint8_t> &data)
std::string SHA1::GetHash(vector<uint8_t>& data)
{
std::stringstream ss;
ss.write((char*)data.data(), data.size());
@ -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;

View file

@ -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<uint8_t> &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<uint8_t>& 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;
};

View file

@ -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
@ -98,7 +98,7 @@ void snes_ntsc_init( snes_ntsc_t* ntsc, snes_ntsc_setup_t const* setup )
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 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 );
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 );
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 );
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(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(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 );
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_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(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(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(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(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(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(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(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(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 );
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_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(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(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(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(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(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(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;
}
}

View file

@ -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,19 +15,19 @@ 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 */
@ -35,26 +35,26 @@ typedef struct 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

View file

@ -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);
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++ )
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;
@ -139,22 +141,22 @@ static void init_filters( init_t* impl, snes_ntsc_setup_t const* setup )
}
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 */
}
}
}
@ -169,7 +171,7 @@ static void init_filters( init_t* impl, snes_ntsc_setup_t const* setup )
*/
/* generate linear rescale kernels */
#if rescale_out > 1
#if rescale_out > 1
{
float weight = 1.0f;
float* out = impl->kernel;
@ -179,70 +181,70 @@ 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
#endif
impl->artifacts = (float) setup->artifacts;
if ( impl->artifacts > 0 )
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;
@ -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 yc1 = (y + qq) * pixel->kernel[1];
float const yc3 = (y - qq) * pixel->kernel[3];
float const* k = &impl->kernel [pixel->offset];
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 );
while (alignment_count > 1 && --alignment_remain);
if ( burst_count <= 1 )
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 <limits.h>
#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

File diff suppressed because it is too large Load diff

View file

@ -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
//
//////////////////////////////////////////////////////////////////////////////

View file

@ -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
#endif
#endif

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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<int>::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<int>::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,
};
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);
enum SliceType
{
NN_SCALE_SLICE_SOURCE,
NN_SCALE_SLICE_TARGET,
};
//parameter tuning
bool equalColorTest(uint32_t col1, uint32_t col2, ColorFormat colFmt, double luminanceWeight, double equalColorTolerance);
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);
//########################### 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