diff --git a/bsnes/Makefile b/bsnes/Makefile index ffe45eb2..4064864b 100755 --- a/bsnes/Makefile +++ b/bsnes/Makefile @@ -17,6 +17,7 @@ objects := libco # profile-guided optimization mode # pgo := instrument # pgo := optimize + ifeq ($(pgo),instrument) flags += -fprofile-generate link += -lgcov diff --git a/bsnes/data/cheats.xml b/bsnes/data/cheats.xml index ff2092ad..e010d7b0 100755 --- a/bsnes/data/cheats.xml +++ b/bsnes/data/cheats.xml @@ -7778,7 +7778,7 @@ Captain Commando (USA) - Invincibility - p1 + Invincibility - P1 CB4E-7FD4 D04E-7F04 B24E-7F64 @@ -8195,6 +8195,32 @@ F3C1-1F5E + + Choujikuu Yousai Macross - Scrambled Valkyrie (Japan) + + Invincibility + 7E0A90FF + + + Infinite health + C268-4F64 + C269-47A4 + + + Infinite absorb charge + C2B2-C4D1 + + + Infinite continues + 7E02AA09 + + + Hit anywhere + DD6B-3FD7 + DD65-3467 + DD66-34D7 + + Chrono Trigger (USA) @@ -10112,10 +10138,6 @@ Infinite lives - P2 DD3B-6FA5 - - Start with 99 lives - both players - 7E106799 - Infinite Shield - P1 7E177BFF @@ -10137,9 +10159,24 @@ 7E17EB08 - Max 2ndGun - P2 + Max 2nd Gun - P2 7E177C08 + + Hit anywhere - both players + 6D23-6FA4 + C22D-A764 + DD28-67A4 + DD2E-6D04 + + + Start with the strongest main weapon and 8 lives - both players + 3CC3-6DA7 + 62C3-6467 + 62C3-6707 + CBC3-6D07 + D6C3-6D67 + Start with 1 Green Power Cube - P1 62CD-AF67 @@ -10184,6 +10221,10 @@ CBC3-6D07 3CC3-6DA7 + + Start with 99 lives - both players + 7E106799 + Start on planet B DFB0-A7DD @@ -25884,12 +25925,12 @@ Lion King, The (USA) - Infinite lives - CE6E-8464 + Almost infinite health + C298-7DDE - Almost infinite energy - C298-7DDE + Infinite lives + CE6E-8464 Roaring doesn't decrease your roar meter @@ -30419,11 +30460,19 @@ Mary Shelley's Frankenstein (USA) + + Invincibility (blinking) + 7E200D09 + Infinite health C2B9-1DA4 8533-3F0D + + Infinite health (alt) + 7E20431D + Energy balls don't deplete health DDE5-3FB0 @@ -30939,6 +30988,11 @@ F0CA-3FA0 DDCA-34D0 + + View ending (select Capcom Championship) + 81829BEE + 81829CE0 + Mega Man X (USA) (Rev 1) @@ -31378,21 +31432,25 @@ Metal Morph (USA) - Start with 255 continues - EE6C-1FDD + Invincibility + 7E038703 - Freeze timer on continue screen - C2AD-4D65 - - - Infinite ammo for all weapons (to change weapons, turn code off, pick up new weapon, turn back on) + Infinite ammo for all weapons (disable to change weapons) C926-C7A1 Infinite continues C9A9-4F65 + + Infinite time on continue screen + C2AD-4D65 + + + Start with 255 continues + EE6C-1FDD + Metal Warriors (USA) @@ -49328,6 +49386,20 @@ Infinite lives A268-4716 + + Hit anywhere + 6DA9-1DA7 + DD87-1D41 + DDA5-4FD7 + + + Keep main weapon after dying + C26C-4446 + + + Start with strongest main weapon + 62C4-1F46 + Super Off Road - The Baja (USA) @@ -49558,18 +49630,19 @@ Super R-Type (USA) - - Start with Invincibility (blinking) - 82C2-DF61 - - - Start with Invincibility (blinking) (alt) - 7E15BD00 - Infinite lives C2C7-6D0F + + Infinite FORCE once obtained + C267-A4D9 + + + Always fire charged shots (hold B) + 7287-0FD1 + DD87-0D61 + Spiral motion gun takes less time to power up 6D80-6DD1 @@ -49602,8 +49675,12 @@ 7D68-6D6B - Once FORCE has been obtained, keep it forever - C267-A4D9 + Start with Invincibility (blinking) + 82C2-DF61 + + + Start with Invincibility (blinking) (alt) + 7E15BD00 Start with 1 life instead of 3 @@ -57641,7 +57718,18 @@ Zombies Ate My Neighbors (USA) - Infinite health + Invincibility, hit anywhere, get items from anywhere (do not use martian gun) - both players + 6DEC-14D4 + DD2F-476D + DD8D-37D7 + DD8E-C767 + + + Invincibility - both players + DD2F-476D + + + Infinite health - both players 3C20-4D0D @@ -57653,7 +57741,7 @@ 7E1CBA0A - Infinite weapons + Infinite weapons - both players DD30-1FA7 @@ -57665,7 +57753,7 @@ DD39-34D4 - Infinite lives + Infinite lives - both players 82AA-CF07 @@ -57860,6 +57948,10 @@ Infinite Weed Wacker - P2 7E1CF250 + + Victims are invincible + 18CC-37DA + Package of 99 Squirtgun shots worth 999 DBEC-4704 diff --git a/bsnes/nall/bps/delta.hpp b/bsnes/nall/bps/delta.hpp index 53bae28c..a3af047c 100755 --- a/bsnes/nall/bps/delta.hpp +++ b/bsnes/nall/bps/delta.hpp @@ -10,6 +10,9 @@ namespace nall { struct bpsdelta { + inline void source(const uint8_t *data, unsigned size); + inline void target(const uint8_t *data, unsigned size); + inline bool source(const string &filename); inline bool target(const string &filename); inline bool create(const string &filename, const string &metadata = ""); @@ -34,17 +37,25 @@ protected: unsigned targetSize; }; +void bpsdelta::source(const uint8_t *data, unsigned size) { + sourceData = data; + sourceSize = size; +} + +void bpsdelta::target(const uint8_t *data, unsigned size) { + targetData = data; + targetSize = size; +} + bool bpsdelta::source(const string &filename) { if(sourceFile.open(filename, filemap::mode::read) == false) return false; - sourceData = sourceFile.data(); - sourceSize = sourceFile.size(); + source(sourceFile.data(), sourceFile.size()); return true; } bool bpsdelta::target(const string &filename) { if(targetFile.open(filename, filemap::mode::read) == false) return false; - targetData = targetFile.data(); - targetSize = targetFile.size(); + target(targetFile.data(), targetFile.size()); return true; } @@ -85,11 +96,8 @@ bool bpsdelta::create(const string &filename, const string &metadata) { encode(markupSize); for(unsigned n = 0; n < markupSize; n++) write(metadata[n]); - Node *sourceTree[65536]; - Node *targetTree[65536]; - - for(unsigned n = 0; n < 65536; n++) sourceTree[n] = 0; - for(unsigned n = 0; n < 65536; n++) targetTree[n] = 0; + Node *sourceTree[65536], *targetTree[65536]; + for(unsigned n = 0; n < 65536; n++) sourceTree[n] = 0, targetTree[n] = 0; //source tree creation for(unsigned offset = 0; offset < sourceSize; offset++) { @@ -118,6 +126,15 @@ bool bpsdelta::create(const string &filename, const string &metadata) { uint16_t symbol = targetData[outputOffset + 0]; if(outputOffset < targetSize - 1) symbol |= targetData[outputOffset + 1] << 8; + { //source read + unsigned length = 0, offset = outputOffset; + while(offset < sourceSize && offset < targetSize && sourceData[offset] == targetData[offset]) { + length++; + offset++; + } + if(length > maxLength) maxLength = length, mode = SourceRead; + } + { //source copy Node *node = sourceTree[symbol]; while(node) { @@ -144,15 +161,6 @@ bool bpsdelta::create(const string &filename, const string &metadata) { targetTree[symbol] = node; } - { //source read - unsigned length = 0, offset = outputOffset; - while(offset < sourceSize && offset < targetSize && sourceData[offset] == targetData[offset]) { - length++; - offset++; - } - if(length > maxLength) maxLength = length, mode = SourceRead; - } - { //target read if(maxLength < 4) { maxLength = min((unsigned)Granularity, targetSize - outputOffset); diff --git a/bsnes/nall/bps/linear.hpp b/bsnes/nall/bps/linear.hpp index c22df39a..df840283 100755 --- a/bsnes/nall/bps/linear.hpp +++ b/bsnes/nall/bps/linear.hpp @@ -10,6 +10,9 @@ namespace nall { struct bpslinear { + inline void source(const uint8_t *data, unsigned size); + inline void target(const uint8_t *data, unsigned size); + inline bool source(const string &filename); inline bool target(const string &filename); inline bool create(const string &filename, const string &metadata = ""); @@ -27,17 +30,25 @@ protected: unsigned targetSize; }; +void bpslinear::source(const uint8_t *data, unsigned size) { + sourceData = data; + sourceSize = size; +} + +void bpslinear::target(const uint8_t *data, unsigned size) { + targetData = data; + targetSize = size; +} + bool bpslinear::source(const string &filename) { if(sourceFile.open(filename, filemap::mode::read) == false) return false; - sourceData = sourceFile.data(); - sourceSize = sourceFile.size(); + source(sourceFile.data(), sourceFile.size()); return true; } bool bpslinear::target(const string &filename) { if(targetFile.open(filename, filemap::mode::read) == false) return false; - targetData = targetFile.data(); - targetSize = targetFile.size(); + target(targetFile.data(), targetFile.size()); return true; } @@ -90,7 +101,7 @@ bool bpslinear::create(const string &filename, const string &metadata) { while(outputOffset < targetSize) { unsigned sourceLength = 0; - for(unsigned n = 0; outputOffset + n < sourceSize; n++) { + for(unsigned n = 0; outputOffset + n < min(sourceSize, targetSize); n++) { if(sourceData[outputOffset + n] != targetData[outputOffset + n]) break; sourceLength++; } diff --git a/bsnes/nall/bps/metadata.hpp b/bsnes/nall/bps/metadata.hpp new file mode 100755 index 00000000..46759e6f --- /dev/null +++ b/bsnes/nall/bps/metadata.hpp @@ -0,0 +1,121 @@ +#ifndef NALL_BPS_METADATA_HPP +#define NALL_BPS_METADATA_HPP + +#include +#include +#include +#include +#include + +namespace nall { + +struct bpsmetadata { + inline bool load(const string &filename); + inline bool save(const string &filename, const string &metadata); + inline string metadata() const; + +protected: + file sourceFile; + string metadataString; +}; + +bool bpsmetadata::load(const string &filename) { + if(sourceFile.open(filename, file::mode::read) == false) return false; + + auto read = [&]() -> uint8_t { + return sourceFile.read(); + }; + + auto decode = [&]() -> uint64_t { + uint64_t data = 0, shift = 1; + while(true) { + uint8_t x = read(); + data += (x & 0x7f) * shift; + if(x & 0x80) break; + shift <<= 7; + data += shift; + } + return data; + }; + + if(read() != 'B') return false; + if(read() != 'P') return false; + if(read() != 'S') return false; + if(read() != '1') return false; + decode(); + decode(); + unsigned metadataSize = decode(); + char data[metadataSize + 1]; + for(unsigned n = 0; n < metadataSize; n++) data[n] = read(); + data[metadataSize] = 0; + metadataString = (const char*)data; + + return true; +} + +bool bpsmetadata::save(const string &filename, const string &metadata) { + file targetFile; + if(targetFile.open(filename, file::mode::write) == false) return false; + if(sourceFile.open() == false) return false; + sourceFile.seek(0); + + auto read = [&]() -> uint8_t { + return sourceFile.read(); + }; + + auto decode = [&]() -> uint64_t { + uint64_t data = 0, shift = 1; + while(true) { + uint8_t x = read(); + data += (x & 0x7f) * shift; + if(x & 0x80) break; + shift <<= 7; + data += shift; + } + return data; + }; + + uint32_t checksum = ~0; + + auto write = [&](uint8_t data) { + targetFile.write(data); + checksum = crc32_adjust(checksum, data); + }; + + auto encode = [&](uint64_t data) { + while(true) { + uint64_t x = data & 0x7f; + data >>= 7; + if(data == 0) { + write(0x80 | x); + break; + } + write(x); + data--; + } + }; + + for(unsigned n = 0; n < 4; n++) write(read()); + encode(decode()); + encode(decode()); + unsigned sourceLength = decode(); + unsigned targetLength = metadata.length(); + encode(targetLength); + sourceFile.seek(sourceLength, file::index::relative); + for(unsigned n = 0; n < targetLength; n++) write(metadata[n]); + unsigned length = sourceFile.size() - sourceFile.offset() - 4; + for(unsigned n = 0; n < length; n++) write(read()); + uint32_t outputChecksum = ~checksum; + for(unsigned n = 0; n < 32; n += 8) write(outputChecksum >> n); + + targetFile.close(); + return true; +} + +string bpsmetadata::metadata() const { + return metadataString; +} + +} + +#endif diff --git a/bsnes/nall/bps/patch.hpp b/bsnes/nall/bps/patch.hpp index e24eba90..85c4dcae 100755 --- a/bsnes/nall/bps/patch.hpp +++ b/bsnes/nall/bps/patch.hpp @@ -18,6 +18,7 @@ struct bpspatch { inline bool source(const string &filename); inline bool target(const string &filename); + inline string metadata() const; inline unsigned size() const; enum result : unsigned { @@ -49,11 +50,10 @@ protected: uint8_t *targetData; unsigned targetSize; -public: unsigned modifySourceSize; unsigned modifyTargetSize; unsigned modifyMarkupSize; - string metadata; + string metadataString; }; bool bpspatch::modify(const uint8_t *data, unsigned size) { @@ -77,6 +77,12 @@ bool bpspatch::modify(const uint8_t *data, unsigned size) { modifySourceSize = decode(); modifyTargetSize = decode(); modifyMarkupSize = decode(); + + char buffer[modifyMarkupSize + 1]; + for(unsigned n = 0; n < modifyMarkupSize; n++) buffer[n] = modifyData[offset++]; + buffer[modifyMarkupSize] = 0; + metadataString = (const char*)buffer; + return true; } @@ -112,6 +118,10 @@ bool bpspatch::target(const string &filename) { return true; } +string bpspatch::metadata() const { + return metadataString; +} + unsigned bpspatch::size() const { return modifyTargetSize; } @@ -152,12 +162,8 @@ bpspatch::result bpspatch::apply() { modifySourceSize = decode(); modifyTargetSize = decode(); - modifyMarkupSize = decode(); - char data[modifyMarkupSize + 1]; - for(unsigned n = 0; n < modifyMarkupSize; n++) data[n] = read(); - data[modifyMarkupSize] = 0; - metadata = (const char*)data; + for(unsigned n = 0; n < modifyMarkupSize; n++) read(); if(modifySourceSize > sourceSize) return result::source_too_small; if(modifyTargetSize > targetSize) return result::target_too_small; diff --git a/bsnes/nall/dsp.hpp b/bsnes/nall/dsp.hpp index 52e43327..009c8b6c 100755 --- a/bsnes/nall/dsp.hpp +++ b/bsnes/nall/dsp.hpp @@ -1,6 +1,8 @@ #ifndef NALL_DSP_HPP #define NALL_DSP_HPP +#define NALL_DSP_INTERNAL_HPP #include +#undef NALL_DSP_INTERNAL_HPP #endif diff --git a/bsnes/nall/dsp/buffer.hpp b/bsnes/nall/dsp/buffer.hpp new file mode 100755 index 00000000..c1b85b8d --- /dev/null +++ b/bsnes/nall/dsp/buffer.hpp @@ -0,0 +1,36 @@ +#ifdef NALL_DSP_INTERNAL_HPP + +struct Buffer { + double *sample[2]; + uint16_t rdoffset; + uint16_t wroffset; + + inline double& read(bool channel, signed offset = 0) { + return sample[channel][(uint16_t)(rdoffset + offset)]; + } + + inline double& write(bool channel, signed offset = 0) { + return sample[channel][(uint16_t)(wroffset + offset)]; + } + + inline void clear() { + for(unsigned n = 0; n < 65536; n++) { + sample[0][n] = 0; + sample[1][n] = 0; + } + rdoffset = 0; + wroffset = 0; + } + + Buffer() { + sample[0] = new double[65536]; + sample[1] = new double[65536]; + } + + ~Buffer() { + delete[] sample[0]; + delete[] sample[1]; + } +}; + +#endif diff --git a/bsnes/nall/dsp/core.hpp b/bsnes/nall/dsp/core.hpp index 20cfdfdc..bec46d93 100755 --- a/bsnes/nall/dsp/core.hpp +++ b/bsnes/nall/dsp/core.hpp @@ -1,27 +1,35 @@ -#ifndef NALL_DSP_EFFECT_HPP -#define NALL_DSP_EFFECT_HPP +#ifdef NALL_DSP_INTERNAL_HPP +#include #include namespace nall { -struct dsp { - inline void set_precision(unsigned precision); - inline void set_frequency(double frequency); - inline void set_volume(double volume); - inline void set_balance(double balance); - inline void set_echo(double echo); +struct DSP { + enum class Resampler : unsigned { + Point, + Linear, + Cosine, + Cubic, + Hermite, + Average, + }; - inline void set_resampler_frequency(double frequency); + inline void setPrecision(unsigned precision); + inline void setFrequency(double frequency); //inputFrequency + inline void setVolume(double volume); + inline void setBalance(double balance); + + inline void setResampler(Resampler resampler); + inline void setResamplerFrequency(double frequency); //outputFrequency inline void sample(signed lchannel, signed rchannel); inline bool pending(); inline void read(signed &lchannel, signed &rchannel); - inline signed clamp(const unsigned bits, const signed x); inline void clear(); - inline dsp(); - inline ~dsp(); + inline DSP(); + inline ~DSP(); protected: struct Settings { @@ -29,196 +37,116 @@ protected: double frequency; double volume; double balance; - double echo; //internal double intensity; } settings; - struct Resampler { + struct ResamplerSettings { + Resampler engine; double frequency; //internal double fraction; double step; } resampler; - inline void resampler_run(); + inline void resamplerRun(); + inline void resamplerWrite(double lchannel, double rchannel); - struct Buffer { - double *sample[2]; - uint16_t rdoffset; - uint16_t wroffset; - inline double& operator()(bool channel, signed offset) { return sample[channel][(uint16_t)(rdoffset + offset)]; } - inline void write(bool channel, signed offset, double data) { sample[channel][(uint16_t)(wroffset + offset)] = data; } - } buffer; + inline void resamplePoint(); + inline void resampleLinear(); + inline void resampleCosine(); + inline void resampleCubic(); + inline void resampleHermite(); + inline void resampleAverage(); - struct Output { - double *sample[2]; - uint16_t rdoffset; - uint16_t wroffset; - inline double& operator()(bool channel, signed offset) { return sample[channel][(uint16_t)(rdoffset + offset)]; } - inline void write(bool channel, signed offset, double data) { sample[channel][(uint16_t)(wroffset + offset)] = data; } - } output; + #include "buffer.hpp" + Buffer buffer; + Buffer output; - inline void adjust_volume(); - inline void adjust_balance(); - inline void adjust_echo(); + inline void adjustVolume(); + inline void adjustBalance(); + inline signed clamp(const unsigned bits, const signed x); }; -void dsp::set_precision(unsigned precision) { - settings.precision = precision; - settings.intensity = 1 << (settings.precision - 1); -} +#include "settings.hpp" -void dsp::set_frequency(double frequency) { - settings.frequency = frequency; - resampler.fraction = 0; - resampler.step = settings.frequency / resampler.frequency; -} - -void dsp::set_volume(double volume) { - settings.volume = volume; -} - -void dsp::set_balance(double balance) { - settings.balance = balance; -} - -void dsp::set_echo(double echo) { - settings.echo = echo; -} - -void dsp::set_resampler_frequency(double frequency) { - resampler.frequency = frequency; - resampler.fraction = 0; - resampler.step = settings.frequency / resampler.frequency; -} - -void dsp::sample(signed lchannel, signed rchannel) { - buffer.write(0, 0, (double)lchannel / settings.intensity); - buffer.write(1, 0, (double)rchannel / settings.intensity); +void DSP::sample(signed lchannel, signed rchannel) { + buffer.write(0) = (double)lchannel / settings.intensity; + buffer.write(1) = (double)rchannel / settings.intensity; buffer.wroffset++; - -#ifdef DSP_NO_RESAMPLER - output.write(0, 0, buffer(0, 0)); - output.write(1, 0, buffer(1, 0)); - output.wroffset++; - buffer.rdoffset++; -#else - resampler_run(); -#endif + resamplerRun(); } -bool dsp::pending() { +bool DSP::pending() { return output.rdoffset != output.wroffset; } -void dsp::read(signed &lchannel, signed &rchannel) { - adjust_volume(); - adjust_balance(); - adjust_echo(); +void DSP::read(signed &lchannel, signed &rchannel) { + adjustVolume(); + adjustBalance(); - lchannel = clamp(settings.precision, output(0, 0) * settings.intensity); - rchannel = clamp(settings.precision, output(1, 0) * settings.intensity); + lchannel = clamp(settings.precision, output.read(0) * settings.intensity); + rchannel = clamp(settings.precision, output.read(1) * settings.intensity); output.rdoffset++; } -void dsp::resampler_run() { - //4-tap hermite - while(resampler.fraction <= 1.0) { - for(unsigned n = 0; n < 2; n++) { - double a = buffer(n, -3); - double b = buffer(n, -2); - double c = buffer(n, -1); - double d = buffer(n, -0); - - const double tension = 0.0; //-1 = low, 0 = normal, +1 = high - const double bias = 0.0; //-1 = left, 0 = even, +1 = right - - double mu1, mu2, mu3, m0, m1, a0, a1, a2, a3; - - mu1 = resampler.fraction; - mu2 = mu1 * mu1; - mu3 = mu2 * mu1; - - m0 = (b - a) * (1.0 + bias) * (1.0 - tension) / 2.0; - m0 += (c - b) * (1.0 - bias) * (1.0 - tension) / 2.0; - m1 = (c - b) * (1.0 + bias) * (1.0 - tension) / 2.0; - m1 += (d - c) * (1.0 - bias) * (1.0 - tension) / 2.0; - - a0 = +2 * mu3 - 3 * mu2 + 1; - a1 = mu3 - 2 * mu2 + mu1; - a2 = mu3 - mu2; - a3 = -2 * mu3 + 3 * mu2; - - double result = (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c); - output.write(n, 0, result); - } - - output.wroffset++; - resampler.fraction += resampler.step; +void DSP::resamplerRun() { + switch(resampler.engine) { + case Resampler::Point: return resamplePoint(); + case Resampler::Linear: return resampleLinear(); + case Resampler::Cosine: return resampleCosine(); + case Resampler::Cubic: return resampleCubic(); + case Resampler::Hermite: return resampleHermite(); + case Resampler::Average: return resampleAverage(); } - - buffer.rdoffset++; - resampler.fraction -= 1.0; } -void dsp::adjust_volume() { - output(0, 0) *= settings.volume; - output(1, 0) *= settings.volume; +void DSP::resamplerWrite(double lchannel, double rchannel) { + output.write(0) = lchannel; + output.write(1) = rchannel; + output.wroffset++; } -void dsp::adjust_balance() { - if(settings.balance < 0.0) output(1, 0) *= 1.0 + settings.balance; - if(settings.balance > 0.0) output(0, 0) *= 1.0 - settings.balance; +#include "resample/point.hpp" +#include "resample/linear.hpp" +#include "resample/cosine.hpp" +#include "resample/cubic.hpp" +#include "resample/hermite.hpp" +#include "resample/average.hpp" + +void DSP::adjustVolume() { + output.read(0) *= settings.volume; + output.read(1) *= settings.volume; } -void dsp::adjust_echo() { - //... +void DSP::adjustBalance() { + if(settings.balance < 0.0) output.read(1) *= 1.0 + settings.balance; + if(settings.balance > 0.0) output.read(0) *= 1.0 - settings.balance; } -signed dsp::clamp(const unsigned bits, const signed x) { +signed DSP::clamp(const unsigned bits, const signed x) { const signed b = 1U << (bits - 1); const signed m = (1U << (bits - 1)) - 1; return (x > m) ? m : (x < -b) ? -b : x; } -void dsp::clear() { +void DSP::clear() { resampler.fraction = 0.0; - resampler.step = 1.0; - for(unsigned n = 0; n < 65536; n++) { - buffer.sample[0][n] = 0.0; - buffer.sample[1][n] = 0.0; - output.sample[0][n] = 0.0; - output.sample[1][n] = 0.0; - } - buffer.rdoffset = 0; - buffer.wroffset = 0; - output.rdoffset = 0; - output.wroffset = 0; + buffer.clear(); + output.clear(); } -dsp::dsp() { - settings.precision = 16; - settings.frequency = 44100.0; - settings.volume = 1.0; - settings.balance = 0.0; - settings.echo = 0.0; - settings.intensity = 1 << (settings.precision - 1); - resampler.frequency = 44100.0; - - buffer.sample[0] = new double[65536]; - buffer.sample[1] = new double[65536]; - output.sample[0] = new double[65536]; - output.sample[1] = new double[65536]; - +DSP::DSP() { + setPrecision(16); + setFrequency(44100.0); + setVolume(1.0); + setBalance(0.0); + setResampler(Resampler::Hermite); + setResamplerFrequency(44100.0); clear(); } -dsp::~dsp() { - delete[] buffer.sample[0]; - delete[] buffer.sample[1]; - delete[] output.sample[0]; - delete[] output.sample[1]; +DSP::~DSP() { } } diff --git a/bsnes/nall/dsp/resample/average.hpp b/bsnes/nall/dsp/resample/average.hpp new file mode 100755 index 00000000..ca97050e --- /dev/null +++ b/bsnes/nall/dsp/resample/average.hpp @@ -0,0 +1,28 @@ +#ifdef NALL_DSP_INTERNAL_HPP + +void DSP::resampleAverage() { + //can only average if input frequency >= output frequency + if(resampler.step < 1.0) return resampleHermite(); + + resampler.fraction += 1.0; + + double scalar = 1.0; + if(resampler.fraction > resampler.step) scalar = 1.0 - (resampler.fraction - resampler.step); + + output.write(0) += buffer.read(0) * scalar; + output.write(1) += buffer.read(1) * scalar; + + if(resampler.fraction >= resampler.step) { + output.write(0) /= resampler.step; + output.write(1) /= resampler.step; + output.wroffset++; + + resampler.fraction -= resampler.step; + output.write(0) = buffer.read(0) * resampler.fraction; + output.write(1) = buffer.read(1) * resampler.fraction; + } + + buffer.rdoffset++; +} + +#endif diff --git a/bsnes/nall/dsp/resample/cosine.hpp b/bsnes/nall/dsp/resample/cosine.hpp new file mode 100755 index 00000000..56fcf8fe --- /dev/null +++ b/bsnes/nall/dsp/resample/cosine.hpp @@ -0,0 +1,25 @@ +#ifdef NALL_DSP_INTERNAL_HPP + +void DSP::resampleCosine() { + while(resampler.fraction <= 1.0) { + double channel[2]; + + for(unsigned n = 0; n < 2; n++) { + double a = buffer.read(n, -1); + double b = buffer.read(n, -0); + + double mu = resampler.fraction; + mu = (1.0 - cos(mu * 3.14159265)) / 2.0; + + channel[n] = a * (1.0 - mu) + b * mu; + } + + resamplerWrite(channel[0], channel[1]); + resampler.fraction += resampler.step; + } + + buffer.rdoffset++; + resampler.fraction -= 1.0; +} + +#endif diff --git a/bsnes/nall/dsp/resample/cubic.hpp b/bsnes/nall/dsp/resample/cubic.hpp new file mode 100755 index 00000000..f975f6aa --- /dev/null +++ b/bsnes/nall/dsp/resample/cubic.hpp @@ -0,0 +1,31 @@ +#ifdef NALL_DSP_INTERNAL_HPP + +void DSP::resampleCubic() { + while(resampler.fraction <= 1.0) { + double channel[2]; + + for(unsigned n = 0; n < 2; n++) { + double a = buffer.read(n, -3); + double b = buffer.read(n, -2); + double c = buffer.read(n, -1); + double d = buffer.read(n, -0); + + double mu = resampler.fraction; + + double A = d - c - a + b; + double B = a - b - A; + double C = c - a; + double D = b; + + channel[n] = A * (mu * 3) + B * (mu * 2) + C * mu + D; + } + + resamplerWrite(channel[0], channel[1]); + resampler.fraction += resampler.step; + } + + buffer.rdoffset++; + resampler.fraction -= 1.0; +} + +#endif diff --git a/bsnes/nall/dsp/resample/hermite.hpp b/bsnes/nall/dsp/resample/hermite.hpp new file mode 100755 index 00000000..a042a55b --- /dev/null +++ b/bsnes/nall/dsp/resample/hermite.hpp @@ -0,0 +1,43 @@ +#ifdef NALL_DSP_INTERNAL_HPP + +void DSP::resampleHermite() { + while(resampler.fraction <= 1.0) { + double channel[2]; + + for(unsigned n = 0; n < 2; n++) { + double a = buffer.read(n, -3); + double b = buffer.read(n, -2); + double c = buffer.read(n, -1); + double d = buffer.read(n, -0); + + const double tension = 0.0; //-1 = low, 0 = normal, +1 = high + const double bias = 0.0; //-1 = left, 0 = even, +1 = right + + double mu1, mu2, mu3, m0, m1, a0, a1, a2, a3; + + mu1 = resampler.fraction; + mu2 = mu1 * mu1; + mu3 = mu2 * mu1; + + m0 = (b - a) * (1.0 + bias) * (1.0 - tension) / 2.0; + m0 += (c - b) * (1.0 - bias) * (1.0 - tension) / 2.0; + m1 = (c - b) * (1.0 + bias) * (1.0 - tension) / 2.0; + m1 += (d - c) * (1.0 - bias) * (1.0 - tension) / 2.0; + + a0 = +2 * mu3 - 3 * mu2 + 1; + a1 = mu3 - 2 * mu2 + mu1; + a2 = mu3 - mu2; + a3 = -2 * mu3 + 3 * mu2; + + channel[n] = (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c); + } + + resamplerWrite(channel[0], channel[1]); + resampler.fraction += resampler.step; + } + + buffer.rdoffset++; + resampler.fraction -= 1.0; +} + +#endif diff --git a/bsnes/nall/dsp/resample/linear.hpp b/bsnes/nall/dsp/resample/linear.hpp new file mode 100755 index 00000000..f4e48f57 --- /dev/null +++ b/bsnes/nall/dsp/resample/linear.hpp @@ -0,0 +1,24 @@ +#ifdef NALL_DSP_INTERNAL_HPP + +void DSP::resampleLinear() { + while(resampler.fraction <= 1.0) { + double channel[2]; + + for(unsigned n = 0; n < 2; n++) { + double a = buffer.read(n, -1); + double b = buffer.read(n, -0); + + double mu = resampler.fraction; + + channel[n] = a * (1.0 - mu) + b * mu; + } + + resamplerWrite(channel[0], channel[1]); + resampler.fraction += resampler.step; + } + + buffer.rdoffset++; + resampler.fraction -= 1.0; +} + +#endif diff --git a/bsnes/nall/dsp/resample/point.hpp b/bsnes/nall/dsp/resample/point.hpp new file mode 100755 index 00000000..51d35935 --- /dev/null +++ b/bsnes/nall/dsp/resample/point.hpp @@ -0,0 +1,24 @@ +#ifdef NALL_DSP_INTERNAL_HPP + +void DSP::resamplePoint() { + while(resampler.fraction <= 1.0) { + double channel[2]; + + for(unsigned n = 0; n < 2; n++) { + double a = buffer.read(n, -1); + double b = buffer.read(n, -0); + + double mu = resampler.fraction; + + channel[n] = mu < 0.5 ? a : b; + } + + resamplerWrite(channel[0], channel[1]); + resampler.fraction += resampler.step; + } + + buffer.rdoffset++; + resampler.fraction -= 1.0; +} + +#endif diff --git a/bsnes/nall/dsp/settings.hpp b/bsnes/nall/dsp/settings.hpp new file mode 100755 index 00000000..c7313d3d --- /dev/null +++ b/bsnes/nall/dsp/settings.hpp @@ -0,0 +1,32 @@ +#ifdef NALL_DSP_INTERNAL_HPP + +void DSP::setPrecision(unsigned precision) { + settings.precision = precision; + settings.intensity = 1 << (settings.precision - 1); +} + +void DSP::setFrequency(double frequency) { + settings.frequency = frequency; + resampler.fraction = 0; + resampler.step = settings.frequency / resampler.frequency; +} + +void DSP::setVolume(double volume) { + settings.volume = volume; +} + +void DSP::setBalance(double balance) { + settings.balance = balance; +} + +void DSP::setResampler(Resampler engine) { + resampler.engine = engine; +} + +void DSP::setResamplerFrequency(double frequency) { + resampler.frequency = frequency; + resampler.fraction = 0; + resampler.step = settings.frequency / resampler.frequency; +} + +#endif diff --git a/bsnes/nall/filemap.hpp b/bsnes/nall/filemap.hpp index f04ec899..7eeac2b0 100755 --- a/bsnes/nall/filemap.hpp +++ b/bsnes/nall/filemap.hpp @@ -47,6 +47,12 @@ namespace nall { } bool p_open(const char *filename, mode mode_) { + if(file::exists(filename) && file::size(filename) == 0) { + p_handle = 0; + p_size = 0; + return true; + } + int desired_access, creation_disposition, flprotect, map_access; switch(mode_) { @@ -133,6 +139,12 @@ namespace nall { } bool p_open(const char *filename, mode mode_) { + if(file::exists(filename) && file::size(filename) == 0) { + p_handle = 0; + p_size = 0; + return true; + } + int open_flags, mmap_flags; switch(mode_) { diff --git a/bsnes/nall/platform.hpp b/bsnes/nall/platform.hpp index 5c226e3e..8e7bb5fe 100755 --- a/bsnes/nall/platform.hpp +++ b/bsnes/nall/platform.hpp @@ -95,6 +95,7 @@ wchar_t fn[_MAX_PATH] = L""; _wfullpath(fn, nall::utf16_t(filename), _MAX_PATH); strcpy(resolvedname, nall::utf8_t(fn)); + for(unsigned n = 0; resolvedname[n]; n++) if(resolvedname[n] == '\\') resolvedname[n] = '/'; return resolvedname; } @@ -102,6 +103,7 @@ wchar_t fp[_MAX_PATH] = L""; SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, fp); strcpy(path, nall::utf8_t(fp)); + for(unsigned n = 0; path[n]; n++) if(path[n] == '\\') path[n] = '/'; return path; } @@ -109,6 +111,7 @@ wchar_t fp[_MAX_PATH] = L""; _wgetcwd(fp, _MAX_PATH); strcpy(path, nall::utf8_t(fp)); + for(unsigned n = 0; path[n]; n++) if(path[n] == '\\') path[n] = '/'; return path; } #else diff --git a/bsnes/snes/audio/audio.cpp b/bsnes/snes/audio/audio.cpp index eaea1c63..d715c69c 100755 --- a/bsnes/snes/audio/audio.cpp +++ b/bsnes/snes/audio/audio.cpp @@ -4,19 +4,17 @@ Audio audio; void Audio::coprocessor_enable(bool state) { coprocessor = state; + dspaudio.clear(); dsp_rdoffset = cop_rdoffset = 0; dsp_wroffset = cop_wroffset = 0; dsp_length = cop_length = 0; - - r_sum_l = r_sum_r = 0; } void Audio::coprocessor_frequency(double input_frequency) { - double output_frequency; - output_frequency = system.apu_frequency() / 768.0; - r_step = input_frequency / output_frequency; - r_frac = 0; + dspaudio.setFrequency(input_frequency); + dspaudio.setResampler(nall::DSP::Resampler::Average); + dspaudio.setResamplerFrequency(system.apu_frequency() / 768.0); } void Audio::sample(int16 left, int16 right) { @@ -31,28 +29,16 @@ void Audio::sample(int16 left, int16 right) { } void Audio::coprocessor_sample(int16 left, int16 right) { - if(r_frac >= 1.0) { - r_frac -= 1.0; - r_sum_l += left; - r_sum_r += right; - return; + dspaudio.sample(left, right); + while(dspaudio.pending()) { + signed left, right; + dspaudio.read(left, right); + + cop_buffer[cop_wroffset] = ((uint16)left << 0) + ((uint16)right << 16); + cop_wroffset = (cop_wroffset + 1) & buffer_mask; + cop_length = (cop_length + 1) & buffer_mask; + flush(); } - - r_sum_l += left * r_frac; - r_sum_r += right * r_frac; - - uint16 output_left = sclamp<16>(int(r_sum_l / r_step)); - uint16 output_right = sclamp<16>(int(r_sum_r / r_step)); - - double first = 1.0 - r_frac; - r_sum_l = left * first; - r_sum_r = right * first; - r_frac = r_step - first; - - cop_buffer[cop_wroffset] = (output_left << 0) + (output_right << 16); - cop_wroffset = (cop_wroffset + 1) & buffer_mask; - cop_length = (cop_length + 1) & buffer_mask; - flush(); } void Audio::init() { diff --git a/bsnes/snes/audio/audio.hpp b/bsnes/snes/audio/audio.hpp index 29d6dbae..f3bc8a4d 100755 --- a/bsnes/snes/audio/audio.hpp +++ b/bsnes/snes/audio/audio.hpp @@ -8,15 +8,13 @@ public: private: bool coprocessor; - enum : unsigned { buffer_size = 32768, buffer_mask = buffer_size - 1 }; + nall::DSP dspaudio; + enum : unsigned { buffer_size = 256, buffer_mask = buffer_size - 1 }; uint32 dsp_buffer[buffer_size], cop_buffer[buffer_size]; unsigned dsp_rdoffset, cop_rdoffset; unsigned dsp_wroffset, cop_wroffset; unsigned dsp_length, cop_length; - double r_step, r_frac; - int r_sum_l, r_sum_r; - void flush(); }; diff --git a/bsnes/snes/snes.hpp b/bsnes/snes/snes.hpp index 03d96414..befdc5ab 100755 --- a/bsnes/snes/snes.hpp +++ b/bsnes/snes/snes.hpp @@ -1,7 +1,7 @@ namespace SNES { namespace Info { static const char Name[] = "bsnes"; - static const char Version[] = "081.04"; + static const char Version[] = "082"; static const unsigned SerializerVersion = 21; } } @@ -19,6 +19,7 @@ namespace SNES { #include #include #include +#include #include #include #include diff --git a/bsnes/ui-gameboy/base.hpp b/bsnes/ui-gameboy/base.hpp index 0cf51c0b..f1afddfe 100755 --- a/bsnes/ui-gameboy/base.hpp +++ b/bsnes/ui-gameboy/base.hpp @@ -30,5 +30,5 @@ struct Application { void main(int argc, char **argv); }; -extern nall::dsp dspaudio; +extern nall::DSP dspaudio; extern Application application; diff --git a/bsnes/ui-gameboy/main.cpp b/bsnes/ui-gameboy/main.cpp index 5224d28e..3bd04b82 100755 --- a/bsnes/ui-gameboy/main.cpp +++ b/bsnes/ui-gameboy/main.cpp @@ -1,5 +1,5 @@ #include "base.hpp" -nall::dsp dspaudio; +nall::DSP dspaudio; Application application; #include "interface.cpp" @@ -56,11 +56,12 @@ void Application::main(int argc, char **argv) { audio.set(Audio::Frequency, 44100u); audio.init(); - dspaudio.set_precision(16); - dspaudio.set_volume(1.0); - dspaudio.set_balance(0.0); - dspaudio.set_frequency(4194304.0); - dspaudio.set_resampler_frequency(44100.0); + dspaudio.setPrecision(16); + dspaudio.setVolume(1.0); + dspaudio.setBalance(0.0); + dspaudio.setFrequency(4194304.0); + dspaudio.setResampler(DSP::Resampler::Average); + dspaudio.setResamplerFrequency(44100.0); #if defined(PLATFORM_WIN) input.driver("RawInput"); diff --git a/bsnes/ui/base.hpp b/bsnes/ui/base.hpp index 12e13dc4..acf9dcbb 100755 --- a/bsnes/ui/base.hpp +++ b/bsnes/ui/base.hpp @@ -61,5 +61,5 @@ private: void saveGeometry(); }; -extern nall::dsp dspaudio; +extern nall::DSP dspaudio; extern Application application; diff --git a/bsnes/ui/main.cpp b/bsnes/ui/main.cpp index 6dfa414b..bb8310d8 100755 --- a/bsnes/ui/main.cpp +++ b/bsnes/ui/main.cpp @@ -1,7 +1,7 @@ #include "base.hpp" #include "interface.cpp" #include "config.cpp" -nall::dsp dspaudio; +nall::DSP dspaudio; Application application; void Application::main(int argc, char **argv) { @@ -105,11 +105,12 @@ void Application::main(int argc, char **argv) { audio.init(); } - dspaudio.set_precision(16); //16-bit signed audio - dspaudio.set_volume((double)config.audio.volume / 100.0); - dspaudio.set_balance((double)((signed)config.audio.balance - 100) / 100.0); - dspaudio.set_frequency(config.audio.inputFrequency); - dspaudio.set_resampler_frequency(config.audio.outputFrequency); + dspaudio.setPrecision(16); //16-bit signed audio + dspaudio.setVolume((double)config.audio.volume / 100.0); + dspaudio.setBalance((double)((signed)config.audio.balance - 100) / 100.0); + dspaudio.setFrequency(config.audio.inputFrequency); + dspaudio.setResampler(DSP::Resampler::Hermite); + dspaudio.setResamplerFrequency(config.audio.outputFrequency); input.driver(config.input.driver); input.set(Input::Handle, mainWindow.viewport.handle()); diff --git a/bsnes/ui/settings/audio.cpp b/bsnes/ui/settings/audio.cpp index 3a6c0fb8..20fc6b6a 100755 --- a/bsnes/ui/settings/audio.cpp +++ b/bsnes/ui/settings/audio.cpp @@ -37,19 +37,19 @@ void AudioSettings::create() { frequencySlider.onChange = [this] { config.audio.inputFrequency = frequencySlider.position() + 31000; - dspaudio.set_frequency(config.audio.inputFrequency); + dspaudio.setFrequency(config.audio.inputFrequency); frequencyValue.setText({ config.audio.inputFrequency, "hz" }); }; volumeSlider.onChange = [this] { config.audio.volume = volumeSlider.position(); - dspaudio.set_volume((double)config.audio.volume / 100.0); + dspaudio.setVolume((double)config.audio.volume / 100.0); volumeValue.setText({ config.audio.volume, "%" }); }; balanceSlider.onChange = [this] { config.audio.balance = balanceSlider.position(); - dspaudio.set_balance((double)((signed)config.audio.balance - 100) / 100.0); + dspaudio.setBalance((double)((signed)config.audio.balance - 100) / 100.0); balanceValue.setText({ (signed)config.audio.balance - 100 }); }; diff --git a/snesfilter/HQ2x/HQ2x.cpp b/snesfilter/HQ2x/HQ2x.cpp index 08aec9b2..f4662b6d 100755 --- a/snesfilter/HQ2x/HQ2x.cpp +++ b/snesfilter/HQ2x/HQ2x.cpp @@ -51,7 +51,7 @@ static void initialize() { double g = (G << 3) | (G >> 2); double b = (B << 3) | (B >> 2); - //bgr888->yuv888 + //bgr888->yuv double y = (r + g + b) * (0.25f * (63.5f / 48.0f)); double u = ((r - b) * 0.25f + 128.0f) * (7.5f / 7.0f); double v = ((g * 2.0f - r - b) * 0.125f + 128.0f) * (7.5f / 6.0f); @@ -59,6 +59,10 @@ static void initialize() { yuvTable[i] = ((unsigned)y << 21) + ((unsigned)u << 11) + ((unsigned)v); } + //counter-clockwise rotation table; one revolution: + //123 369 12346789 + //4.6 -> 2.8 = + //789 147 36928147 for(unsigned n = 0; n < 256; n++) { rotate[n] = ((n >> 2) & 0x11) | ((n << 2) & 0x88) | ((n & 0x01) << 5) | ((n & 0x08) << 3) @@ -83,8 +87,7 @@ static uint16_t pack(uint32_t n) { n &= 0x03e07c1f; return n | (n >> 16); } static uint16_t blend1(uint32_t A, uint32_t B) { grow(A); grow(B); - A = (A * 3 + B) >> 2; - return pack(A); + return pack((A * 3 + B) >> 2); } static uint16_t blend2(uint32_t A, uint32_t B, uint32_t C) { diff --git a/snespurify/cc-gtk.sh b/snespurify/cc-gtk.sh index 30b4e71a..d5724b6f 100755 --- a/snespurify/cc-gtk.sh +++ b/snespurify/cc-gtk.sh @@ -1,4 +1,4 @@ g++-4.5 -std=gnu++0x -I. -O3 -fomit-frame-pointer -c phoenix/phoenix.cpp `pkg-config --cflags gtk+-2.0` -DPHOENIX_GTK -g++-4.5 -std=gnu++0x -I. -O3 -fomit-frame-pointer -c snespurify.cpp -DPHOENIX_GTK +g++-4.5 -std=gnu++0x -I. -O3 -fomit-frame-pointer -c snespurify.cpp g++-4.5 -s -o snespurify-gtk snespurify.o phoenix.o `pkg-config --libs gtk+-2.0` -lX11 rm *.o diff --git a/snespurify/cc-qt.sh b/snespurify/cc-qt.sh index 6a063a4f..fd25e7d1 100755 --- a/snespurify/cc-qt.sh +++ b/snespurify/cc-qt.sh @@ -1,5 +1,5 @@ moc -i -o phoenix/qt/qt.moc phoenix/qt/qt.moc.hpp g++-4.5 -std=gnu++0x -I. -O3 -fomit-frame-pointer -c phoenix/phoenix.cpp `pkg-config --cflags QtCore QtGui` -DPHOENIX_QT -g++-4.5 -std=gnu++0x -I. -O3 -fomit-frame-pointer -c snespurify.cpp -DPHOENIX_QT +g++-4.5 -std=gnu++0x -I. -O3 -fomit-frame-pointer -c snespurify.cpp g++-4.5 -s -o snespurify-qt snespurify.o phoenix.o `pkg-config --libs QtCore QtGui` rm *.o diff --git a/snespurify/cc-windows.bat b/snespurify/cc-windows.bat index 72d3af6f..992e70e2 100755 --- a/snespurify/cc-windows.bat +++ b/snespurify/cc-windows.bat @@ -1,6 +1,6 @@ -windres phoenix/windows/phoenix.rc phoenix-resource.o -g++ -std=gnu++0x -I. -O3 -fomit-frame-pointer -c phoenix/phoenix.cpp -DPHOENIX_WINDOWS -g++ -std=gnu++0x -I. -O3 -fomit-frame-pointer -c snespurify.cpp -DPHOENIX_WINDOWS -g++ -mwindows -s -o snespurify snespurify.o phoenix.o phoenix-resource.o -lkernel32 -luser32 -lgdi32 -ladvapi32 -lcomctl32 -lcomdlg32 -lshell32 -lole32 -@pause -@del *.o +windres phoenix/windows/phoenix.rc phoenix-resource.o +g++ -std=gnu++0x -I. -O3 -fomit-frame-pointer -c phoenix/phoenix.cpp -DPHOENIX_WINDOWS +g++ -std=gnu++0x -I. -O3 -fomit-frame-pointer -c snespurify.cpp +g++ -mwindows -s -o snespurify snespurify.o phoenix.o phoenix-resource.o -lkernel32 -luser32 -lgdi32 -ladvapi32 -lcomctl32 -lcomdlg32 -lshell32 -lole32 +@pause +@del *.o diff --git a/snespurify/nall/array.hpp b/snespurify/nall/array.hpp index 9cfe7758..e1fb1fcb 100755 --- a/snespurify/nall/array.hpp +++ b/snespurify/nall/array.hpp @@ -54,6 +54,10 @@ namespace nall { operator[](buffersize) = data; } + void remove() { + if(size > 0) resize(size - 1); //remove last element only + } + template void insert(unsigned index, const U list) { unsigned listsize = container_size(list); resize(buffersize + listsize); @@ -133,6 +137,12 @@ namespace nall { if(index >= buffersize) throw "array[] out of bounds"; return pool[index]; } + + //iteration + T* begin() { return &pool[0]; } + T* end() { return &pool[buffersize]; } + const T* begin() const { return &pool[0]; } + const T* end() const { return &pool[buffersize]; } }; template struct has_size> { enum { value = true }; }; diff --git a/snespurify/nall/base64.hpp b/snespurify/nall/base64.hpp index e41c87b7..ee59c1be 100755 --- a/snespurify/nall/base64.hpp +++ b/snespurify/nall/base64.hpp @@ -72,6 +72,7 @@ namespace nall { private: static char enc(uint8_t n) { + //base64 for URL encodings static char lookup_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; return lookup_table[n & 63]; } diff --git a/snespurify/nall/bmp.hpp b/snespurify/nall/bmp.hpp new file mode 100755 index 00000000..33cdf4dc --- /dev/null +++ b/snespurify/nall/bmp.hpp @@ -0,0 +1,101 @@ +#ifndef NALL_BMP_HPP +#define NALL_BMP_HPP + +#include + +//BMP reader / writer +//author: byuu +//note: only 24-bit RGB and 32-bit ARGB uncompressed images supported + +namespace nall { + +struct bmp { + inline static bool read(const string &filename, uint32_t *&data, unsigned &width, unsigned &height); + inline static bool write(const string &filename, const uint32_t *data, unsigned width, unsigned height, unsigned pitch, bool alpha = false); +}; + +bool bmp::read(const string &filename, uint32_t *&data, unsigned &width, unsigned &height) { + file fp; + if(fp.open(filename, file::mode::read) == false) return false; + if(fp.size() < 0x36) return false; + + if(fp.readm(2) != 0x424d) return false; + fp.seek(0x000a); + unsigned offset = fp.readl(4); + unsigned dibsize = fp.readl(4); + if(dibsize != 40) return false; + signed headerWidth = fp.readl(4); + if(headerWidth < 0) return false; + signed headerHeight = fp.readl(4); + fp.readl(2); + unsigned bitsPerPixel = fp.readl(2); + if(bitsPerPixel != 24 && bitsPerPixel != 32) return false; + unsigned compression = fp.readl(4); + if(compression != 0) return false; + fp.seek(offset); + + bool noFlip = headerHeight < 0; + width = headerWidth, height = abs(headerHeight); + data = new uint32_t[width * height]; + + unsigned bytesPerPixel = bitsPerPixel / 8; + unsigned alignedWidth = width * bytesPerPixel; + unsigned paddingLength = 0; + while(alignedWidth % 4) alignedWidth++, paddingLength++; + + for(unsigned y = 0; y < height; y++) { + uint32_t *p = noFlip ? data + y * width : data + (height - 1 - y) * width; + for(unsigned x = 0; x < width; x++, p++) { + *p = fp.readl(bytesPerPixel); + if(bytesPerPixel == 3) *p |= 255 << 24; + } + if(paddingLength) fp.readl(paddingLength); + } + + fp.close(); + return true; +} + +bool bmp::write(const string &filename, const uint32_t *data, unsigned width, unsigned height, unsigned pitch, bool alpha) { + file fp; + if(fp.open(filename, file::mode::write) == false) return false; + + unsigned bitsPerPixel = alpha ? 32 : 24; + unsigned bytesPerPixel = bitsPerPixel / 8; + unsigned alignedWidth = width * bytesPerPixel; + unsigned paddingLength = 0; + unsigned imageSize = alignedWidth * height; + unsigned fileSize = 0x36 + imageSize; + while(alignedWidth % 4) alignedWidth++, paddingLength++; + + fp.writem(0x424d, 2); //signature + fp.writel(fileSize, 4); //file size + fp.writel(0, 2); //reserved + fp.writel(0, 2); //reserved + fp.writel(0x36, 4); //offset + + fp.writel(40, 4); //DIB size + fp.writel(width, 4); //width + fp.writel(-height, 4); //height + fp.writel(1, 2); //color planes + fp.writel(bitsPerPixel, 2); //bits per pixel + fp.writel(0, 4); //compression method (BI_RGB) + fp.writel(imageSize, 4); //image data size + fp.writel(3780, 4); //horizontal resolution + fp.writel(3780, 4); //vertical resolution + fp.writel(0, 4); //palette size + fp.writel(0, 4); //important color count + + for(unsigned y = 0; y < height; y++) { + const uint32_t *p = (const uint32_t*)((const uint8_t*)data + y * pitch); + for(unsigned x = 0; x < width; x++) fp.writel(*p++, bytesPerPixel); + if(paddingLength) fp.writel(0, paddingLength); + } + + fp.close(); + return true; +} + +} + +#endif diff --git a/snespurify/nall/bps/delta.hpp b/snespurify/nall/bps/delta.hpp new file mode 100755 index 00000000..a3af047c --- /dev/null +++ b/snespurify/nall/bps/delta.hpp @@ -0,0 +1,214 @@ +#ifndef NALL_BPS_DELTA_HPP +#define NALL_BPS_DELTA_HPP + +#include +#include +#include +#include +#include + +namespace nall { + +struct bpsdelta { + inline void source(const uint8_t *data, unsigned size); + inline void target(const uint8_t *data, unsigned size); + + inline bool source(const string &filename); + inline bool target(const string &filename); + inline bool create(const string &filename, const string &metadata = ""); + +protected: + enum : unsigned { SourceRead, TargetRead, SourceCopy, TargetCopy }; + enum : unsigned { Granularity = 1 }; + + struct Node { + unsigned offset; + Node *next; + inline Node() : offset(0), next(0) {} + inline ~Node() { if(next) delete next; } + }; + + filemap sourceFile; + const uint8_t *sourceData; + unsigned sourceSize; + + filemap targetFile; + const uint8_t *targetData; + unsigned targetSize; +}; + +void bpsdelta::source(const uint8_t *data, unsigned size) { + sourceData = data; + sourceSize = size; +} + +void bpsdelta::target(const uint8_t *data, unsigned size) { + targetData = data; + targetSize = size; +} + +bool bpsdelta::source(const string &filename) { + if(sourceFile.open(filename, filemap::mode::read) == false) return false; + source(sourceFile.data(), sourceFile.size()); + return true; +} + +bool bpsdelta::target(const string &filename) { + if(targetFile.open(filename, filemap::mode::read) == false) return false; + target(targetFile.data(), targetFile.size()); + return true; +} + +bool bpsdelta::create(const string &filename, const string &metadata) { + file modifyFile; + if(modifyFile.open(filename, file::mode::write) == false) return false; + + uint32_t sourceChecksum = ~0, modifyChecksum = ~0; + unsigned sourceRelativeOffset = 0, targetRelativeOffset = 0, outputOffset = 0; + + auto write = [&](uint8_t data) { + modifyFile.write(data); + modifyChecksum = crc32_adjust(modifyChecksum, data); + }; + + auto encode = [&](uint64_t data) { + while(true) { + uint64_t x = data & 0x7f; + data >>= 7; + if(data == 0) { + write(0x80 | x); + break; + } + write(x); + data--; + } + }; + + write('B'); + write('P'); + write('S'); + write('1'); + + encode(sourceSize); + encode(targetSize); + + unsigned markupSize = metadata.length(); + encode(markupSize); + for(unsigned n = 0; n < markupSize; n++) write(metadata[n]); + + Node *sourceTree[65536], *targetTree[65536]; + for(unsigned n = 0; n < 65536; n++) sourceTree[n] = 0, targetTree[n] = 0; + + //source tree creation + for(unsigned offset = 0; offset < sourceSize; offset++) { + uint16_t symbol = sourceData[offset + 0]; + sourceChecksum = crc32_adjust(sourceChecksum, symbol); + if(offset < sourceSize - 1) symbol |= sourceData[offset + 1] << 8; + Node *node = new Node; + node->offset = offset; + node->next = sourceTree[symbol]; + sourceTree[symbol] = node; + } + + unsigned targetReadLength = 0; + + auto targetReadFlush = [&]() { + if(targetReadLength) { + encode(TargetRead | ((targetReadLength - 1) << 2)); + unsigned offset = outputOffset - targetReadLength; + while(targetReadLength) write(targetData[offset++]), targetReadLength--; + } + }; + + while(outputOffset < targetSize) { + unsigned maxLength = 0, maxOffset = 0, mode = TargetRead; + + uint16_t symbol = targetData[outputOffset + 0]; + if(outputOffset < targetSize - 1) symbol |= targetData[outputOffset + 1] << 8; + + { //source read + unsigned length = 0, offset = outputOffset; + while(offset < sourceSize && offset < targetSize && sourceData[offset] == targetData[offset]) { + length++; + offset++; + } + if(length > maxLength) maxLength = length, mode = SourceRead; + } + + { //source copy + Node *node = sourceTree[symbol]; + while(node) { + unsigned length = 0, x = node->offset, y = outputOffset; + while(x < sourceSize && y < targetSize && sourceData[x++] == targetData[y++]) length++; + if(length > maxLength) maxLength = length, maxOffset = node->offset, mode = SourceCopy; + node = node->next; + } + } + + { //target copy + Node *node = targetTree[symbol]; + while(node) { + unsigned length = 0, x = node->offset, y = outputOffset; + while(y < targetSize && targetData[x++] == targetData[y++]) length++; + if(length > maxLength) maxLength = length, maxOffset = node->offset, mode = TargetCopy; + node = node->next; + } + + //target tree append + node = new Node; + node->offset = outputOffset; + node->next = targetTree[symbol]; + targetTree[symbol] = node; + } + + { //target read + if(maxLength < 4) { + maxLength = min((unsigned)Granularity, targetSize - outputOffset); + mode = TargetRead; + } + } + + if(mode != TargetRead) targetReadFlush(); + + switch(mode) { + case SourceRead: + encode(SourceRead | ((maxLength - 1) << 2)); + break; + case TargetRead: + //delay write to group sequential TargetRead commands into one + targetReadLength += maxLength; + break; + case SourceCopy: + case TargetCopy: + encode(mode | ((maxLength - 1) << 2)); + signed relativeOffset; + if(mode == SourceCopy) { + relativeOffset = maxOffset - sourceRelativeOffset; + sourceRelativeOffset = maxOffset + maxLength; + } else { + relativeOffset = maxOffset - targetRelativeOffset; + targetRelativeOffset = maxOffset + maxLength; + } + encode((relativeOffset < 0) | (abs(relativeOffset) << 1)); + break; + } + + outputOffset += maxLength; + } + + targetReadFlush(); + + sourceChecksum = ~sourceChecksum; + for(unsigned n = 0; n < 32; n += 8) write(sourceChecksum >> n); + uint32_t targetChecksum = crc32_calculate(targetData, targetSize); + for(unsigned n = 0; n < 32; n += 8) write(targetChecksum >> n); + uint32_t outputChecksum = ~modifyChecksum; + for(unsigned n = 0; n < 32; n += 8) write(outputChecksum >> n); + + modifyFile.close(); + return true; +} + +} + +#endif diff --git a/snespurify/nall/bps/linear.hpp b/snespurify/nall/bps/linear.hpp new file mode 100755 index 00000000..df840283 --- /dev/null +++ b/snespurify/nall/bps/linear.hpp @@ -0,0 +1,152 @@ +#ifndef NALL_BPS_LINEAR_HPP +#define NALL_BPS_LINEAR_HPP + +#include +#include +#include +#include +#include + +namespace nall { + +struct bpslinear { + inline void source(const uint8_t *data, unsigned size); + inline void target(const uint8_t *data, unsigned size); + + inline bool source(const string &filename); + inline bool target(const string &filename); + inline bool create(const string &filename, const string &metadata = ""); + +protected: + enum : unsigned { SourceRead, TargetRead, SourceCopy, TargetCopy }; + enum : unsigned { Granularity = 1 }; + + filemap sourceFile; + const uint8_t *sourceData; + unsigned sourceSize; + + filemap targetFile; + const uint8_t *targetData; + unsigned targetSize; +}; + +void bpslinear::source(const uint8_t *data, unsigned size) { + sourceData = data; + sourceSize = size; +} + +void bpslinear::target(const uint8_t *data, unsigned size) { + targetData = data; + targetSize = size; +} + +bool bpslinear::source(const string &filename) { + if(sourceFile.open(filename, filemap::mode::read) == false) return false; + source(sourceFile.data(), sourceFile.size()); + return true; +} + +bool bpslinear::target(const string &filename) { + if(targetFile.open(filename, filemap::mode::read) == false) return false; + target(targetFile.data(), targetFile.size()); + return true; +} + +bool bpslinear::create(const string &filename, const string &metadata) { + file modifyFile; + if(modifyFile.open(filename, file::mode::write) == false) return false; + + uint32_t modifyChecksum = ~0; + unsigned targetRelativeOffset = 0, outputOffset = 0; + + auto write = [&](uint8_t data) { + modifyFile.write(data); + modifyChecksum = crc32_adjust(modifyChecksum, data); + }; + + auto encode = [&](uint64_t data) { + while(true) { + uint64_t x = data & 0x7f; + data >>= 7; + if(data == 0) { + write(0x80 | x); + break; + } + write(x); + data--; + } + }; + + unsigned targetReadLength = 0; + + auto targetReadFlush = [&]() { + if(targetReadLength) { + encode(TargetRead | ((targetReadLength - 1) << 2)); + unsigned offset = outputOffset - targetReadLength; + while(targetReadLength) write(targetData[offset++]), targetReadLength--; + } + }; + + write('B'); + write('P'); + write('S'); + write('1'); + + encode(sourceSize); + encode(targetSize); + + unsigned markupSize = metadata.length(); + encode(markupSize); + for(unsigned n = 0; n < markupSize; n++) write(metadata[n]); + + while(outputOffset < targetSize) { + unsigned sourceLength = 0; + for(unsigned n = 0; outputOffset + n < min(sourceSize, targetSize); n++) { + if(sourceData[outputOffset + n] != targetData[outputOffset + n]) break; + sourceLength++; + } + + unsigned rleLength = 0; + for(unsigned n = 1; outputOffset + n < targetSize; n++) { + if(targetData[outputOffset] != targetData[outputOffset + n]) break; + rleLength++; + } + + if(rleLength >= 4) { + //write byte to repeat + targetReadLength++; + outputOffset++; + targetReadFlush(); + + //copy starting from repetition byte + encode(TargetCopy | ((rleLength - 1) << 2)); + unsigned relativeOffset = (outputOffset - 1) - targetRelativeOffset; + encode(relativeOffset << 1); + outputOffset += rleLength; + targetRelativeOffset = outputOffset - 1; + } else if(sourceLength >= 4) { + targetReadFlush(); + encode(SourceRead | ((sourceLength - 1) << 2)); + outputOffset += sourceLength; + } else { + targetReadLength += Granularity; + outputOffset += Granularity; + } + } + + targetReadFlush(); + + uint32_t sourceChecksum = crc32_calculate(sourceData, sourceSize); + for(unsigned n = 0; n < 32; n += 8) write(sourceChecksum >> n); + uint32_t targetChecksum = crc32_calculate(targetData, targetSize); + for(unsigned n = 0; n < 32; n += 8) write(targetChecksum >> n); + uint32_t outputChecksum = ~modifyChecksum; + for(unsigned n = 0; n < 32; n += 8) write(outputChecksum >> n); + + modifyFile.close(); + return true; +} + +} + +#endif diff --git a/snespurify/nall/bps/metadata.hpp b/snespurify/nall/bps/metadata.hpp new file mode 100755 index 00000000..46759e6f --- /dev/null +++ b/snespurify/nall/bps/metadata.hpp @@ -0,0 +1,121 @@ +#ifndef NALL_BPS_METADATA_HPP +#define NALL_BPS_METADATA_HPP + +#include +#include +#include +#include +#include + +namespace nall { + +struct bpsmetadata { + inline bool load(const string &filename); + inline bool save(const string &filename, const string &metadata); + inline string metadata() const; + +protected: + file sourceFile; + string metadataString; +}; + +bool bpsmetadata::load(const string &filename) { + if(sourceFile.open(filename, file::mode::read) == false) return false; + + auto read = [&]() -> uint8_t { + return sourceFile.read(); + }; + + auto decode = [&]() -> uint64_t { + uint64_t data = 0, shift = 1; + while(true) { + uint8_t x = read(); + data += (x & 0x7f) * shift; + if(x & 0x80) break; + shift <<= 7; + data += shift; + } + return data; + }; + + if(read() != 'B') return false; + if(read() != 'P') return false; + if(read() != 'S') return false; + if(read() != '1') return false; + decode(); + decode(); + unsigned metadataSize = decode(); + char data[metadataSize + 1]; + for(unsigned n = 0; n < metadataSize; n++) data[n] = read(); + data[metadataSize] = 0; + metadataString = (const char*)data; + + return true; +} + +bool bpsmetadata::save(const string &filename, const string &metadata) { + file targetFile; + if(targetFile.open(filename, file::mode::write) == false) return false; + if(sourceFile.open() == false) return false; + sourceFile.seek(0); + + auto read = [&]() -> uint8_t { + return sourceFile.read(); + }; + + auto decode = [&]() -> uint64_t { + uint64_t data = 0, shift = 1; + while(true) { + uint8_t x = read(); + data += (x & 0x7f) * shift; + if(x & 0x80) break; + shift <<= 7; + data += shift; + } + return data; + }; + + uint32_t checksum = ~0; + + auto write = [&](uint8_t data) { + targetFile.write(data); + checksum = crc32_adjust(checksum, data); + }; + + auto encode = [&](uint64_t data) { + while(true) { + uint64_t x = data & 0x7f; + data >>= 7; + if(data == 0) { + write(0x80 | x); + break; + } + write(x); + data--; + } + }; + + for(unsigned n = 0; n < 4; n++) write(read()); + encode(decode()); + encode(decode()); + unsigned sourceLength = decode(); + unsigned targetLength = metadata.length(); + encode(targetLength); + sourceFile.seek(sourceLength, file::index::relative); + for(unsigned n = 0; n < targetLength; n++) write(metadata[n]); + unsigned length = sourceFile.size() - sourceFile.offset() - 4; + for(unsigned n = 0; n < length; n++) write(read()); + uint32_t outputChecksum = ~checksum; + for(unsigned n = 0; n < 32; n += 8) write(outputChecksum >> n); + + targetFile.close(); + return true; +} + +string bpsmetadata::metadata() const { + return metadataString; +} + +} + +#endif diff --git a/snespurify/nall/bps/patch.hpp b/snespurify/nall/bps/patch.hpp new file mode 100755 index 00000000..85c4dcae --- /dev/null +++ b/snespurify/nall/bps/patch.hpp @@ -0,0 +1,219 @@ +#ifndef NALL_BPS_PATCH_HPP +#define NALL_BPS_PATCH_HPP + +#include +#include +#include +#include +#include + +namespace nall { + +struct bpspatch { + inline bool modify(const uint8_t *data, unsigned size); + inline void source(const uint8_t *data, unsigned size); + inline void target(uint8_t *data, unsigned size); + + inline bool modify(const string &filename); + inline bool source(const string &filename); + inline bool target(const string &filename); + + inline string metadata() const; + inline unsigned size() const; + + enum result : unsigned { + unknown, + success, + patch_too_small, + patch_invalid_header, + source_too_small, + target_too_small, + source_checksum_invalid, + target_checksum_invalid, + patch_checksum_invalid, + }; + + inline result apply(); + +protected: + enum : unsigned { SourceRead, TargetRead, SourceCopy, TargetCopy }; + + filemap modifyFile; + const uint8_t *modifyData; + unsigned modifySize; + + filemap sourceFile; + const uint8_t *sourceData; + unsigned sourceSize; + + filemap targetFile; + uint8_t *targetData; + unsigned targetSize; + + unsigned modifySourceSize; + unsigned modifyTargetSize; + unsigned modifyMarkupSize; + string metadataString; +}; + +bool bpspatch::modify(const uint8_t *data, unsigned size) { + if(size < 19) return false; + modifyData = data; + modifySize = size; + + unsigned offset = 4; + auto decode = [&]() -> uint64_t { + uint64_t data = 0, shift = 1; + while(true) { + uint8_t x = modifyData[offset++]; + data += (x & 0x7f) * shift; + if(x & 0x80) break; + shift <<= 7; + data += shift; + } + return data; + }; + + modifySourceSize = decode(); + modifyTargetSize = decode(); + modifyMarkupSize = decode(); + + char buffer[modifyMarkupSize + 1]; + for(unsigned n = 0; n < modifyMarkupSize; n++) buffer[n] = modifyData[offset++]; + buffer[modifyMarkupSize] = 0; + metadataString = (const char*)buffer; + + return true; +} + +void bpspatch::source(const uint8_t *data, unsigned size) { + sourceData = data; + sourceSize = size; +} + +void bpspatch::target(uint8_t *data, unsigned size) { + targetData = data; + targetSize = size; +} + +bool bpspatch::modify(const string &filename) { + if(modifyFile.open(filename, filemap::mode::read) == false) return false; + return modify(modifyFile.data(), modifyFile.size()); +} + +bool bpspatch::source(const string &filename) { + if(sourceFile.open(filename, filemap::mode::read) == false) return false; + source(sourceFile.data(), sourceFile.size()); + return true; +} + +bool bpspatch::target(const string &filename) { + file fp; + if(fp.open(filename, file::mode::write) == false) return false; + fp.truncate(modifyTargetSize); + fp.close(); + + if(targetFile.open(filename, filemap::mode::readwrite) == false) return false; + target(targetFile.data(), targetFile.size()); + return true; +} + +string bpspatch::metadata() const { + return metadataString; +} + +unsigned bpspatch::size() const { + return modifyTargetSize; +} + +bpspatch::result bpspatch::apply() { + if(modifySize < 19) return result::patch_too_small; + + uint32_t modifyChecksum = ~0, targetChecksum = ~0; + unsigned modifyOffset = 0, sourceRelativeOffset = 0, targetRelativeOffset = 0, outputOffset = 0; + + auto read = [&]() -> uint8_t { + uint8_t data = modifyData[modifyOffset++]; + modifyChecksum = crc32_adjust(modifyChecksum, data); + return data; + }; + + auto decode = [&]() -> uint64_t { + uint64_t data = 0, shift = 1; + while(true) { + uint8_t x = read(); + data += (x & 0x7f) * shift; + if(x & 0x80) break; + shift <<= 7; + data += shift; + } + return data; + }; + + auto write = [&](uint8_t data) { + targetData[outputOffset++] = data; + targetChecksum = crc32_adjust(targetChecksum, data); + }; + + if(read() != 'B') return result::patch_invalid_header; + if(read() != 'P') return result::patch_invalid_header; + if(read() != 'S') return result::patch_invalid_header; + if(read() != '1') return result::patch_invalid_header; + + modifySourceSize = decode(); + modifyTargetSize = decode(); + modifyMarkupSize = decode(); + for(unsigned n = 0; n < modifyMarkupSize; n++) read(); + + if(modifySourceSize > sourceSize) return result::source_too_small; + if(modifyTargetSize > targetSize) return result::target_too_small; + + while(modifyOffset < modifySize - 12) { + unsigned length = decode(); + unsigned mode = length & 3; + length = (length >> 2) + 1; + + switch(mode) { + case SourceRead: + while(length--) write(sourceData[outputOffset]); + break; + case TargetRead: + while(length--) write(read()); + break; + case SourceCopy: + case TargetCopy: + signed offset = decode(); + bool negative = offset & 1; + offset >>= 1; + if(negative) offset = -offset; + + if(mode == SourceCopy) { + sourceRelativeOffset += offset; + while(length--) write(sourceData[sourceRelativeOffset++]); + } else { + targetRelativeOffset += offset; + while(length--) write(targetData[targetRelativeOffset++]); + } + break; + } + } + + uint32_t modifySourceChecksum = 0, modifyTargetChecksum = 0, modifyModifyChecksum = 0; + for(unsigned n = 0; n < 32; n += 8) modifySourceChecksum |= read() << n; + for(unsigned n = 0; n < 32; n += 8) modifyTargetChecksum |= read() << n; + uint32_t checksum = ~modifyChecksum; + for(unsigned n = 0; n < 32; n += 8) modifyModifyChecksum |= read() << n; + + uint32_t sourceChecksum = crc32_calculate(sourceData, modifySourceSize); + targetChecksum = ~targetChecksum; + + if(sourceChecksum != modifySourceChecksum) return result::source_checksum_invalid; + if(targetChecksum != modifyTargetChecksum) return result::target_checksum_invalid; + if(checksum != modifyModifyChecksum) return result::patch_checksum_invalid; + + return result::success; +} + +} + +#endif diff --git a/snespurify/nall/compositor.hpp b/snespurify/nall/compositor.hpp new file mode 100755 index 00000000..6d5c46c9 --- /dev/null +++ b/snespurify/nall/compositor.hpp @@ -0,0 +1,79 @@ +#ifndef NALL_COMPOSITOR_HPP +#define NALL_COMPOSITOR_HPP + +#include + +namespace nall { + +struct compositor { + inline static bool enabled(); + inline static bool enable(bool status); +}; + +#if defined(PLATFORM_X) + +bool compositor::enabled() { + FILE *fp = popen("xfconf-query -c xfwm4 -p '/general/use_compositing'", "r"); + if(fp == 0) return false; + + char buffer[512]; + if(fgets(buffer, sizeof buffer, fp) == 0) return false; + + if(!memcmp(buffer, "true", 4)) return true; + return false; +} + +bool compositor::enable(bool status) { + FILE *fp; + if(status) { + fp = popen("xfconf-query -c xfwm4 -p '/general/use_compositing' -t 'bool' -s 'true'", "r"); + } else { + fp = popen("xfconf-query -c xfwm4 -p '/general/use_compositing' -t 'bool' -s 'false'", "r"); + } + if(fp == 0) return false; + pclose(fp); + return true; +} + +#elif defined(PLATFORM_WIN) + +bool compositor::enabled() { + HMODULE module = GetModuleHandleW(L"dwmapi"); + if(module == 0) module = LoadLibraryW(L"dwmapi"); + if(module == 0) return false; + + auto pDwmIsCompositionEnabled = (HRESULT (WINAPI*)(BOOL*))GetProcAddress(module, "DwmIsCompositionEnabled"); + if(pDwmIsCompositionEnabled == 0) return false; + + BOOL result; + if(pDwmIsCompositionEnabled(&result) != S_OK) return false; + return result; +} + +bool compositor::enable(bool status) { + HMODULE module = GetModuleHandleW(L"dwmapi"); + if(module == 0) module = LoadLibraryW(L"dwmapi"); + if(module == 0) return false; + + auto pDwmEnableComposition = (HRESULT (WINAPI*)(UINT))GetProcAddress(module, "DwmEnableComposition"); + if(pDwmEnableComposition == 0) return false; + + if(pDwmEnableComposition(status) != S_OK) return false; + return true; +} + +#else + +bool compositor::enabled() { + return false; +} + +bool compositor::enable(bool) { + return false; +} + +#endif + +} + +#endif diff --git a/snespurify/nall/config.hpp b/snespurify/nall/config.hpp index b8381b16..99aaee08 100755 --- a/snespurify/nall/config.hpp +++ b/snespurify/nall/config.hpp @@ -34,11 +34,11 @@ namespace nall { string get() const { switch(type) { - case boolean_t: return string() << *(bool*)data; - case signed_t: return string() << *(signed*)data; - case unsigned_t: return string() << *(unsigned*)data; - case double_t: return string() << *(double*)data; - case string_t: return string() << "\"" << *(string*)data << "\""; + case boolean_t: return { *(bool*)data }; + case signed_t: return { *(signed*)data }; + case unsigned_t: return { *(unsigned*)data }; + case double_t: return { *(double*)data }; + case string_t: return { "\"", *(string*)data, "\"" }; } return "???"; } @@ -105,9 +105,9 @@ namespace nall { if(fp.open(filename, file::mode::write)) { for(unsigned i = 0; i < list.size(); i++) { string output; - output << list[i].name << " = " << list[i].get(); - if(list[i].desc != "") output << " # " << list[i].desc; - output << "\r\n"; + output.append(list[i].name, " = ", list[i].get()); + if(list[i].desc != "") output.append(" # ", list[i].desc); + output.append("\r\n"); fp.print(output); } diff --git a/snespurify/nall/dictionary.hpp b/snespurify/nall/dictionary.hpp deleted file mode 100755 index dcb04151..00000000 --- a/snespurify/nall/dictionary.hpp +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef NALL_DICTIONARY_HPP -#define NALL_DICTIONARY_HPP - -#include -#include -#include - -namespace nall { - class dictionary { - public: - string operator[](const char *input) { - for(unsigned i = 0; i < index_input.size(); i++) { - if(index_input[i] == input) return index_output[i]; - } - - //no match, use input; remove input identifier, if one exists - if(strbegin(input, "{{")) { - if(auto pos = strpos(input, "}}")) { - string temp = substr(input, pos() + 2); - return temp; - } - } - - return input; - } - - bool import(const char *filename) { - string data; - if(data.readfile(filename) == false) return false; - data.ltrim<1>("\xef\xbb\xbf"); //remove UTF-8 marker, if it exists - data.replace("\r", ""); - - lstring line; - line.split("\n", data); - for(unsigned i = 0; i < line.size(); i++) { - lstring part; - //format: "Input" = "Output" - part.qsplit("=", line[i]); - if(part.size() != 2) continue; - - //remove whitespace - part[0].trim(); - part[1].trim(); - - //remove quotes - part[0].trim<1>("\""); - part[1].trim<1>("\""); - - unsigned n = index_input.size(); - index_input[n] = part[0]; - index_output[n] = part[1]; - } - - return true; - } - - void reset() { - index_input.reset(); - index_output.reset(); - } - - ~dictionary() { - reset(); - } - - dictionary& operator=(const dictionary&) = delete; - dictionary(const dictionary&) = delete; - - protected: - lstring index_input; - lstring index_output; - }; -} - -#endif diff --git a/snespurify/nall/directory.hpp b/snespurify/nall/directory.hpp index c4f94c9a..7fbc15f4 100755 --- a/snespurify/nall/directory.hpp +++ b/snespurify/nall/directory.hpp @@ -6,7 +6,7 @@ #include #if defined(_WIN32) - #include + #include #else #include #include @@ -42,20 +42,21 @@ struct directory { if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) { if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { string name = (const char*)utf8_t(data.cFileName); - if(wildcard(name, pattern)) list.append(string(name, "/")); + if(wildcard(name, pattern)) list.append(name); } } while(FindNextFile(handle, &data) != false) { if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) { if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { string name = (const char*)utf8_t(data.cFileName); - if(wildcard(name, pattern)) list.append(string(name, "/")); + if(wildcard(name, pattern)) list.append(name); } } } FindClose(handle); } if(list.size() > 0) sort(&list[0], list.size()); + foreach(name, list) name.append("/"); //must append after sorting return list; } @@ -109,14 +110,14 @@ struct directory { if(!strcmp(ep->d_name, ".")) continue; if(!strcmp(ep->d_name, "..")) continue; if(ep->d_type & DT_DIR) { - if(wildcard(ep->d_name, pattern)) list.append(string(ep->d_name, "/")); + if(wildcard(ep->d_name, pattern)) list.append(ep->d_name); } } closedir(dp); } if(list.size() > 0) sort(&list[0], list.size()); + foreach(name, list) name.append("/"); //must append after sorting return list; - } inline lstring directory::files(const string &pathname, const string &pattern) { diff --git a/snespurify/nall/dl.hpp b/snespurify/nall/dl.hpp index ebfa5585..c697958c 100755 --- a/snespurify/nall/dl.hpp +++ b/snespurify/nall/dl.hpp @@ -12,7 +12,7 @@ #include #elif defined(PLATFORM_WIN) #include - #include + #include #endif namespace nall { diff --git a/snespurify/nall/dsp.hpp b/snespurify/nall/dsp.hpp new file mode 100755 index 00000000..009c8b6c --- /dev/null +++ b/snespurify/nall/dsp.hpp @@ -0,0 +1,8 @@ +#ifndef NALL_DSP_HPP +#define NALL_DSP_HPP + +#define NALL_DSP_INTERNAL_HPP +#include +#undef NALL_DSP_INTERNAL_HPP + +#endif diff --git a/snespurify/nall/dsp/buffer.hpp b/snespurify/nall/dsp/buffer.hpp new file mode 100755 index 00000000..c1b85b8d --- /dev/null +++ b/snespurify/nall/dsp/buffer.hpp @@ -0,0 +1,36 @@ +#ifdef NALL_DSP_INTERNAL_HPP + +struct Buffer { + double *sample[2]; + uint16_t rdoffset; + uint16_t wroffset; + + inline double& read(bool channel, signed offset = 0) { + return sample[channel][(uint16_t)(rdoffset + offset)]; + } + + inline double& write(bool channel, signed offset = 0) { + return sample[channel][(uint16_t)(wroffset + offset)]; + } + + inline void clear() { + for(unsigned n = 0; n < 65536; n++) { + sample[0][n] = 0; + sample[1][n] = 0; + } + rdoffset = 0; + wroffset = 0; + } + + Buffer() { + sample[0] = new double[65536]; + sample[1] = new double[65536]; + } + + ~Buffer() { + delete[] sample[0]; + delete[] sample[1]; + } +}; + +#endif diff --git a/snespurify/nall/dsp/core.hpp b/snespurify/nall/dsp/core.hpp new file mode 100755 index 00000000..bec46d93 --- /dev/null +++ b/snespurify/nall/dsp/core.hpp @@ -0,0 +1,154 @@ +#ifdef NALL_DSP_INTERNAL_HPP + +#include +#include + +namespace nall { + +struct DSP { + enum class Resampler : unsigned { + Point, + Linear, + Cosine, + Cubic, + Hermite, + Average, + }; + + inline void setPrecision(unsigned precision); + inline void setFrequency(double frequency); //inputFrequency + inline void setVolume(double volume); + inline void setBalance(double balance); + + inline void setResampler(Resampler resampler); + inline void setResamplerFrequency(double frequency); //outputFrequency + + inline void sample(signed lchannel, signed rchannel); + inline bool pending(); + inline void read(signed &lchannel, signed &rchannel); + + inline void clear(); + inline DSP(); + inline ~DSP(); + +protected: + struct Settings { + unsigned precision; + double frequency; + double volume; + double balance; + //internal + double intensity; + } settings; + + struct ResamplerSettings { + Resampler engine; + double frequency; + //internal + double fraction; + double step; + } resampler; + + inline void resamplerRun(); + inline void resamplerWrite(double lchannel, double rchannel); + + inline void resamplePoint(); + inline void resampleLinear(); + inline void resampleCosine(); + inline void resampleCubic(); + inline void resampleHermite(); + inline void resampleAverage(); + + #include "buffer.hpp" + Buffer buffer; + Buffer output; + + inline void adjustVolume(); + inline void adjustBalance(); + inline signed clamp(const unsigned bits, const signed x); +}; + +#include "settings.hpp" + +void DSP::sample(signed lchannel, signed rchannel) { + buffer.write(0) = (double)lchannel / settings.intensity; + buffer.write(1) = (double)rchannel / settings.intensity; + buffer.wroffset++; + resamplerRun(); +} + +bool DSP::pending() { + return output.rdoffset != output.wroffset; +} + +void DSP::read(signed &lchannel, signed &rchannel) { + adjustVolume(); + adjustBalance(); + + lchannel = clamp(settings.precision, output.read(0) * settings.intensity); + rchannel = clamp(settings.precision, output.read(1) * settings.intensity); + output.rdoffset++; +} + +void DSP::resamplerRun() { + switch(resampler.engine) { + case Resampler::Point: return resamplePoint(); + case Resampler::Linear: return resampleLinear(); + case Resampler::Cosine: return resampleCosine(); + case Resampler::Cubic: return resampleCubic(); + case Resampler::Hermite: return resampleHermite(); + case Resampler::Average: return resampleAverage(); + } +} + +void DSP::resamplerWrite(double lchannel, double rchannel) { + output.write(0) = lchannel; + output.write(1) = rchannel; + output.wroffset++; +} + +#include "resample/point.hpp" +#include "resample/linear.hpp" +#include "resample/cosine.hpp" +#include "resample/cubic.hpp" +#include "resample/hermite.hpp" +#include "resample/average.hpp" + +void DSP::adjustVolume() { + output.read(0) *= settings.volume; + output.read(1) *= settings.volume; +} + +void DSP::adjustBalance() { + if(settings.balance < 0.0) output.read(1) *= 1.0 + settings.balance; + if(settings.balance > 0.0) output.read(0) *= 1.0 - settings.balance; +} + +signed DSP::clamp(const unsigned bits, const signed x) { + const signed b = 1U << (bits - 1); + const signed m = (1U << (bits - 1)) - 1; + return (x > m) ? m : (x < -b) ? -b : x; +} + +void DSP::clear() { + resampler.fraction = 0.0; + buffer.clear(); + output.clear(); +} + +DSP::DSP() { + setPrecision(16); + setFrequency(44100.0); + setVolume(1.0); + setBalance(0.0); + setResampler(Resampler::Hermite); + setResamplerFrequency(44100.0); + clear(); +} + +DSP::~DSP() { +} + +} + +#endif diff --git a/snespurify/nall/dsp/resample/average.hpp b/snespurify/nall/dsp/resample/average.hpp new file mode 100755 index 00000000..ca97050e --- /dev/null +++ b/snespurify/nall/dsp/resample/average.hpp @@ -0,0 +1,28 @@ +#ifdef NALL_DSP_INTERNAL_HPP + +void DSP::resampleAverage() { + //can only average if input frequency >= output frequency + if(resampler.step < 1.0) return resampleHermite(); + + resampler.fraction += 1.0; + + double scalar = 1.0; + if(resampler.fraction > resampler.step) scalar = 1.0 - (resampler.fraction - resampler.step); + + output.write(0) += buffer.read(0) * scalar; + output.write(1) += buffer.read(1) * scalar; + + if(resampler.fraction >= resampler.step) { + output.write(0) /= resampler.step; + output.write(1) /= resampler.step; + output.wroffset++; + + resampler.fraction -= resampler.step; + output.write(0) = buffer.read(0) * resampler.fraction; + output.write(1) = buffer.read(1) * resampler.fraction; + } + + buffer.rdoffset++; +} + +#endif diff --git a/snespurify/nall/dsp/resample/cosine.hpp b/snespurify/nall/dsp/resample/cosine.hpp new file mode 100755 index 00000000..56fcf8fe --- /dev/null +++ b/snespurify/nall/dsp/resample/cosine.hpp @@ -0,0 +1,25 @@ +#ifdef NALL_DSP_INTERNAL_HPP + +void DSP::resampleCosine() { + while(resampler.fraction <= 1.0) { + double channel[2]; + + for(unsigned n = 0; n < 2; n++) { + double a = buffer.read(n, -1); + double b = buffer.read(n, -0); + + double mu = resampler.fraction; + mu = (1.0 - cos(mu * 3.14159265)) / 2.0; + + channel[n] = a * (1.0 - mu) + b * mu; + } + + resamplerWrite(channel[0], channel[1]); + resampler.fraction += resampler.step; + } + + buffer.rdoffset++; + resampler.fraction -= 1.0; +} + +#endif diff --git a/snespurify/nall/dsp/resample/cubic.hpp b/snespurify/nall/dsp/resample/cubic.hpp new file mode 100755 index 00000000..f975f6aa --- /dev/null +++ b/snespurify/nall/dsp/resample/cubic.hpp @@ -0,0 +1,31 @@ +#ifdef NALL_DSP_INTERNAL_HPP + +void DSP::resampleCubic() { + while(resampler.fraction <= 1.0) { + double channel[2]; + + for(unsigned n = 0; n < 2; n++) { + double a = buffer.read(n, -3); + double b = buffer.read(n, -2); + double c = buffer.read(n, -1); + double d = buffer.read(n, -0); + + double mu = resampler.fraction; + + double A = d - c - a + b; + double B = a - b - A; + double C = c - a; + double D = b; + + channel[n] = A * (mu * 3) + B * (mu * 2) + C * mu + D; + } + + resamplerWrite(channel[0], channel[1]); + resampler.fraction += resampler.step; + } + + buffer.rdoffset++; + resampler.fraction -= 1.0; +} + +#endif diff --git a/snespurify/nall/dsp/resample/hermite.hpp b/snespurify/nall/dsp/resample/hermite.hpp new file mode 100755 index 00000000..a042a55b --- /dev/null +++ b/snespurify/nall/dsp/resample/hermite.hpp @@ -0,0 +1,43 @@ +#ifdef NALL_DSP_INTERNAL_HPP + +void DSP::resampleHermite() { + while(resampler.fraction <= 1.0) { + double channel[2]; + + for(unsigned n = 0; n < 2; n++) { + double a = buffer.read(n, -3); + double b = buffer.read(n, -2); + double c = buffer.read(n, -1); + double d = buffer.read(n, -0); + + const double tension = 0.0; //-1 = low, 0 = normal, +1 = high + const double bias = 0.0; //-1 = left, 0 = even, +1 = right + + double mu1, mu2, mu3, m0, m1, a0, a1, a2, a3; + + mu1 = resampler.fraction; + mu2 = mu1 * mu1; + mu3 = mu2 * mu1; + + m0 = (b - a) * (1.0 + bias) * (1.0 - tension) / 2.0; + m0 += (c - b) * (1.0 - bias) * (1.0 - tension) / 2.0; + m1 = (c - b) * (1.0 + bias) * (1.0 - tension) / 2.0; + m1 += (d - c) * (1.0 - bias) * (1.0 - tension) / 2.0; + + a0 = +2 * mu3 - 3 * mu2 + 1; + a1 = mu3 - 2 * mu2 + mu1; + a2 = mu3 - mu2; + a3 = -2 * mu3 + 3 * mu2; + + channel[n] = (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c); + } + + resamplerWrite(channel[0], channel[1]); + resampler.fraction += resampler.step; + } + + buffer.rdoffset++; + resampler.fraction -= 1.0; +} + +#endif diff --git a/snespurify/nall/dsp/resample/linear.hpp b/snespurify/nall/dsp/resample/linear.hpp new file mode 100755 index 00000000..f4e48f57 --- /dev/null +++ b/snespurify/nall/dsp/resample/linear.hpp @@ -0,0 +1,24 @@ +#ifdef NALL_DSP_INTERNAL_HPP + +void DSP::resampleLinear() { + while(resampler.fraction <= 1.0) { + double channel[2]; + + for(unsigned n = 0; n < 2; n++) { + double a = buffer.read(n, -1); + double b = buffer.read(n, -0); + + double mu = resampler.fraction; + + channel[n] = a * (1.0 - mu) + b * mu; + } + + resamplerWrite(channel[0], channel[1]); + resampler.fraction += resampler.step; + } + + buffer.rdoffset++; + resampler.fraction -= 1.0; +} + +#endif diff --git a/snespurify/nall/dsp/resample/point.hpp b/snespurify/nall/dsp/resample/point.hpp new file mode 100755 index 00000000..51d35935 --- /dev/null +++ b/snespurify/nall/dsp/resample/point.hpp @@ -0,0 +1,24 @@ +#ifdef NALL_DSP_INTERNAL_HPP + +void DSP::resamplePoint() { + while(resampler.fraction <= 1.0) { + double channel[2]; + + for(unsigned n = 0; n < 2; n++) { + double a = buffer.read(n, -1); + double b = buffer.read(n, -0); + + double mu = resampler.fraction; + + channel[n] = mu < 0.5 ? a : b; + } + + resamplerWrite(channel[0], channel[1]); + resampler.fraction += resampler.step; + } + + buffer.rdoffset++; + resampler.fraction -= 1.0; +} + +#endif diff --git a/snespurify/nall/dsp/settings.hpp b/snespurify/nall/dsp/settings.hpp new file mode 100755 index 00000000..c7313d3d --- /dev/null +++ b/snespurify/nall/dsp/settings.hpp @@ -0,0 +1,32 @@ +#ifdef NALL_DSP_INTERNAL_HPP + +void DSP::setPrecision(unsigned precision) { + settings.precision = precision; + settings.intensity = 1 << (settings.precision - 1); +} + +void DSP::setFrequency(double frequency) { + settings.frequency = frequency; + resampler.fraction = 0; + resampler.step = settings.frequency / resampler.frequency; +} + +void DSP::setVolume(double volume) { + settings.volume = volume; +} + +void DSP::setBalance(double balance) { + settings.balance = balance; +} + +void DSP::setResampler(Resampler engine) { + resampler.engine = engine; +} + +void DSP::setResamplerFrequency(double frequency) { + resampler.frequency = frequency; + resampler.fraction = 0; + resampler.step = settings.frequency / resampler.frequency; +} + +#endif diff --git a/snespurify/nall/file.hpp b/snespurify/nall/file.hpp index 103c7d4a..40453448 100755 --- a/snespurify/nall/file.hpp +++ b/snespurify/nall/file.hpp @@ -1,22 +1,14 @@ #ifndef NALL_FILE_HPP #define NALL_FILE_HPP -#include -#include - -#if !defined(_WIN32) - #include -#else - #include -#endif - +#include #include #include -#include #include +#include namespace nall { - inline FILE* fopen_utf8(const char *utf8_filename, const char *mode) { + inline FILE* fopen_utf8(const string &utf8_filename, const char *mode) { #if !defined(_WIN32) return fopen(utf8_filename, mode); #else @@ -28,6 +20,29 @@ namespace nall { public: enum class mode : unsigned { read, write, readwrite, writeread }; enum class index : unsigned { absolute, relative }; + enum class time : unsigned { create, modify, access }; + + static bool read(const string &filename, uint8_t *&data, unsigned &size) { + file fp; + if(fp.open(filename, mode::read) == false) return false; + size = fp.size(); + data = new uint8_t[size]; + fp.read(data, size); + fp.close(); + return true; + } + + static bool read(const string &filename, const uint8_t *&data, unsigned &size) { + return file::read(filename, (uint8_t*&)data, size); + } + + static bool write(const string &filename, const uint8_t *data, unsigned size) { + file fp; + if(fp.open(filename, mode::write) == false) return false; + fp.write(data, size); + fp.close(); + return true; + } uint8_t read() { if(!fp) return 0xff; //file not open @@ -142,52 +157,60 @@ namespace nall { return file_offset >= file_size; } - static bool exists(const char *fn) { + static bool exists(const string &filename) { #if !defined(_WIN32) - FILE *fp = fopen(fn, "rb"); + struct stat64 data; + return stat64(filename, &data) == 0; #else - FILE *fp = _wfopen(utf16_t(fn), L"rb"); + struct __stat64 data; + return _wstat64(utf16_t(filename), &data) == 0; #endif - if(fp) { - fclose(fp); - return true; - } - return false; } - static unsigned size(const char *fn) { + static uintmax_t size(const string &filename) { #if !defined(_WIN32) - FILE *fp = fopen(fn, "rb"); + struct stat64 data; + stat64(filename, &data); #else - FILE *fp = _wfopen(utf16_t(fn), L"rb"); + struct __stat64 data; + _wstat64(utf16_t(filename), &data); #endif - unsigned filesize = 0; - if(fp) { - fseek(fp, 0, SEEK_END); - filesize = ftell(fp); - fclose(fp); + return S_ISREG(data.st_mode) ? data.st_size : 0u; + } + + static time_t timestamp(const string &filename, file::time mode = file::time::create) { + #if !defined(_WIN32) + struct stat64 data; + stat64(filename, &data); + #else + struct __stat64 data; + _wstat64(utf16_t(filename), &data); + #endif + switch(mode) { default: + case file::time::create: return data.st_ctime; + case file::time::modify: return data.st_mtime; + case file::time::access: return data.st_atime; } - return filesize; } bool open() { return fp; } - bool open(const char *fn, mode mode_) { + bool open(const string &filename, mode mode_) { if(fp) return false; switch(file_mode = mode_) { #if !defined(_WIN32) - case mode::read: fp = fopen(fn, "rb"); break; - case mode::write: fp = fopen(fn, "wb+"); break; //need read permission for buffering - case mode::readwrite: fp = fopen(fn, "rb+"); break; - case mode::writeread: fp = fopen(fn, "wb+"); break; + case mode::read: fp = fopen(filename, "rb" ); break; + case mode::write: fp = fopen(filename, "wb+"); break; //need read permission for buffering + case mode::readwrite: fp = fopen(filename, "rb+"); break; + case mode::writeread: fp = fopen(filename, "wb+"); break; #else - case mode::read: fp = _wfopen(utf16_t(fn), L"rb"); break; - case mode::write: fp = _wfopen(utf16_t(fn), L"wb+"); break; - case mode::readwrite: fp = _wfopen(utf16_t(fn), L"rb+"); break; - case mode::writeread: fp = _wfopen(utf16_t(fn), L"wb+"); break; + case mode::read: fp = _wfopen(utf16_t(filename), L"rb" ); break; + case mode::write: fp = _wfopen(utf16_t(filename), L"wb+"); break; + case mode::readwrite: fp = _wfopen(utf16_t(filename), L"rb+"); break; + case mode::writeread: fp = _wfopen(utf16_t(filename), L"wb+"); break; #endif } if(!fp) return false; diff --git a/snespurify/nall/filemap.hpp b/snespurify/nall/filemap.hpp index 5e8cc059..7eeac2b0 100755 --- a/snespurify/nall/filemap.hpp +++ b/snespurify/nall/filemap.hpp @@ -2,7 +2,7 @@ #define NALL_FILEMAP_HPP #include -#include +#include #include #include @@ -47,6 +47,12 @@ namespace nall { } bool p_open(const char *filename, mode mode_) { + if(file::exists(filename) && file::size(filename) == 0) { + p_handle = 0; + p_size = 0; + return true; + } + int desired_access, creation_disposition, flprotect, map_access; switch(mode_) { @@ -133,6 +139,12 @@ namespace nall { } bool p_open(const char *filename, mode mode_) { + if(file::exists(filename) && file::size(filename) == 0) { + p_handle = 0; + p_size = 0; + return true; + } + int open_flags, mmap_flags; switch(mode_) { diff --git a/snespurify/nall/gameboy/cartridge.hpp b/snespurify/nall/gameboy/cartridge.hpp index 0e1b28d8..af04e0bb 100755 --- a/snespurify/nall/gameboy/cartridge.hpp +++ b/snespurify/nall/gameboy/cartridge.hpp @@ -6,7 +6,7 @@ namespace nall { class GameBoyCartridge { public: string xml; - inline GameBoyCartridge(const uint8_t *data, unsigned size); + inline GameBoyCartridge(uint8_t *data, unsigned size); //private: struct Information { @@ -21,7 +21,7 @@ public: } info; }; -GameBoyCartridge::GameBoyCartridge(const uint8_t *romdata, unsigned romsize) { +GameBoyCartridge::GameBoyCartridge(uint8_t *romdata, unsigned romsize) { xml = "\n"; if(romsize < 0x4000) return; @@ -34,6 +34,20 @@ GameBoyCartridge::GameBoyCartridge(const uint8_t *romdata, unsigned romsize) { info.romsize = 0; info.ramsize = 0; + unsigned base = romsize - 0x8000; + if(romdata[base + 0x0104] == 0xce && romdata[base + 0x0105] == 0xed + && romdata[base + 0x0106] == 0x66 && romdata[base + 0x0107] == 0x66 + && romdata[base + 0x0108] == 0xcc && romdata[base + 0x0109] == 0x0d + && romdata[base + 0x0147] >= 0x0b && romdata[base + 0x0147] <= 0x0d + ) { + //MMM01 stores header at bottom of image + //flip this around for consistency with all other mappers + uint8_t header[0x8000]; + memcpy(header, romdata + base, 0x8000); + memmove(romdata + 0x8000, romdata, romsize - 0x8000); + memcpy(romdata, header, 0x8000); + } + switch(romdata[0x0147]) { case 0x00: info.mapper = "none"; break; case 0x01: info.mapper = "MBC1"; break; @@ -86,17 +100,17 @@ GameBoyCartridge::GameBoyCartridge(const uint8_t *romdata, unsigned romsize) { if(info.mapper == "MBC2") info.ramsize = 512; //512 x 4-bit - xml << "\n"; + xml.append("\n"); - xml << " \n"; //TODO: trust/check info.romsize? + xml.append(" \n"); //TODO: trust/check info.romsize? if(info.ramsize > 0) - xml << " \n"; + xml.append(" \n"); - xml << "\n"; + xml.append("\n"); xml.transform("'", "\""); } diff --git a/snespurify/nall/gzip.hpp b/snespurify/nall/gzip.hpp new file mode 100755 index 00000000..635d3277 --- /dev/null +++ b/snespurify/nall/gzip.hpp @@ -0,0 +1,87 @@ +#ifndef NALL_GZIP_HPP +#define NALL_GZIP_HPP + +#include +#include + +namespace nall { + +struct gzip { + string filename; + uint8_t *data; + unsigned size; + + bool decompress(const string &filename); + bool decompress(const uint8_t *data, unsigned size); + + gzip(); + ~gzip(); +}; + +bool gzip::decompress(const string &filename) { + uint8_t *data; + unsigned size; + if(file::read(filename, data, size) == false) return false; + bool result = decompress(data, size); + delete[] data; + return result; +} + +bool gzip::decompress(const uint8_t *data, unsigned size) { + if(size < 18) return false; + if(data[0] != 0x1f) return false; + if(data[1] != 0x8b) return false; + unsigned cm = data[2]; + unsigned flg = data[3]; + unsigned mtime = data[4]; + mtime |= data[5] << 8; + mtime |= data[6] << 16; + mtime |= data[7] << 24; + unsigned xfl = data[8]; + unsigned os = data[9]; + unsigned p = 10; + unsigned isize = data[size - 4]; + isize |= data[size - 3] << 8; + isize |= data[size - 2] << 16; + isize |= data[size - 1] << 24; + filename = ""; + + if(flg & 0x04) { //FEXTRA + unsigned xlen = data[p + 0]; + xlen |= data[p + 1] << 8; + p += 2 + xlen; + } + + if(flg & 0x08) { //FNAME + char buffer[PATH_MAX]; + for(unsigned n = 0; n < PATH_MAX; n++, p++) { + buffer[n] = data[p]; + if(data[p] == 0) break; + } + if(data[p++]) return false; + filename = buffer; + } + + if(flg & 0x10) { //FCOMMENT + while(data[p++]); + } + + if(flg & 0x02) { //FHCRC + p += 2; + } + + this->size = isize; + this->data = new uint8_t[this->size]; + return inflate(this->data, this->size, data + p, size - p - 8); +} + +gzip::gzip() : data(0) { +} + +gzip::~gzip() { + if(data) delete[] data; +} + +} + +#endif diff --git a/snespurify/nall/http.hpp b/snespurify/nall/http.hpp new file mode 100755 index 00000000..1b2eab4f --- /dev/null +++ b/snespurify/nall/http.hpp @@ -0,0 +1,176 @@ +#ifndef NALL_HTTP_HPP +#define NALL_HTTP_HPP + +#if !defined(_WIN32) + #include + #include + #include + #include +#else + #include + #include + #include +#endif + +#include +#include + +namespace nall { + +struct http { + string hostname; + addrinfo *serverinfo; + int serversocket; + string header; + + inline void download(const string &path, uint8_t *&data, unsigned &size) { + data = 0; + size = 0; + + send({ + "GET ", path, " HTTP/1.1\r\n" + "Host: ", hostname, "\r\n" + "Connection: close\r\n" + "\r\n" + }); + + header = downloadHeader(); + downloadContent(data, size); + } + + inline bool connect(string host, unsigned port) { + hostname = host; + + addrinfo hints; + memset(&hints, 0, sizeof(addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + + int status = getaddrinfo(hostname, string(port), &hints, &serverinfo); + if(status != 0) return false; + + serversocket = socket(serverinfo->ai_family, serverinfo->ai_socktype, serverinfo->ai_protocol); + if(serversocket == -1) return false; + + int result = ::connect(serversocket, serverinfo->ai_addr, serverinfo->ai_addrlen); + if(result == -1) return false; + + return true; + } + + inline bool send(const string &data) { + return send((const uint8_t*)(const char*)data, data.length()); + } + + inline bool send(const uint8_t *data, unsigned size) { + while(size) { + int length = ::send(serversocket, (const char*)data, size, 0); + if(length == -1) return false; + data += length; + size -= length; + } + return true; + } + + inline string downloadHeader() { + string output; + do { + char buffer[2]; + int length = recv(serversocket, buffer, 1, 0); + if(length <= 0) return output; + buffer[1] = 0; + output.append(buffer); + } while(output.endswith("\r\n\r\n") == false); + return output; + } + + inline string downloadChunkLength() { + string output; + do { + char buffer[2]; + int length = recv(serversocket, buffer, 1, 0); + if(length <= 0) return output; + buffer[1] = 0; + output.append(buffer); + } while(output.endswith("\r\n") == false); + return output; + } + + inline void downloadContent(uint8_t *&data, unsigned &size) { + unsigned capacity = 0; + + if(header.iposition("\r\nTransfer-Encoding: chunked\r\n")) { + while(true) { + unsigned length = hex(downloadChunkLength()); + if(length == 0) break; + capacity += length; + data = (uint8_t*)realloc(data, capacity); + + char buffer[length]; + while(length) { + int packetlength = recv(serversocket, buffer, length, 0); + if(packetlength <= 0) break; + memcpy(data + size, buffer, packetlength); + size += packetlength; + length -= packetlength; + } + } + } else if(auto position = header.iposition("\r\nContent-Length: ")) { + unsigned length = decimal((const char*)header + position() + 16); + while(length) { + char buffer[256]; + int packetlength = recv(serversocket, buffer, min(256, length), 0); + if(packetlength <= 0) break; + capacity += packetlength; + data = (uint8_t*)realloc(data, capacity); + memcpy(data + size, buffer, packetlength); + size += packetlength; + length -= packetlength; + } + } else { + while(true) { + char buffer[256]; + int packetlength = recv(serversocket, buffer, 256, 0); + if(packetlength <= 0) break; + capacity += packetlength; + data = (uint8_t*)realloc(data, capacity); + memcpy(data + size, buffer, packetlength); + size += packetlength; + } + } + + data = (uint8_t*)realloc(data, capacity + 1); + data[capacity] = 0; + } + + inline void disconnect() { + close(serversocket); + freeaddrinfo(serverinfo); + serverinfo = 0; + serversocket = -1; + } + + #ifdef _WIN32 + inline int close(int sock) { + return closesocket(sock); + } + + inline http() { + int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if(sock == INVALID_SOCKET && WSAGetLastError() == WSANOTINITIALISED) { + WSADATA wsaData; + if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { + WSACleanup(); + return; + } + } else { + close(sock); + } + } + #endif +}; + +} + +#endif diff --git a/snespurify/nall/inflate.hpp b/snespurify/nall/inflate.hpp new file mode 100755 index 00000000..c989e3f1 --- /dev/null +++ b/snespurify/nall/inflate.hpp @@ -0,0 +1,358 @@ +#ifndef NALL_INFLATE_HPP +#define NALL_INFLATE_HPP + +#include + +namespace nall { + +namespace puff { + inline int puff( + unsigned char *dest, unsigned long *destlen, + unsigned char *source, unsigned long *sourcelen + ); +} + +inline bool inflate( + uint8_t *target, unsigned targetLength, + const uint8_t *source, unsigned sourceLength +) { + unsigned long tl = targetLength, sl = sourceLength; + int result = puff::puff((unsigned char*)target, &tl, (unsigned char*)source, &sl); + return result == 0; +} + +namespace puff { + +//zlib/contrib/puff.c +//version 2.1* +//author: Mark Adler +//license: zlib +//ported by: byuu + +//* I have corrected a bug in fixed(), where it was accessing uninitialized +// memory: calling construct() with lencode prior to initializing lencode.count + +enum { + MAXBITS = 15, + MAXLCODES = 286, + MAXDCODES = 30, + FIXLCODES = 288, + MAXCODES = MAXLCODES + MAXDCODES, +}; + +struct state { + unsigned char *out; + unsigned long outlen; + unsigned long outcnt; + + unsigned char *in; + unsigned long inlen; + unsigned long incnt; + int bitbuf; + int bitcnt; + + jmp_buf env; +}; + +struct huffman { + short *count; + short *symbol; +}; + +inline int bits(state *s, int need) { + long val; + + val = s->bitbuf; + while(s->bitcnt < need) { + if(s->incnt == s->inlen) longjmp(s->env, 1); + val |= (long)(s->in[s->incnt++]) << s->bitcnt; + s->bitcnt += 8; + } + + s->bitbuf = (int)(val >> need); + s->bitcnt -= need; + + return (int)(val & ((1L << need) - 1)); +} + +inline int stored(state *s) { + unsigned len; + + s->bitbuf = 0; + s->bitcnt = 0; + + if(s->incnt + 4 > s->inlen) return 2; + len = s->in[s->incnt++]; + len |= s->in[s->incnt++] << 8; + if(s->in[s->incnt++] != (~len & 0xff) || + s->in[s->incnt++] != ((~len >> 8) & 0xff) + ) return 2; + + if(s->incnt + len > s->inlen) return 2; + if(s->out != 0) { + if(s->outcnt + len > s->outlen) return 1; + while(len--) s->out[s->outcnt++] = s->in[s->incnt++]; + } else { + s->outcnt += len; + s->incnt += len; + } + + return 0; +} + +inline int decode(state *s, huffman *h) { + int len, code, first, count, index, bitbuf, left; + short *next; + + bitbuf = s->bitbuf; + left = s->bitcnt; + code = first = index = 0; + len = 1; + next = h->count + 1; + while(true) { + while(left--) { + code |= bitbuf & 1; + bitbuf >>= 1; + count = *next++; + if(code - count < first) { + s->bitbuf = bitbuf; + s->bitcnt = (s->bitcnt - len) & 7; + return h->symbol[index + (code - first)]; + } + index += count; + first += count; + first <<= 1; + code <<= 1; + len++; + } + left = (MAXBITS + 1) - len; + if(left == 0) break; + if(s->incnt == s->inlen) longjmp(s->env, 1); + bitbuf = s->in[s->incnt++]; + if(left > 8) left = 8; + } + + return -10; +} + +inline int construct(huffman *h, short *length, int n) { + int symbol, len, left; + short offs[MAXBITS + 1]; + + for(len = 0; len <= MAXBITS; len++) h->count[len] = 0; + for(symbol = 0; symbol < n; symbol++) h->count[length[symbol]]++; + if(h->count[0] == n) return 0; + + left = 1; + for(len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= h->count[len]; + if(left < 0) return left; + } + + offs[1] = 0; + for(len = 1; len < MAXBITS; len++) offs[len + 1] = offs[len] + h->count[len]; + + for(symbol = 0; symbol < n; symbol++) { + if(length[symbol] != 0) h->symbol[offs[length[symbol]]++] = symbol; + } + + return left; +} + +inline int codes(state *s, huffman *lencode, huffman *distcode) { + int symbol, len; + unsigned dist; + static const short lens[29] = { + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258 + }; + static const short lext[29] = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 + }; + static const short dists[30] = { + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577 + }; + static const short dext[30] = { + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13 + }; + + do { + symbol = decode(s, lencode); + if(symbol < 0) return symbol; + if(symbol < 256) { + if(s->out != 0) { + if(s->outcnt == s->outlen) return 1; + s->out[s->outcnt] = symbol; + } + s->outcnt++; + } else if(symbol > 256) { + symbol -= 257; + if(symbol >= 29) return -10; + len = lens[symbol] + bits(s, lext[symbol]); + + symbol = decode(s, distcode); + if(symbol < 0) return symbol; + dist = dists[symbol] + bits(s, dext[symbol]); +#ifndef INFLATE_ALLOW_INVALID_DISTANCE_TOO_FAR + if(dist > s->outcnt) return -11; +#endif + + if(s->out != 0) { + if(s->outcnt + len > s->outlen) return 1; + while(len--) { + s->out[s->outcnt] = +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOO_FAR + dist > s->outcnt ? 0 : +#endif + s->out[s->outcnt - dist]; + s->outcnt++; + } + } else { + s->outcnt += len; + } + } + } while(symbol != 256); + + return 0; +} + +inline int fixed(state *s) { + static int virgin = 1; + static short lencnt[MAXBITS + 1], lensym[FIXLCODES]; + static short distcnt[MAXBITS + 1], distsym[MAXDCODES]; + static huffman lencode, distcode; + + if(virgin) { + int symbol = 0; + short lengths[FIXLCODES]; + + lencode.count = lencnt; + lencode.symbol = lensym; + distcode.count = distcnt; + distcode.symbol = distsym; + + for(; symbol < 144; symbol++) lengths[symbol] = 8; + for(; symbol < 256; symbol++) lengths[symbol] = 9; + for(; symbol < 280; symbol++) lengths[symbol] = 7; + for(; symbol < FIXLCODES; symbol++) lengths[symbol] = 8; + construct(&lencode, lengths, FIXLCODES); + + for(symbol = 0; symbol < MAXDCODES; symbol++) lengths[symbol] = 5; + construct(&distcode, lengths, MAXDCODES); + + virgin = 0; + } + + return codes(s, &lencode, &distcode); +} + +inline int dynamic(state *s) { + int nlen, ndist, ncode, index, err; + short lengths[MAXCODES]; + short lencnt[MAXBITS + 1], lensym[MAXLCODES]; + short distcnt[MAXBITS + 1], distsym[MAXDCODES]; + huffman lencode, distcode; + static const short order[19] = { + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 + }; + + lencode.count = lencnt; + lencode.symbol = lensym; + distcode.count = distcnt; + distcode.symbol = distsym; + + nlen = bits(s, 5) + 257; + ndist = bits(s, 5) + 1; + ncode = bits(s, 4) + 4; + if(nlen > MAXLCODES || ndist > MAXDCODES) return -3; + + for(index = 0; index < ncode; index++) lengths[order[index]] = bits(s, 3); + for(; index < 19; index++) lengths[order[index]] = 0; + + err = construct(&lencode, lengths, 19); + if(err != 0) return -4; + + index = 0; + while(index < nlen + ndist) { + int symbol, len; + + symbol = decode(s, &lencode); + if(symbol < 16) { + lengths[index++] = symbol; + } else { + len = 0; + if(symbol == 16) { + if(index == 0) return -5; + len = lengths[index - 1]; + symbol = 3 + bits(s, 2); + } else if(symbol == 17) { + symbol = 3 + bits(s, 3); + } else { + symbol = 11 + bits(s, 7); + } + if(index + symbol > nlen + ndist) return -6; + while(symbol--) lengths[index++] = len; + } + } + + if(lengths[256] == 0) return -9; + + err = construct(&lencode, lengths, nlen); + if(err < 0 || (err > 0 && nlen - lencode.count[0] != 1)) return -7; + + err = construct(&distcode, lengths + nlen, ndist); + if(err < 0 || (err > 0 && ndist - distcode.count[0] != 1)) return -8; + + return codes(s, &lencode, &distcode); +} + +inline int puff( + unsigned char *dest, unsigned long *destlen, + unsigned char *source, unsigned long *sourcelen +) { + state s; + int last, type, err; + + s.out = dest; + s.outlen = *destlen; + s.outcnt = 0; + + s.in = source; + s.inlen = *sourcelen; + s.incnt = 0; + s.bitbuf = 0; + s.bitcnt = 0; + + if(setjmp(s.env) != 0) { + err = 2; + } else { + do { + last = bits(&s, 1); + type = bits(&s, 2); + err = type == 0 ? stored(&s) + : type == 1 ? fixed(&s) + : type == 2 ? dynamic(&s) + : -1; + if(err != 0) break; + } while(!last); + } + + if(err <= 0) { + *destlen = s.outcnt; + *sourcelen = s.incnt; + } + + return err; +} + +} + +} + +#endif diff --git a/snespurify/nall/input.hpp b/snespurify/nall/input.hpp index 1fd680f4..cd765393 100755 --- a/snespurify/nall/input.hpp +++ b/snespurify/nall/input.hpp @@ -110,7 +110,7 @@ struct Keyboard { break; } } - return string() << "KB" << ID << "::" << KeyboardScancodeName[index]; + return { "KB", ID, "::", KeyboardScancodeName[index] }; } uint16_t operator[](Scancode code) const { return Base + ID * Size + code; } @@ -207,7 +207,7 @@ struct Mouse { break; } } - return string() << "MS" << ID << "::" << MouseScancodeName[index]; + return { "MS", ID, "::", MouseScancodeName[index] }; } uint16_t operator[](Scancode code) const { return Base + ID * Size + code; } @@ -330,7 +330,7 @@ struct Joypad { index = code - (Base + Size * i); } } - return string() << "JP" << ID << "::" << JoypadScancodeName[index]; + return { "JP", ID, "::", JoypadScancodeName[index] }; } uint16_t operator[](Scancode code) const { return Base + ID * Size + code; } diff --git a/snespurify/nall/ips.hpp b/snespurify/nall/ips.hpp new file mode 100755 index 00000000..87c7de25 --- /dev/null +++ b/snespurify/nall/ips.hpp @@ -0,0 +1,110 @@ +#ifndef NALL_IPS_HPP +#define NALL_IPS_HPP + +#include +#include +#include + +namespace nall { + +struct ips { + inline bool apply(); + inline void source(const uint8_t *data, unsigned size); + inline void modify(const uint8_t *data, unsigned size); + inline bool source(const string &filename); + inline bool modify(const string &filename); + inline ips(); + inline ~ips(); + + uint8_t *data; + unsigned size; + const uint8_t *sourceData; + unsigned sourceSize; + const uint8_t *modifyData; + unsigned modifySize; +}; + +bool ips::apply() { + if(modifySize < 8) return false; + if(modifyData[0] != 'P') return false; + if(modifyData[1] != 'A') return false; + if(modifyData[2] != 'T') return false; + if(modifyData[3] != 'C') return false; + if(modifyData[4] != 'H') return false; + + if(data) delete[] data; + data = new uint8_t[16 * 1024 * 1024 + 65536](); //maximum size of IPS patch + single-tag padding + size = sourceSize; + memcpy(data, sourceData, sourceSize); + unsigned offset = 5; + + while(true) { + unsigned address, length; + + if(offset > modifySize - 3) break; + address = modifyData[offset++] << 16; + address |= modifyData[offset++] << 8; + address |= modifyData[offset++] << 0; + + if(address == 0x454f46) { //EOF + if(offset == modifySize) return true; + if(offset == modifySize - 3) { + size = modifyData[offset++] << 16; + size |= modifyData[offset++] << 8; + size |= modifyData[offset++] << 0; + return true; + } + } + + if(offset > modifySize - 2) break; + length = modifyData[offset++] << 8; + length |= modifyData[offset++] << 0; + + if(length) { //Copy + if(offset > modifySize - length) break; + while(length--) data[address++] = modifyData[offset++]; + } else { //RLE + if(offset > modifySize - 3) break; + length = modifyData[offset++] << 8; + length |= modifyData[offset++] << 0; + if(length == 0) break; //illegal + while(length--) data[address++] = modifyData[offset]; + offset++; + } + + size = max(size, address); + } + + delete[] data; + data = 0; + return false; +} + +void ips::source(const uint8_t *data, unsigned size) { + sourceData = data, sourceSize = size; +} + +void ips::modify(const uint8_t *data, unsigned size) { + modifyData = data, modifySize = size; +} + +bool ips::source(const string &filename) { + return file::read(filename, sourceData, sourceSize); +} + +bool ips::modify(const string &filename) { + return file::read(filename, modifyData, modifySize); +} + +ips::ips() : data(0), sourceData(0), modifyData(0) { +} + +ips::~ips() { + if(data) delete[] data; + if(sourceData) delete[] sourceData; + if(modifyData) delete[] modifyData; +} + +} + +#endif diff --git a/snespurify/nall/lzss.hpp b/snespurify/nall/lzss.hpp index 202bc814..147e1e62 100755 --- a/snespurify/nall/lzss.hpp +++ b/snespurify/nall/lzss.hpp @@ -1,81 +1,165 @@ #ifndef NALL_LZSS_HPP #define NALL_LZSS_HPP -#include -#include +#include +#include #include +#include namespace nall { - class lzss { - public: - static bool encode(uint8_t *&output, unsigned &outlength, const uint8_t *input, unsigned inlength) { - output = new(zeromemory) uint8_t[inlength * 9 / 8 + 9]; - unsigned i = 0, o = 0; - while(i < inlength) { - unsigned flagoffset = o++; - uint8_t flag = 0x00; +//19:5 pulldown +//8:1 marker: d7-d0 +//length: { 4 - 35 }, offset: { 1 - 0x80000 } +//4-byte file size header +//little-endian encoding +struct lzss { + inline void source(const uint8_t *data, unsigned size); + inline bool source(const string &filename); + inline unsigned size() const; + inline bool compress(const string &filename); + inline bool decompress(uint8_t *targetData, unsigned targetSize); + inline bool decompress(const string &filename); - for(unsigned b = 0; b < 8 && i < inlength; b++) { - unsigned longest = 0, pointer; - for(unsigned index = 1; index < 4096; index++) { - unsigned count = 0; - while(true) { - if(count >= 15 + 3) break; //verify pattern match is not longer than max length - if(i + count >= inlength) break; //verify pattern match does not read past end of input - if(i + count < index) break; //verify read is not before start of input - if(input[i + count] != input[i + count - index]) break; //verify pattern still matches - count++; - } +protected: + struct Node { + unsigned offset; + Node *next; + inline Node() : offset(0), next(0) {} + inline ~Node() { if(next) delete next; } + } *tree[65536]; - if(count > longest) { - longest = count; - pointer = index; - } - } + filemap sourceFile; + const uint8_t *sourceData; + unsigned sourceSize; - if(longest < 3) output[o++] = input[i++]; - else { - flag |= 1 << b; - uint16_t x = ((longest - 3) << 12) + pointer; - output[o++] = x; - output[o++] = x >> 8; - i += longest; - } +public: + inline lzss() : sourceData(0), sourceSize(0) {} +}; + +void lzss::source(const uint8_t *data, unsigned size) { + sourceData = data; + sourceSize = size; +} + +bool lzss::source(const string &filename) { + if(sourceFile.open(filename, filemap::mode::read) == false) return false; + sourceData = sourceFile.data(); + sourceSize = sourceFile.size(); + return true; +} + +unsigned lzss::size() const { + unsigned size = 0; + if(sourceSize < 4) return size; + for(unsigned n = 0; n < 32; n += 8) size |= sourceData[n >> 3] << n; + return size; +} + +bool lzss::compress(const string &filename) { + file targetFile; + if(targetFile.open(filename, file::mode::write) == false) return false; + + for(unsigned n = 0; n < 32; n += 8) targetFile.write(sourceSize >> n); + for(unsigned n = 0; n < 65536; n++) tree[n] = 0; + + uint8_t buffer[25]; + unsigned sourceOffset = 0; + + while(sourceOffset < sourceSize) { + uint8_t mask = 0x00; + unsigned bufferOffset = 1; + + for(unsigned iteration = 0; iteration < 8; iteration++) { + if(sourceOffset >= sourceSize) break; + + uint16_t symbol = sourceData[sourceOffset + 0]; + if(sourceOffset < sourceSize - 1) symbol |= sourceData[sourceOffset + 1] << 8; + Node *node = tree[symbol]; + unsigned maxLength = 0, maxOffset = 0; + + while(node) { + if(node->offset < sourceOffset - 0x80000) { + //out-of-range: all subsequent nodes will also be, so free up their memory + if(node->next) { delete node->next; node->next = 0; } + break; } - output[flagoffset] = flag; + unsigned length = 0, x = sourceOffset, y = node->offset; + while(length < 35 && x < sourceSize && sourceData[x++] == sourceData[y++]) length++; + if(length > maxLength) maxLength = length, maxOffset = node->offset; + if(length == 35) break; + + node = node->next; } - outlength = o; - return true; - } + //attach current symbol to top of tree for subsequent searches + node = new Node; + node->offset = sourceOffset; + node->next = tree[symbol]; + tree[symbol] = node; - static bool decode(uint8_t *&output, const uint8_t *input, unsigned length) { - output = new(zeromemory) uint8_t[length]; - - unsigned i = 0, o = 0; - while(o < length) { - uint8_t flag = input[i++]; - - for(unsigned b = 0; b < 8 && o < length; b++) { - if(!(flag & (1 << b))) output[o++] = input[i++]; - else { - uint16_t offset = input[i++]; - offset += input[i++] << 8; - uint16_t lookuplength = (offset >> 12) + 3; - offset &= 4095; - for(unsigned index = 0; index < lookuplength && o + index < length; index++) { - output[o + index] = output[o + index - offset]; - } - o += lookuplength; - } - } + if(maxLength < 4) { + buffer[bufferOffset++] = sourceData[sourceOffset++]; + } else { + unsigned output = ((maxLength - 4) << 19) | (sourceOffset - 1 - maxOffset); + for(unsigned n = 0; n < 24; n += 8) buffer[bufferOffset++] = output >> n; + mask |= 0x80 >> iteration; + sourceOffset += maxLength; } - - return true; } - }; + + buffer[0] = mask; + targetFile.write(buffer, bufferOffset); + } + + sourceFile.close(); + targetFile.close(); + return true; +} + +bool lzss::decompress(uint8_t *targetData, unsigned targetSize) { + if(targetSize < size()) return false; + + unsigned sourceOffset = 4, targetOffset = 0; + while(sourceOffset < sourceSize) { + uint8_t mask = sourceData[sourceOffset++]; + + for(unsigned iteration = 0; iteration < 8; iteration++) { + if(sourceOffset >= sourceSize) break; + + if((mask & (0x80 >> iteration)) == 0) { + targetData[targetOffset++] = sourceData[sourceOffset++]; + } else { + unsigned code = 0; + for(unsigned n = 0; n < 24; n += 8) code |= sourceData[sourceOffset++] << n; + unsigned length = (code >> 19) + 4; + unsigned offset = targetOffset - 1 - (code & 0x7ffff); + while(length--) targetData[targetOffset++] = targetData[offset++]; + } + } + } +} + +bool lzss::decompress(const string &filename) { + if(sourceSize < 4) return false; + unsigned targetSize = size(); + + file fp; + if(fp.open(filename, file::mode::write) == false) return false; + fp.truncate(targetSize); + fp.close(); + + filemap targetFile; + if(targetFile.open(filename, filemap::mode::readwrite) == false) return false; + uint8_t *targetData = targetFile.data(); + + bool result = decompress(targetData, targetSize); + sourceFile.close(); + targetFile.close(); + return result; +} + } #endif diff --git a/snespurify/nall/platform.hpp b/snespurify/nall/platform.hpp index 72eeec09..8e7bb5fe 100755 --- a/snespurify/nall/platform.hpp +++ b/snespurify/nall/platform.hpp @@ -1,7 +1,12 @@ #ifndef NALL_PLATFORM_HPP #define NALL_PLATFORM_HPP -#include +#if defined(_WIN32) + //minimum version needed for _wstat64, etc + #undef __MSVCRT_VERSION__ + #define __MSVCRT_VERSION__ 0x0601 + #include +#endif //========================= //standard platform headers @@ -18,16 +23,19 @@ #include #include +#include +#include + #if defined(_WIN32) #include #include #include + #include #undef interface #define dllexport __declspec(dllexport) #else #include #include - #include #define dllexport #endif @@ -53,11 +61,11 @@ #if defined(_WIN32) #define getcwd _getcwd #define ftruncate _chsize - #define putenv _putenv #define mkdir(n, m) _wmkdir(nall::utf16_t(n)) + #define putenv _putenv #define rmdir _rmdir - #define vsnprintf _vsnprintf #define usleep(n) Sleep(n / 1000) + #define vsnprintf _vsnprintf #endif //================ @@ -87,6 +95,7 @@ wchar_t fn[_MAX_PATH] = L""; _wfullpath(fn, nall::utf16_t(filename), _MAX_PATH); strcpy(resolvedname, nall::utf8_t(fn)); + for(unsigned n = 0; resolvedname[n]; n++) if(resolvedname[n] == '\\') resolvedname[n] = '/'; return resolvedname; } @@ -94,6 +103,7 @@ wchar_t fp[_MAX_PATH] = L""; SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, fp); strcpy(path, nall::utf8_t(fp)); + for(unsigned n = 0; path[n]; n++) if(path[n] == '\\') path[n] = '/'; return path; } @@ -101,6 +111,7 @@ wchar_t fp[_MAX_PATH] = L""; _wgetcwd(fp, _MAX_PATH); strcpy(path, nall::utf8_t(fp)); + for(unsigned n = 0; path[n]; n++) if(path[n] == '\\') path[n] = '/'; return path; } #else diff --git a/snespurify/nall/png.hpp b/snespurify/nall/png.hpp new file mode 100755 index 00000000..ba6f05f8 --- /dev/null +++ b/snespurify/nall/png.hpp @@ -0,0 +1,423 @@ +#ifndef NALL_PNG_HPP +#define NALL_PNG_HPP + +//PNG image decoder +//author: byuu + +#include +#include + +namespace nall { + +struct png { + uint32_t *data; + unsigned size; + + struct Info { + unsigned width; + unsigned height; + unsigned bitDepth; + unsigned colorType; + unsigned compressionMethod; + unsigned filterType; + unsigned interlaceMethod; + + unsigned bytesPerPixel; + unsigned pitch; + + uint8_t palette[256][3]; + } info; + + uint8_t *rawData; + unsigned rawSize; + + inline bool decode(const string &filename); + inline bool decode(const uint8_t *sourceData, unsigned sourceSize); + inline void transform(); + inline void alphaTransform(uint32_t rgb = 0xffffff); + inline png(); + inline ~png(); + +protected: + enum class FourCC : unsigned { + IHDR = 0x49484452, + PLTE = 0x504c5445, + IDAT = 0x49444154, + IEND = 0x49454e44, + }; + + static const unsigned interlace[7][4]; + unsigned bitpos; + + inline unsigned inflateSize(); + inline bool deinterlace(const uint8_t *&inputData, unsigned pass); + inline bool filter(uint8_t *outputData, const uint8_t *inputData, unsigned width, unsigned height); + inline unsigned read(const uint8_t *data, unsigned length); + inline unsigned decode(const uint8_t *&data); + inline unsigned readbits(const uint8_t *&data); + inline unsigned scale(unsigned n); +}; + +bool png::decode(const string &filename) { + uint8_t *data; + unsigned size; + if(file::read(filename, data, size) == false) return false; + bool result = decode(data, size); + delete[] data; + return result; +} + +bool png::decode(const uint8_t *sourceData, unsigned sourceSize) { + if(sourceSize < 8) return false; + if(read(sourceData + 0, 4) != 0x89504e47) return false; + if(read(sourceData + 4, 4) != 0x0d0a1a0a) return false; + + uint8_t *compressedData = 0; + unsigned compressedSize = 0; + + unsigned offset = 8; + while(offset < sourceSize) { + unsigned length = read(sourceData + offset + 0, 4); + unsigned fourCC = read(sourceData + offset + 4, 4); + unsigned checksum = read(sourceData + offset + 8 + length, 4); + + if(fourCC == (unsigned)FourCC::IHDR) { + info.width = read(sourceData + offset + 8, 4); + info.height = read(sourceData + offset + 12, 4); + info.bitDepth = read(sourceData + offset + 16, 1); + info.colorType = read(sourceData + offset + 17, 1); + info.compressionMethod = read(sourceData + offset + 18, 1); + info.filterType = read(sourceData + offset + 19, 1); + info.interlaceMethod = read(sourceData + offset + 20, 1); + + if(info.bitDepth == 0 || info.bitDepth > 16) return false; + if(info.bitDepth & (info.bitDepth - 1)) return false; //not a power of two + if(info.compressionMethod != 0) return false; + if(info.filterType != 0) return false; + if(info.interlaceMethod != 0 && info.interlaceMethod != 1) return false; + + switch(info.colorType) { + case 0: info.bytesPerPixel = info.bitDepth * 1; break; //L + case 2: info.bytesPerPixel = info.bitDepth * 3; break; //R,G,B + case 3: info.bytesPerPixel = info.bitDepth * 1; break; //P + case 4: info.bytesPerPixel = info.bitDepth * 2; break; //L,A + case 6: info.bytesPerPixel = info.bitDepth * 4; break; //R,G,B,A + default: return false; + } + + if(info.colorType == 2 || info.colorType == 4 || info.colorType == 6) + if(info.bitDepth != 8 && info.bitDepth != 16) return false; + if(info.colorType == 3 && info.bitDepth == 16) return false; + + info.bytesPerPixel = (info.bytesPerPixel + 7) / 8; + info.pitch = (int)info.width * info.bytesPerPixel; + } + + if(fourCC == (unsigned)FourCC::PLTE) { + if(length % 3) return false; + for(unsigned n = 0, p = offset + 8; n < length / 3; n++) { + info.palette[n][0] = sourceData[p++]; + info.palette[n][1] = sourceData[p++]; + info.palette[n][2] = sourceData[p++]; + } + } + + if(fourCC == (unsigned)FourCC::IDAT) { + compressedData = (uint8_t*)realloc(compressedData, compressedSize + length); + memcpy(compressedData + compressedSize, sourceData + offset + 8, length); + compressedSize += length; + } + + if(fourCC == (unsigned)FourCC::IEND) { + break; + } + + offset += 4 + 4 + length + 4; + } + + unsigned interlacedSize = inflateSize(); + uint8_t *interlacedData = new uint8_t[interlacedSize]; + + bool result = inflate(interlacedData, interlacedSize, compressedData + 2, compressedSize - 6); + delete[] compressedData; + + if(result == false) { + delete[] interlacedData; + return false; + } + + rawSize = info.width * info.height * info.bytesPerPixel; + rawData = new uint8_t[rawSize]; + + if(info.interlaceMethod == 0) { + if(filter(rawData, interlacedData, info.width, info.height) == false) { + delete[] interlacedData; + delete[] rawData; + rawData = 0; + return false; + } + } else { + const uint8_t *passData = interlacedData; + for(unsigned pass = 0; pass < 7; pass++) { + if(deinterlace(passData, pass) == false) { + delete[] interlacedData; + delete[] rawData; + rawData = 0; + return false; + } + } + } + + delete[] interlacedData; + return true; +} + +const unsigned png::interlace[7][4] = { + //x-distance, y-distance, x-origin, y-origin + { 8, 8, 0, 0 }, + { 8, 8, 4, 0 }, + { 4, 8, 0, 4 }, + { 4, 4, 2, 0 }, + { 2, 4, 0, 2 }, + { 2, 2, 1, 0 }, + { 1, 2, 0, 1 }, +}; + +unsigned png::inflateSize() { + if(info.interlaceMethod == 0) { + return info.width * info.height * info.bytesPerPixel + info.height; + } + + unsigned size = 0; + for(unsigned pass = 0; pass < 7; pass++) { + unsigned xd = interlace[pass][0], yd = interlace[pass][1]; + unsigned xo = interlace[pass][2], yo = interlace[pass][3]; + unsigned width = (info.width + (xd - xo - 1)) / xd; + unsigned height = (info.height + (yd - yo - 1)) / yd; + if(width == 0 || height == 0) continue; + size += width * height * info.bytesPerPixel + height; + } + return size; +} + +bool png::deinterlace(const uint8_t *&inputData, unsigned pass) { + unsigned xd = interlace[pass][0], yd = interlace[pass][1]; + unsigned xo = interlace[pass][2], yo = interlace[pass][3]; + unsigned width = (info.width + (xd - xo - 1)) / xd; + unsigned height = (info.height + (yd - yo - 1)) / yd; + if(width == 0 || height == 0) return true; + + unsigned outputSize = width * height * info.bytesPerPixel; + uint8_t *outputData = new uint8_t[outputSize]; + bool result = filter(outputData, inputData, width, height); + + const uint8_t *rd = outputData; + for(unsigned y = yo; y < info.height; y += yd) { + uint8_t *wr = rawData + y * info.pitch; + for(unsigned x = xo; x < info.width; x += xd) { + for(unsigned b = 0; b < info.bytesPerPixel; b++) { + wr[x * info.bytesPerPixel + b] = *rd++; + } + } + } + + inputData += outputSize + height; + delete[] outputData; + return result; +} + +bool png::filter(uint8_t *outputData, const uint8_t *inputData, unsigned width, unsigned height) { + uint8_t *wr = outputData; + const uint8_t *rd = inputData; + int bpp = info.bytesPerPixel, pitch = width * bpp; + for(int y = 0; y < height; y++) { + uint8_t filter = *rd++; + + switch(filter) { + case 0x00: //None + for(int x = 0; x < pitch; x++) { + wr[x] = rd[x]; + } + break; + + case 0x01: //Subtract + for(int x = 0; x < pitch; x++) { + wr[x] = rd[x] + (x - bpp < 0 ? 0 : wr[x - bpp]); + } + break; + + case 0x02: //Above + for(int x = 0; x < pitch; x++) { + wr[x] = rd[x] + (y - 1 < 0 ? 0 : wr[x - pitch]); + } + break; + + case 0x03: //Average + for(int x = 0; x < pitch; x++) { + short a = x - bpp < 0 ? 0 : wr[x - bpp]; + short b = y - 1 < 0 ? 0 : wr[x - pitch]; + + wr[x] = rd[x] + (uint8_t)((a + b) / 2); + } + break; + + case 0x04: //Paeth + for(int x = 0; x < pitch; x++) { + short a = x - bpp < 0 ? 0 : wr[x - bpp]; + short b = y - 1 < 0 ? 0 : wr[x - pitch]; + short c = x - bpp < 0 || y - 1 < 0 ? 0 : wr[x - pitch - bpp]; + + short p = a + b - c; + short pa = p > a ? p - a : a - p; + short pb = p > b ? p - b : b - p; + short pc = p > c ? p - c : c - p; + + uint8_t paeth = (uint8_t)((pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c); + + wr[x] = rd[x] + paeth; + } + break; + + default: //Invalid + return false; + } + + rd += pitch; + wr += pitch; + } + + return true; +} + +unsigned png::read(const uint8_t *data, unsigned length) { + unsigned result = 0; + while(length--) result = (result << 8) | (*data++); + return result; +} + +unsigned png::decode(const uint8_t *&data) { + unsigned p, r, g, b, a; + + switch(info.colorType) { + case 0: //L + r = g = b = scale(readbits(data)); + a = 0xff; + break; + case 2: //R,G,B + r = scale(readbits(data)); + g = scale(readbits(data)); + b = scale(readbits(data)); + a = 0xff; + break; + case 3: //P + p = readbits(data); + r = info.palette[p][0]; + g = info.palette[p][1]; + b = info.palette[p][2]; + a = 0xff; + break; + case 4: //L,A + r = g = b = scale(readbits(data)); + a = scale(readbits(data)); + break; + case 6: //R,G,B,A + r = scale(readbits(data)); + g = scale(readbits(data)); + b = scale(readbits(data)); + a = scale(readbits(data)); + break; + } + + return (a << 24) | (r << 16) | (g << 8) | (b << 0); +} + +unsigned png::readbits(const uint8_t *&data) { + unsigned result = 0; + switch(info.bitDepth) { + case 1: + result = (*data >> bitpos) & 1; + bitpos++; + if(bitpos == 8) { data++; bitpos = 0; } + break; + case 2: + result = (*data >> bitpos) & 3; + bitpos += 2; + if(bitpos == 8) { data++; bitpos = 0; } + break; + case 4: + result = (*data >> bitpos) & 15; + bitpos += 4; + if(bitpos == 8) { data++; bitpos = 0; } + break; + case 8: + result = *data++; + break; + case 16: + result = (data[0] << 8) | (data[1] << 0); + data += 2; + break; + } + return result; +} + +unsigned png::scale(unsigned n) { + switch(info.bitDepth) { + case 1: return n ? 0xff : 0x00; + case 2: return n * 0x55; + case 4: return n * 0x11; + case 8: return n; + case 16: return n >> 8; + } + return 0; +} + +void png::transform() { + if(data) delete[] data; + data = new uint32_t[info.width * info.height]; + + bitpos = 0; + const uint8_t *rd = rawData; + for(unsigned y = 0; y < info.height; y++) { + uint32_t *wr = data + y * info.width; + for(unsigned x = 0; x < info.width; x++) { + wr[x] = decode(rd); + } + } +} + +void png::alphaTransform(uint32_t rgb) { + transform(); + + uint8_t ir = rgb >> 16; + uint8_t ig = rgb >> 8; + uint8_t ib = rgb >> 0; + + uint32_t *p = data; + for(unsigned y = 0; y < info.height; y++) { + for(unsigned x = 0; x < info.width; x++) { + uint32_t pixel = *p; + uint8_t a = pixel >> 24; + uint8_t r = pixel >> 16; + uint8_t g = pixel >> 8; + uint8_t b = pixel >> 0; + + r = (r * a) + (ir * (255 - a)) >> 8; + g = (g * a) + (ig * (255 - a)) >> 8; + b = (b * a) + (ib * (255 - a)) >> 8; + + *p++ = (255 << 24) | (r << 16) | (g << 8) | (b << 0); + } + } +} + +png::png() : data(0), rawData(0) { +} + +png::~png() { + if(data) delete[] data; + if(rawData) delete[] rawData; +} + +} + +#endif diff --git a/snespurify/nall/resource.hpp b/snespurify/nall/resource.hpp new file mode 100755 index 00000000..f8fd5153 --- /dev/null +++ b/snespurify/nall/resource.hpp @@ -0,0 +1,61 @@ +#ifndef NALL_RESOURCE_HPP +#define NALL_RESOURCE_HPP + +#include +#include + +namespace nall { + +struct resource { + //create resource with "zip -9 resource.zip resource" + static bool encode(const char *outputFilename, const char *inputFilename) { + file fp; + if(fp.open(inputFilename, file::mode::read) == false) return false; + unsigned size = fp.size(); + uint8_t *data = new uint8_t[size]; + fp.read(data, size); + fp.close(); + + fp.open(outputFilename, file::mode::write); + fp.print("static const uint8_t data[", size, "] = {\n"); + uint8_t *p = data; + while(size) { + fp.print(" "); + for(unsigned n = 0; n < 32 && size; n++, size--) { + fp.print((unsigned)*p++, ","); + } + fp.print("\n"); + } + fp.print("};\n"); + fp.close(); + + delete[] data; + } + + uint8_t *data; + unsigned size; + + //extract first file from ZIP archive + bool decode(const uint8_t *cdata, unsigned csize) { + if(data) delete[] data; + + zip archive; + if(archive.open(cdata, csize) == false) return false; + if(archive.file.size() == 0) return false; + bool result = archive.extract(archive.file[0], data, size); + archive.close(); + + return result; + } + + resource() : data(0), size(0) { + } + + ~resource() { + if(data) delete[] data; + } +}; + +} + +#endif diff --git a/snespurify/nall/sha256.hpp b/snespurify/nall/sha256.hpp index 7f41f04e..c63367a7 100755 --- a/snespurify/nall/sha256.hpp +++ b/snespurify/nall/sha256.hpp @@ -3,6 +3,8 @@ //author: vladitx +#include + namespace nall { #define PTR(t, a) ((t*)(a)) @@ -49,7 +51,7 @@ namespace nall { uint64_t len; }; - void sha256_init(sha256_ctx *p) { + inline void sha256_init(sha256_ctx *p) { memset(p, 0, sizeof(sha256_ctx)); memcpy(p->h, T_H, sizeof(T_H)); } @@ -90,7 +92,7 @@ namespace nall { p->inlen = 0; } - void sha256_chunk(sha256_ctx *p, const uint8_t *s, unsigned len) { + inline void sha256_chunk(sha256_ctx *p, const uint8_t *s, unsigned len) { unsigned l; p->len += len; @@ -107,7 +109,7 @@ namespace nall { } } - void sha256_final(sha256_ctx *p) { + inline void sha256_final(sha256_ctx *p) { uint64_t len; p->in[p->inlen++] = 0x80; @@ -124,7 +126,7 @@ namespace nall { sha256_block(p); } - void sha256_hash(sha256_ctx *p, uint8_t *s) { + inline void sha256_hash(sha256_ctx *p, uint8_t *s) { uint32_t *t = (uint32_t*)s; for(unsigned i = 0; i < 8; i++) ST32BE(t++, p->h[i]); } diff --git a/snespurify/nall/snes/cartridge.hpp b/snespurify/nall/snes/cartridge.hpp index e3c0e0c5..6847ba3a 100755 --- a/snespurify/nall/snes/cartridge.hpp +++ b/snespurify/nall/snes/cartridge.hpp @@ -111,422 +111,426 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) { string xml = "\n"; if(type == TypeBsx) { - xml << ""; + xml.append(""); xmlMemoryMap = xml.transform("'", "\""); return; } if(type == TypeSufamiTurbo) { - xml << ""; + xml.append(""); xmlMemoryMap = xml.transform("'", "\""); return; } if(type == TypeGameBoy) { - xml << "\n"; + xml.append("\n"); if(gameboy_ram_size(data, size) > 0) { - xml << " \n"; + xml.append(" \n"); } - xml << "\n"; + xml.append("\n"); xmlMemoryMap = xml.transform("'", "\""); return; } - xml << "\n"; + xml.append(">\n"); if(type == TypeSuperGameBoy1Bios) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); } else if(type == TypeSuperGameBoy2Bios) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + } else if(has_cx4) { + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); } else if(has_spc7110) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); if(has_spc7110rtc) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); } - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); } else if(mapper == LoROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); if(ram_size > 0) { - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); if((rom_size > 0x200000) || (ram_size > 32 * 1024)) { - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); } else { - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); } - xml << " \n"; + xml.append(" \n"); } } else if(mapper == HiROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); if(ram_size > 0) { - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); if((rom_size > 0x200000) || (ram_size > 32 * 1024)) { - xml << " \n"; + xml.append(" \n"); } else { - xml << " \n"; + xml.append(" \n"); } - xml << " \n"; + xml.append(" \n"); } } else if(mapper == ExLoROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); if(ram_size > 0) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); } } else if(mapper == ExHiROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); if(ram_size > 0) { - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); if((rom_size > 0x200000) || (ram_size > 32 * 1024)) { - xml << " \n"; + xml.append(" \n"); } else { - xml << " \n"; + xml.append(" \n"); } - xml << " \n"; + xml.append(" \n"); } } else if(mapper == SuperFXROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); } else if(mapper == SA1ROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); } else if(mapper == BSCLoROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); } else if(mapper == BSCHiROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); } else if(mapper == BSXROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); } else if(mapper == STROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); } if(has_srtc) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); } if(has_sdd1) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - - if(has_cx4) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); } if(has_dsp1) { - xml << " \n"; + xml.append(" \n"); if(dsp1_mapper == DSP1LoROM1MB) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); } else if(dsp1_mapper == DSP1LoROM2MB) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); } else if(dsp1_mapper == DSP1HiROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); } - xml << " \n"; + xml.append(" \n"); } if(has_dsp2) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); } if(has_dsp3) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); } if(has_dsp4) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); } if(has_obc1) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); } if(has_st010) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); } if(has_st011) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); } if(has_st018) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); + xml.append(" \n"); } - xml << "\n"; + xml.append("\n"); xmlMemoryMap = xml.transform("'", "\""); } diff --git a/snespurify/nall/stack.hpp b/snespurify/nall/stack.hpp new file mode 100755 index 00000000..a4aacfa7 --- /dev/null +++ b/snespurify/nall/stack.hpp @@ -0,0 +1,29 @@ +#ifndef NALL_STACK_HPP +#define NALL_STACK_HPP + +#include +#include + +namespace nall { + template struct stack : public linear_vector { + void push(const T &value) { + linear_vector::append(value); + } + + T pull() { + if(linear_vector::size() == 0) throw; + T value = linear_vector::operator[](linear_vector::size() - 1); + linear_vector::remove(linear_vector::size() - 1); + return value; + } + + T& operator()() { + if(linear_vector::size() == 0) throw; + return linear_vector::operator[](linear_vector::size() - 1); + } + }; + + template struct has_size> { enum { value = true }; }; +} + +#endif diff --git a/snespurify/nall/string.hpp b/snespurify/nall/string.hpp index 9acc2e9d..91bee596 100755 --- a/snespurify/nall/string.hpp +++ b/snespurify/nall/string.hpp @@ -2,7 +2,9 @@ #define NALL_STRING_HPP #include +#include #include +#include #include #include diff --git a/snespurify/nall/string/base.hpp b/snespurify/nall/string/base.hpp index f6172c26..ef331515 100755 --- a/snespurify/nall/string/base.hpp +++ b/snespurify/nall/string/base.hpp @@ -6,12 +6,14 @@ #include #include #include +#include #include -#include #include +#include namespace nall { class string; + class lstring; template inline const char* to_string(T); class string { @@ -20,13 +22,13 @@ namespace nall { template inline string& assign(Args&&... args); template inline string& append(Args&&... args); - inline string& assign_(const char*); - inline string& append_(const char*); inline bool readfile(const string&); - inline string& replace (const char*, const char*); - inline string& qreplace(const char*, const char*); + template inline string& replace(const char*, const char*); + template inline string& ireplace(const char*, const char*); + template inline string& qreplace(const char*, const char*); + template inline string& iqreplace(const char*, const char*); inline unsigned length() const; @@ -43,17 +45,18 @@ namespace nall { inline string& lower(); inline string& upper(); + inline string& qlower(); + inline string& qupper(); inline string& transform(const char *before, const char *after); template inline string& ltrim(const char *key = " "); template inline string& rtrim(const char *key = " "); - template inline string& trim (const char *key = " "); + template inline string& trim(const char *key = " ", const char *rkey = 0); inline optional position(const char *key) const; + inline optional iposition(const char *key) const; inline optional qposition(const char *key) const; - - template inline string& operator= (T value); - template inline string& operator<<(T value); + inline optional iqposition(const char *key) const; inline operator const char*() const; inline char* operator()(); @@ -74,10 +77,16 @@ namespace nall { inline string(string&&); inline ~string(); + //internal functions + inline string& assign_(const char*); + inline string& append_(const char*); + protected: char *data; unsigned size; + template inline string& ureplace(const char*, const char*); + #if defined(QSTRING_H) public: inline operator QString() const; @@ -89,36 +98,43 @@ namespace nall { template inline lstring& operator<<(T value); inline optional find(const char*) const; - template inline void split (const char*, const char*); - template inline void qsplit(const char*, const char*); + template inline lstring& split(const char*, const char*); + template inline lstring& isplit(const char*, const char*); + template inline lstring& qsplit(const char*, const char*); + template inline lstring& iqsplit(const char*, const char*); lstring(); lstring(std::initializer_list); + + protected: + template inline lstring& usplit(const char*, const char*); }; //compare.hpp inline char chrlower(char c); inline char chrupper(char c); - inline int stricmp(const char *str1, const char *str2); + inline int istrcmp(const char *str1, const char *str2); inline bool wildcard(const char *str, const char *pattern); inline bool iwildcard(const char *str, const char *pattern); - inline bool strbegin (const char *str, const char *key); - inline bool stribegin(const char *str, const char *key); - inline bool strend (const char *str, const char *key); - inline bool striend(const char *str, const char *key); + inline bool strbegin(const char *str, const char *key); + inline bool istrbegin(const char *str, const char *key); + inline bool strend(const char *str, const char *key); + inline bool istrend(const char *str, const char *key); //convert.hpp inline char* strlower(char *str); inline char* strupper(char *str); + inline char* qstrlower(char *str); + inline char* qstrupper(char *str); inline char* strtr(char *dest, const char *before, const char *after); - inline uintmax_t hex (const char *str); - inline intmax_t integer(const char *str); + inline uintmax_t hex(const char *str); + inline intmax_t integer(const char *str); inline uintmax_t decimal(const char *str); - inline uintmax_t binary (const char *str); - inline double fp (const char *str); + inline uintmax_t binary(const char *str); + inline double fp(const char *str); //math.hpp - inline bool strint (const char *str, int &result); + inline bool strint(const char *str, int &result); inline bool strmath(const char *str, int &result); //platform.hpp @@ -132,26 +148,31 @@ namespace nall { //strpos.hpp inline optional strpos(const char *str, const char *key); + inline optional istrpos(const char *str, const char *key); inline optional qstrpos(const char *str, const char *key); + inline optional iqstrpos(const char *str, const char *key); + template inline optional ustrpos(const char *str, const char *key); //trim.hpp template inline char* ltrim(char *str, const char *key = " "); template inline char* rtrim(char *str, const char *key = " "); - template inline char* trim (char *str, const char *key = " "); + template inline char* trim(char *str, const char *key = " ", const char *rkey = 0); //utility.hpp + template alwaysinline bool chrequal(char x, char y); + template alwaysinline bool quoteskip(T *&p); + template alwaysinline bool quotecopy(char *&t, T *&p); inline unsigned strlcpy(string &dest, const char *src, unsigned length); inline unsigned strlcat(string &dest, const char *src, unsigned length); - inline string substr(const char *src, unsigned start = 0, unsigned length = 0); + inline string substr(const char *src, unsigned start = 0, unsigned length = ~0u); + inline string sha256(const uint8_t *data, unsigned size); - inline string integer(intmax_t value); - template inline string linteger(intmax_t value); - template inline string rinteger(intmax_t value); - inline string decimal(uintmax_t value); - template inline string ldecimal(uintmax_t value); - template inline string rdecimal(uintmax_t value); - template inline string hex(uintmax_t value); - template inline string binary(uintmax_t value); + template inline string integer(intmax_t value); + template inline string linteger(intmax_t value); + template inline string decimal(uintmax_t value); + template inline string ldecimal(uintmax_t value); + template inline string hex(uintmax_t value); + template inline string binary(uintmax_t value); inline unsigned fp(char *str, double value); inline string fp(double value); diff --git a/snespurify/nall/string/cast.hpp b/snespurify/nall/string/cast.hpp index 14f005da..2d010bfa 100755 --- a/snespurify/nall/string/cast.hpp +++ b/snespurify/nall/string/cast.hpp @@ -6,16 +6,15 @@ namespace nall { //this is needed, as C++0x does not support explicit template specialization inside classes template<> inline const char* to_string (bool v) { return v ? "true" : "false"; } template<> inline const char* to_string (signed int v) { static char temp[256]; snprintf(temp, 255, "%+d", v); return temp; } -template<> inline const char* to_string (unsigned int v) { static char temp[256]; snprintf(temp, 255, "%u", v); return temp; } -template<> inline const char* to_string (double v) { static char temp[256]; snprintf(temp, 255, "%f", v); return temp; } +template<> inline const char* to_string (unsigned int v) { static char temp[256]; snprintf(temp, 255, "%u", v); return temp; } +template<> inline const char* to_string (intmax_t v) { static char temp[256]; snprintf(temp, 255, "%+lld", (long long)v); return temp; } +template<> inline const char* to_string (uintmax_t v) { static char temp[256]; snprintf(temp, 255, "%llu", (unsigned long long)v); return temp; } +template<> inline const char* to_string (double v) { static char temp[256]; snprintf(temp, 255, "%f", v); return temp; } template<> inline const char* to_string (char *v) { return v; } template<> inline const char* to_string (const char *v) { return v; } template<> inline const char* to_string (string v) { return v; } template<> inline const char* to_string(const string &v) { return v; } -template string& string::operator= (T value) { return assign(to_string(value)); } -template string& string::operator<<(T value) { return append(to_string(value)); } - template lstring& lstring::operator<<(T value) { operator[](size()).assign(to_string(value)); return *this; diff --git a/snespurify/nall/string/compare.hpp b/snespurify/nall/string/compare.hpp index bce0895b..ad311d74 100755 --- a/snespurify/nall/string/compare.hpp +++ b/snespurify/nall/string/compare.hpp @@ -11,7 +11,7 @@ char chrupper(char c) { return (c >= 'a' && c <= 'z') ? c - ('a' - 'A') : c; } -int stricmp(const char *str1, const char *str2) { +int istrcmp(const char *str1, const char *str2) { while(*str1) { if(chrlower(*str1) != chrlower(*str2)) break; str1++, str2++; @@ -66,7 +66,7 @@ bool strbegin(const char *str, const char *key) { return (!memcmp(str, key, ksl)); } -bool stribegin(const char *str, const char *key) { +bool istrbegin(const char *str, const char *key) { int ssl = strlen(str), ksl = strlen(key); if(ksl > ssl) return false; @@ -89,7 +89,7 @@ bool strend(const char *str, const char *key) { return (!memcmp(str + ssl - ksl, key, ksl)); } -bool striend(const char *str, const char *key) { +bool istrend(const char *str, const char *key) { int ssl = strlen(str), ksl = strlen(key); if(ksl > ssl) return false; diff --git a/snespurify/nall/string/convert.hpp b/snespurify/nall/string/convert.hpp index 603d2e0e..3dd487f6 100755 --- a/snespurify/nall/string/convert.hpp +++ b/snespurify/nall/string/convert.hpp @@ -23,6 +23,26 @@ char* strupper(char *str) { return str; } +char* qstrlower(char *s) { + if(!s) return 0; + bool quoted = false; + while(*s) { + if(*s == '\"' || *s == '\'') quoted ^= 1; + if(quoted == false && *s >= 'A' && *s <= 'Z') *s += 0x20; + s++; + } +} + +char* qstrupper(char *s) { + if(!s) return 0; + bool quoted = false; + while(*s) { + if(*s == '\"' || *s == '\'') quoted ^= 1; + if(quoted == false && *s >= 'a' && *s <= 'z') *s -= 0x20; + s++; + } +} + char* strtr(char *dest, const char *before, const char *after) { if(!dest || !before || !after) return dest; int sl = strlen(dest), bsl = strlen(before), asl = strlen(after); diff --git a/snespurify/nall/string/math.hpp b/snespurify/nall/string/math.hpp index ea8b99c8..d4bc9d25 100755 --- a/snespurify/nall/string/math.hpp +++ b/snespurify/nall/string/math.hpp @@ -3,6 +3,8 @@ namespace nall { +static function eval_fallback; + static int eval_integer(const char *&s) { if(!*s) throw "unrecognized_integer"; int value = 0, x = *s, y = *(s + 1); @@ -58,7 +60,7 @@ static int eval_integer(const char *&s) { } static int eval(const char *&s, int depth = 0) { - while(*s == ' ' || *s == '\t') s++; //trim whitespace + while(*s == ' ' || *s == '\t') s++; //trim whitespace if(!*s) throw "unrecognized_token"; int value = 0, x = *s, y = *(s + 1); @@ -74,10 +76,12 @@ static int eval(const char *&s, int depth = 0) { else if((x >= '0' && x <= '9') || x == '\'') value = eval_integer(s); + else if(eval_fallback) value = eval_fallback(s); //optional user-defined syntax parsing + else throw "unrecognized_token"; while(true) { - while(*s == ' ' || *s == '\t') s++; //trim whitespace + while(*s == ' ' || *s == '\t') s++; //trim whitespace if(!*s) break; x = *s, y = *(s + 1); diff --git a/snespurify/nall/string/replace.hpp b/snespurify/nall/string/replace.hpp index db405a9b..7c7a09d4 100755 --- a/snespurify/nall/string/replace.hpp +++ b/snespurify/nall/string/replace.hpp @@ -3,100 +3,49 @@ namespace nall { -string& string::replace(const char *key, const char *token) { - int i, z, ksl = strlen(key), tsl = strlen(token), ssl = length(); - unsigned int replace_count = 0, size = ssl; - char *buffer; +template +string& string::ureplace(const char *key, const char *token) { + if(!key || !*key) return *this; + enum : unsigned { limit = Limit ? Limit : ~0u }; - if(ksl <= ssl) { - if(tsl > ksl) { //the new string may be longer than the old string... - for(i = 0; i <= ssl - ksl;) { //so let's find out how big of a string we'll need... - if(!memcmp(data + i, key, ksl)) { - replace_count++; - i += ksl; - } else i++; - } - size = ssl + ((tsl - ksl) * replace_count); - reserve(size); + const char *p = data; + unsigned counter = 0, keyLength = 0; + + while(*p) { + if(quoteskip(p)) continue; + for(unsigned n = 0;; n++) { + if(key[n] == 0) { counter++; p += n; keyLength = n; break; } + if(!chrequal(key[n], p[n])) { p++; break; } } - - buffer = new char[size + 1]; - for(i = z = 0; i < ssl;) { - if(i <= ssl - ksl) { - if(!memcmp(data + i, key, ksl)) { - memcpy(buffer + z, token, tsl); - z += tsl; - i += ksl; - } else buffer[z++] = data[i++]; - } else buffer[z++] = data[i++]; - } - buffer[z] = 0; - - assign(buffer); - delete[] buffer; } + if(counter == 0) return *this; + if(Limit) counter = min(counter, Limit); + + char *t = data, *base; + unsigned tokenLength = strlen(token); + if(tokenLength > keyLength) { + t = base = strdup(data); + reserve((unsigned)(p - data) + ((tokenLength - keyLength) * counter)); + } + char *o = data; + + while(*t && counter) { + if(quotecopy(o, t)) continue; + for(unsigned n = 0;; n++) { + if(key[n] == 0) { counter--; memcpy(o, token, tokenLength); t += keyLength; o += tokenLength; break; } + if(!chrequal(key[n], t[n])) { *o++ = *t++; break; } + } + } + do *o++ = *t; while(*t++); + if(tokenLength > keyLength) free(base); return *this; } -string& string::qreplace(const char *key, const char *token) { - int i, l, z, ksl = strlen(key), tsl = strlen(token), ssl = length(); - unsigned int replace_count = 0, size = ssl; - uint8_t x; - char *buffer; - - if(ksl <= ssl) { - if(tsl > ksl) { - for(i = 0; i <= ssl - ksl;) { - x = data[i]; - if(x == '\"' || x == '\'') { - l = i; - i++; - while(data[i++] != x) { - if(i == ssl) { - i = l; - break; - } - } - } - if(!memcmp(data + i, key, ksl)) { - replace_count++; - i += ksl; - } else i++; - } - size = ssl + ((tsl - ksl) * replace_count); - reserve(size); - } - - buffer = new char[size + 1]; - for(i = z = 0; i < ssl;) { - x = data[i]; - if(x == '\"' || x == '\'') { - l = i++; - while(data[i] != x && i < ssl)i++; - if(i >= ssl)i = l; - else { - memcpy(buffer + z, data + l, i - l); - z += i - l; - } - } - if(i <= ssl - ksl) { - if(!memcmp(data + i, key, ksl)) { - memcpy(buffer + z, token, tsl); - z += tsl; - i += ksl; - replace_count++; - } else buffer[z++] = data[i++]; - } else buffer[z++] = data[i++]; - } - buffer[z] = 0; - - assign(buffer); - delete[] buffer; - } - - return *this; -} +template string &string::replace(const char *key, const char *token) { return ureplace(key, token); } +template string &string::ireplace(const char *key, const char *token) { return ureplace(key, token); } +template string &string::qreplace(const char *key, const char *token) { return ureplace(key, token); } +template string &string::iqreplace(const char *key, const char *token) { return ureplace(key, token); } }; diff --git a/snespurify/nall/string/split.hpp b/snespurify/nall/string/split.hpp index 8d3ca877..1644401b 100755 --- a/snespurify/nall/string/split.hpp +++ b/snespurify/nall/string/split.hpp @@ -3,56 +3,36 @@ namespace nall { -template void lstring::split(const char *key, const char *src) { - unsigned limit = Limit; +template lstring& lstring::usplit(const char *key, const char *base) { reset(); + if(!key || !*key) return *this; - int ssl = strlen(src), ksl = strlen(key); - int lp = 0, split_count = 0; + const char *p = base; + unsigned counter = 0; - for(int i = 0; i <= ssl - ksl;) { - if(!memcmp(src + i, key, ksl)) { - strlcpy(operator[](split_count++), src + lp, i - lp + 1); - i += ksl; - lp = i; - if(!--limit) break; - } else i++; - } - - operator[](split_count++) = src + lp; -} - -template void lstring::qsplit(const char *key, const char *src) { - unsigned limit = Limit; - reset(); - - int ssl = strlen(src), ksl = strlen(key); - int lp = 0, split_count = 0; - - for(int i = 0; i <= ssl - ksl;) { - uint8_t x = src[i]; - - if(x == '\"' || x == '\'') { - int z = i++; //skip opening quote - while(i < ssl && src[i] != x) i++; - if(i >= ssl) i = z; //failed match, rewind i - else { - i++; //skip closing quote - continue; //restart in case next char is also a quote + while(*p) { + if(Limit) if(counter >= Limit) break; + if(quoteskip(p)) continue; + for(unsigned n = 0;; n++) { + if(key[n] == 0) { + strlcpy(operator[](counter++), base, (unsigned)(p - base + 1)); + p += n; + base = p; + break; } + if(!chrequal(key[n], p[n])) { p++; break; } } - - if(!memcmp(src + i, key, ksl)) { - strlcpy(operator[](split_count++), src + lp, i - lp + 1); - i += ksl; - lp = i; - if(!--limit) break; - } else i++; } - operator[](split_count++) = src + lp; + operator[](counter) = base; + return *this; } +template lstring& lstring::split(const char *key, const char *src) { return usplit(key, src); } +template lstring& lstring::isplit(const char *key, const char *src) { return usplit(key, src); } +template lstring& lstring::qsplit(const char *key, const char *src) { return usplit(key, src); } +template lstring& lstring::iqsplit(const char *key, const char *src) { return usplit(key, src); } + }; #endif diff --git a/snespurify/nall/string/strpos.hpp b/snespurify/nall/string/strpos.hpp index 1907a2f3..3b28923e 100755 --- a/snespurify/nall/string/strpos.hpp +++ b/snespurify/nall/string/strpos.hpp @@ -2,40 +2,33 @@ #define NALL_STRING_STRPOS_HPP //usage example: -//if(auto pos = strpos(str, key)) print(pos(), "\n"); -//prints position of key within str, only if it is found +//if(auto position = strpos(str, key)) print(position(), "\n"); +//prints position of key within str; but only if it is found namespace nall { -optional strpos(const char *str, const char *key) { - unsigned ssl = strlen(str), ksl = strlen(key); - if(ksl > ssl) return { false, 0 }; +template +optional ustrpos(const char *str, const char *key) { + const char *base = str; - for(unsigned i = 0; i <= ssl - ksl; i++) { - if(!memcmp(str + i, key, ksl)) return { true, i }; - } - - return { false, 0 }; -} - -optional qstrpos(const char *str, const char *key) { - unsigned ssl = strlen(str), ksl = strlen(key); - if(ksl > ssl) return { false, 0 }; - - for(unsigned i = 0; i <= ssl - ksl;) { - uint8_t x = str[i]; - if(x == '\"' || x == '\'') { - uint8_t z = i++; - while(str[i] != x && i < ssl) i++; - if(i >= ssl) i = z; + while(*str) { + if(quoteskip(str)) continue; + for(unsigned n = 0;; n++) { + if(key[n] == 0) return { true, (unsigned)(str - base) }; + if(str[n] == 0) return { false, 0 }; + if(!chrequal(str[n], key[n])) break; } - if(!memcmp(str + i, key, ksl)) return { true, i }; - i++; + str++; } return { false, 0 }; } +optional strpos(const char *str, const char *key) { return ustrpos(str, key); } +optional istrpos(const char *str, const char *key) { return ustrpos(str, key); } +optional qstrpos(const char *str, const char *key) { return ustrpos(str, key); } +optional iqstrpos(const char *str, const char *key) { return ustrpos(str, key); } + } #endif diff --git a/snespurify/nall/string/trim.hpp b/snespurify/nall/string/trim.hpp index f5355d7d..d1f15ee1 100755 --- a/snespurify/nall/string/trim.hpp +++ b/snespurify/nall/string/trim.hpp @@ -29,7 +29,8 @@ template char* rtrim(char *str, const char *key) { return str; } -template char* trim(char *str, const char *key) { +template char* trim(char *str, const char *key, const char *rkey) { + if(rkey) return ltrim(rtrim(str, rkey), key); return ltrim(rtrim(str, key), key); } diff --git a/snespurify/nall/string/utility.hpp b/snespurify/nall/string/utility.hpp index 8e6c1005..13faaf64 100755 --- a/snespurify/nall/string/utility.hpp +++ b/snespurify/nall/string/utility.hpp @@ -3,6 +3,38 @@ namespace nall { +template +bool chrequal(char x, char y) { + if(Insensitive) return chrlower(x) == chrlower(y); + return x == y; +} + +template +bool quoteskip(T *&p) { + if(Quoted == false) return false; + if(*p != '\'' && *p != '\"') return false; + + while(*p == '\'' || *p == '\"') { + char x = *p++; + while(*p && *p++ != x); + } + return true; +} + +template +bool quotecopy(char *&t, T *&p) { + if(Quoted == false) return false; + if(*p != '\'' && *p != '\"') return false; + + while(*p == '\'' || *p == '\"') { + char x = *p++; + *t++ = x; + while(*p && *p != x) *t++ = *p++; + *t++ = *p++; + } + return true; +} + unsigned strlcpy(string &dest, const char *src, unsigned length) { dest.reserve(length); return strlcpy(dest(), src, length); @@ -15,7 +47,7 @@ unsigned strlcat(string &dest, const char *src, unsigned length) { string substr(const char *src, unsigned start, unsigned length) { string dest; - if(length == 0) { + if(length == ~0u) { //copy entire string dest = src + start; } else { @@ -25,35 +57,21 @@ string substr(const char *src, unsigned start, unsigned length) { return dest; } +string sha256(const uint8_t *data, unsigned size) { + sha256_ctx sha; + uint8_t hash[32]; + sha256_init(&sha); + sha256_chunk(&sha, data, size); + sha256_final(&sha); + sha256_hash(&sha, hash); + string result; + foreach(byte, hash) result.append(hex<2>(byte)); + return result; +} + /* arithmetic <> string */ -string integer(intmax_t value) { - bool negative = value < 0; - if(negative) value = abs(value); - - char buffer[64]; - unsigned size = 0; - - do { - unsigned n = value % 10; - buffer[size++] = '0' + n; - value /= 10; - } while(value); - buffer[size++] = negative ? '-' : '+'; - buffer[size] = 0; - - char result[size + 1]; - memset(result, '0', size); - result[size] = 0; - - for(signed x = size - 1, y = 0; x >= 0 && y < size; x--, y++) { - result[x] = buffer[y]; - } - - return (const char*)result; -} - -template string linteger(intmax_t value) { +template string integer(intmax_t value) { bool negative = value < 0; if(negative) value = abs(value); @@ -70,34 +88,7 @@ template string linteger(intmax_t value) { unsigned length = (length_ == 0 ? size : length_); char result[length + 1]; - memset(result, ' ', length); - result[length] = 0; - - for(signed x = 0, y = size - 1; x < length && y >= 0; x++, y--) { - result[x] = buffer[y]; - } - - return (const char*)result; -} - -template string rinteger(intmax_t value) { - bool negative = value < 0; - if(negative) value = abs(value); - - char buffer[64]; - unsigned size = 0; - - do { - unsigned n = value % 10; - buffer[size++] = '0' + n; - value /= 10; - } while(value); - buffer[size++] = negative ? '-' : '+'; - buffer[size] = 0; - - unsigned length = (length_ == 0 ? size : length_); - char result[length + 1]; - memset(result, ' ', length); + memset(result, padding, length); result[length] = 0; for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) { @@ -107,29 +98,10 @@ template string rinteger(intmax_t value) { return (const char*)result; } -string decimal(uintmax_t value) { - char buffer[64]; - unsigned size = 0; - - do { - unsigned n = value % 10; - buffer[size++] = '0' + n; - value /= 10; - } while(value); - buffer[size] = 0; - - char result[size + 1]; - memset(result, '0', size); - result[size] = 0; - - for(signed x = size - 1, y = 0; x >= 0 && y < size; x--, y++) { - result[x] = buffer[y]; - } - - return (const char*)result; -} - -template string ldecimal(uintmax_t value) { +template string linteger(intmax_t value) { + bool negative = value < 0; + if(negative) value = abs(value); + char buffer[64]; unsigned size = 0; @@ -138,11 +110,12 @@ template string ldecimal(uintmax_t value) { buffer[size++] = '0' + n; value /= 10; } while(value); + buffer[size++] = negative ? '-' : '+'; buffer[size] = 0; unsigned length = (length_ == 0 ? size : length_); char result[length + 1]; - memset(result, ' ', length); + memset(result, padding, length); result[length] = 0; for(signed x = 0, y = size - 1; x < length && y >= 0; x++, y--) { @@ -152,7 +125,7 @@ template string ldecimal(uintmax_t value) { return (const char*)result; } -template string rdecimal(uintmax_t value) { +template string decimal(uintmax_t value) { char buffer[64]; unsigned size = 0; @@ -165,7 +138,7 @@ template string rdecimal(uintmax_t value) { unsigned length = (length_ == 0 ? size : length_); char result[length + 1]; - memset(result, ' ', length); + memset(result, padding, length); result[length] = 0; for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) { @@ -175,7 +148,30 @@ template string rdecimal(uintmax_t value) { return (const char*)result; } -template string hex(uintmax_t value) { +template string ldecimal(uintmax_t value) { + char buffer[64]; + unsigned size = 0; + + do { + unsigned n = value % 10; + buffer[size++] = '0' + n; + value /= 10; + } while(value); + buffer[size] = 0; + + unsigned length = (length_ == 0 ? size : length_); + char result[length + 1]; + memset(result, padding, length); + result[length] = 0; + + for(signed x = 0, y = size - 1; x < length && y >= 0; x++, y--) { + result[x] = buffer[y]; + } + + return (const char*)result; +} + +template string hex(uintmax_t value) { char buffer[64]; unsigned size = 0; @@ -187,7 +183,7 @@ template string hex(uintmax_t value) { unsigned length = (length_ == 0 ? size : length_); char result[length + 1]; - memset(result, '0', length); + memset(result, padding, length); result[length] = 0; for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) { @@ -197,7 +193,7 @@ template string hex(uintmax_t value) { return (const char*)result; } -template string binary(uintmax_t value) { +template string binary(uintmax_t value) { char buffer[256]; unsigned size = 0; @@ -209,7 +205,7 @@ template string binary(uintmax_t value) { unsigned length = (length_ == 0 ? size : length_); char result[length + 1]; - memset(result, '0', length); + memset(result, padding, length); result[length] = 0; for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) { diff --git a/snespurify/nall/string/wrapper.hpp b/snespurify/nall/string/wrapper.hpp index eadf0a10..a28c1ced 100755 --- a/snespurify/nall/string/wrapper.hpp +++ b/snespurify/nall/string/wrapper.hpp @@ -6,27 +6,31 @@ namespace nall { unsigned string::length() const { return strlen(data); } bool string::equals(const char *str) const { return !strcmp(data, str); } -bool string::iequals(const char *str) const { return !stricmp(data, str); } +bool string::iequals(const char *str) const { return !istrcmp(data, str); } bool string::wildcard(const char *str) const { return nall::wildcard(data, str); } bool string::iwildcard(const char *str) const { return nall::iwildcard(data, str); } bool string::beginswith(const char *str) const { return strbegin(data, str); } -bool string::ibeginswith(const char *str) const { return stribegin(data, str); } +bool string::ibeginswith(const char *str) const { return istrbegin(data, str); } bool string::endswith(const char *str) const { return strend(data, str); } -bool string::iendswith(const char *str) const { return striend(data, str); } +bool string::iendswith(const char *str) const { return istrend(data, str); } string& string::lower() { nall::strlower(data); return *this; } string& string::upper() { nall::strupper(data); return *this; } +string& string::qlower() { nall::qstrlower(data); return *this; } +string& string::qupper() { nall::qstrupper(data); return *this; } string& string::transform(const char *before, const char *after) { nall::strtr(data, before, after); return *this; } template string& string::ltrim(const char *key) { nall::ltrim(data, key); return *this; } template string& string::rtrim(const char *key) { nall::rtrim(data, key); return *this; } -template string& string::trim (const char *key) { nall::trim (data, key); return *this; } +template string& string::trim(const char *key, const char *rkey) { nall::trim (data, key, rkey); return *this; } optional string::position(const char *key) const { return strpos(data, key); } +optional string::iposition(const char *key) const { return istrpos(data, key); } optional string::qposition(const char *key) const { return qstrpos(data, key); } +optional string::iqposition(const char *key) const { return iqstrpos(data, key); } } diff --git a/snespurify/nall/string/xml.hpp b/snespurify/nall/string/xml.hpp index 185a89f9..47653786 100755 --- a/snespurify/nall/string/xml.hpp +++ b/snespurify/nall/string/xml.hpp @@ -77,7 +77,7 @@ inline string xml_element::parse() const { if(auto pos = strpos(source, "]]>")) { if(pos() - 9 > 0) { string cdata = substr(source, 9, pos() - 9); - data << cdata; + data.append(cdata); offset += strlen(cdata); } source += 9 + offset + 3; diff --git a/snespurify/nall/utility.hpp b/snespurify/nall/utility.hpp index 60bda562..1f5699e5 100755 --- a/snespurify/nall/utility.hpp +++ b/snespurify/nall/utility.hpp @@ -26,6 +26,7 @@ namespace nall { public: inline operator bool() const { return valid; } inline const T& operator()() const { if(!valid) throw; return value; } + inline optional& operator=(const optional &source) { valid = source.valid; value = source.value; return *this; } inline optional(bool valid, const T &value) : valid(valid), value(value) {} }; diff --git a/snespurify/nall/vector.hpp b/snespurify/nall/vector.hpp index c6ef24f2..f98eb375 100755 --- a/snespurify/nall/vector.hpp +++ b/snespurify/nall/vector.hpp @@ -94,14 +94,15 @@ namespace nall { else resize(objectsize - count); } - inline T& operator[](unsigned index) { - if(index >= objectsize) resize(index + 1); - return pool[index]; + linear_vector() : pool(0), poolsize(0), objectsize(0) { } - inline const T& operator[](unsigned index) const { - if(index >= objectsize) throw "vector[] out of bounds"; - return pool[index]; + linear_vector(std::initializer_list list) : pool(0), poolsize(0), objectsize(0) { + for(const T *p = list.begin(); p != list.end(); ++p) append(*p); + } + + ~linear_vector() { + reset(); } //copy @@ -132,17 +133,22 @@ namespace nall { operator=(std::move(source)); } - //construction - linear_vector() : pool(0), poolsize(0), objectsize(0) { + //index + inline T& operator[](unsigned index) { + if(index >= objectsize) resize(index + 1); + return pool[index]; } - linear_vector(std::initializer_list list) : pool(0), poolsize(0), objectsize(0) { - for(const T *p = list.begin(); p != list.end(); ++p) append(*p); + inline const T& operator[](unsigned index) const { + if(index >= objectsize) throw "vector[] out of bounds"; + return pool[index]; } - ~linear_vector() { - reset(); - } + //iteration + T* begin() { return &pool[0]; } + T* end() { return &pool[objectsize]; } + const T* begin() const { return &pool[0]; } + const T* end() const { return &pool[objectsize]; } }; //pointer_vector @@ -222,15 +228,15 @@ namespace nall { else resize(objectsize - count); } - inline T& operator[](unsigned index) { - if(index >= objectsize) resize(index + 1); - if(!pool[index]) pool[index] = new T; - return *pool[index]; + pointer_vector() : pool(0), poolsize(0), objectsize(0) { } - inline const T& operator[](unsigned index) const { - if(index >= objectsize || !pool[index]) throw "vector[] out of bounds"; - return *pool[index]; + pointer_vector(std::initializer_list list) : pool(0), poolsize(0), objectsize(0) { + for(const T *p = list.begin(); p != list.end(); ++p) append(*p); + } + + ~pointer_vector() { + reset(); } //copy @@ -261,17 +267,31 @@ namespace nall { operator=(std::move(source)); } - //construction - pointer_vector() : pool(0), poolsize(0), objectsize(0) { + //index + inline T& operator[](unsigned index) { + if(index >= objectsize) resize(index + 1); + if(!pool[index]) pool[index] = new T; + return *pool[index]; } - pointer_vector(std::initializer_list list) : pool(0), poolsize(0), objectsize(0) { - for(const T *p = list.begin(); p != list.end(); ++p) append(*p); + inline const T& operator[](unsigned index) const { + if(index >= objectsize || !pool[index]) throw "vector[] out of bounds"; + return *pool[index]; } - ~pointer_vector() { - reset(); - } + //iteration + struct iterator { + bool operator!=(const iterator &source) const { return index != source.index; } + T& operator*() { return vector.operator[](index); } + iterator& operator++() { index++; return *this; } + iterator(pointer_vector &vector, unsigned index) : vector(vector), index(index) {} + private: + pointer_vector &vector; + unsigned index; + }; + + iterator begin() { return iterator(*this, 0); } + iterator end() { return iterator(*this, objectsize); } }; template struct has_size> { enum { value = true }; }; diff --git a/snespurify/nall/windows/detour.hpp b/snespurify/nall/windows/detour.hpp new file mode 100755 index 00000000..e270f318 --- /dev/null +++ b/snespurify/nall/windows/detour.hpp @@ -0,0 +1,192 @@ +#ifndef NALL_WINDOWS_DETOUR_HPP +#define NALL_WINDOWS_DETOUR_HPP + +#include +#include +#include +#include +#include + +namespace nall { + +#define Copy 0 +#define RelNear 1 + +struct detour { + static bool insert(const string &moduleName, const string &functionName, void *&source, void *target); + static bool remove(const string &moduleName, const string &functionName, void *&source); + +protected: + static unsigned length(const uint8_t *function); + static unsigned mirror(uint8_t *target, const uint8_t *source); + + struct opcode { + uint16_t prefix; + unsigned length; + unsigned mode; + uint16_t modify; + }; + static opcode opcodes[]; +}; + +//TODO: +//* fs:, gs: should force another opcode copy +//* conditional branches within +5-byte range should fail +detour::opcode detour::opcodes[] = { + { 0x50, 1 }, //push eax + { 0x51, 1 }, //push ecx + { 0x52, 1 }, //push edx + { 0x53, 1 }, //push ebx + { 0x54, 1 }, //push esp + { 0x55, 1 }, //push ebp + { 0x56, 1 }, //push esi + { 0x57, 1 }, //push edi + { 0x58, 1 }, //pop eax + { 0x59, 1 }, //pop ecx + { 0x5a, 1 }, //pop edx + { 0x5b, 1 }, //pop ebx + { 0x5c, 1 }, //pop esp + { 0x5d, 1 }, //pop ebp + { 0x5e, 1 }, //pop esi + { 0x5f, 1 }, //pop edi + { 0x64, 1 }, //fs: + { 0x65, 1 }, //gs: + { 0x68, 5 }, //push dword + { 0x6a, 2 }, //push byte + { 0x74, 2, RelNear, 0x0f84 }, //je near -> je far + { 0x75, 2, RelNear, 0x0f85 }, //jne near -> jne far + { 0x89, 2 }, //mov reg,reg + { 0x8b, 2 }, //mov reg,reg + { 0x90, 1 }, //nop + { 0xa1, 5 }, //mov eax,[dword] + { 0xeb, 2, RelNear, 0xe9 }, //jmp near -> jmp far +}; + +bool detour::insert(const string &moduleName, const string &functionName, void *&source, void *target) { + HMODULE module = GetModuleHandleW(utf16_t(moduleName)); + if(!module) return false; + + uint8_t *sourceData = (uint8_t*)GetProcAddress(module, functionName); + if(!sourceData) return false; + + unsigned sourceLength = detour::length(sourceData); + if(sourceLength < 5) { + //unable to clone enough bytes to insert hook + #if 1 + string output = { "detour::insert(", moduleName, "::", functionName, ") failed: " }; + for(unsigned n = 0; n < 16; n++) output.append(hex<2>(sourceData[n]), " "); + output.rtrim<1>(" "); + MessageBoxA(0, output, "nall::detour", MB_OK); + #endif + return false; + } + + uint8_t *mirrorData = new uint8_t[512](); + detour::mirror(mirrorData, sourceData); + + DWORD privileges; + VirtualProtect((void*)mirrorData, 512, PAGE_EXECUTE_READWRITE, &privileges); + VirtualProtect((void*)sourceData, 256, PAGE_EXECUTE_READWRITE, &privileges); + uintmax_t address = (uintmax_t)target - ((uintmax_t)sourceData + 5); + sourceData[0] = 0xe9; //jmp target + sourceData[1] = address >> 0; + sourceData[2] = address >> 8; + sourceData[3] = address >> 16; + sourceData[4] = address >> 24; + VirtualProtect((void*)sourceData, 256, privileges, &privileges); + + source = (void*)mirrorData; + return true; +} + +bool detour::remove(const string &moduleName, const string &functionName, void *&source) { + HMODULE module = GetModuleHandleW(utf16_t(moduleName)); + if(!module) return false; + + uint8_t *sourceData = (uint8_t*)GetProcAddress(module, functionName); + if(!sourceData) return false; + + uint8_t *mirrorData = (uint8_t*)source; + if(mirrorData == sourceData) return false; //hook was never installed + + unsigned length = detour::length(256 + mirrorData); + if(length < 5) return false; + + DWORD privileges; + VirtualProtect((void*)sourceData, 256, PAGE_EXECUTE_READWRITE, &privileges); + for(unsigned n = 0; n < length; n++) sourceData[n] = mirrorData[256 + n]; + VirtualProtect((void*)sourceData, 256, privileges, &privileges); + + source = (void*)sourceData; + delete[] mirrorData; + return true; +} + +unsigned detour::length(const uint8_t *function) { + unsigned length = 0; + while(length < 5) { + detour::opcode *opcode = 0; + foreach(op, detour::opcodes) { + if(function[length] == op.prefix) { + opcode = &op; + break; + } + } + if(opcode == 0) break; + length += opcode->length; + } + return length; +} + +unsigned detour::mirror(uint8_t *target, const uint8_t *source) { + const uint8_t *entryPoint = source; + for(unsigned n = 0; n < 256; n++) target[256 + n] = source[n]; + + unsigned size = detour::length(source); + while(size) { + detour::opcode *opcode = 0; + foreach(op, detour::opcodes) { + if(*source == op.prefix) { + opcode = &op; + break; + } + } + + switch(opcode->mode) { + case Copy: + for(unsigned n = 0; n < opcode->length; n++) *target++ = *source++; + break; + case RelNear: { + source++; + uintmax_t sourceAddress = (uintmax_t)source + 1 + (int8_t)*source; + *target++ = opcode->modify; + if(opcode->modify >> 8) *target++ = opcode->modify >> 8; + uintmax_t targetAddress = (uintmax_t)target + 4; + uintmax_t address = sourceAddress - targetAddress; + *target++ = address >> 0; + *target++ = address >> 8; + *target++ = address >> 16; + *target++ = address >> 24; + source += 2; + } break; + } + + size -= opcode->length; + } + + uintmax_t address = (entryPoint + detour::length(entryPoint)) - (target + 5); + *target++ = 0xe9; //jmp entryPoint + *target++ = address >> 0; + *target++ = address >> 8; + *target++ = address >> 16; + *target++ = address >> 24; + + return source - entryPoint; +} + +#undef Implied +#undef RelNear + +} + +#endif diff --git a/snespurify/nall/windows/launcher.hpp b/snespurify/nall/windows/launcher.hpp new file mode 100755 index 00000000..914683ec --- /dev/null +++ b/snespurify/nall/windows/launcher.hpp @@ -0,0 +1,94 @@ +#ifndef NALL_WINDOWS_LAUNCHER_HPP +#define NALL_WINDOWS_LAUNCHER_HPP + +namespace nall { + +//launch a new process and inject specified DLL into it + +bool launch(const char *applicationName, const char *libraryName, uint32_t entryPoint) { + //if a launcher does not send at least one message, a wait cursor will appear + PostThreadMessage(GetCurrentThreadId(), WM_USER, 0, 0); + MSG msg; + GetMessage(&msg, 0, 0, 0); + + STARTUPINFOW si; + PROCESS_INFORMATION pi; + + memset(&si, 0, sizeof(STARTUPINFOW)); + BOOL result = CreateProcessW( + utf16_t(applicationName), GetCommandLineW(), NULL, NULL, TRUE, + DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS, //do not break if application creates its own processes + NULL, NULL, &si, &pi + ); + if(result == false) return false; + + uint8_t entryData[1024], entryHook[1024] = { + 0x68, 0x00, 0x00, 0x00, 0x00, //push libraryName + 0xb8, 0x00, 0x00, 0x00, 0x00, //mov eax,LoadLibraryW + 0xff, 0xd0, //call eax + 0xcd, 0x03, //int 3 + }; + + entryHook[1] = (uint8_t)((entryPoint + 14) >> 0); + entryHook[2] = (uint8_t)((entryPoint + 14) >> 8); + entryHook[3] = (uint8_t)((entryPoint + 14) >> 16); + entryHook[4] = (uint8_t)((entryPoint + 14) >> 24); + + uint32_t pLoadLibraryW = (uint32_t)GetProcAddress(GetModuleHandleW(L"kernel32"), "LoadLibraryW"); + entryHook[6] = pLoadLibraryW >> 0; + entryHook[7] = pLoadLibraryW >> 8; + entryHook[8] = pLoadLibraryW >> 16; + entryHook[9] = pLoadLibraryW >> 24; + + utf16_t buffer = utf16_t(libraryName); + memcpy(entryHook + 14, buffer, 2 * wcslen(buffer) + 2); + + while(true) { + DEBUG_EVENT event; + WaitForDebugEvent(&event, INFINITE); + + if(event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break; + + if(event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) { + if(event.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) { + if(event.u.Exception.ExceptionRecord.ExceptionAddress == (void*)(entryPoint + 14 - 1)) { + HANDLE hProcess = OpenProcess(0, FALSE, event.dwProcessId); + HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, event.dwThreadId); + + CONTEXT context; + context.ContextFlags = CONTEXT_FULL; + GetThreadContext(hThread, &context); + + WriteProcessMemory(pi.hProcess, (void*)entryPoint, (void*)&entryData, sizeof entryData, NULL); + context.Eip = entryPoint; + SetThreadContext(hThread, &context); + + CloseHandle(hThread); + CloseHandle(hProcess); + } + + ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE); + continue; + } + + ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_EXCEPTION_NOT_HANDLED); + continue; + } + + if(event.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT) { + ReadProcessMemory(pi.hProcess, (void*)entryPoint, (void*)&entryData, sizeof entryData, NULL); + WriteProcessMemory(pi.hProcess, (void*)entryPoint, (void*)&entryHook, sizeof entryHook, NULL); + + ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE); + continue; + } + + ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE); + } + + return true; +} + +} + +#endif diff --git a/snespurify/nall/utf8.hpp b/snespurify/nall/windows/utf8.hpp similarity index 100% rename from snespurify/nall/utf8.hpp rename to snespurify/nall/windows/utf8.hpp diff --git a/snespurify/nall/zip.hpp b/snespurify/nall/zip.hpp new file mode 100755 index 00000000..ad9c7506 --- /dev/null +++ b/snespurify/nall/zip.hpp @@ -0,0 +1,124 @@ +#ifndef NALL_UNZIP_HPP +#define NALL_UNZIP_HPP + +#include +#include +#include +#include + +namespace nall { + +struct zip { + struct File { + string name; + const uint8_t *data; + unsigned size; + unsigned csize; + unsigned cmode; //0 = uncompressed, 8 = deflate + unsigned crc32; + }; + + inline bool open(const string &filename) { + close(); + if(fm.open(filename, filemap::mode::read) == false) return false; + if(open(fm.data(), fm.size()) == false) { + fm.close(); + return false; + } + return true; + } + + inline bool open(const uint8_t *data, unsigned size) { + if(size < 22) return false; + + filedata = data; + filesize = size; + + file.reset(); + + const uint8_t *footer = data + size - 22; + const uint8_t *directory = data + read(footer + 16, 4); + + while(true) { + unsigned signature = read(directory + 0, 4); + if(signature != 0x02014b50) break; + + File file; + file.cmode = read(directory + 10, 2); + file.crc32 = read(directory + 16, 4); + file.csize = read(directory + 20, 4); + file.size = read(directory + 24, 4); + + unsigned namelength = read(directory + 28, 2); + unsigned extralength = read(directory + 30, 2); + unsigned commentlength = read(directory + 32, 2); + + char *filename = new char[namelength + 1]; + memcpy(filename, directory + 46, namelength); + filename[namelength] = 0; + file.name = filename; + delete[] filename; + + unsigned offset = read(directory + 42, 4); + unsigned offsetNL = read(data + offset + 26, 2); + unsigned offsetEL = read(data + offset + 28, 2); + file.data = data + offset + 30 + offsetNL + offsetEL; + + directory += 46 + namelength + extralength + commentlength; + + this->file.append(file); + } + + return true; + } + + inline bool extract(File &file, uint8_t *&data, unsigned &size) { + data = 0, size = 0; + + if(file.cmode == 0) { + size = file.size; + data = new uint8_t[size]; + memcpy(data, file.data, size); + return true; + } + + if(file.cmode == 8) { + size = file.size; + data = new uint8_t[size]; + if(inflate(data, size, file.data, file.csize) == false) { + delete[] data; + size = 0; + return false; + } + return true; + } + + return false; + } + + inline void close() { + if(fm.open()) fm.close(); + } + + ~zip() { + close(); + } + +protected: + filemap fm; + const uint8_t *filedata; + unsigned filesize; + + unsigned read(const uint8_t *data, unsigned size) { + unsigned result = 0, shift = 0; + while(size--) { result |= *data++ << shift; shift += 8; } + return result; + } + +public: + linear_vector file; +}; + +} + +#endif diff --git a/snespurify/phoenix/core/core.cpp b/snespurify/phoenix/core/core.cpp index ddb868cb..63c152b2 100755 --- a/snespurify/phoenix/core/core.cpp +++ b/snespurify/phoenix/core/core.cpp @@ -34,6 +34,10 @@ void Font::setSize(unsigned size) { state.size = size; return p.setSize(size); } void Font::setUnderline(bool underline) { state.underline = underline; return p.setUnderline(underline); } Font::Font() : state(*new State), p(*new pFont(*this)) { p.constructor(); } +void Timer::setEnabled(bool enabled) { state.enabled = enabled; return p.setEnabled(enabled); } +void Timer::setInterval(unsigned milliseconds) { state.milliseconds = milliseconds; return p.setInterval(milliseconds); } +Timer::Timer() : state(*new State), p(*new pTimer(*this)) { p.constructor(); } + MessageWindow::Response MessageWindow::information(Window &parent, const string &text, MessageWindow::Buttons buttons) { return pMessageWindow::information(parent, text, buttons); } MessageWindow::Response MessageWindow::question(Window &parent, const string &text, MessageWindow::Buttons buttons) { return pMessageWindow::question(parent, text, buttons); } MessageWindow::Response MessageWindow::warning(Window &parent, const string &text, MessageWindow::Buttons buttons) { return pMessageWindow::warning(parent, text, buttons); } @@ -43,11 +47,12 @@ Window Window::None; void Window::append(Layout &layout) { state.layout.append(layout); return p.append(layout); } void Window::append(Menu &menu) { state.menu.append(menu); ((Action&)menu).state.parent = this; return p.append(menu); } void Window::append(Widget &widget) { state.widget.append(widget); return p.append(widget); } +Color Window::backgroundColor() { return p.backgroundColor(); } Geometry Window::frameGeometry() { Geometry geometry = p.geometry(), margin = p.frameMargin(); return { geometry.x - margin.x, geometry.y - margin.y, geometry.width + margin.width, geometry.height + margin.height }; } Geometry Window::frameMargin() { return p.frameMargin(); } bool Window::focused() { return p.focused(); } Geometry Window::geometry() { return p.geometry(); } -void Window::setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue) { state.backgroundColor = true; state.backgroundColorRed = red; state.backgroundColorGreen = green; state.backgroundColorBlue = blue; return p.setBackgroundColor(red, green, blue); } +void Window::setBackgroundColor(const Color &color) { state.backgroundColorOverride = true; state.backgroundColor = color; return p.setBackgroundColor(color); } void Window::setFrameGeometry(const Geometry &geometry) { Geometry margin = p.frameMargin(); return setGeometry({ geometry.x + margin.x, geometry.y + margin.y, geometry.width - margin.width, geometry.height - margin.height }); } void Window::setFocused() { return p.setFocused(); } void Window::setFullScreen(bool fullScreen) { state.fullScreen = fullScreen; return p.setFullScreen(fullScreen); } @@ -89,6 +94,7 @@ RadioItem::RadioItem() : state(*new State), base_from_member(*new p bool Widget::enabled() { return state.enabled; } Font& Widget::font() { return p.font(); } +Geometry Widget::geometry() { return state.geometry; } Geometry Widget::minimumGeometry() { return p.minimumGeometry(); } void Widget::setEnabled(bool enabled) { state.enabled = enabled; return p.setEnabled(enabled); } void Widget::setFocused() { return p.setFocused(); } @@ -124,6 +130,11 @@ void HexEdit::setRows(unsigned rows) { state.rows = rows; return p.setRows(rows) void HexEdit::update() { return p.update(); } HexEdit::HexEdit() : state(*new State), base_from_member(*new pHexEdit(*this)), Widget(base_from_member::value), p(base_from_member::value) { p.constructor(); } +unsigned HorizontalScrollBar::position() { return p.position(); } +void HorizontalScrollBar::setLength(unsigned length) { state.length = length; return p.setLength(length); } +void HorizontalScrollBar::setPosition(unsigned position) { state.position = position; return p.setPosition(position); } +HorizontalScrollBar::HorizontalScrollBar() : state(*new State), base_from_member(*new pHorizontalScrollBar(*this)), Widget(base_from_member::value), p(base_from_member::value) { p.constructor(); } + unsigned HorizontalSlider::position() { return p.position(); } void HorizontalSlider::setLength(unsigned length) { state.length = length; return p.setLength(length); } void HorizontalSlider::setPosition(unsigned position) { state.position = position; return p.setPosition(position); } @@ -168,6 +179,11 @@ void TextEdit::setWordWrap(bool wordWrap) { state.wordWrap = wordWrap; return p. string TextEdit::text() { return p.text(); } TextEdit::TextEdit() : state(*new State), base_from_member(*new pTextEdit(*this)), Widget(base_from_member::value), p(base_from_member::value) { p.constructor(); } +unsigned VerticalScrollBar::position() { return p.position(); } +void VerticalScrollBar::setLength(unsigned length) { state.length = length; return p.setLength(length); } +void VerticalScrollBar::setPosition(unsigned position) { state.position = position; return p.setPosition(position); } +VerticalScrollBar::VerticalScrollBar() : state(*new State), base_from_member(*new pVerticalScrollBar(*this)), Widget(base_from_member::value), p(base_from_member::value) { p.constructor(); } + unsigned VerticalSlider::position() { return p.position(); } void VerticalSlider::setLength(unsigned length) { state.length = length; return p.setLength(length); } void VerticalSlider::setPosition(unsigned position) { state.position = position; return p.setPosition(position); } diff --git a/snespurify/phoenix/core/core.hpp b/snespurify/phoenix/core/core.hpp index 2f087b42..c09909ed 100755 --- a/snespurify/phoenix/core/core.hpp +++ b/snespurify/phoenix/core/core.hpp @@ -6,6 +6,7 @@ struct Widget; struct pOS; struct pFont; +struct pTimer; struct pWindow; struct pAction; struct pMenu; @@ -20,6 +21,7 @@ struct pCanvas; struct pCheckBox; struct pComboBox; struct pHexEdit; +struct pHorizontalScrollBar; struct pHorizontalSlider; struct pLabel; struct pLineEdit; @@ -27,6 +29,7 @@ struct pListView; struct pProgressBar; struct pRadioBox; struct pTextEdit; +struct pVerticalScrollBar; struct pVerticalSlider; struct pViewport; @@ -42,6 +45,12 @@ struct Geometry { inline Geometry(signed x, signed y, unsigned width, unsigned height) : x(x), y(y), width(width), height(height) {} }; +struct Color { + uint8_t red, green, blue, alpha; + inline Color() : red(0), green(0), blue(0), alpha(255) {} + inline Color(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha = 255) : red(red), green(green), blue(blue), alpha(alpha) {} +}; + struct Object { Object(); Object& operator=(const Object&) = delete; @@ -82,6 +91,18 @@ struct Font : Object { pFont &p; }; +struct Timer : Object { + nall::function onTimeout; + + void setEnabled(bool enabled = true); + void setInterval(unsigned milliseconds); + + Timer(); + struct State; + State &state; + pTimer &p; +}; + struct MessageWindow : Object { enum class Buttons : unsigned { Ok, @@ -111,11 +132,12 @@ struct Window : Object { void append(Layout &layout); void append(Menu &menu); void append(Widget &widget); + Color backgroundColor(); Geometry frameGeometry(); Geometry frameMargin(); bool focused(); Geometry geometry(); - void setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue); + void setBackgroundColor(const Color &color); void setFrameGeometry(const Geometry &geometry); void setFocused(); void setFullScreen(bool fullScreen = true); @@ -210,6 +232,7 @@ struct Layout : Object { struct Widget : Object { bool enabled(); Font& font(); + Geometry geometry(); Geometry minimumGeometry(); void setEnabled(bool enabled = true); void setFocused(); @@ -287,6 +310,19 @@ struct HexEdit : private nall::base_from_member, Widget { pHexEdit &p; }; +struct HorizontalScrollBar : private nall::base_from_member, Widget { + nall::function onChange; + + unsigned position(); + void setLength(unsigned length); + void setPosition(unsigned position); + + HorizontalScrollBar(); + struct State; + State &state; + pHorizontalScrollBar &p; +}; + struct HorizontalSlider : private nall::base_from_member, Widget { nall::function onChange; @@ -393,6 +429,19 @@ struct TextEdit : private nall::base_from_member, Widget { pTextEdit &p; }; +struct VerticalScrollBar : private nall::base_from_member, Widget { + nall::function onChange; + + unsigned position(); + void setLength(unsigned length); + void setPosition(unsigned position); + + VerticalScrollBar(); + struct State; + State &state; + pVerticalScrollBar &p; +}; + struct VerticalSlider : private nall::base_from_member, Widget { nall::function onChange; diff --git a/snespurify/phoenix/core/state.hpp b/snespurify/phoenix/core/state.hpp index a4d99bf7..cbe6970c 100755 --- a/snespurify/phoenix/core/state.hpp +++ b/snespurify/phoenix/core/state.hpp @@ -13,9 +13,19 @@ struct Font::State { } }; +struct Timer::State { + bool enabled; + unsigned milliseconds; + + State() { + enabled = false; + milliseconds = 0; + } +}; + struct Window::State { - bool backgroundColor; - unsigned backgroundColorRed, backgroundColorGreen, backgroundColorBlue; + bool backgroundColorOverride; + Color backgroundColor; bool fullScreen; Geometry geometry; reference_array layout; @@ -32,10 +42,8 @@ struct Window::State { Font *widgetFont; State() { - backgroundColor = false; - backgroundColorRed = 0; - backgroundColorGreen = 0; - backgroundColorBlue = 0; + backgroundColorOverride = false; + backgroundColor = { 0, 0, 0, 255 }; fullScreen = false; geometry = { 128, 128, 256, 256 }; menuFont = 0; @@ -142,6 +150,16 @@ struct HexEdit::State { } }; +struct HorizontalScrollBar::State { + unsigned length; + unsigned position; + + State() { + length = 101; + position = 0; + } +}; + struct HorizontalSlider::State { unsigned length; unsigned position; @@ -213,6 +231,16 @@ struct TextEdit::State { } }; +struct VerticalScrollBar::State { + unsigned length; + unsigned position; + + State() { + length = 101; + position = 0; + } +}; + struct VerticalSlider::State { unsigned length; unsigned position; diff --git a/snespurify/phoenix/gtk/font.cpp b/snespurify/phoenix/gtk/font.cpp index 93bc0303..9f4f840b 100755 --- a/snespurify/phoenix/gtk/font.cpp +++ b/snespurify/phoenix/gtk/font.cpp @@ -29,4 +29,6 @@ void pFont::constructor() { gtkFont = pango_font_description_new(); PangoContext *context = gdk_pango_context_get_for_screen(gdk_screen_get_default()); gtkLayout = pango_layout_new(context); + font.setFamily("Sans"); + font.setSize(8); } diff --git a/snespurify/phoenix/gtk/gtk.cpp b/snespurify/phoenix/gtk/gtk.cpp index c711d7a2..de35e588 100755 --- a/snespurify/phoenix/gtk/gtk.cpp +++ b/snespurify/phoenix/gtk/gtk.cpp @@ -2,6 +2,7 @@ #include "settings.cpp" #include "font.cpp" +#include "timer.cpp" #include "message-window.cpp" #include "window.cpp" @@ -18,6 +19,7 @@ #include "widget/check-box.cpp" #include "widget/combo-box.cpp" #include "widget/hex-edit.cpp" +#include "widget/horizontal-scroll-bar.cpp" #include "widget/horizontal-slider.cpp" #include "widget/label.cpp" #include "widget/line-edit.cpp" @@ -25,16 +27,36 @@ #include "widget/progress-bar.cpp" #include "widget/radio-box.cpp" #include "widget/text-edit.cpp" +#include "widget/vertical-scroll-bar.cpp" #include "widget/vertical-slider.cpp" #include "widget/viewport.cpp" Font pOS::defaultFont; Geometry pOS::availableGeometry() { - //TODO: is there a GTK+ function for this? - //should return desktopGeometry() sans panels, toolbars, docks, etc. - Geometry geometry = desktopGeometry(); - return { geometry.x + 64, geometry.y + 64, geometry.width - 128, geometry.height - 128 }; + Display *display = XOpenDisplay(0); + int screen = DefaultScreen(display); + + static Atom atom = X11None; + if(atom == X11None) atom = XInternAtom(display, "_NET_WORKAREA", True); + + int format; + unsigned char *data = 0; + unsigned long items, after; + Atom returnAtom; + + int result = XGetWindowProperty( + display, RootWindow(display, screen), atom, 0, 4, False, XA_CARDINAL, &returnAtom, &format, &items, &after, &data + ); + + XCloseDisplay(display); + + if(result == Success && returnAtom == XA_CARDINAL && format == 32 && items == 4) { + unsigned long *workarea = (unsigned long*)data; + return { (signed)workarea[0], (signed)workarea[1], (unsigned)workarea[2], (unsigned)workarea[3] }; + } + + return desktopGeometry(); } Geometry pOS::desktopGeometry() { @@ -149,7 +171,7 @@ void pOS::initialize() { " GtkComboBox::appears-as-list = 1\n" " GtkTreeView::vertical-separator = 0\n" "}\n" - "class \"GtkComboBox\" style \"phoenix-gtk\"\n" + //"class \"GtkComboBox\" style \"phoenix-gtk\"\n" "class \"GtkTreeView\" style \"phoenix-gtk\"\n" ); } diff --git a/snespurify/phoenix/gtk/gtk.hpp b/snespurify/phoenix/gtk/gtk.hpp index f6abacce..bd2f19fd 100755 --- a/snespurify/phoenix/gtk/gtk.hpp +++ b/snespurify/phoenix/gtk/gtk.hpp @@ -57,6 +57,16 @@ struct pFont : public pObject { void constructor(); }; +struct pTimer : public pObject { + Timer &timer; + + void setEnabled(bool enabled); + void setInterval(unsigned milliseconds); + + pTimer(Timer &timer) : timer(timer) {} + void constructor(); +}; + struct pMessageWindow : public pObject { static MessageWindow::Response information(Window &parent, const string &text, MessageWindow::Buttons buttons); static MessageWindow::Response question(Window &parent, const string &text, MessageWindow::Buttons buttons); @@ -72,14 +82,16 @@ struct pWindow : public pObject { GtkWidget *statusContainer; GtkWidget *menu; GtkWidget *status; + GdkEventConfigure lastConfigure; void append(Layout &layout); void append(Menu &menu); void append(Widget &widget); + Color backgroundColor(); bool focused(); Geometry frameMargin(); Geometry geometry(); - void setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue); + void setBackgroundColor(const Color &color); void setFocused(); void setFullScreen(bool fullScreen); void setGeometry(const Geometry &geometry); @@ -192,8 +204,7 @@ struct pButton : public pWidget { struct pCanvas : public pWidget { Canvas &canvas; - uint32_t *bufferRGB; - uint32_t *bufferBGR; + cairo_surface_t *surface; uint32_t* buffer(); void setGeometry(const Geometry &geometry); @@ -201,7 +212,6 @@ struct pCanvas : public pWidget { pCanvas(Canvas &canvas) : pWidget(canvas), canvas(canvas) {} void constructor(); - void redraw(); }; struct pCheckBox : public pWidget { @@ -254,6 +264,18 @@ struct pHexEdit : public pWidget { void updateScroll(); }; +struct pHorizontalScrollBar : public pWidget { + HorizontalScrollBar &horizontalScrollBar; + + Geometry minimumGeometry(); + unsigned position(); + void setLength(unsigned length); + void setPosition(unsigned position); + + pHorizontalScrollBar(HorizontalScrollBar &horizontalScrollBar) : pWidget(horizontalScrollBar), horizontalScrollBar(horizontalScrollBar) {} + void constructor(); +}; + struct pHorizontalSlider : public pWidget { HorizontalSlider &horizontalSlider; @@ -358,6 +380,18 @@ struct pTextEdit : public pWidget { void constructor(); }; +struct pVerticalScrollBar : public pWidget { + VerticalScrollBar &verticalScrollBar; + + Geometry minimumGeometry(); + unsigned position(); + void setLength(unsigned length); + void setPosition(unsigned position); + + pVerticalScrollBar(VerticalScrollBar &verticalScrollBar) : pWidget(verticalScrollBar), verticalScrollBar(verticalScrollBar) {} + void constructor(); +}; + struct pVerticalSlider : public pWidget { VerticalSlider &verticalSlider; diff --git a/snespurify/phoenix/gtk/timer.cpp b/snespurify/phoenix/gtk/timer.cpp new file mode 100755 index 00000000..d04183f8 --- /dev/null +++ b/snespurify/phoenix/gtk/timer.cpp @@ -0,0 +1,24 @@ +static guint Timer_trigger(pTimer *self) { + //timer may have been disabled prior to triggering, so check state + if(self->timer.state.enabled) { + if(self->timer.onTimeout) self->timer.onTimeout(); + } + //callback may have disabled timer, so check state again + if(self->timer.state.enabled) { + g_timeout_add(self->timer.state.milliseconds, (GSourceFunc)Timer_trigger, (gpointer)self); + } + //kill this timer instance (it is spawned above if needed again) + return false; +} + +void pTimer::setEnabled(bool enabled) { + if(enabled) { + g_timeout_add(timer.state.milliseconds, (GSourceFunc)Timer_trigger, (gpointer)this); + } +} + +void pTimer::setInterval(unsigned milliseconds) { +} + +void pTimer::constructor() { +} diff --git a/snespurify/phoenix/gtk/widget/button.cpp b/snespurify/phoenix/gtk/widget/button.cpp index 360ccedf..f657bb06 100755 --- a/snespurify/phoenix/gtk/widget/button.cpp +++ b/snespurify/phoenix/gtk/widget/button.cpp @@ -5,7 +5,7 @@ static void Button_tick(Button *self) { Geometry pButton::minimumGeometry() { Font &font = pWidget::font(); Geometry geometry = font.geometry(button.state.text); - return { 0, 0, geometry.width + 24, geometry.height + 14 }; + return { 0, 0, geometry.width + 24, geometry.height + 12 }; } void pButton::setText(const string &text) { diff --git a/snespurify/phoenix/gtk/widget/canvas.cpp b/snespurify/phoenix/gtk/widget/canvas.cpp index 2a0d479b..c2261d17 100755 --- a/snespurify/phoenix/gtk/widget/canvas.cpp +++ b/snespurify/phoenix/gtk/widget/canvas.cpp @@ -1,17 +1,21 @@ -static void Canvas_expose(pCanvas *self) { - self->redraw(); +static gboolean Canvas_expose(GtkWidget *widget, GdkEvent *event, pCanvas *self) { + cairo_t *context = gdk_cairo_create(gtk_widget_get_window(widget)); + cairo_set_source_surface(context, self->surface, 0, 0); + cairo_paint(context); + cairo_destroy(context); + return true; } uint32_t* pCanvas::buffer() { - return bufferRGB; + return (uint32_t*)cairo_image_surface_get_data(surface); } void pCanvas::setGeometry(const Geometry &geometry) { - delete[] bufferRGB; - delete[] bufferBGR; + if(geometry.width == cairo_image_surface_get_width(surface) + && geometry.height == cairo_image_surface_get_height(surface)) return; - bufferRGB = new uint32_t[geometry.width * geometry.height](); - bufferBGR = new uint32_t[geometry.width * geometry.height](); + cairo_surface_destroy(surface); + surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, geometry.width, geometry.height); pWidget::setGeometry(geometry); update(); @@ -19,41 +23,16 @@ void pCanvas::setGeometry(const Geometry &geometry) { void pCanvas::update() { if(gtk_widget_get_realized(gtkWidget) == false) return; - GdkRectangle rect; - rect.x = 0; - rect.y = 0; - rect.width = gtkWidget->allocation.width; - rect.height = gtkWidget->allocation.height; - gdk_window_invalidate_rect(gtkWidget->window, &rect, true); + gdk_window_invalidate_rect(gtk_widget_get_window(gtkWidget), 0, true); } void pCanvas::constructor() { - bufferRGB = new uint32_t[256 * 256](); - bufferBGR = new uint32_t[256 * 256](); - + surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, 256, 256); gtkWidget = gtk_drawing_area_new(); GdkColor color; color.pixel = color.red = color.green = color.blue = 0; gtk_widget_modify_bg(gtkWidget, GTK_STATE_NORMAL, &color); gtk_widget_set_double_buffered(gtkWidget, false); gtk_widget_add_events(gtkWidget, GDK_EXPOSURE_MASK); - g_signal_connect_swapped(G_OBJECT(gtkWidget), "expose_event", G_CALLBACK(Canvas_expose), (gpointer)this); -} - -void pCanvas::redraw() { - if(gtk_widget_get_realized(gtkWidget) == false) return; - uint32_t *rgb = bufferRGB, *bgr = bufferBGR; - for(unsigned y = gtkWidget->allocation.height; y; y--) { - for(unsigned x = gtkWidget->allocation.width; x; x--) { - uint32_t pixel = *rgb++; - *bgr++ = ((pixel << 16) & 0xff0000) | (pixel & 0x00ff00) | ((pixel >> 16) & 0x0000ff); - } - } - - gdk_draw_rgb_32_image( - gtkWidget->window, - gtkWidget->style->fg_gc[GTK_WIDGET_STATE(gtkWidget)], - 0, 0, gtkWidget->allocation.width, gtkWidget->allocation.height, - GDK_RGB_DITHER_NONE, (guchar*)bufferBGR, sizeof(uint32_t) * gtkWidget->allocation.width - ); + g_signal_connect(G_OBJECT(gtkWidget), "expose_event", G_CALLBACK(Canvas_expose), (gpointer)this); } diff --git a/snespurify/phoenix/gtk/widget/combo-box.cpp b/snespurify/phoenix/gtk/widget/combo-box.cpp index 0ea1e200..348e95d0 100755 --- a/snespurify/phoenix/gtk/widget/combo-box.cpp +++ b/snespurify/phoenix/gtk/widget/combo-box.cpp @@ -13,14 +13,12 @@ Geometry pComboBox::minimumGeometry() { foreach(item, comboBox.state.text) maximumWidth = max(maximumWidth, font.geometry(item).width); Geometry geometry = font.geometry(" "); - return { 0, 0, maximumWidth + 44, geometry.height + 10 }; + return { 0, 0, maximumWidth + 44, geometry.height + 12 }; } void pComboBox::reset() { locked = true; - for(signed n = itemCounter - 1; n >= 0; n--) { - gtk_combo_box_remove_text(GTK_COMBO_BOX(gtkWidget), n); - } + gtk_list_store_clear(GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(gtkWidget)))); itemCounter = 0; locked = false; } diff --git a/snespurify/phoenix/gtk/widget/hex-edit.cpp b/snespurify/phoenix/gtk/widget/hex-edit.cpp index 481ab77d..7aa61a07 100755 --- a/snespurify/phoenix/gtk/widget/hex-edit.cpp +++ b/snespurify/phoenix/gtk/widget/hex-edit.cpp @@ -112,17 +112,17 @@ bool pHexEdit::keyPress(unsigned scancode) { unsigned cursorY = position / lineWidth; unsigned cursorX = position % lineWidth; - if(scancode == GDK_Home) { + if(scancode == GDK_KEY_Home) { setCursorPosition(cursorY * lineWidth + 10); return true; } - if(scancode == GDK_End) { + if(scancode == GDK_KEY_End) { setCursorPosition(cursorY * lineWidth + 10 + (hexEdit.state.columns * 3 - 1)); return true; } - if(scancode == GDK_Up) { + if(scancode == GDK_KEY_Up) { if(cursorY != 0) return false; signed newOffset = hexEdit.state.offset - hexEdit.state.columns; @@ -133,7 +133,7 @@ bool pHexEdit::keyPress(unsigned scancode) { return true; } - if(scancode == GDK_Down) { + if(scancode == GDK_KEY_Down) { if(cursorY != hexEdit.state.rows - 1) return false; signed newOffset = hexEdit.state.offset + hexEdit.state.columns; @@ -144,7 +144,7 @@ bool pHexEdit::keyPress(unsigned scancode) { return true; } - if(scancode == GDK_Page_Up) { + if(scancode == GDK_KEY_Page_Up) { signed newOffset = hexEdit.state.offset - hexEdit.state.columns * hexEdit.state.rows; if(newOffset >= 0) { hexEdit.setOffset(newOffset); @@ -155,7 +155,7 @@ bool pHexEdit::keyPress(unsigned scancode) { return true; } - if(scancode == GDK_Page_Down) { + if(scancode == GDK_KEY_Page_Down) { signed newOffset = hexEdit.state.offset + hexEdit.state.columns * hexEdit.state.rows; for(unsigned n = 0; n < hexEdit.state.rows; n++) { if(newOffset + hexEdit.state.columns * hexEdit.state.rows - (hexEdit.state.columns - 1) <= hexEdit.state.length) { diff --git a/snespurify/phoenix/gtk/widget/horizontal-scroll-bar.cpp b/snespurify/phoenix/gtk/widget/horizontal-scroll-bar.cpp new file mode 100755 index 00000000..f260cb58 --- /dev/null +++ b/snespurify/phoenix/gtk/widget/horizontal-scroll-bar.cpp @@ -0,0 +1,29 @@ +static void HorizontalScrollBar_change(HorizontalScrollBar *self) { + if(self->state.position == self->position()) return; + self->state.position = self->position(); + if(self->onChange) self->onChange(); +} + +Geometry pHorizontalScrollBar::minimumGeometry() { + return { 0, 0, 0, 20 }; +} + +unsigned pHorizontalScrollBar::position() { + return (unsigned)gtk_range_get_value(GTK_RANGE(gtkWidget)); +} + +void pHorizontalScrollBar::setLength(unsigned length) { + length += length == 0; + gtk_range_set_range(GTK_RANGE(gtkWidget), 0, length - 1); + gtk_range_set_increments(GTK_RANGE(gtkWidget), 1, length >> 3); +} + +void pHorizontalScrollBar::setPosition(unsigned position) { + gtk_range_set_value(GTK_RANGE(gtkWidget), position); +} + +void pHorizontalScrollBar::constructor() { + gtkWidget = gtk_hscrollbar_new(0); + setLength(101); + g_signal_connect_swapped(G_OBJECT(gtkWidget), "value-changed", G_CALLBACK(HorizontalScrollBar_change), (gpointer)&horizontalScrollBar); +} diff --git a/snespurify/phoenix/gtk/widget/horizontal-slider.cpp b/snespurify/phoenix/gtk/widget/horizontal-slider.cpp index 89a17a8a..4541b6fd 100755 --- a/snespurify/phoenix/gtk/widget/horizontal-slider.cpp +++ b/snespurify/phoenix/gtk/widget/horizontal-slider.cpp @@ -15,6 +15,7 @@ unsigned pHorizontalSlider::position() { void pHorizontalSlider::setLength(unsigned length) { length += length == 0; gtk_range_set_range(GTK_RANGE(gtkWidget), 0, length - 1); + gtk_range_set_increments(GTK_RANGE(gtkWidget), 1, length >> 3); } void pHorizontalSlider::setPosition(unsigned position) { @@ -24,5 +25,6 @@ void pHorizontalSlider::setPosition(unsigned position) { void pHorizontalSlider::constructor() { gtkWidget = gtk_hscale_new_with_range(0, 100, 1); gtk_scale_set_draw_value(GTK_SCALE(gtkWidget), false); + setLength(101); g_signal_connect_swapped(G_OBJECT(gtkWidget), "value-changed", G_CALLBACK(HorizontalSlider_change), (gpointer)&horizontalSlider); } diff --git a/snespurify/phoenix/gtk/widget/line-edit.cpp b/snespurify/phoenix/gtk/widget/line-edit.cpp index e783b3e2..e630b3f5 100755 --- a/snespurify/phoenix/gtk/widget/line-edit.cpp +++ b/snespurify/phoenix/gtk/widget/line-edit.cpp @@ -13,7 +13,7 @@ Geometry pLineEdit::minimumGeometry() { } void pLineEdit::setEditable(bool editable) { - gtk_entry_set_editable(GTK_ENTRY(gtkWidget), editable); + gtk_editable_set_editable(GTK_EDITABLE(gtkWidget), editable); } void pLineEdit::setText(const string &text) { diff --git a/snespurify/phoenix/gtk/widget/vertical-scroll-bar.cpp b/snespurify/phoenix/gtk/widget/vertical-scroll-bar.cpp new file mode 100755 index 00000000..bde3b73f --- /dev/null +++ b/snespurify/phoenix/gtk/widget/vertical-scroll-bar.cpp @@ -0,0 +1,29 @@ +static void VerticalScrollBar_change(VerticalScrollBar *self) { + if(self->state.position == self->position()) return; + self->state.position = self->position(); + if(self->onChange) self->onChange(); +} + +Geometry pVerticalScrollBar::minimumGeometry() { + return { 0, 0, 20, 0 }; +} + +unsigned pVerticalScrollBar::position() { + return (unsigned)gtk_range_get_value(GTK_RANGE(gtkWidget)); +} + +void pVerticalScrollBar::setLength(unsigned length) { + length += length == 0; + gtk_range_set_range(GTK_RANGE(gtkWidget), 0, length - 1); + gtk_range_set_increments(GTK_RANGE(gtkWidget), 1, length >> 3); +} + +void pVerticalScrollBar::setPosition(unsigned position) { + gtk_range_set_value(GTK_RANGE(gtkWidget), position); +} + +void pVerticalScrollBar::constructor() { + gtkWidget = gtk_vscrollbar_new(0); + setLength(101); + g_signal_connect_swapped(G_OBJECT(gtkWidget), "value-changed", G_CALLBACK(VerticalScrollBar_change), (gpointer)&verticalScrollBar); +} diff --git a/snespurify/phoenix/gtk/widget/vertical-slider.cpp b/snespurify/phoenix/gtk/widget/vertical-slider.cpp index b19632f7..ebe59ee7 100755 --- a/snespurify/phoenix/gtk/widget/vertical-slider.cpp +++ b/snespurify/phoenix/gtk/widget/vertical-slider.cpp @@ -15,6 +15,7 @@ unsigned pVerticalSlider::position() { void pVerticalSlider::setLength(unsigned length) { length += length == 0; gtk_range_set_range(GTK_RANGE(gtkWidget), 0, length - 1); + gtk_range_set_increments(GTK_RANGE(gtkWidget), 1, length >> 3); } void pVerticalSlider::setPosition(unsigned position) { @@ -24,5 +25,6 @@ void pVerticalSlider::setPosition(unsigned position) { void pVerticalSlider::constructor() { gtkWidget = gtk_vscale_new_with_range(0, 100, 1); gtk_scale_set_draw_value(GTK_SCALE(gtkWidget), false); + setLength(101); g_signal_connect_swapped(G_OBJECT(gtkWidget), "value-changed", G_CALLBACK(VerticalSlider_change), (gpointer)&verticalSlider); } diff --git a/snespurify/phoenix/gtk/widget/viewport.cpp b/snespurify/phoenix/gtk/widget/viewport.cpp index fd3bae57..7683c7f9 100755 --- a/snespurify/phoenix/gtk/widget/viewport.cpp +++ b/snespurify/phoenix/gtk/widget/viewport.cpp @@ -1,5 +1,5 @@ uintptr_t pViewport::handle() { - return GDK_WINDOW_XID(gtkWidget->window); + return GDK_WINDOW_XID(gtk_widget_get_window(gtkWidget)); } void pViewport::constructor() { diff --git a/snespurify/phoenix/gtk/window.cpp b/snespurify/phoenix/gtk/window.cpp index 632929dc..85beae54 100755 --- a/snespurify/phoenix/gtk/window.cpp +++ b/snespurify/phoenix/gtk/window.cpp @@ -1,70 +1,79 @@ static void Action_setFont(GtkWidget *widget, gpointer font); static void Widget_setFont(GtkWidget *widget, gpointer font); -static gint Window_close(Window *window) { +static gint Window_close(GtkWidget *widget, GdkEvent *event, Window *window) { if(window->onClose) window->onClose(); window->setVisible(false); return true; } -static gboolean Window_configure(Window *window) { +static gboolean Window_expose(GtkWidget *widget, GdkEvent *event, Window *window) { + cairo_t *context = gdk_cairo_create(widget->window); + + Color color = window->backgroundColor(); + double red = (double)color.red / 255.0; + double green = (double)color.green / 255.0; + double blue = (double)color.blue / 255.0; + double alpha = (double)color.alpha / 255.0; + + if(gdk_screen_is_composited(gdk_screen_get_default())) { + cairo_set_source_rgba(context, red, green, blue, alpha); + } else { + cairo_set_source_rgb(context, red, green, blue); + } + + cairo_set_operator(context, CAIRO_OPERATOR_SOURCE); + cairo_paint(context); + cairo_destroy(context); + + return false; +} + +static gboolean Window_configure(GtkWidget *widget, GdkEvent *event, Window *window) { if(gtk_widget_get_realized(window->p.widget) == false) return false; + GdkWindow *gdkWindow = gtk_widget_get_window(widget); //update geometry settings - Display *display = XOpenDisplay(0); - XWindowAttributes attributes, parentAttributes; - XGetWindowAttributes(display, GDK_WINDOW_XID(window->p.widget->window), &attributes); - X11Window rootWindow, parentWindow, *childWindow = 0; - unsigned int childCount; - XQueryTree(display, GDK_WINDOW_XID(window->p.widget->window), &rootWindow, &parentWindow, &childWindow, &childCount); - XGetWindowAttributes(display, parentWindow, &parentAttributes); - if(childWindow) XFree(childWindow); - XCloseDisplay(display); + GdkRectangle border, client; + gdk_window_get_frame_extents(gdkWindow, &border); + gdk_window_get_geometry(gdkWindow, 0, 0, &client.width, &client.height, 0); + gdk_window_get_origin(gdkWindow, &client.x, &client.y); - settings.frameGeometryX = attributes.x; - settings.frameGeometryY = attributes.y; - settings.frameGeometryWidth = parentAttributes.width - attributes.width; - settings.frameGeometryHeight = parentAttributes.height - attributes.height; - - GtkAllocation menuAllocation, statusAllocation; - gtk_widget_get_allocation(window->p.menu, &menuAllocation); - gtk_widget_get_allocation(window->p.status, &statusAllocation); - - if(menuAllocation.height > 1) settings.menuGeometryHeight = menuAllocation.height; - if(statusAllocation.height > 1) settings.statusGeometryHeight = statusAllocation.height; - - //calculate current window position - signed eventX = parentAttributes.x + attributes.x; - signed eventY = parentAttributes.y + attributes.y + window->p.menuHeight(); - unsigned eventWidth = attributes.width; - unsigned eventHeight = attributes.height - window->p.menuHeight() - window->p.statusHeight(); + settings.frameGeometryX = client.x - border.x; + settings.frameGeometryY = client.y - border.y; + settings.frameGeometryWidth = border.width - client.width; + settings.frameGeometryHeight = border.height - client.height; //move - if(window->p.locked == false && window->state.fullScreen == false) { - if(window->state.geometry.x != eventX || window->state.geometry.y != eventY) { - window->state.geometry.x = eventX; - window->state.geometry.y = eventY; + if(event->configure.x != window->p.lastConfigure.x + || event->configure.y != window->p.lastConfigure.y + ) { + if(window->state.fullScreen == false) { + window->state.geometry.x = client.x; + window->state.geometry.y = client.y + window->p.menuHeight(); } + if(window->p.locked == false && window->onMove) window->onMove(); } - if(window->onMove) window->onMove(); - //size - if(window->p.locked == false && window->state.fullScreen == false) { - if(window->state.geometry.width != eventWidth || window->state.geometry.height != eventHeight) { - window->state.geometry.width = eventWidth; - window->state.geometry.height = eventHeight; + if(event->configure.width != window->p.lastConfigure.width + || event->configure.height != window->p.lastConfigure.height + ) { + if(window->state.fullScreen == false) { + window->state.geometry.width = client.width; + window->state.geometry.height = client.height - window->p.menuHeight() - window->p.statusHeight(); } + + foreach(layout, window->state.layout) { + Geometry geometry = window->geometry(); + geometry.x = geometry.y = 0; + layout.setGeometry(geometry); + } + + if(window->p.locked == false && window->onSize) window->onSize(); } - foreach(layout, window->state.layout) { - Geometry geometry = window->geometry(); - geometry.x = geometry.y = 0; - layout.setGeometry(geometry); - } - - if(window->onSize) window->onSize(); - + window->p.lastConfigure = event->configure; return false; } @@ -77,7 +86,7 @@ void pWindow::append(Layout &layout) { void pWindow::append(Menu &subMenu) { if(window.state.menuFont) subMenu.p.setFont(*window.state.menuFont); - gtk_menu_bar_append(menu, subMenu.p.widget); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), subMenu.p.widget); gtk_widget_show(subMenu.p.widget); } @@ -90,6 +99,12 @@ void pWindow::append(Widget &widget) { widget.setVisible(); } +Color pWindow::backgroundColor() { + if(window.state.backgroundColorOverride) return window.state.backgroundColor; + GdkColor color = widget->style->bg[GTK_STATE_NORMAL]; + return { (uint8_t)(color.red >> 8), (uint8_t)(color.green >> 8), (uint8_t)(color.blue >> 8), 255 }; +} + Geometry pWindow::frameMargin() { if(window.state.fullScreen) return { 0, menuHeight(), 0, menuHeight() + statusHeight() }; return { @@ -111,13 +126,13 @@ Geometry pWindow::geometry() { return window.state.geometry; } -void pWindow::setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue) { - GdkColor color; - color.pixel = (red << 16) | (green << 8) | (blue << 0); - color.red = (red << 8) | (red << 0); - color.green = (green << 8) | (green << 0); - color.blue = (blue << 8) | (blue << 0); - gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, &color); +void pWindow::setBackgroundColor(const Color &color) { + GdkColor gdkColor; + gdkColor.pixel = (color.red << 16) | (color.green << 8) | (color.blue << 0); + gdkColor.red = (color.red << 8) | (color.red << 0); + gdkColor.green = (color.green << 8) | (color.green << 0); + gdkColor.blue = (color.blue << 8) | (color.blue << 0); + gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, &gdkColor); } void pWindow::setFocused() { @@ -129,14 +144,12 @@ void pWindow::setFullScreen(bool fullScreen) { gtk_window_unfullscreen(GTK_WINDOW(widget)); gtk_window_set_resizable(GTK_WINDOW(widget), window.state.resizable); gtk_window_set_decorated(GTK_WINDOW(widget), true); - locked = true; for(unsigned n = 0; n < 4; n++) { setGeometry(window.state.geometry); gtk_widget_set_size_request(widget, -1, -1); OS::processEvents(); usleep(2000); } - locked = false; } else { gtk_window_fullscreen(GTK_WINDOW(widget)); gtk_window_set_decorated(GTK_WINDOW(widget), false); @@ -198,7 +211,15 @@ void pWindow::setWidgetFont(Font &font) { } void pWindow::constructor() { + memset(&lastConfigure, 0, sizeof(GdkEventConfigure)); widget = gtk_window_new(GTK_WINDOW_TOPLEVEL); + + if(gdk_screen_is_composited(gdk_screen_get_default())) { + gtk_widget_set_colormap(widget, gdk_screen_get_rgba_colormap(gdk_screen_get_default())); + } else { + gtk_widget_set_colormap(widget, gdk_screen_get_rgb_colormap(gdk_screen_get_default())); + } + gtk_window_set_resizable(GTK_WINDOW(widget), true); gtk_widget_set_app_paintable(widget, true); gtk_widget_add_events(widget, GDK_CONFIGURE); @@ -224,8 +245,9 @@ void pWindow::constructor() { setTitle(""); setGeometry(window.state.geometry); - g_signal_connect_swapped(G_OBJECT(widget), "delete-event", G_CALLBACK(Window_close), (gpointer)&window); - g_signal_connect_swapped(G_OBJECT(widget), "configure-event", G_CALLBACK(Window_configure), (gpointer)&window); + g_signal_connect(G_OBJECT(widget), "delete-event", G_CALLBACK(Window_close), (gpointer)&window); + g_signal_connect(G_OBJECT(widget), "expose-event", G_CALLBACK(Window_expose), (gpointer)&window); + g_signal_connect(G_OBJECT(widget), "configure-event", G_CALLBACK(Window_configure), (gpointer)&window); } unsigned pWindow::menuHeight() { diff --git a/snespurify/phoenix/nall/Makefile b/snespurify/phoenix/nall/Makefile deleted file mode 100755 index 9a93bd23..00000000 --- a/snespurify/phoenix/nall/Makefile +++ /dev/null @@ -1,109 +0,0 @@ -# Makefile -# author: byuu -# license: public domain - -[A-Z] = A B C D E F G H I J K L M N O P Q R S T U V W X Y Z -[a-z] = a b c d e f g h i j k l m n o p q r s t u v w x y z -[0-9] = 0 1 2 3 4 5 6 7 8 9 -[markup] = ` ~ ! @ \# $$ % ^ & * ( ) - _ = + [ { ] } \ | ; : ' " , < . > / ? -[all] = $([A-Z]) $([a-z]) $([0-9]) $([markup]) -[space] := -[space] += - -##### -# platform detection -##### - -ifeq ($(platform),) - uname := $(shell uname -a) - ifeq ($(uname),) - platform := win - delete = del $(subst /,\,$1) - else ifneq ($(findstring Darwin,$(uname)),) - platform := osx - delete = rm -f $1 - else - platform := x - delete = rm -f $1 - endif -endif - -ifeq ($(compiler),) - ifeq ($(platform),win) - compiler := gcc - else ifeq ($(platform),osx) - compiler := gcc-mp-4.5 - else - compiler := gcc-4.5 - endif -endif - -ifeq ($(prefix),) - prefix := /usr/local -endif - -##### -# function rwildcard(directory, pattern) -##### -rwildcard = \ - $(strip \ - $(filter $(if $2,$2,%), \ - $(foreach f, \ - $(wildcard $1*), \ - $(eval t = $(call rwildcard,$f/)) \ - $(if $t,$t,$f) \ - ) \ - ) \ - ) - -##### -# function strtr(source, from, to) -##### -strtr = \ - $(eval __temp := $1) \ - $(strip \ - $(foreach c, \ - $(join $(addsuffix :,$2),$3), \ - $(eval __temp := \ - $(subst $(word 1,$(subst :, ,$c)),$(word 2,$(subst :, ,$c)),$(__temp)) \ - ) \ - ) \ - $(__temp) \ - ) - -##### -# function strupper(source) -##### -strupper = $(call strtr,$1,$([a-z]),$([A-Z])) - -##### -# function strlower(source) -##### -strlower = $(call strtr,$1,$([A-Z]),$([a-z])) - -##### -# function strlen(source) -##### -strlen = \ - $(eval __temp := $(subst $([space]),_,$1)) \ - $(words \ - $(strip \ - $(foreach c, \ - $([all]), \ - $(eval __temp := \ - $(subst $c,$c ,$(__temp)) \ - ) \ - ) \ - $(__temp) \ - ) \ - ) - -##### -# function streq(source) -##### -streq = $(if $(filter-out xx,x$(subst $1,,$2)$(subst $2,,$1)x),,1) - -##### -# function strne(source) -##### -strne = $(if $(filter-out xx,x$(subst $1,,$2)$(subst $2,,$1)x),1,) diff --git a/snespurify/phoenix/nall/algorithm.hpp b/snespurify/phoenix/nall/algorithm.hpp deleted file mode 100755 index 037f0bb7..00000000 --- a/snespurify/phoenix/nall/algorithm.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef NALL_ALGORITHM_HPP -#define NALL_ALGORITHM_HPP - -#undef min -#undef max - -namespace nall { - template T min(const T &t, const U &u) { - return t < u ? t : u; - } - - template T max(const T &t, const U &u) { - return t > u ? t : u; - } -} - -#endif diff --git a/snespurify/phoenix/nall/any.hpp b/snespurify/phoenix/nall/any.hpp deleted file mode 100755 index b31cff3c..00000000 --- a/snespurify/phoenix/nall/any.hpp +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef NALL_ANY_HPP -#define NALL_ANY_HPP - -#include -#include -#include - -namespace nall { - class any { - public: - bool empty() const { return container; } - const std::type_info& type() const { return container ? container->type() : typeid(void); } - - template any& operator=(const T& value_) { - typedef typename static_if< - std::is_array::value, - typename std::remove_extent::type>::type*, - T - >::type auto_t; - - if(type() == typeid(auto_t)) { - static_cast*>(container)->value = (auto_t)value_; - } else { - if(container) delete container; - container = new holder((auto_t)value_); - } - - return *this; - } - - any() : container(0) {} - template any(const T& value_) : container(0) { operator=(value_); } - - private: - struct placeholder { - virtual const std::type_info& type() const = 0; - } *container; - - template struct holder : placeholder { - T value; - const std::type_info& type() const { return typeid(T); } - holder(const T& value_) : value(value_) {} - }; - - template friend T any_cast(any&); - template friend T any_cast(const any&); - template friend T* any_cast(any*); - template friend const T* any_cast(const any*); - }; - - template T any_cast(any &value) { - typedef typename std::remove_reference::type nonref; - if(value.type() != typeid(nonref)) throw; - return static_cast*>(value.container)->value; - } - - template T any_cast(const any &value) { - typedef const typename std::remove_reference::type nonref; - if(value.type() != typeid(nonref)) throw; - return static_cast*>(value.container)->value; - } - - template T* any_cast(any *value) { - if(!value || value->type() != typeid(T)) return 0; - return &static_cast*>(value->container)->value; - } - - template const T* any_cast(const any *value) { - if(!value || value->type() != typeid(T)) return 0; - return &static_cast*>(value->container)->value; - } -} - -#endif diff --git a/snespurify/phoenix/nall/array.hpp b/snespurify/phoenix/nall/array.hpp deleted file mode 100755 index 9cfe7758..00000000 --- a/snespurify/phoenix/nall/array.hpp +++ /dev/null @@ -1,141 +0,0 @@ -#ifndef NALL_ARRAY_HPP -#define NALL_ARRAY_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace nall { - //dynamic vector array - //neither constructor nor destructor is ever invoked; - //thus, this should only be used for POD objects. - template class array { - protected: - T *pool; - unsigned poolsize, buffersize; - - public: - unsigned size() const { return buffersize; } - unsigned capacity() const { return poolsize; } - - void reset() { - if(pool) free(pool); - pool = 0; - poolsize = 0; - buffersize = 0; - } - - void reserve(unsigned newsize) { - if(newsize == poolsize) return; - - pool = (T*)realloc(pool, newsize * sizeof(T)); - poolsize = newsize; - buffersize = min(buffersize, newsize); - } - - void resize(unsigned newsize) { - if(newsize > poolsize) reserve(bit::round(newsize)); //round reserve size up to power of 2 - buffersize = newsize; - } - - T* get(unsigned minsize = 0) { - if(minsize > buffersize) resize(minsize); - if(minsize > buffersize) throw "array[] out of bounds"; - return pool; - } - - void append(const T data) { - operator[](buffersize) = data; - } - - template void insert(unsigned index, const U list) { - unsigned listsize = container_size(list); - resize(buffersize + listsize); - memmove(pool + index + listsize, pool + index, (buffersize - index) * sizeof(T)); - foreach(item, list) pool[index++] = item; - } - - void insert(unsigned index, const T item) { - insert(index, array{ item }); - } - - void remove(unsigned index, unsigned count = 1) { - for(unsigned i = index; count + i < buffersize; i++) { - pool[i] = pool[count + i]; - } - if(count + index >= buffersize) resize(index); //every element >= index was removed - else resize(buffersize - count); - } - - optional find(const T data) { - for(unsigned i = 0; i < size(); i++) if(pool[i] == data) return { true, i }; - return { false, 0 }; - } - - void clear() { - memset(pool, 0, buffersize * sizeof(T)); - } - - array() : pool(0), poolsize(0), buffersize(0) { - } - - array(std::initializer_list list) : pool(0), poolsize(0), buffersize(0) { - for(const T *p = list.begin(); p != list.end(); ++p) append(*p); - } - - ~array() { - reset(); - } - - //copy - array& operator=(const array &source) { - if(pool) free(pool); - buffersize = source.buffersize; - poolsize = source.poolsize; - pool = (T*)malloc(sizeof(T) * poolsize); //allocate entire pool size, - memcpy(pool, source.pool, sizeof(T) * buffersize); //... but only copy used pool objects - return *this; - } - - array(const array &source) : pool(0), poolsize(0), buffersize(0) { - operator=(source); - } - - //move - array& operator=(array &&source) { - if(pool) free(pool); - pool = source.pool; - poolsize = source.poolsize; - buffersize = source.buffersize; - source.pool = 0; - source.reset(); - return *this; - } - - array(array &&source) : pool(0), poolsize(0), buffersize(0) { - operator=(std::move(source)); - } - - //index - inline T& operator[](unsigned index) { - if(index >= buffersize) resize(index + 1); - if(index >= buffersize) throw "array[] out of bounds"; - return pool[index]; - } - - inline const T& operator[](unsigned index) const { - if(index >= buffersize) throw "array[] out of bounds"; - return pool[index]; - } - }; - - template struct has_size> { enum { value = true }; }; -} - -#endif diff --git a/snespurify/phoenix/nall/base64.hpp b/snespurify/phoenix/nall/base64.hpp deleted file mode 100755 index e41c87b7..00000000 --- a/snespurify/phoenix/nall/base64.hpp +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef NALL_BASE64_HPP -#define NALL_BASE64_HPP - -#include -#include - -namespace nall { - class base64 { - public: - static bool encode(char *&output, const uint8_t* input, unsigned inlength) { - output = new char[inlength * 8 / 6 + 6](); - - unsigned i = 0, o = 0; - while(i < inlength) { - switch(i % 3) { - case 0: { - output[o++] = enc(input[i] >> 2); - output[o] = enc((input[i] & 3) << 4); - } break; - - case 1: { - uint8_t prev = dec(output[o]); - output[o++] = enc(prev + (input[i] >> 4)); - output[o] = enc((input[i] & 15) << 2); - } break; - - case 2: { - uint8_t prev = dec(output[o]); - output[o++] = enc(prev + (input[i] >> 6)); - output[o++] = enc(input[i] & 63); - } break; - } - - i++; - } - - return true; - } - - static bool decode(uint8_t *&output, unsigned &outlength, const char *input) { - unsigned inlength = strlen(input), infix = 0; - output = new uint8_t[inlength](); - - unsigned i = 0, o = 0; - while(i < inlength) { - uint8_t x = dec(input[i]); - - switch(i++ & 3) { - case 0: { - output[o] = x << 2; - } break; - - case 1: { - output[o++] |= x >> 4; - output[o] = (x & 15) << 4; - } break; - - case 2: { - output[o++] |= x >> 2; - output[o] = (x & 3) << 6; - } break; - - case 3: { - output[o++] |= x; - } break; - } - } - - outlength = o; - return true; - } - - private: - static char enc(uint8_t n) { - static char lookup_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; - return lookup_table[n & 63]; - } - - static uint8_t dec(char n) { - if(n >= 'A' && n <= 'Z') return n - 'A'; - if(n >= 'a' && n <= 'z') return n - 'a' + 26; - if(n >= '0' && n <= '9') return n - '0' + 52; - if(n == '-') return 62; - if(n == '_') return 63; - return 0; - } - }; -} - -#endif diff --git a/snespurify/phoenix/nall/bit.hpp b/snespurify/phoenix/nall/bit.hpp deleted file mode 100755 index ca6ea29a..00000000 --- a/snespurify/phoenix/nall/bit.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef NALL_BIT_HPP -#define NALL_BIT_HPP - -namespace nall { - template inline unsigned uclamp(const unsigned x) { - enum { y = (1U << (bits - 1)) + ((1U << (bits - 1)) - 1) }; - return y + ((x - y) & -(x < y)); //min(x, y); - } - - template inline unsigned uclip(const unsigned x) { - enum { m = (1U << (bits - 1)) + ((1U << (bits - 1)) - 1) }; - return (x & m); - } - - template inline signed sclamp(const signed x) { - enum { b = 1U << (bits - 1), m = (1U << (bits - 1)) - 1 }; - return (x > m) ? m : (x < -b) ? -b : x; - } - - template inline signed sclip(const signed x) { - enum { b = 1U << (bits - 1), m = (1U << bits) - 1 }; - return ((x & m) ^ b) - b; - } - - namespace bit { - //lowest(0b1110) == 0b0010 - template inline T lowest(const T x) { - return x & -x; - } - - //clear_lowest(0b1110) == 0b1100 - template inline T clear_lowest(const T x) { - return x & (x - 1); - } - - //set_lowest(0b0101) == 0b0111 - template inline T set_lowest(const T x) { - return x | (x + 1); - } - - //round up to next highest single bit: - //round(15) == 16, round(16) == 16, round(17) == 32 - inline unsigned round(unsigned x) { - if((x & (x - 1)) == 0) return x; - while(x & (x - 1)) x &= x - 1; - return x << 1; - } - } -} - -#endif diff --git a/snespurify/phoenix/nall/concept.hpp b/snespurify/phoenix/nall/concept.hpp deleted file mode 100755 index 47167e21..00000000 --- a/snespurify/phoenix/nall/concept.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef NALL_CONCEPT_HPP -#define NALL_CONCEPT_HPP - -#include -#include - -namespace nall { - //unsigned count() const; - template struct has_count { enum { value = false }; }; - - //unsigned length() const; - template struct has_length { enum { value = false }; }; - - //unsigned size() const; - template struct has_size { enum { value = false }; }; - - template unsigned container_size(const T& object, typename mp_enable_if>::type = 0) { - return object.count(); - } - - template unsigned container_size(const T& object, typename mp_enable_if>::type = 0) { - return object.length(); - } - - template unsigned container_size(const T& object, typename mp_enable_if>::type = 0) { - return object.size(); - } - - template unsigned container_size(const T& object, typename mp_enable_if>::type = 0) { - return sizeof(T) / sizeof(typename std::remove_extent::type); - } -} - -#endif diff --git a/snespurify/phoenix/nall/config.hpp b/snespurify/phoenix/nall/config.hpp deleted file mode 100755 index b8381b16..00000000 --- a/snespurify/phoenix/nall/config.hpp +++ /dev/null @@ -1,123 +0,0 @@ -#ifndef NALL_CONFIG_HPP -#define NALL_CONFIG_HPP - -#include -#include -#include - -namespace nall { - namespace configuration_traits { - template struct is_boolean { enum { value = false }; }; - template<> struct is_boolean { enum { value = true }; }; - - template struct is_signed { enum { value = false }; }; - template<> struct is_signed { enum { value = true }; }; - - template struct is_unsigned { enum { value = false }; }; - template<> struct is_unsigned { enum { value = true }; }; - - template struct is_double { enum { value = false }; }; - template<> struct is_double { enum { value = true }; }; - - template struct is_string { enum { value = false }; }; - template<> struct is_string { enum { value = true }; }; - } - - class configuration { - public: - enum type_t { boolean_t, signed_t, unsigned_t, double_t, string_t, unknown_t }; - struct item_t { - uintptr_t data; - string name; - string desc; - type_t type; - - string get() const { - switch(type) { - case boolean_t: return string() << *(bool*)data; - case signed_t: return string() << *(signed*)data; - case unsigned_t: return string() << *(unsigned*)data; - case double_t: return string() << *(double*)data; - case string_t: return string() << "\"" << *(string*)data << "\""; - } - return "???"; - } - - void set(string s) { - switch(type) { - case boolean_t: *(bool*)data = (s == "true"); break; - case signed_t: *(signed*)data = integer(s); break; - case unsigned_t: *(unsigned*)data = decimal(s); break; - case double_t: *(double*)data = fp(s); break; - case string_t: s.trim("\""); *(string*)data = s; break; - } - } - }; - linear_vector list; - - template - void attach(T &data, const char *name, const char *desc = "") { - unsigned n = list.size(); - list[n].data = (uintptr_t)&data; - list[n].name = name; - list[n].desc = desc; - - if(configuration_traits::is_boolean::value) list[n].type = boolean_t; - else if(configuration_traits::is_signed::value) list[n].type = signed_t; - else if(configuration_traits::is_unsigned::value) list[n].type = unsigned_t; - else if(configuration_traits::is_double::value) list[n].type = double_t; - else if(configuration_traits::is_string::value) list[n].type = string_t; - else list[n].type = unknown_t; - } - - virtual bool load(const char *filename) { - string data; - if(data.readfile(filename) == true) { - data.replace("\r", ""); - lstring line; - line.split("\n", data); - - for(unsigned i = 0; i < line.size(); i++) { - if(auto position = qstrpos(line[i], "#")) line[i][position()] = 0; - if(!qstrpos(line[i], " = ")) continue; - - lstring part; - part.qsplit(" = ", line[i]); - part[0].trim(); - part[1].trim(); - - for(unsigned n = 0; n < list.size(); n++) { - if(part[0] == list[n].name) { - list[n].set(part[1]); - break; - } - } - } - - return true; - } else { - return false; - } - } - - virtual bool save(const char *filename) const { - file fp; - if(fp.open(filename, file::mode::write)) { - for(unsigned i = 0; i < list.size(); i++) { - string output; - output << list[i].name << " = " << list[i].get(); - if(list[i].desc != "") output << " # " << list[i].desc; - output << "\r\n"; - fp.print(output); - } - - fp.close(); - return true; - } else { - return false; - } - } - }; -} - -#endif diff --git a/snespurify/phoenix/nall/crc32.hpp b/snespurify/phoenix/nall/crc32.hpp deleted file mode 100755 index ad36fbf6..00000000 --- a/snespurify/phoenix/nall/crc32.hpp +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef NALL_CRC32_HPP -#define NALL_CRC32_HPP - -#include - -namespace nall { - const uint32_t crc32_table[256] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, - 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, - 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, - 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, - 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, - 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, - 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, - 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, - 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, - 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, - 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, - 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, - 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, - 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, - 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, - 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, - 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, - 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d - }; - - inline uint32_t crc32_adjust(uint32_t crc32, uint8_t input) { - return ((crc32 >> 8) & 0x00ffffff) ^ crc32_table[(crc32 ^ input) & 0xff]; - } - - inline uint32_t crc32_calculate(const uint8_t *data, unsigned length) { - uint32_t crc32 = ~0; - for(unsigned i = 0; i < length; i++) { - crc32 = crc32_adjust(crc32, data[i]); - } - return ~crc32; - } -} - -#endif diff --git a/snespurify/phoenix/nall/detect.hpp b/snespurify/phoenix/nall/detect.hpp deleted file mode 100755 index b4991aaf..00000000 --- a/snespurify/phoenix/nall/detect.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef NALL_DETECT_HPP -#define NALL_DETECT_HPP - -/* Compiler detection */ - -#if defined(__GNUC__) - #define COMPILER_GCC -#elif defined(_MSC_VER) - #define COMPILER_VISUALC -#endif - -/* Platform detection */ - -#if defined(_WIN32) - #define PLATFORM_WIN -#elif defined(__APPLE__) - #define PLATFORM_OSX -#elif defined(linux) || defined(__sun__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) - #define PLATFORM_X -#endif - -/* Endian detection */ - -#if defined(__i386__) || defined(__amd64__) || defined(_M_IX86) || defined(_M_AMD64) - #define ARCH_LSB -#elif defined(__powerpc__) || defined(_M_PPC) || defined(__BIG_ENDIAN__) - #define ARCH_MSB -#endif - -#endif diff --git a/snespurify/phoenix/nall/dictionary.hpp b/snespurify/phoenix/nall/dictionary.hpp deleted file mode 100755 index dcb04151..00000000 --- a/snespurify/phoenix/nall/dictionary.hpp +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef NALL_DICTIONARY_HPP -#define NALL_DICTIONARY_HPP - -#include -#include -#include - -namespace nall { - class dictionary { - public: - string operator[](const char *input) { - for(unsigned i = 0; i < index_input.size(); i++) { - if(index_input[i] == input) return index_output[i]; - } - - //no match, use input; remove input identifier, if one exists - if(strbegin(input, "{{")) { - if(auto pos = strpos(input, "}}")) { - string temp = substr(input, pos() + 2); - return temp; - } - } - - return input; - } - - bool import(const char *filename) { - string data; - if(data.readfile(filename) == false) return false; - data.ltrim<1>("\xef\xbb\xbf"); //remove UTF-8 marker, if it exists - data.replace("\r", ""); - - lstring line; - line.split("\n", data); - for(unsigned i = 0; i < line.size(); i++) { - lstring part; - //format: "Input" = "Output" - part.qsplit("=", line[i]); - if(part.size() != 2) continue; - - //remove whitespace - part[0].trim(); - part[1].trim(); - - //remove quotes - part[0].trim<1>("\""); - part[1].trim<1>("\""); - - unsigned n = index_input.size(); - index_input[n] = part[0]; - index_output[n] = part[1]; - } - - return true; - } - - void reset() { - index_input.reset(); - index_output.reset(); - } - - ~dictionary() { - reset(); - } - - dictionary& operator=(const dictionary&) = delete; - dictionary(const dictionary&) = delete; - - protected: - lstring index_input; - lstring index_output; - }; -} - -#endif diff --git a/snespurify/phoenix/nall/directory.hpp b/snespurify/phoenix/nall/directory.hpp deleted file mode 100755 index df0bf086..00000000 --- a/snespurify/phoenix/nall/directory.hpp +++ /dev/null @@ -1,151 +0,0 @@ -#ifndef NALL_DIRECTORY_HPP -#define NALL_DIRECTORY_HPP - -#include -#include -#include - -#if defined(_WIN32) - #include -#else - #include - #include - #include -#endif - -namespace nall { - -struct directory { - static bool exists(const string &pathname); - static lstring folders(const string &pathname, const string &pattern = "*"); - static lstring files(const string &pathname, const string &pattern = "*"); - static lstring contents(const string &pathname, const string &pattern = "*"); -}; - -#if defined(_WIN32) - inline bool directory::exists(const string &pathname) { - DWORD result = GetFileAttributes(utf16_t(pathname)); - if(result == INVALID_FILE_ATTRIBUTES) return false; - return (result & FILE_ATTRIBUTE_DIRECTORY); - } - - inline lstring directory::folders(const string &pathname, const string &pattern) { - lstring list; - string path = pathname; - path.transform("/", "\\"); - if(!strend(path, "\\")) path.append("\\"); - path.append("*"); - HANDLE handle; - WIN32_FIND_DATA data; - handle = FindFirstFile(utf16_t(path), &data); - if(handle != INVALID_HANDLE_VALUE) { - if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) { - if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - string name = utf8_t(data.cFileName); - if(wildcard(name, pattern)) list.append(string(name, "/")); - } - } - while(FindNextFile(handle, &data) != false) { - if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) { - if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - string name = utf8_t(data.cFileName); - if(wildcard(name, pattern)) list.append(string(name, "/")); - } - } - } - FindClose(handle); - } - if(list.size() > 0) sort(&list[0], list.size()); - return list; - } - - inline lstring directory::files(const string &pathname, const string &pattern) { - lstring list; - string path = pathname; - path.transform("/", "\\"); - if(!strend(path, "\\")) path.append("\\"); - path.append("*"); - HANDLE handle; - WIN32_FIND_DATA data; - handle = FindFirstFile(utf16_t(path), &data); - if(handle != INVALID_HANDLE_VALUE) { - if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { - string name = utf8_t(data.cFileName); - if(wildcard(name, pattern)) list.append(name); - } - while(FindNextFile(handle, &data) != false) { - if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { - string name = utf8_t(data.cFileName); - if(wildcard(name, pattern)) list.append(name); - } - } - FindClose(handle); - } - if(list.size() > 0) sort(&list[0], list.size()); - return list; - } - - inline lstring directory::contents(const string &pathname, const string &pattern) { - lstring folders = directory::folders(pathname); //pattern search of contents() should only filter files - lstring files = directory::files(pathname, pattern); - foreach(file, files) folders.append(file); - return folders; - } -#else - inline bool directory::exists(const string &pathname) { - DIR *dp = opendir(pathname); - if(!dp) return false; - closedir(dp); - return true; - } - - inline lstring directory::folders(const string &pathname, const string &pattern) { - lstring list; - DIR *dp; - struct dirent *ep; - dp = opendir(pathname); - if(dp) { - while(ep = readdir(dp)) { - if(!strcmp(ep->d_name, ".")) continue; - if(!strcmp(ep->d_name, "..")) continue; - if(ep->d_type & DT_DIR) { - if(wildcard(ep->d_name, pattern)) list.append(string(ep->d_name, "/")); - } - } - closedir(dp); - } - if(list.size() > 0) sort(&list[0], list.size()); - return list; - - } - - inline lstring directory::files(const string &pathname, const string &pattern) { - lstring list; - DIR *dp; - struct dirent *ep; - dp = opendir(pathname); - if(dp) { - while(ep = readdir(dp)) { - if(!strcmp(ep->d_name, ".")) continue; - if(!strcmp(ep->d_name, "..")) continue; - if((ep->d_type & DT_DIR) == 0) { - if(wildcard(ep->d_name, pattern)) list.append(ep->d_name); - } - } - closedir(dp); - } - if(list.size() > 0) sort(&list[0], list.size()); - return list; - } - - inline lstring directory::contents(const string &pathname, const string &pattern) { - lstring folders = directory::folders(pathname); //pattern search of contents() should only filter files - lstring files = directory::files(pathname, pattern); - foreach(file, files) folders.append(file); - return folders; - } -#endif - -} - -#endif diff --git a/snespurify/phoenix/nall/dl.hpp b/snespurify/phoenix/nall/dl.hpp deleted file mode 100755 index ebfa5585..00000000 --- a/snespurify/phoenix/nall/dl.hpp +++ /dev/null @@ -1,115 +0,0 @@ -#ifndef NALL_DL_HPP -#define NALL_DL_HPP - -//dynamic linking support - -#include -#include -#include -#include - -#if defined(PLATFORM_X) || defined(PLATFORM_OSX) - #include -#elif defined(PLATFORM_WIN) - #include - #include -#endif - -namespace nall { - struct library { - bool opened() const { return handle; } - bool open(const char*, const char* = ""); - bool open_absolute(const char*); - void* sym(const char*); - void close(); - - library() : handle(0) {} - ~library() { close(); } - - library& operator=(const library&) = delete; - library(const library&) = delete; - - private: - uintptr_t handle; - }; - - #if defined(PLATFORM_X) - inline bool library::open(const char *name, const char *path) { - if(handle) close(); - handle = (uintptr_t)dlopen(string(path, *path && !strend(path, "/") ? "/" : "", "lib", name, ".so"), RTLD_LAZY); - if(!handle) handle = (uintptr_t)dlopen(string("/usr/local/lib/lib", name, ".so"), RTLD_LAZY); - return handle; - } - - inline bool library::open_absolute(const char *name) { - if(handle) close(); - handle = (uintptr_t)dlopen(name, RTLD_LAZY); - return handle; - } - - inline void* library::sym(const char *name) { - if(!handle) return 0; - return dlsym((void*)handle, name); - } - - inline void library::close() { - if(!handle) return; - dlclose((void*)handle); - handle = 0; - } - #elif defined(PLATFORM_OSX) - inline bool library::open(const char *name, const char *path) { - if(handle) close(); - handle = (uintptr_t)dlopen(string(path, *path && !strend(path, "/") ? "/" : "", "lib", name, ".dylib"), RTLD_LAZY); - if(!handle) handle = (uintptr_t)dlopen(string("/usr/local/lib/lib", name, ".dylib"), RTLD_LAZY); - return handle; - } - - inline bool library::open_absolute(const char *name) { - if(handle) close(); - handle = (uintptr_t)dlopen(name, RTLD_LAZY); - return handle; - } - - inline void* library::sym(const char *name) { - if(!handle) return 0; - return dlsym((void*)handle, name); - } - - inline void library::close() { - if(!handle) return; - dlclose((void*)handle); - handle = 0; - } - #elif defined(PLATFORM_WIN) - inline bool library::open(const char *name, const char *path) { - if(handle) close(); - string filepath(path, *path && !strend(path, "/") && !strend(path, "\\") ? "\\" : "", name, ".dll"); - handle = (uintptr_t)LoadLibraryW(utf16_t(filepath)); - return handle; - } - - inline bool library::open_absolute(const char *name) { - if(handle) close(); - handle = (uintptr_t)LoadLibraryW(utf16_t(name)); - return handle; - } - - inline void* library::sym(const char *name) { - if(!handle) return 0; - return (void*)GetProcAddress((HMODULE)handle, name); - } - - inline void library::close() { - if(!handle) return; - FreeLibrary((HMODULE)handle); - handle = 0; - } - #else - inline bool library::open(const char*, const char*) { return false; } - inline void* library::sym(const char*) { return 0; } - inline void library::close() {} - #endif -}; - -#endif diff --git a/snespurify/phoenix/nall/endian.hpp b/snespurify/phoenix/nall/endian.hpp deleted file mode 100755 index 40d15633..00000000 --- a/snespurify/phoenix/nall/endian.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef NALL_ENDIAN_HPP -#define NALL_ENDIAN_HPP - -#if !defined(ARCH_MSB) - //little-endian: uint8_t[] { 0x01, 0x02, 0x03, 0x04 } == 0x04030201 - #define order_lsb2(a,b) a,b - #define order_lsb3(a,b,c) a,b,c - #define order_lsb4(a,b,c,d) a,b,c,d - #define order_lsb5(a,b,c,d,e) a,b,c,d,e - #define order_lsb6(a,b,c,d,e,f) a,b,c,d,e,f - #define order_lsb7(a,b,c,d,e,f,g) a,b,c,d,e,f,g - #define order_lsb8(a,b,c,d,e,f,g,h) a,b,c,d,e,f,g,h - #define order_msb2(a,b) b,a - #define order_msb3(a,b,c) c,b,a - #define order_msb4(a,b,c,d) d,c,b,a - #define order_msb5(a,b,c,d,e) e,d,c,b,a - #define order_msb6(a,b,c,d,e,f) f,e,d,c,b,a - #define order_msb7(a,b,c,d,e,f,g) g,f,e,d,c,b,a - #define order_msb8(a,b,c,d,e,f,g,h) h,g,f,e,d,c,b,a -#else - //big-endian: uint8_t[] { 0x01, 0x02, 0x03, 0x04 } == 0x01020304 - #define order_lsb2(a,b) b,a - #define order_lsb3(a,b,c) c,b,a - #define order_lsb4(a,b,c,d) d,c,b,a - #define order_lsb5(a,b,c,d,e) e,d,c,b,a - #define order_lsb6(a,b,c,d,e,f) f,e,d,c,b,a - #define order_lsb7(a,b,c,d,e,f,g) g,f,e,d,c,b,a - #define order_lsb8(a,b,c,d,e,f,g,h) h,g,f,e,d,c,b,a - #define order_msb2(a,b) a,b - #define order_msb3(a,b,c) a,b,c - #define order_msb4(a,b,c,d) a,b,c,d - #define order_msb5(a,b,c,d,e) a,b,c,d,e - #define order_msb6(a,b,c,d,e,f) a,b,c,d,e,f - #define order_msb7(a,b,c,d,e,f,g) a,b,c,d,e,f,g - #define order_msb8(a,b,c,d,e,f,g,h) a,b,c,d,e,f,g,h -#endif - -#endif diff --git a/snespurify/phoenix/nall/file.hpp b/snespurify/phoenix/nall/file.hpp deleted file mode 100755 index 103c7d4a..00000000 --- a/snespurify/phoenix/nall/file.hpp +++ /dev/null @@ -1,261 +0,0 @@ -#ifndef NALL_FILE_HPP -#define NALL_FILE_HPP - -#include -#include - -#if !defined(_WIN32) - #include -#else - #include -#endif - -#include -#include -#include -#include - -namespace nall { - inline FILE* fopen_utf8(const char *utf8_filename, const char *mode) { - #if !defined(_WIN32) - return fopen(utf8_filename, mode); - #else - return _wfopen(utf16_t(utf8_filename), utf16_t(mode)); - #endif - } - - class file { - public: - enum class mode : unsigned { read, write, readwrite, writeread }; - enum class index : unsigned { absolute, relative }; - - uint8_t read() { - if(!fp) return 0xff; //file not open - if(file_mode == mode::write) return 0xff; //reads not permitted - if(file_offset >= file_size) return 0xff; //cannot read past end of file - buffer_sync(); - return buffer[(file_offset++) & buffer_mask]; - } - - uintmax_t readl(unsigned length = 1) { - uintmax_t data = 0; - for(int i = 0; i < length; i++) { - data |= (uintmax_t)read() << (i << 3); - } - return data; - } - - uintmax_t readm(unsigned length = 1) { - uintmax_t data = 0; - while(length--) { - data <<= 8; - data |= read(); - } - return data; - } - - void read(uint8_t *buffer, unsigned length) { - while(length--) *buffer++ = read(); - } - - void write(uint8_t data) { - if(!fp) return; //file not open - if(file_mode == mode::read) return; //writes not permitted - buffer_sync(); - buffer[(file_offset++) & buffer_mask] = data; - buffer_dirty = true; - if(file_offset > file_size) file_size = file_offset; - } - - void writel(uintmax_t data, unsigned length = 1) { - while(length--) { - write(data); - data >>= 8; - } - } - - void writem(uintmax_t data, unsigned length = 1) { - for(int i = length - 1; i >= 0; i--) { - write(data >> (i << 3)); - } - } - - void write(const uint8_t *buffer, unsigned length) { - while(length--) write(*buffer++); - } - - template void print(Args... args) { - string data(args...); - const char *p = data; - while(*p) write(*p++); - } - - void flush() { - buffer_flush(); - fflush(fp); - } - - void seek(int offset, index index_ = index::absolute) { - if(!fp) return; //file not open - buffer_flush(); - - uintmax_t req_offset = file_offset; - switch(index_) { - case index::absolute: req_offset = offset; break; - case index::relative: req_offset += offset; break; - } - - if(req_offset < 0) req_offset = 0; //cannot seek before start of file - if(req_offset > file_size) { - if(file_mode == mode::read) { //cannot seek past end of file - req_offset = file_size; - } else { //pad file to requested location - file_offset = file_size; - while(file_size < req_offset) write(0x00); - } - } - - file_offset = req_offset; - } - - int offset() { - if(!fp) return -1; //file not open - return file_offset; - } - - int size() { - if(!fp) return -1; //file not open - return file_size; - } - - bool truncate(unsigned size) { - if(!fp) return false; //file not open - #if !defined(_WIN32) - return ftruncate(fileno(fp), size) == 0; - #else - return _chsize(fileno(fp), size) == 0; - #endif - } - - bool end() { - if(!fp) return true; //file not open - return file_offset >= file_size; - } - - static bool exists(const char *fn) { - #if !defined(_WIN32) - FILE *fp = fopen(fn, "rb"); - #else - FILE *fp = _wfopen(utf16_t(fn), L"rb"); - #endif - if(fp) { - fclose(fp); - return true; - } - return false; - } - - static unsigned size(const char *fn) { - #if !defined(_WIN32) - FILE *fp = fopen(fn, "rb"); - #else - FILE *fp = _wfopen(utf16_t(fn), L"rb"); - #endif - unsigned filesize = 0; - if(fp) { - fseek(fp, 0, SEEK_END); - filesize = ftell(fp); - fclose(fp); - } - return filesize; - } - - bool open() { - return fp; - } - - bool open(const char *fn, mode mode_) { - if(fp) return false; - - switch(file_mode = mode_) { - #if !defined(_WIN32) - case mode::read: fp = fopen(fn, "rb"); break; - case mode::write: fp = fopen(fn, "wb+"); break; //need read permission for buffering - case mode::readwrite: fp = fopen(fn, "rb+"); break; - case mode::writeread: fp = fopen(fn, "wb+"); break; - #else - case mode::read: fp = _wfopen(utf16_t(fn), L"rb"); break; - case mode::write: fp = _wfopen(utf16_t(fn), L"wb+"); break; - case mode::readwrite: fp = _wfopen(utf16_t(fn), L"rb+"); break; - case mode::writeread: fp = _wfopen(utf16_t(fn), L"wb+"); break; - #endif - } - if(!fp) return false; - buffer_offset = -1; //invalidate buffer - file_offset = 0; - fseek(fp, 0, SEEK_END); - file_size = ftell(fp); - fseek(fp, 0, SEEK_SET); - return true; - } - - void close() { - if(!fp) return; - buffer_flush(); - fclose(fp); - fp = 0; - } - - file() { - memset(buffer, 0, sizeof buffer); - buffer_offset = -1; - buffer_dirty = false; - fp = 0; - file_offset = 0; - file_size = 0; - file_mode = mode::read; - } - - ~file() { - close(); - } - - file& operator=(const file&) = delete; - file(const file&) = delete; - - private: - enum { buffer_size = 1 << 12, buffer_mask = buffer_size - 1 }; - char buffer[buffer_size]; - int buffer_offset; - bool buffer_dirty; - FILE *fp; - unsigned file_offset; - unsigned file_size; - mode file_mode; - - void buffer_sync() { - if(!fp) return; //file not open - if(buffer_offset != (file_offset & ~buffer_mask)) { - buffer_flush(); - buffer_offset = file_offset & ~buffer_mask; - fseek(fp, buffer_offset, SEEK_SET); - unsigned length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask); - if(length) unsigned unused = fread(buffer, 1, length, fp); - } - } - - void buffer_flush() { - if(!fp) return; //file not open - if(file_mode == mode::read) return; //buffer cannot be written to - if(buffer_offset < 0) return; //buffer unused - if(buffer_dirty == false) return; //buffer unmodified since read - fseek(fp, buffer_offset, SEEK_SET); - unsigned length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask); - if(length) unsigned unused = fwrite(buffer, 1, length, fp); - buffer_offset = -1; //invalidate buffer - buffer_dirty = false; - } - }; -} - -#endif diff --git a/snespurify/phoenix/nall/filemap.hpp b/snespurify/phoenix/nall/filemap.hpp deleted file mode 100755 index 52acb2fa..00000000 --- a/snespurify/phoenix/nall/filemap.hpp +++ /dev/null @@ -1,200 +0,0 @@ -#ifndef NALL_FILEMAP_HPP -#define NALL_FILEMAP_HPP - -#include -#include - -#include -#include -#if defined(_WIN32) - #include -#else - #include - #include - #include - #include - #include -#endif - -namespace nall { - class filemap { - public: - enum class mode : unsigned { read, write, readwrite, writeread }; - - bool opened() const { return p_opened(); } - bool open(const char *filename, mode mode_) { return p_open(filename, mode_); } - void close() { return p_close(); } - unsigned size() const { return p_size; } - uint8_t* data() { return p_handle; } - const uint8_t* data() const { return p_handle; } - filemap() : p_size(0), p_handle(0) { p_ctor(); } - filemap(const char *filename, mode mode_) : p_size(0), p_handle(0) { p_ctor(); p_open(filename, mode_); } - ~filemap() { p_dtor(); } - - private: - unsigned p_size; - uint8_t *p_handle; - - #if defined(_WIN32) - //============= - //MapViewOfFile - //============= - - HANDLE p_filehandle, p_maphandle; - - bool p_opened() const { - return p_handle; - } - - bool p_open(const char *filename, mode mode_) { - int desired_access, creation_disposition, flprotect, map_access; - - switch(mode_) { - default: return false; - case mode::read: - desired_access = GENERIC_READ; - creation_disposition = OPEN_EXISTING; - flprotect = PAGE_READONLY; - map_access = FILE_MAP_READ; - break; - case mode::write: - //write access requires read access - desired_access = GENERIC_WRITE; - creation_disposition = CREATE_ALWAYS; - flprotect = PAGE_READWRITE; - map_access = FILE_MAP_ALL_ACCESS; - break; - case mode::readwrite: - desired_access = GENERIC_READ | GENERIC_WRITE; - creation_disposition = OPEN_EXISTING; - flprotect = PAGE_READWRITE; - map_access = FILE_MAP_ALL_ACCESS; - break; - case mode::writeread: - desired_access = GENERIC_READ | GENERIC_WRITE; - creation_disposition = CREATE_NEW; - flprotect = PAGE_READWRITE; - map_access = FILE_MAP_ALL_ACCESS; - break; - } - - p_filehandle = CreateFileW(utf16_t(filename), desired_access, FILE_SHARE_READ, NULL, - creation_disposition, FILE_ATTRIBUTE_NORMAL, NULL); - if(p_filehandle == INVALID_HANDLE_VALUE) return false; - - p_size = GetFileSize(p_filehandle, NULL); - - p_maphandle = CreateFileMapping(p_filehandle, NULL, flprotect, 0, p_size, NULL); - if(p_maphandle == INVALID_HANDLE_VALUE) { - CloseHandle(p_filehandle); - p_filehandle = INVALID_HANDLE_VALUE; - return false; - } - - p_handle = (uint8_t*)MapViewOfFile(p_maphandle, map_access, 0, 0, p_size); - return p_handle; - } - - void p_close() { - if(p_handle) { - UnmapViewOfFile(p_handle); - p_handle = 0; - } - - if(p_maphandle != INVALID_HANDLE_VALUE) { - CloseHandle(p_maphandle); - p_maphandle = INVALID_HANDLE_VALUE; - } - - if(p_filehandle != INVALID_HANDLE_VALUE) { - CloseHandle(p_filehandle); - p_filehandle = INVALID_HANDLE_VALUE; - } - } - - void p_ctor() { - p_filehandle = INVALID_HANDLE_VALUE; - p_maphandle = INVALID_HANDLE_VALUE; - } - - void p_dtor() { - close(); - } - - #else - //==== - //mmap - //==== - - int p_fd; - - bool p_opened() const { - return p_handle; - } - - bool p_open(const char *filename, mode mode_) { - int open_flags, mmap_flags; - - switch(mode_) { - default: return false; - case mode::read: - open_flags = O_RDONLY; - mmap_flags = PROT_READ; - break; - case mode::write: - open_flags = O_RDWR | O_CREAT; //mmap() requires read access - mmap_flags = PROT_WRITE; - break; - case mode::readwrite: - open_flags = O_RDWR; - mmap_flags = PROT_READ | PROT_WRITE; - break; - case mode::writeread: - open_flags = O_RDWR | O_CREAT; - mmap_flags = PROT_READ | PROT_WRITE; - break; - } - - p_fd = ::open(filename, open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - if(p_fd < 0) return false; - - struct stat p_stat; - fstat(p_fd, &p_stat); - p_size = p_stat.st_size; - - p_handle = (uint8_t*)mmap(0, p_size, mmap_flags, MAP_SHARED, p_fd, 0); - if(p_handle == MAP_FAILED) { - p_handle = 0; - ::close(p_fd); - p_fd = -1; - return false; - } - - return p_handle; - } - - void p_close() { - if(p_handle) { - munmap(p_handle, p_size); - p_handle = 0; - } - - if(p_fd >= 0) { - ::close(p_fd); - p_fd = -1; - } - } - - void p_ctor() { - p_fd = -1; - } - - void p_dtor() { - p_close(); - } - - #endif - }; -} - -#endif diff --git a/snespurify/phoenix/nall/foreach.hpp b/snespurify/phoenix/nall/foreach.hpp deleted file mode 100755 index 031913c8..00000000 --- a/snespurify/phoenix/nall/foreach.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef NALL_FOREACH_HPP -#define NALL_FOREACH_HPP - -#include -#include - -#undef foreach - -#define foreach2(iter, object) foreach3(iter, object, foreach_counter) -#define foreach3(iter, object, foreach_counter) \ - for(unsigned foreach_counter = 0, foreach_limit = container_size(object), foreach_once = 0, foreach_broken = 0; foreach_counter < foreach_limit && foreach_broken == 0; foreach_counter++, foreach_once = 0) \ - for(auto &iter = object[foreach_counter]; foreach_once == 0 && (foreach_broken = 1); foreach_once++, foreach_broken = 0) - -#define foreach_impl(...) foreach_decl(__VA_ARGS__, foreach3(__VA_ARGS__), foreach2(__VA_ARGS__), foreach_too_few_arguments) -#define foreach_decl(_1, _2, _3, N, ...) N -#define foreach(...) foreach_impl(__VA_ARGS__) - -#endif diff --git a/snespurify/phoenix/nall/function.hpp b/snespurify/phoenix/nall/function.hpp deleted file mode 100755 index 35b76881..00000000 --- a/snespurify/phoenix/nall/function.hpp +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef NALL_FUNCTION_HPP -#define NALL_FUNCTION_HPP - -namespace nall { - template class function; - - template class function { - struct container { - virtual R operator()(P... p) const = 0; - virtual container* copy() const = 0; - virtual ~container() {} - } *callback; - - struct global : container { - R (*function)(P...); - R operator()(P... p) const { return function(std::forward

(p)...); } - container* copy() const { return new global(function); } - global(R (*function)(P...)) : function(function) {} - }; - - template struct member : container { - R (C::*function)(P...); - C *object; - R operator()(P... p) const { return (object->*function)(std::forward

(p)...); } - container* copy() const { return new member(function, object); } - member(R (C::*function)(P...), C *object) : function(function), object(object) {} - }; - - template struct lambda : container { - mutable L object; - R operator()(P... p) const { return object(std::forward

(p)...); } - container* copy() const { return new lambda(object); } - lambda(const L& object) : object(object) {} - }; - - public: - operator bool() const { return callback; } - R operator()(P... p) const { return (*callback)(std::forward

(p)...); } - void reset() { if(callback) { delete callback; callback = 0; } } - - function& operator=(const function &source) { - if(this != &source) { - if(callback) { delete callback; callback = 0; } - if(source.callback) callback = source.callback->copy(); - } - return *this; - } - - function(const function &source) : callback(0) { operator=(source); } - function() : callback(0) {} - function(void *function) : callback(0) { if(function) callback = new global((R (*)(P...))function); } - function(R (*function)(P...)) { callback = new global(function); } - template function(R (C::*function)(P...), C *object) { callback = new member(function, object); } - template function(R (C::*function)(P...) const, C *object) { callback = new member((R (C::*)(P...))function, object); } - template function(const L& object) { callback = new lambda(object); } - ~function() { if(callback) delete callback; } - }; -} - -#endif diff --git a/snespurify/phoenix/nall/gameboy/cartridge.hpp b/snespurify/phoenix/nall/gameboy/cartridge.hpp deleted file mode 100755 index 0e1b28d8..00000000 --- a/snespurify/phoenix/nall/gameboy/cartridge.hpp +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef NALL_GAMEBOY_CARTRIDGE_HPP -#define NALL_GAMEBOY_CARTRIDGE_HPP - -namespace nall { - -class GameBoyCartridge { -public: - string xml; - inline GameBoyCartridge(const uint8_t *data, unsigned size); - -//private: - struct Information { - string mapper; - bool ram; - bool battery; - bool rtc; - bool rumble; - - unsigned romsize; - unsigned ramsize; - } info; -}; - -GameBoyCartridge::GameBoyCartridge(const uint8_t *romdata, unsigned romsize) { - xml = "\n"; - if(romsize < 0x4000) return; - - info.mapper = "unknown"; - info.ram = false; - info.battery = false; - info.rtc = false; - info.rumble = false; - - info.romsize = 0; - info.ramsize = 0; - - switch(romdata[0x0147]) { - case 0x00: info.mapper = "none"; break; - case 0x01: info.mapper = "MBC1"; break; - case 0x02: info.mapper = "MBC1"; info.ram = true; break; - case 0x03: info.mapper = "MBC1"; info.ram = true; info.battery = true; break; - case 0x05: info.mapper = "MBC2"; info.ram = true; break; - case 0x06: info.mapper = "MBC2"; info.ram = true; info.battery = true; break; - case 0x08: info.mapper = "none"; info.ram = true; break; - case 0x09: info.mapper = "MBC0"; info.ram = true; info.battery = true; break; - case 0x0b: info.mapper = "MMM01"; break; - case 0x0c: info.mapper = "MMM01"; info.ram = true; break; - case 0x0d: info.mapper = "MMM01"; info.ram = true; info.battery = true; break; - case 0x0f: info.mapper = "MBC3"; info.rtc = true; info.battery = true; break; - case 0x10: info.mapper = "MBC3"; info.rtc = true; info.ram = true; info.battery = true; break; - case 0x11: info.mapper = "MBC3"; break; - case 0x12: info.mapper = "MBC3"; info.ram = true; break; - case 0x13: info.mapper = "MBC3"; info.ram = true; info.battery = true; break; - case 0x19: info.mapper = "MBC5"; break; - case 0x1a: info.mapper = "MBC5"; info.ram = true; break; - case 0x1b: info.mapper = "MBC5"; info.ram = true; info.battery = true; break; - case 0x1c: info.mapper = "MBC5"; info.rumble = true; break; - case 0x1d: info.mapper = "MBC5"; info.rumble = true; info.ram = true; break; - case 0x1e: info.mapper = "MBC5"; info.rumble = true; info.ram = true; info.battery = true; break; - case 0xfc: break; //Pocket Camera - case 0xfd: break; //Bandai TAMA5 - case 0xfe: info.mapper = "HuC3"; break; - case 0xff: info.mapper = "HuC1"; info.ram = true; info.battery = true; break; - } - - switch(romdata[0x0148]) { default: - case 0x00: info.romsize = 2 * 16 * 1024; break; - case 0x01: info.romsize = 4 * 16 * 1024; break; - case 0x02: info.romsize = 8 * 16 * 1024; break; - case 0x03: info.romsize = 16 * 16 * 1024; break; - case 0x04: info.romsize = 32 * 16 * 1024; break; - case 0x05: info.romsize = 64 * 16 * 1024; break; - case 0x06: info.romsize = 128 * 16 * 1024; break; - case 0x07: info.romsize = 256 * 16 * 1024; break; - case 0x52: info.romsize = 72 * 16 * 1024; break; - case 0x53: info.romsize = 80 * 16 * 1024; break; - case 0x54: info.romsize = 96 * 16 * 1024; break; - } - - switch(romdata[0x0149]) { default: - case 0x00: info.ramsize = 0 * 1024; break; - case 0x01: info.ramsize = 2 * 1024; break; - case 0x02: info.ramsize = 8 * 1024; break; - case 0x03: info.ramsize = 32 * 1024; break; - } - - if(info.mapper == "MBC2") info.ramsize = 512; //512 x 4-bit - - xml << "\n"; - - xml << " \n"; //TODO: trust/check info.romsize? - - if(info.ramsize > 0) - xml << " \n"; - - xml << "\n"; - xml.transform("'", "\""); -} - -} - -#endif diff --git a/snespurify/phoenix/nall/input.hpp b/snespurify/phoenix/nall/input.hpp deleted file mode 100755 index 1fd680f4..00000000 --- a/snespurify/phoenix/nall/input.hpp +++ /dev/null @@ -1,386 +0,0 @@ -#ifndef NALL_INPUT_HPP -#define NALL_INPUT_HPP - -#include -#include -#include - -#include -#include - -namespace nall { - -struct Keyboard; -Keyboard& keyboard(unsigned = 0); - -static const char KeyboardScancodeName[][64] = { - "Escape", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", - "PrintScreen", "ScrollLock", "Pause", "Tilde", - "Num1", "Num2", "Num3", "Num4", "Num5", "Num6", "Num7", "Num8", "Num9", "Num0", - "Dash", "Equal", "Backspace", - "Insert", "Delete", "Home", "End", "PageUp", "PageDown", - "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", - "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", - "LeftBracket", "RightBracket", "Backslash", "Semicolon", "Apostrophe", "Comma", "Period", "Slash", - "Keypad1", "Keypad2", "Keypad3", "Keypad4", "Keypad5", "Keypad6", "Keypad7", "Keypad8", "Keypad9", "Keypad0", - "Point", "Enter", "Add", "Subtract", "Multiply", "Divide", - "NumLock", "CapsLock", - "Up", "Down", "Left", "Right", - "Tab", "Return", "Spacebar", "Menu", - "Shift", "Control", "Alt", "Super", -}; - -struct Keyboard { - const unsigned ID; - enum { Base = 1 }; - enum { Count = 8, Size = 128 }; - - enum Scancode { - Escape, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, - PrintScreen, ScrollLock, Pause, Tilde, - Num1, Num2, Num3, Num4, Num5, Num6, Num7, Num8, Num9, Num0, - Dash, Equal, Backspace, - Insert, Delete, Home, End, PageUp, PageDown, - A, B, C, D, E, F, G, H, I, J, K, L, M, - N, O, P, Q, R, S, T, U, V, W, X, Y, Z, - LeftBracket, RightBracket, Backslash, Semicolon, Apostrophe, Comma, Period, Slash, - Keypad1, Keypad2, Keypad3, Keypad4, Keypad5, Keypad6, Keypad7, Keypad8, Keypad9, Keypad0, - Point, Enter, Add, Subtract, Multiply, Divide, - NumLock, CapsLock, - Up, Down, Left, Right, - Tab, Return, Spacebar, Menu, - Shift, Control, Alt, Super, - Limit, - }; - - static signed numberDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).belongsTo(scancode)) return i; - } - return -1; - } - - static signed keyDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).isKey(scancode)) return scancode - keyboard(i).key(Escape); - } - return -1; - } - - static signed modifierDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).isModifier(scancode)) return scancode - keyboard(i).key(Shift); - } - return -1; - } - - static bool isAnyKey(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).isKey(scancode)) return true; - } - return false; - } - - static bool isAnyModifier(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).isModifier(scancode)) return true; - } - return false; - } - - static uint16_t decode(const char *name) { - string s(name); - if(!strbegin(name, "KB")) return 0; - s.ltrim("KB"); - unsigned id = decimal(s); - auto pos = strpos(s, "::"); - if(!pos) return 0; - s = substr(s, pos() + 2); - for(unsigned i = 0; i < Limit; i++) { - if(s == KeyboardScancodeName[i]) return Base + Size * id + i; - } - return 0; - } - - string encode(uint16_t code) const { - unsigned index = 0; - for(unsigned i = 0; i < Count; i++) { - if(code >= Base + Size * i && code < Base + Size * (i + 1)) { - index = code - (Base + Size * i); - break; - } - } - return string() << "KB" << ID << "::" << KeyboardScancodeName[index]; - } - - uint16_t operator[](Scancode code) const { return Base + ID * Size + code; } - uint16_t key(unsigned id) const { return Base + Size * ID + id; } - bool isKey(unsigned id) const { return id >= key(Escape) && id <= key(Menu); } - bool isModifier(unsigned id) const { return id >= key(Shift) && id <= key(Super); } - bool belongsTo(uint16_t scancode) const { return isKey(scancode) || isModifier(scancode); } - - Keyboard(unsigned ID_) : ID(ID_) {} -}; - -inline Keyboard& keyboard(unsigned id) { - static Keyboard kb0(0), kb1(1), kb2(2), kb3(3), kb4(4), kb5(5), kb6(6), kb7(7); - switch(id) { default: - case 0: return kb0; case 1: return kb1; case 2: return kb2; case 3: return kb3; - case 4: return kb4; case 5: return kb5; case 6: return kb6; case 7: return kb7; - } -} - -static const char MouseScancodeName[][64] = { - "Xaxis", "Yaxis", "Zaxis", - "Button0", "Button1", "Button2", "Button3", "Button4", "Button5", "Button6", "Button7", -}; - -struct Mouse; -Mouse& mouse(unsigned = 0); - -struct Mouse { - const unsigned ID; - enum { Base = Keyboard::Base + Keyboard::Size * Keyboard::Count }; - enum { Count = 8, Size = 16 }; - enum { Axes = 3, Buttons = 8 }; - - enum Scancode { - Xaxis, Yaxis, Zaxis, - Button0, Button1, Button2, Button3, Button4, Button5, Button6, Button7, - Limit, - }; - - static signed numberDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).belongsTo(scancode)) return i; - } - return -1; - } - - static signed axisDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).isAxis(scancode)) return scancode - mouse(i).axis(0); - } - return -1; - } - - static signed buttonDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).isButton(scancode)) return scancode - mouse(i).button(0); - } - return -1; - } - - static bool isAnyAxis(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).isAxis(scancode)) return true; - } - return false; - } - - static bool isAnyButton(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).isButton(scancode)) return true; - } - return false; - } - - static uint16_t decode(const char *name) { - string s(name); - if(!strbegin(name, "MS")) return 0; - s.ltrim("MS"); - unsigned id = decimal(s); - auto pos = strpos(s, "::"); - if(!pos) return 0; - s = substr(s, pos() + 2); - for(unsigned i = 0; i < Limit; i++) { - if(s == MouseScancodeName[i]) return Base + Size * id + i; - } - return 0; - } - - string encode(uint16_t code) const { - unsigned index = 0; - for(unsigned i = 0; i < Count; i++) { - if(code >= Base + Size * i && code < Base + Size * (i + 1)) { - index = code - (Base + Size * i); - break; - } - } - return string() << "MS" << ID << "::" << MouseScancodeName[index]; - } - - uint16_t operator[](Scancode code) const { return Base + ID * Size + code; } - uint16_t axis(unsigned id) const { return Base + Size * ID + Xaxis + id; } - uint16_t button(unsigned id) const { return Base + Size * ID + Button0 + id; } - bool isAxis(unsigned id) const { return id >= axis(0) && id <= axis(2); } - bool isButton(unsigned id) const { return id >= button(0) && id <= button(7); } - bool belongsTo(uint16_t scancode) const { return isAxis(scancode) || isButton(scancode); } - - Mouse(unsigned ID_) : ID(ID_) {} -}; - -inline Mouse& mouse(unsigned id) { - static Mouse ms0(0), ms1(1), ms2(2), ms3(3), ms4(4), ms5(5), ms6(6), ms7(7); - switch(id) { default: - case 0: return ms0; case 1: return ms1; case 2: return ms2; case 3: return ms3; - case 4: return ms4; case 5: return ms5; case 6: return ms6; case 7: return ms7; - } -} - -static const char JoypadScancodeName[][64] = { - "Hat0", "Hat1", "Hat2", "Hat3", "Hat4", "Hat5", "Hat6", "Hat7", - "Axis0", "Axis1", "Axis2", "Axis3", "Axis4", "Axis5", "Axis6", "Axis7", - "Axis8", "Axis9", "Axis10", "Axis11", "Axis12", "Axis13", "Axis14", "Axis15", - "Button0", "Button1", "Button2", "Button3", "Button4", "Button5", "Button6", "Button7", - "Button8", "Button9", "Button10", "Button11", "Button12", "Button13", "Button14", "Button15", - "Button16", "Button17", "Button18", "Button19", "Button20", "Button21", "Button22", "Button23", - "Button24", "Button25", "Button26", "Button27", "Button28", "Button29", "Button30", "Button31", -}; - -struct Joypad; -Joypad& joypad(unsigned = 0); - -struct Joypad { - const unsigned ID; - enum { Base = Mouse::Base + Mouse::Size * Mouse::Count }; - enum { Count = 8, Size = 64 }; - enum { Hats = 8, Axes = 16, Buttons = 32 }; - - enum Scancode { - Hat0, Hat1, Hat2, Hat3, Hat4, Hat5, Hat6, Hat7, - Axis0, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7, - Axis8, Axis9, Axis10, Axis11, Axis12, Axis13, Axis14, Axis15, - Button0, Button1, Button2, Button3, Button4, Button5, Button6, Button7, - Button8, Button9, Button10, Button11, Button12, Button13, Button14, Button15, - Button16, Button17, Button18, Button19, Button20, Button21, Button22, Button23, - Button24, Button25, Button26, Button27, Button28, Button29, Button30, Button31, - Limit, - }; - - enum Hat { HatCenter = 0, HatUp = 1, HatRight = 2, HatDown = 4, HatLeft = 8 }; - - static signed numberDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).belongsTo(scancode)) return i; - } - return -1; - } - - static signed hatDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isHat(scancode)) return scancode - joypad(i).hat(0); - } - return -1; - } - - static signed axisDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isAxis(scancode)) return scancode - joypad(i).axis(0); - } - return -1; - } - - static signed buttonDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isButton(scancode)) return scancode - joypad(i).button(0); - } - return -1; - } - - static bool isAnyHat(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isHat(scancode)) return true; - } - return false; - } - - static bool isAnyAxis(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isAxis(scancode)) return true; - } - return false; - } - - static bool isAnyButton(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isButton(scancode)) return true; - } - return false; - } - - static uint16_t decode(const char *name) { - string s(name); - if(!strbegin(name, "JP")) return 0; - s.ltrim("JP"); - unsigned id = decimal(s); - auto pos = strpos(s, "::"); - if(!pos) return 0; - s = substr(s, pos() + 2); - for(unsigned i = 0; i < Limit; i++) { - if(s == JoypadScancodeName[i]) return Base + Size * id + i; - } - return 0; - } - - string encode(uint16_t code) const { - unsigned index = 0; - for(unsigned i = 0; i < Count; i++) { - if(code >= Base + Size * i && code < Base + Size * (i + 1)) { - index = code - (Base + Size * i); - } - } - return string() << "JP" << ID << "::" << JoypadScancodeName[index]; - } - - uint16_t operator[](Scancode code) const { return Base + ID * Size + code; } - uint16_t hat(unsigned id) const { return Base + Size * ID + Hat0 + id; } - uint16_t axis(unsigned id) const { return Base + Size * ID + Axis0 + id; } - uint16_t button(unsigned id) const { return Base + Size * ID + Button0 + id; } - bool isHat(unsigned id) const { return id >= hat(0) && id <= hat(7); } - bool isAxis(unsigned id) const { return id >= axis(0) && id <= axis(15); } - bool isButton(unsigned id) const { return id >= button(0) && id <= button(31); } - bool belongsTo(uint16_t scancode) const { return isHat(scancode) || isAxis(scancode) || isButton(scancode); } - - Joypad(unsigned ID_) : ID(ID_) {} -}; - -inline Joypad& joypad(unsigned id) { - static Joypad jp0(0), jp1(1), jp2(2), jp3(3), jp4(4), jp5(5), jp6(6), jp7(7); - switch(id) { default: - case 0: return jp0; case 1: return jp1; case 2: return jp2; case 3: return jp3; - case 4: return jp4; case 5: return jp5; case 6: return jp6; case 7: return jp7; - } -} - -struct Scancode { - enum { None = 0, Limit = Joypad::Base + Joypad::Size * Joypad::Count }; - - static uint16_t decode(const char *name) { - uint16_t code; - code = Keyboard::decode(name); - if(code) return code; - code = Mouse::decode(name); - if(code) return code; - code = Joypad::decode(name); - if(code) return code; - return None; - } - - static string encode(uint16_t code) { - for(unsigned i = 0; i < Keyboard::Count; i++) { - if(keyboard(i).belongsTo(code)) return keyboard(i).encode(code); - } - for(unsigned i = 0; i < Mouse::Count; i++) { - if(mouse(i).belongsTo(code)) return mouse(i).encode(code); - } - for(unsigned i = 0; i < Joypad::Count; i++) { - if(joypad(i).belongsTo(code)) return joypad(i).encode(code); - } - return "None"; - } -}; - -} - -#endif diff --git a/snespurify/phoenix/nall/lzss.hpp b/snespurify/phoenix/nall/lzss.hpp deleted file mode 100755 index 202bc814..00000000 --- a/snespurify/phoenix/nall/lzss.hpp +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef NALL_LZSS_HPP -#define NALL_LZSS_HPP - -#include -#include -#include - -namespace nall { - class lzss { - public: - static bool encode(uint8_t *&output, unsigned &outlength, const uint8_t *input, unsigned inlength) { - output = new(zeromemory) uint8_t[inlength * 9 / 8 + 9]; - - unsigned i = 0, o = 0; - while(i < inlength) { - unsigned flagoffset = o++; - uint8_t flag = 0x00; - - for(unsigned b = 0; b < 8 && i < inlength; b++) { - unsigned longest = 0, pointer; - for(unsigned index = 1; index < 4096; index++) { - unsigned count = 0; - while(true) { - if(count >= 15 + 3) break; //verify pattern match is not longer than max length - if(i + count >= inlength) break; //verify pattern match does not read past end of input - if(i + count < index) break; //verify read is not before start of input - if(input[i + count] != input[i + count - index]) break; //verify pattern still matches - count++; - } - - if(count > longest) { - longest = count; - pointer = index; - } - } - - if(longest < 3) output[o++] = input[i++]; - else { - flag |= 1 << b; - uint16_t x = ((longest - 3) << 12) + pointer; - output[o++] = x; - output[o++] = x >> 8; - i += longest; - } - } - - output[flagoffset] = flag; - } - - outlength = o; - return true; - } - - static bool decode(uint8_t *&output, const uint8_t *input, unsigned length) { - output = new(zeromemory) uint8_t[length]; - - unsigned i = 0, o = 0; - while(o < length) { - uint8_t flag = input[i++]; - - for(unsigned b = 0; b < 8 && o < length; b++) { - if(!(flag & (1 << b))) output[o++] = input[i++]; - else { - uint16_t offset = input[i++]; - offset += input[i++] << 8; - uint16_t lookuplength = (offset >> 12) + 3; - offset &= 4095; - for(unsigned index = 0; index < lookuplength && o + index < length; index++) { - output[o + index] = output[o + index - offset]; - } - o += lookuplength; - } - } - } - - return true; - } - }; -} - -#endif diff --git a/snespurify/phoenix/nall/moduloarray.hpp b/snespurify/phoenix/nall/moduloarray.hpp deleted file mode 100755 index be549ae9..00000000 --- a/snespurify/phoenix/nall/moduloarray.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef NALL_MODULO_HPP -#define NALL_MODULO_HPP - -#include - -namespace nall { - template class modulo_array { - public: - inline T operator[](int index) const { - return buffer[size + index]; - } - - inline T read(int index) const { - return buffer[size + index]; - } - - inline void write(unsigned index, const T value) { - buffer[index] = - buffer[index + size] = - buffer[index + size + size] = value; - } - - void serialize(serializer &s) { - s.array(buffer, size * 3); - } - - modulo_array() { - buffer = new T[size * 3](); - } - - ~modulo_array() { - delete[] buffer; - } - - private: - T *buffer; - }; -} - -#endif diff --git a/snespurify/phoenix/nall/platform.hpp b/snespurify/phoenix/nall/platform.hpp deleted file mode 100755 index 72eeec09..00000000 --- a/snespurify/phoenix/nall/platform.hpp +++ /dev/null @@ -1,122 +0,0 @@ -#ifndef NALL_PLATFORM_HPP -#define NALL_PLATFORM_HPP - -#include - -//========================= -//standard platform headers -//========================= - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(_WIN32) - #include - #include - #include - #undef interface - #define dllexport __declspec(dllexport) -#else - #include - #include - #include - #define dllexport -#endif - -//================== -//warning supression -//================== - -//Visual C++ -#if defined(_MSC_VER) - //disable libc "deprecation" warnings - #pragma warning(disable:4996) -#endif - -//================ -//POSIX compliance -//================ - -#if defined(_MSC_VER) - #define PATH_MAX _MAX_PATH - #define va_copy(dest, src) ((dest) = (src)) -#endif - -#if defined(_WIN32) - #define getcwd _getcwd - #define ftruncate _chsize - #define putenv _putenv - #define mkdir(n, m) _wmkdir(nall::utf16_t(n)) - #define rmdir _rmdir - #define vsnprintf _vsnprintf - #define usleep(n) Sleep(n / 1000) -#endif - -//================ -//inline expansion -//================ - -#if defined(__GNUC__) - #define noinline __attribute__((noinline)) - #define inline inline - #define alwaysinline inline __attribute__((always_inline)) -#elif defined(_MSC_VER) - #define noinline __declspec(noinline) - #define inline inline - #define alwaysinline inline __forceinline -#else - #define noinline - #define inline inline - #define alwaysinline inline -#endif - -//========================= -//file system functionality -//========================= - -#if defined(_WIN32) - inline char* realpath(const char *filename, char *resolvedname) { - wchar_t fn[_MAX_PATH] = L""; - _wfullpath(fn, nall::utf16_t(filename), _MAX_PATH); - strcpy(resolvedname, nall::utf8_t(fn)); - return resolvedname; - } - - inline char* userpath(char *path) { - wchar_t fp[_MAX_PATH] = L""; - SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, fp); - strcpy(path, nall::utf8_t(fp)); - return path; - } - - inline char* getcwd(char *path) { - wchar_t fp[_MAX_PATH] = L""; - _wgetcwd(fp, _MAX_PATH); - strcpy(path, nall::utf8_t(fp)); - return path; - } -#else - //realpath() already exists - - inline char* userpath(char *path) { - *path = 0; - struct passwd *userinfo = getpwuid(getuid()); - if(userinfo) strcpy(path, userinfo->pw_dir); - return path; - } - - inline char *getcwd(char *path) { - return getcwd(path, PATH_MAX); - } -#endif - -#endif - diff --git a/snespurify/phoenix/nall/priorityqueue.hpp b/snespurify/phoenix/nall/priorityqueue.hpp deleted file mode 100755 index 7104e791..00000000 --- a/snespurify/phoenix/nall/priorityqueue.hpp +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef NALL_PRIORITYQUEUE_HPP -#define NALL_PRIORITYQUEUE_HPP - -#include -#include -#include -#include - -namespace nall { - template void priority_queue_nocallback(type_t) {} - - //priority queue implementation using binary min-heap array; - //does not require normalize() function. - //O(1) find (tick) - //O(log n) insert (enqueue) - //O(log n) remove (dequeue) - template class priority_queue { - public: - inline void tick(unsigned ticks) { - basecounter += ticks; - while(heapsize && gte(basecounter, heap[0].counter)) callback(dequeue()); - } - - //counter is relative to current time (eg enqueue(64, ...) fires in 64 ticks); - //counter cannot exceed std::numeric_limits::max() >> 1. - void enqueue(unsigned counter, type_t event) { - unsigned child = heapsize++; - counter += basecounter; - - while(child) { - unsigned parent = (child - 1) >> 1; - if(gte(counter, heap[parent].counter)) break; - - heap[child].counter = heap[parent].counter; - heap[child].event = heap[parent].event; - child = parent; - } - - heap[child].counter = counter; - heap[child].event = event; - } - - type_t dequeue() { - type_t event(heap[0].event); - unsigned parent = 0; - unsigned counter = heap[--heapsize].counter; - - while(true) { - unsigned child = (parent << 1) + 1; - if(child >= heapsize) break; - if(child + 1 < heapsize && gte(heap[child].counter, heap[child + 1].counter)) child++; - if(gte(heap[child].counter, counter)) break; - - heap[parent].counter = heap[child].counter; - heap[parent].event = heap[child].event; - parent = child; - } - - heap[parent].counter = counter; - heap[parent].event = heap[heapsize].event; - return event; - } - - void reset() { - basecounter = 0; - heapsize = 0; - } - - void serialize(serializer &s) { - s.integer(basecounter); - s.integer(heapsize); - for(unsigned n = 0; n < heapcapacity; n++) { - s.integer(heap[n].counter); - s.integer(heap[n].event); - } - } - - priority_queue(unsigned size, function callback_ = &priority_queue_nocallback) - : callback(callback_) { - heap = new heap_t[size]; - heapcapacity = size; - reset(); - } - - ~priority_queue() { - delete[] heap; - } - - priority_queue& operator=(const priority_queue&) = delete; - priority_queue(const priority_queue&) = delete; - - private: - function callback; - unsigned basecounter; - unsigned heapsize; - unsigned heapcapacity; - struct heap_t { - unsigned counter; - type_t event; - } *heap; - - //return true if x is greater than or equal to y - inline bool gte(unsigned x, unsigned y) { - return x - y < (std::numeric_limits::max() >> 1); - } - }; -} - -#endif diff --git a/snespurify/phoenix/nall/property.hpp b/snespurify/phoenix/nall/property.hpp deleted file mode 100755 index 6fd33acd..00000000 --- a/snespurify/phoenix/nall/property.hpp +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef NALL_PROPERTY_HPP -#define NALL_PROPERTY_HPP - -//nall::property implements ownership semantics into container classes -//example: property::readonly implies that only owner has full -//access to type; and all other code has readonly access. -// -//this code relies on extended friend semantics from C++0x to work, as it -//declares a friend class via a template paramter. it also exploits a bug in -//G++ 4.x to work even in C++98 mode. -// -//if compiling elsewhere, simply remove the friend class and private semantics - -//property can be used either of two ways: -//struct foo { -// property::readonly x; -// property::readwrite y; -//}; -//-or- -//struct foo : property { -// readonly x; -// readwrite y; -//}; - -//return types are const T& (byref) instead fo T (byval) to avoid major speed -//penalties for objects with expensive copy constructors - -//operator-> provides access to underlying object type: -//readonly foo; -//foo->bar(); -//... will call Object::bar(); - -//operator='s reference is constant so as to avoid leaking a reference handle -//that could bypass access restrictions - -//both constant and non-constant operators are provided, though it may be -//necessary to cast first, for instance: -//struct foo : property { readonly bar; } object; -//int main() { int value = const_cast(object); } - -//writeonly is useful for objects that have non-const reads, but const writes. -//however, to avoid leaking handles, the interface is very restricted. the only -//way to write is via operator=, which requires conversion via eg copy -//constructor. example: -//struct foo { -// foo(bool value) { ... } -//}; -//writeonly bar; -//bar = true; - -namespace nall { - template struct property { - template struct traits { typedef T type; }; - - template struct readonly { - const T* operator->() const { return &value; } - const T& operator()() const { return value; } - operator const T&() const { return value; } - private: - T* operator->() { return &value; } - operator T&() { return value; } - const T& operator=(const T& value_) { return value = value_; } - T value; - friend class traits::type; - }; - - template struct writeonly { - void operator=(const T& value_) { value = value_; } - private: - const T* operator->() const { return &value; } - const T& operator()() const { return value; } - operator const T&() const { return value; } - T* operator->() { return &value; } - operator T&() { return value; } - T value; - friend class traits::type; - }; - - template struct readwrite { - const T* operator->() const { return &value; } - const T& operator()() const { return value; } - operator const T&() const { return value; } - T* operator->() { return &value; } - operator T&() { return value; } - const T& operator=(const T& value_) { return value = value_; } - T value; - }; - }; -} - -#endif diff --git a/snespurify/phoenix/nall/public_cast.hpp b/snespurify/phoenix/nall/public_cast.hpp deleted file mode 100755 index 331800e1..00000000 --- a/snespurify/phoenix/nall/public_cast.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef NALL_PUBLIC_CAST_HPP -#define NALL_PUBLIC_CAST_HPP - -//this is a proof-of-concept-*only* C++ access-privilege elevation exploit. -//this code is 100% legal C++, per C++98 section 14.7.2 paragraph 8: -//"access checking rules do not apply to names in explicit instantiations." -//usage example: - -//struct N { typedef void (Class::*)(); }; -//template class public_cast; -//(class.*public_cast::value); - -//Class::Reference may be public, protected or private -//Class::Reference may be a function, object or variable - -namespace nall { - template struct public_cast; - - template struct public_cast { - static typename T::type value; - }; - - template typename T::type public_cast::value; - - template struct public_cast { - static typename T::type value; - }; - - template typename T::type public_cast::value = public_cast::value = P; -} - -#endif diff --git a/snespurify/phoenix/nall/random.hpp b/snespurify/phoenix/nall/random.hpp deleted file mode 100755 index 74ebc2d2..00000000 --- a/snespurify/phoenix/nall/random.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef NALL_RANDOM_HPP -#define NALL_RANDOM_HPP - -namespace nall { - //pseudo-random number generator - inline unsigned prng() { - static unsigned n = 0; - return n = (n >> 1) ^ (((n & 1) - 1) & 0xedb88320); - } - - struct random_cyclic { - unsigned seed; - inline unsigned operator()() { - return seed = (seed >> 1) ^ (((seed & 1) - 1) & 0xedb88320); - } - random_cyclic() : seed(0) {} - }; -} - -#endif diff --git a/snespurify/phoenix/nall/reference_array.hpp b/snespurify/phoenix/nall/reference_array.hpp deleted file mode 100755 index ac47c32b..00000000 --- a/snespurify/phoenix/nall/reference_array.hpp +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef NALL_REFERENCE_ARRAY_HPP -#define NALL_REFERENCE_ARRAY_HPP - -#include -#include -#include - -namespace nall { - template struct reference_array { - protected: - typedef typename std::remove_reference::type *Tptr; - Tptr *pool; - unsigned poolsize, buffersize; - - public: - unsigned size() const { return buffersize; } - unsigned capacity() const { return poolsize; } - - void reset() { - if(pool) free(pool); - pool = 0; - poolsize = 0; - buffersize = 0; - } - - void reserve(unsigned newsize) { - if(newsize == poolsize) return; - - pool = (Tptr*)realloc(pool, newsize * sizeof(T)); - poolsize = newsize; - buffersize = min(buffersize, newsize); - } - - void resize(unsigned newsize) { - if(newsize > poolsize) reserve(bit::round(newsize)); - buffersize = newsize; - } - - void append(const T data) { - unsigned index = buffersize++; - if(index >= poolsize) resize(index + 1); - pool[index] = &data; - } - - template reference_array(Args&... args) : pool(0), poolsize(0), buffersize(0) { - construct(args...); - } - - ~reference_array() { - reset(); - } - - reference_array& operator=(const reference_array &source) { - if(pool) free(pool); - buffersize = source.buffersize; - poolsize = source.poolsize; - pool = (Tptr*)malloc(sizeof(T) * poolsize); - memcpy(pool, source.pool, sizeof(T) * buffersize); - return *this; - } - - reference_array& operator=(const reference_array &&source) { - if(pool) free(pool); - pool = source.pool; - poolsize = source.poolsize; - buffersize = source.buffersize; - source.pool = 0; - source.reset(); - return *this; - } - - inline T operator[](unsigned index) { - if(index >= buffersize) throw "reference_array[] out of bounds"; - return *pool[index]; - } - - inline const T operator[](unsigned index) const { - if(index >= buffersize) throw "reference_array[] out of bounds"; - return *pool[index]; - } - - private: - void construct() { - } - - void construct(const reference_array &source) { - operator=(source); - } - - void construct(const reference_array &&source) { - operator=(std::move(source)); - } - - template void construct(T data, Args&... args) { - append(data); - construct(args...); - } - }; - - template struct has_size> { enum { value = true }; }; -} - -#endif diff --git a/snespurify/phoenix/nall/serial.hpp b/snespurify/phoenix/nall/serial.hpp deleted file mode 100755 index 9ac8451a..00000000 --- a/snespurify/phoenix/nall/serial.hpp +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef NALL_SERIAL_HPP -#define NALL_SERIAL_HPP - -#include -#include -#include -#include - -#include - -namespace nall { - class serial { - public: - //-1 on error, otherwise return bytes read - int read(uint8_t *data, unsigned length) { - if(port_open == false) return -1; - return ::read(port, (void*)data, length); - } - - //-1 on error, otherwise return bytes written - int write(const uint8_t *data, unsigned length) { - if(port_open == false) return -1; - return ::write(port, (void*)data, length); - } - - bool open(const char *portname, unsigned rate, bool flowcontrol) { - close(); - - port = ::open(portname, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK); - if(port == -1) return false; - - if(ioctl(port, TIOCEXCL) == -1) { close(); return false; } - if(fcntl(port, F_SETFL, 0) == -1) { close(); return false; } - if(tcgetattr(port, &original_attr) == -1) { close(); return false; } - - termios attr = original_attr; - cfmakeraw(&attr); - cfsetspeed(&attr, rate); - - attr.c_lflag &=~ (ECHO | ECHONL | ISIG | ICANON | IEXTEN); - attr.c_iflag &=~ (BRKINT | PARMRK | INPCK | ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF | IXANY); - attr.c_iflag |= (IGNBRK | IGNPAR); - attr.c_oflag &=~ (OPOST); - attr.c_cflag &=~ (CSIZE | CSTOPB | PARENB | CLOCAL); - attr.c_cflag |= (CS8 | CREAD); - if(flowcontrol == false) { - attr.c_cflag &= ~CRTSCTS; - } else { - attr.c_cflag |= CRTSCTS; - } - attr.c_cc[VTIME] = attr.c_cc[VMIN] = 0; - - if(tcsetattr(port, TCSANOW, &attr) == -1) { close(); return false; } - return port_open = true; - } - - void close() { - if(port != -1) { - tcdrain(port); - if(port_open == true) { - tcsetattr(port, TCSANOW, &original_attr); - port_open = false; - } - ::close(port); - port = -1; - } - } - - serial() { - port = -1; - port_open = false; - } - - ~serial() { - close(); - } - - private: - int port; - bool port_open; - termios original_attr; - }; -} - -#endif diff --git a/snespurify/phoenix/nall/serializer.hpp b/snespurify/phoenix/nall/serializer.hpp deleted file mode 100755 index ff2337ab..00000000 --- a/snespurify/phoenix/nall/serializer.hpp +++ /dev/null @@ -1,146 +0,0 @@ -#ifndef NALL_SERIALIZER_HPP -#define NALL_SERIALIZER_HPP - -#include -#include -#include -#include - -namespace nall { - //serializer: a class designed to save and restore the state of classes. - // - //benefits: - //- data() will be portable in size (it is not necessary to specify type sizes.) - //- data() will be portable in endianness (always stored internally as little-endian.) - //- one serialize function can both save and restore class states. - // - //caveats: - //- only plain-old-data can be stored. complex classes must provide serialize(serializer&); - //- floating-point usage is not portable across platforms - - class serializer { - public: - enum mode_t { Load, Save, Size }; - - mode_t mode() const { - return imode; - } - - const uint8_t* data() const { - return idata; - } - - unsigned size() const { - return isize; - } - - unsigned capacity() const { - return icapacity; - } - - template void floatingpoint(T &value) { - enum { size = sizeof(T) }; - //this is rather dangerous, and not cross-platform safe; - //but there is no standardized way to export FP-values - uint8_t *p = (uint8_t*)&value; - if(imode == Save) { - for(unsigned n = 0; n < size; n++) idata[isize++] = p[n]; - } else if(imode == Load) { - for(unsigned n = 0; n < size; n++) p[n] = idata[isize++]; - } else { - isize += size; - } - } - - template void integer(T &value) { - enum { size = std::is_same::value ? 1 : sizeof(T) }; - if(imode == Save) { - for(unsigned n = 0; n < size; n++) idata[isize++] = value >> (n << 3); - } else if(imode == Load) { - value = 0; - for(unsigned n = 0; n < size; n++) value |= idata[isize++] << (n << 3); - } else if(imode == Size) { - isize += size; - } - } - - template void array(T &array) { - enum { size = sizeof(T) / sizeof(typename std::remove_extent::type) }; - for(unsigned n = 0; n < size; n++) integer(array[n]); - } - - template void array(T array, unsigned size) { - for(unsigned n = 0; n < size; n++) integer(array[n]); - } - - //copy - serializer& operator=(const serializer &s) { - if(idata) delete[] idata; - - imode = s.imode; - idata = new uint8_t[s.icapacity]; - isize = s.isize; - icapacity = s.icapacity; - - memcpy(idata, s.idata, s.icapacity); - return *this; - } - - serializer(const serializer &s) : idata(0) { - operator=(s); - } - - //move - serializer& operator=(serializer &&s) { - if(idata) delete[] idata; - - imode = s.imode; - idata = s.idata; - isize = s.isize; - icapacity = s.icapacity; - - s.idata = 0; - return *this; - } - - serializer(serializer &&s) { - operator=(std::move(s)); - } - - //construction - serializer() { - imode = Size; - idata = 0; - isize = 0; - icapacity = 0; - } - - serializer(unsigned capacity) { - imode = Save; - idata = new uint8_t[capacity](); - isize = 0; - icapacity = capacity; - } - - serializer(const uint8_t *data, unsigned capacity) { - imode = Load; - idata = new uint8_t[capacity]; - isize = 0; - icapacity = capacity; - memcpy(idata, data, capacity); - } - - ~serializer() { - if(idata) delete[] idata; - } - - private: - mode_t imode; - uint8_t *idata; - unsigned isize; - unsigned icapacity; - }; - -}; - -#endif diff --git a/snespurify/phoenix/nall/sha256.hpp b/snespurify/phoenix/nall/sha256.hpp deleted file mode 100755 index 7f41f04e..00000000 --- a/snespurify/phoenix/nall/sha256.hpp +++ /dev/null @@ -1,143 +0,0 @@ -#ifndef NALL_SHA256_HPP -#define NALL_SHA256_HPP - -//author: vladitx - -namespace nall { - #define PTR(t, a) ((t*)(a)) - - #define SWAP32(x) ((uint32_t)( \ - (((uint32_t)(x) & 0x000000ff) << 24) | \ - (((uint32_t)(x) & 0x0000ff00) << 8) | \ - (((uint32_t)(x) & 0x00ff0000) >> 8) | \ - (((uint32_t)(x) & 0xff000000) >> 24) \ - )) - - #define ST32(a, d) *PTR(uint32_t, a) = (d) - #define ST32BE(a, d) ST32(a, SWAP32(d)) - - #define LD32(a) *PTR(uint32_t, a) - #define LD32BE(a) SWAP32(LD32(a)) - - #define LSL32(x, n) ((uint32_t)(x) << (n)) - #define LSR32(x, n) ((uint32_t)(x) >> (n)) - #define ROR32(x, n) (LSR32(x, n) | LSL32(x, 32 - (n))) - - //first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19 - static const uint32_t T_H[8] = { - 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, - }; - - //first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311 - static const uint32_t T_K[64] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, - }; - - struct sha256_ctx { - uint8_t in[64]; - unsigned inlen; - - uint32_t w[64]; - uint32_t h[8]; - uint64_t len; - }; - - void sha256_init(sha256_ctx *p) { - memset(p, 0, sizeof(sha256_ctx)); - memcpy(p->h, T_H, sizeof(T_H)); - } - - static void sha256_block(sha256_ctx *p) { - unsigned i; - uint32_t s0, s1; - uint32_t a, b, c, d, e, f, g, h; - uint32_t t1, t2, maj, ch; - - for(i = 0; i < 16; i++) p->w[i] = LD32BE(p->in + i * 4); - - for(i = 16; i < 64; i++) { - s0 = ROR32(p->w[i - 15], 7) ^ ROR32(p->w[i - 15], 18) ^ LSR32(p->w[i - 15], 3); - s1 = ROR32(p->w[i - 2], 17) ^ ROR32(p->w[i - 2], 19) ^ LSR32(p->w[i - 2], 10); - p->w[i] = p->w[i - 16] + s0 + p->w[i - 7] + s1; - } - - a = p->h[0]; b = p->h[1]; c = p->h[2]; d = p->h[3]; - e = p->h[4]; f = p->h[5]; g = p->h[6]; h = p->h[7]; - - for(i = 0; i < 64; i++) { - s0 = ROR32(a, 2) ^ ROR32(a, 13) ^ ROR32(a, 22); - maj = (a & b) ^ (a & c) ^ (b & c); - t2 = s0 + maj; - s1 = ROR32(e, 6) ^ ROR32(e, 11) ^ ROR32(e, 25); - ch = (e & f) ^ (~e & g); - t1 = h + s1 + ch + T_K[i] + p->w[i]; - - h = g; g = f; f = e; e = d + t1; - d = c; c = b; b = a; a = t1 + t2; - } - - p->h[0] += a; p->h[1] += b; p->h[2] += c; p->h[3] += d; - p->h[4] += e; p->h[5] += f; p->h[6] += g; p->h[7] += h; - - //next block - p->inlen = 0; - } - - void sha256_chunk(sha256_ctx *p, const uint8_t *s, unsigned len) { - unsigned l; - p->len += len; - - while(len) { - l = 64 - p->inlen; - l = (len < l) ? len : l; - - memcpy(p->in + p->inlen, s, l); - s += l; - p->inlen += l; - len -= l; - - if(p->inlen == 64) sha256_block(p); - } - } - - void sha256_final(sha256_ctx *p) { - uint64_t len; - p->in[p->inlen++] = 0x80; - - if(p->inlen > 56) { - memset(p->in + p->inlen, 0, 64 - p->inlen); - sha256_block(p); - } - - memset(p->in + p->inlen, 0, 56 - p->inlen); - - len = p->len << 3; - ST32BE(p->in + 56, len >> 32); - ST32BE(p->in + 60, len); - sha256_block(p); - } - - void sha256_hash(sha256_ctx *p, uint8_t *s) { - uint32_t *t = (uint32_t*)s; - for(unsigned i = 0; i < 8; i++) ST32BE(t++, p->h[i]); - } - - #undef PTR - #undef SWAP32 - #undef ST32 - #undef ST32BE - #undef LD32 - #undef LD32BE - #undef LSL32 - #undef LSR32 - #undef ROR32 -} - -#endif diff --git a/snespurify/phoenix/nall/snes/cartridge.hpp b/snespurify/phoenix/nall/snes/cartridge.hpp deleted file mode 100755 index e3c0e0c5..00000000 --- a/snespurify/phoenix/nall/snes/cartridge.hpp +++ /dev/null @@ -1,878 +0,0 @@ -#ifndef NALL_SNES_CARTRIDGE_HPP -#define NALL_SNES_CARTRIDGE_HPP - -namespace nall { - -class SNESCartridge { -public: - string xmlMemoryMap; - inline SNESCartridge(const uint8_t *data, unsigned size); - -//private: - inline void read_header(const uint8_t *data, unsigned size); - inline unsigned find_header(const uint8_t *data, unsigned size); - inline unsigned score_header(const uint8_t *data, unsigned size, unsigned addr); - inline unsigned gameboy_ram_size(const uint8_t *data, unsigned size); - inline bool gameboy_has_rtc(const uint8_t *data, unsigned size); - - enum HeaderField { - CartName = 0x00, - Mapper = 0x15, - RomType = 0x16, - RomSize = 0x17, - RamSize = 0x18, - CartRegion = 0x19, - Company = 0x1a, - Version = 0x1b, - Complement = 0x1c, //inverse checksum - Checksum = 0x1e, - ResetVector = 0x3c, - }; - - enum Mode { - ModeNormal, - ModeBsxSlotted, - ModeBsx, - ModeSufamiTurbo, - ModeSuperGameBoy, - }; - - enum Type { - TypeNormal, - TypeBsxSlotted, - TypeBsxBios, - TypeBsx, - TypeSufamiTurboBios, - TypeSufamiTurbo, - TypeSuperGameBoy1Bios, - TypeSuperGameBoy2Bios, - TypeGameBoy, - TypeUnknown, - }; - - enum Region { - NTSC, - PAL, - }; - - enum MemoryMapper { - LoROM, - HiROM, - ExLoROM, - ExHiROM, - SuperFXROM, - SA1ROM, - SPC7110ROM, - BSCLoROM, - BSCHiROM, - BSXROM, - STROM, - }; - - enum DSP1MemoryMapper { - DSP1Unmapped, - DSP1LoROM1MB, - DSP1LoROM2MB, - DSP1HiROM, - }; - - bool loaded; //is a base cartridge inserted? - unsigned crc32; //crc32 of all cartridges (base+slot(s)) - unsigned rom_size; - unsigned ram_size; - - Mode mode; - Type type; - Region region; - MemoryMapper mapper; - DSP1MemoryMapper dsp1_mapper; - - bool has_bsx_slot; - bool has_superfx; - bool has_sa1; - bool has_srtc; - bool has_sdd1; - bool has_spc7110; - bool has_spc7110rtc; - bool has_cx4; - bool has_dsp1; - bool has_dsp2; - bool has_dsp3; - bool has_dsp4; - bool has_obc1; - bool has_st010; - bool has_st011; - bool has_st018; -}; - -SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) { - read_header(data, size); - - string xml = "\n"; - - if(type == TypeBsx) { - xml << ""; - xmlMemoryMap = xml.transform("'", "\""); - return; - } - - if(type == TypeSufamiTurbo) { - xml << ""; - xmlMemoryMap = xml.transform("'", "\""); - return; - } - - if(type == TypeGameBoy) { - xml << "\n"; - if(gameboy_ram_size(data, size) > 0) { - xml << " \n"; - } - xml << "\n"; - xmlMemoryMap = xml.transform("'", "\""); - return; - } - - xml << "\n"; - - if(type == TypeSuperGameBoy1Bios) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } else if(type == TypeSuperGameBoy2Bios) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } else if(has_spc7110) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - if(has_spc7110rtc) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } else if(mapper == LoROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - - if(ram_size > 0) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - if((rom_size > 0x200000) || (ram_size > 32 * 1024)) { - xml << " \n"; - xml << " \n"; - } else { - xml << " \n"; - xml << " \n"; - } - xml << " \n"; - } - } else if(mapper == HiROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - - if(ram_size > 0) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - if((rom_size > 0x200000) || (ram_size > 32 * 1024)) { - xml << " \n"; - } else { - xml << " \n"; - } - xml << " \n"; - } - } else if(mapper == ExLoROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - - if(ram_size > 0) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - } else if(mapper == ExHiROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - - if(ram_size > 0) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - if((rom_size > 0x200000) || (ram_size > 32 * 1024)) { - xml << " \n"; - } else { - xml << " \n"; - } - xml << " \n"; - } - } else if(mapper == SuperFXROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } else if(mapper == SA1ROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } else if(mapper == BSCLoROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } else if(mapper == BSCHiROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } else if(mapper == BSXROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } else if(mapper == STROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - - if(has_srtc) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - - if(has_sdd1) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - - if(has_cx4) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - - if(has_dsp1) { - xml << " \n"; - if(dsp1_mapper == DSP1LoROM1MB) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } else if(dsp1_mapper == DSP1LoROM2MB) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } else if(dsp1_mapper == DSP1HiROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - xml << " \n"; - } - - if(has_dsp2) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - - if(has_dsp3) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - - if(has_dsp4) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - - if(has_obc1) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - - if(has_st010) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - - if(has_st011) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - - if(has_st018) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - - xml << "\n"; - xmlMemoryMap = xml.transform("'", "\""); -} - -void SNESCartridge::read_header(const uint8_t *data, unsigned size) { - type = TypeUnknown; - mapper = LoROM; - dsp1_mapper = DSP1Unmapped; - region = NTSC; - rom_size = size; - ram_size = 0; - - has_bsx_slot = false; - has_superfx = false; - has_sa1 = false; - has_srtc = false; - has_sdd1 = false; - has_spc7110 = false; - has_spc7110rtc = false; - has_cx4 = false; - has_dsp1 = false; - has_dsp2 = false; - has_dsp3 = false; - has_dsp4 = false; - has_obc1 = false; - has_st010 = false; - has_st011 = false; - has_st018 = false; - - //===================== - //detect Game Boy carts - //===================== - - if(size >= 0x0140) { - if(data[0x0104] == 0xce && data[0x0105] == 0xed && data[0x0106] == 0x66 && data[0x0107] == 0x66 - && data[0x0108] == 0xcc && data[0x0109] == 0x0d && data[0x010a] == 0x00 && data[0x010b] == 0x0b) { - type = TypeGameBoy; - return; - } - } - - if(size < 32768) { - type = TypeUnknown; - return; - } - - const unsigned index = find_header(data, size); - const uint8_t mapperid = data[index + Mapper]; - const uint8_t rom_type = data[index + RomType]; - const uint8_t rom_size = data[index + RomSize]; - const uint8_t company = data[index + Company]; - const uint8_t regionid = data[index + CartRegion] & 0x7f; - - ram_size = 1024 << (data[index + RamSize] & 7); - if(ram_size == 1024) ram_size = 0; //no RAM present - - //0, 1, 13 = NTSC; 2 - 12 = PAL - region = (regionid <= 1 || regionid >= 13) ? NTSC : PAL; - - //======================= - //detect BS-X flash carts - //======================= - - if(data[index + 0x13] == 0x00 || data[index + 0x13] == 0xff) { - if(data[index + 0x14] == 0x00) { - const uint8_t n15 = data[index + 0x15]; - if(n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c || n15 == 0xbc || n15 == 0xfc) { - if(data[index + 0x1a] == 0x33 || data[index + 0x1a] == 0xff) { - type = TypeBsx; - mapper = BSXROM; - region = NTSC; //BS-X only released in Japan - return; - } - } - } - } - - //========================= - //detect Sufami Turbo carts - //========================= - - if(!memcmp(data, "BANDAI SFC-ADX", 14)) { - if(!memcmp(data + 16, "SFC-ADX BACKUP", 14)) { - type = TypeSufamiTurboBios; - } else { - type = TypeSufamiTurbo; - } - mapper = STROM; - region = NTSC; //Sufami Turbo only released in Japan - return; //RAM size handled outside this routine - } - - //========================== - //detect Super Game Boy BIOS - //========================== - - if(!memcmp(data + index, "Super GAMEBOY2", 14)) { - type = TypeSuperGameBoy2Bios; - return; - } - - if(!memcmp(data + index, "Super GAMEBOY", 13)) { - type = TypeSuperGameBoy1Bios; - return; - } - - //===================== - //detect standard carts - //===================== - - //detect presence of BS-X flash cartridge connector (reads extended header information) - if(data[index - 14] == 'Z') { - if(data[index - 11] == 'J') { - uint8_t n13 = data[index - 13]; - if((n13 >= 'A' && n13 <= 'Z') || (n13 >= '0' && n13 <= '9')) { - if(company == 0x33 || (data[index - 10] == 0x00 && data[index - 4] == 0x00)) { - has_bsx_slot = true; - } - } - } - } - - if(has_bsx_slot) { - if(!memcmp(data + index, "Satellaview BS-X ", 21)) { - //BS-X base cart - type = TypeBsxBios; - mapper = BSXROM; - region = NTSC; //BS-X only released in Japan - return; //RAM size handled internally by load_cart_bsx() -> BSXCart class - } else { - type = TypeBsxSlotted; - mapper = (index == 0x7fc0 ? BSCLoROM : BSCHiROM); - region = NTSC; //BS-X slotted cartridges only released in Japan - } - } else { - //standard cart - type = TypeNormal; - - if(index == 0x7fc0 && size >= 0x401000) { - mapper = ExLoROM; - } else if(index == 0x7fc0 && mapperid == 0x32) { - mapper = ExLoROM; - } else if(index == 0x7fc0) { - mapper = LoROM; - } else if(index == 0xffc0) { - mapper = HiROM; - } else { //index == 0x40ffc0 - mapper = ExHiROM; - } - } - - if(mapperid == 0x20 && (rom_type == 0x13 || rom_type == 0x14 || rom_type == 0x15 || rom_type == 0x1a)) { - has_superfx = true; - mapper = SuperFXROM; - ram_size = 1024 << (data[index - 3] & 7); - if(ram_size == 1024) ram_size = 0; - } - - if(mapperid == 0x23 && (rom_type == 0x32 || rom_type == 0x34 || rom_type == 0x35)) { - has_sa1 = true; - mapper = SA1ROM; - } - - if(mapperid == 0x35 && rom_type == 0x55) { - has_srtc = true; - } - - if(mapperid == 0x32 && (rom_type == 0x43 || rom_type == 0x45)) { - has_sdd1 = true; - } - - if(mapperid == 0x3a && (rom_type == 0xf5 || rom_type == 0xf9)) { - has_spc7110 = true; - has_spc7110rtc = (rom_type == 0xf9); - mapper = SPC7110ROM; - } - - if(mapperid == 0x20 && rom_type == 0xf3) { - has_cx4 = true; - } - - if((mapperid == 0x20 || mapperid == 0x21) && rom_type == 0x03) { - has_dsp1 = true; - } - - if(mapperid == 0x30 && rom_type == 0x05 && company != 0xb2) { - has_dsp1 = true; - } - - if(mapperid == 0x31 && (rom_type == 0x03 || rom_type == 0x05)) { - has_dsp1 = true; - } - - if(has_dsp1 == true) { - if((mapperid & 0x2f) == 0x20 && size <= 0x100000) { - dsp1_mapper = DSP1LoROM1MB; - } else if((mapperid & 0x2f) == 0x20) { - dsp1_mapper = DSP1LoROM2MB; - } else if((mapperid & 0x2f) == 0x21) { - dsp1_mapper = DSP1HiROM; - } - } - - if(mapperid == 0x20 && rom_type == 0x05) { - has_dsp2 = true; - } - - if(mapperid == 0x30 && rom_type == 0x05 && company == 0xb2) { - has_dsp3 = true; - } - - if(mapperid == 0x30 && rom_type == 0x03) { - has_dsp4 = true; - } - - if(mapperid == 0x30 && rom_type == 0x25) { - has_obc1 = true; - } - - if(mapperid == 0x30 && rom_type == 0xf6 && rom_size >= 10) { - has_st010 = true; - } - - if(mapperid == 0x30 && rom_type == 0xf6 && rom_size < 10) { - has_st011 = true; - } - - if(mapperid == 0x30 && rom_type == 0xf5) { - has_st018 = true; - } -} - -unsigned SNESCartridge::find_header(const uint8_t *data, unsigned size) { - unsigned score_lo = score_header(data, size, 0x007fc0); - unsigned score_hi = score_header(data, size, 0x00ffc0); - unsigned score_ex = score_header(data, size, 0x40ffc0); - if(score_ex) score_ex += 4; //favor ExHiROM on images > 32mbits - - if(score_lo >= score_hi && score_lo >= score_ex) { - return 0x007fc0; - } else if(score_hi >= score_ex) { - return 0x00ffc0; - } else { - return 0x40ffc0; - } -} - -unsigned SNESCartridge::score_header(const uint8_t *data, unsigned size, unsigned addr) { - if(size < addr + 64) return 0; //image too small to contain header at this location? - int score = 0; - - uint16_t resetvector = data[addr + ResetVector] | (data[addr + ResetVector + 1] << 8); - uint16_t checksum = data[addr + Checksum ] | (data[addr + Checksum + 1] << 8); - uint16_t complement = data[addr + Complement ] | (data[addr + Complement + 1] << 8); - - uint8_t resetop = data[(addr & ~0x7fff) | (resetvector & 0x7fff)]; //first opcode executed upon reset - uint8_t mapper = data[addr + Mapper] & ~0x10; //mask off irrelevent FastROM-capable bit - - //$00:[000-7fff] contains uninitialized RAM and MMIO. - //reset vector must point to ROM at $00:[8000-ffff] to be considered valid. - if(resetvector < 0x8000) return 0; - - //some images duplicate the header in multiple locations, and others have completely - //invalid header information that cannot be relied upon. - //below code will analyze the first opcode executed at the specified reset vector to - //determine the probability that this is the correct header. - - //most likely opcodes - if(resetop == 0x78 //sei - || resetop == 0x18 //clc (clc; xce) - || resetop == 0x38 //sec (sec; xce) - || resetop == 0x9c //stz $nnnn (stz $4200) - || resetop == 0x4c //jmp $nnnn - || resetop == 0x5c //jml $nnnnnn - ) score += 8; - - //plausible opcodes - if(resetop == 0xc2 //rep #$nn - || resetop == 0xe2 //sep #$nn - || resetop == 0xad //lda $nnnn - || resetop == 0xae //ldx $nnnn - || resetop == 0xac //ldy $nnnn - || resetop == 0xaf //lda $nnnnnn - || resetop == 0xa9 //lda #$nn - || resetop == 0xa2 //ldx #$nn - || resetop == 0xa0 //ldy #$nn - || resetop == 0x20 //jsr $nnnn - || resetop == 0x22 //jsl $nnnnnn - ) score += 4; - - //implausible opcodes - if(resetop == 0x40 //rti - || resetop == 0x60 //rts - || resetop == 0x6b //rtl - || resetop == 0xcd //cmp $nnnn - || resetop == 0xec //cpx $nnnn - || resetop == 0xcc //cpy $nnnn - ) score -= 4; - - //least likely opcodes - if(resetop == 0x00 //brk #$nn - || resetop == 0x02 //cop #$nn - || resetop == 0xdb //stp - || resetop == 0x42 //wdm - || resetop == 0xff //sbc $nnnnnn,x - ) score -= 8; - - //at times, both the header and reset vector's first opcode will match ... - //fallback and rely on info validity in these cases to determine more likely header. - - //a valid checksum is the biggest indicator of a valid header. - if((checksum + complement) == 0xffff && (checksum != 0) && (complement != 0)) score += 4; - - if(addr == 0x007fc0 && mapper == 0x20) score += 2; //0x20 is usually LoROM - if(addr == 0x00ffc0 && mapper == 0x21) score += 2; //0x21 is usually HiROM - if(addr == 0x007fc0 && mapper == 0x22) score += 2; //0x22 is usually ExLoROM - if(addr == 0x40ffc0 && mapper == 0x25) score += 2; //0x25 is usually ExHiROM - - if(data[addr + Company] == 0x33) score += 2; //0x33 indicates extended header - if(data[addr + RomType] < 0x08) score++; - if(data[addr + RomSize] < 0x10) score++; - if(data[addr + RamSize] < 0x08) score++; - if(data[addr + CartRegion] < 14) score++; - - if(score < 0) score = 0; - return score; -} - -unsigned SNESCartridge::gameboy_ram_size(const uint8_t *data, unsigned size) { - if(size < 512) return 0; - switch(data[0x0149]) { - case 0x00: return 0 * 1024; - case 0x01: return 8 * 1024; - case 0x02: return 8 * 1024; - case 0x03: return 32 * 1024; - case 0x04: return 128 * 1024; - case 0x05: return 128 * 1024; - default: return 128 * 1024; - } -} - -bool SNESCartridge::gameboy_has_rtc(const uint8_t *data, unsigned size) { - if(size < 512) return false; - if(data[0x0147] == 0x0f ||data[0x0147] == 0x10) return true; - return false; -} - -} - -#endif diff --git a/snespurify/phoenix/nall/snes/cpu.hpp b/snespurify/phoenix/nall/snes/cpu.hpp deleted file mode 100755 index 28f5ddb5..00000000 --- a/snespurify/phoenix/nall/snes/cpu.hpp +++ /dev/null @@ -1,458 +0,0 @@ -#ifndef NALL_SNES_CPU_HPP -#define NALL_SNES_CPU_HPP - -namespace nall { - -struct SNESCPU { - enum : unsigned { - Implied, // - Constant, //#$00 - AccumConstant, //#$00 - IndexConstant, //#$00 - Direct, //$00 - DirectX, //$00,x - DirectY, //$00,y - IDirect, //($00) - IDirectX, //($00,x) - IDirectY, //($00),y - ILDirect, //[$00] - ILDirectY, //[$00],y - Address, //$0000 - AddressX, //$0000,x - AddressY, //$0000,y - IAddressX, //($0000,x) - ILAddress, //[$0000] - PAddress, //PBR:$0000 - PIAddress, //PBR:($0000) - Long, //$000000 - LongX, //$000000,x - Stack, //$00,s - IStackY, //($00,s),y - BlockMove, //$00,$00 - RelativeShort, //+/- $00 - RelativeLong, //+/- $0000 - }; - - struct OpcodeInfo { - char name[4]; - unsigned mode; - }; - - static const OpcodeInfo opcodeInfo[256]; - - static unsigned getOpcodeLength(bool accum, bool index, uint8_t opcode); - static string disassemble(unsigned pc, bool accum, bool index, uint8_t opcode, uint8_t pl, uint8_t ph, uint8_t pb); -}; - -const SNESCPU::OpcodeInfo SNESCPU::opcodeInfo[256] = { - //0x00 - 0x0f - { "brk", Constant }, - { "ora", IDirectX }, - { "cop", Constant }, - { "ora", Stack }, - - { "tsb", Direct }, - { "ora", Direct }, - { "asl", Direct }, - { "ora", ILDirect }, - - { "php", Implied }, - { "ora", AccumConstant }, - { "asl", Implied }, - { "phd", Implied }, - - { "tsb", Address }, - { "ora", Address }, - { "asl", Address }, - { "ora", Long }, - - //0x10 - 0x1f - { "bpl", RelativeShort }, - { "ora", IDirectY }, - { "ora", IDirect }, - { "ora", IStackY }, - - { "trb", Direct }, - { "ora", DirectX }, - { "asl", DirectX }, - { "ora", ILDirectY }, - - { "clc", Implied }, - { "ora", AddressY }, - { "inc", Implied }, - { "tcs", Implied }, - - { "trb", Address }, - { "ora", AddressX }, - { "asl", AddressX }, - { "ora", LongX }, - - //0x20 - 0x2f - { "jsr", Address }, - { "and", IDirectX }, - { "jsl", Long }, - { "and", Stack }, - - { "bit", Direct }, - { "and", Direct }, - { "rol", Direct }, - { "and", ILDirect }, - - { "plp", Implied }, - { "and", AccumConstant }, - { "rol", Implied }, - { "pld", Implied }, - - { "bit", Address }, - { "and", Address }, - { "rol", Address }, - { "and", Long }, - - //0x30 - 0x3f - { "bmi", RelativeShort }, - { "and", IDirectY }, - { "and", IDirect }, - { "and", IStackY }, - - { "bit", DirectX }, - { "and", DirectX }, - { "rol", DirectX }, - { "and", ILDirectY }, - - { "sec", Implied }, - { "and", AddressY }, - { "dec", Implied }, - { "tsc", Implied }, - - { "bit", AddressX }, - { "and", AddressX }, - { "rol", AddressX }, - { "and", LongX }, - - //0x40 - 0x4f - { "rti", Implied }, - { "eor", IDirectX }, - { "wdm", Constant }, - { "eor", Stack }, - - { "mvp", BlockMove }, - { "eor", Direct }, - { "lsr", Direct }, - { "eor", ILDirect }, - - { "pha", Implied }, - { "eor", AccumConstant }, - { "lsr", Implied }, - { "phk", Implied }, - - { "jmp", PAddress }, - { "eor", Address }, - { "lsr", Address }, - { "eor", Long }, - - //0x50 - 0x5f - { "bvc", RelativeShort }, - { "eor", IDirectY }, - { "eor", IDirect }, - { "eor", IStackY }, - - { "mvn", BlockMove }, - { "eor", DirectX }, - { "lsr", DirectX }, - { "eor", ILDirectY }, - - { "cli", Implied }, - { "eor", AddressY }, - { "phy", Implied }, - { "tcd", Implied }, - - { "jml", Long }, - { "eor", AddressX }, - { "lsr", AddressX }, - { "eor", LongX }, - - //0x60 - 0x6f - { "rts", Implied }, - { "adc", IDirectX }, - { "per", Address }, - { "adc", Stack }, - - { "stz", Direct }, - { "adc", Direct }, - { "ror", Direct }, - { "adc", ILDirect }, - - { "pla", Implied }, - { "adc", AccumConstant }, - { "ror", Implied }, - { "rtl", Implied }, - - { "jmp", PIAddress }, - { "adc", Address }, - { "ror", Address }, - { "adc", Long }, - - //0x70 - 0x7f - { "bvs", RelativeShort }, - { "adc", IDirectY }, - { "adc", IDirect }, - { "adc", IStackY }, - - { "stz", DirectX }, - { "adc", DirectX }, - { "ror", DirectX }, - { "adc", ILDirectY }, - - { "sei", Implied }, - { "adc", AddressY }, - { "ply", Implied }, - { "tdc", Implied }, - - { "jmp", IAddressX }, - { "adc", AddressX }, - { "ror", AddressX }, - { "adc", LongX }, - - //0x80 - 0x8f - { "bra", RelativeShort }, - { "sta", IDirectX }, - { "brl", RelativeLong }, - { "sta", Stack }, - - { "sty", Direct }, - { "sta", Direct }, - { "stx", Direct }, - { "sta", ILDirect }, - - { "dey", Implied }, - { "bit", AccumConstant }, - { "txa", Implied }, - { "phb", Implied }, - - { "sty", Address }, - { "sta", Address }, - { "stx", Address }, - { "sta", Long }, - - //0x90 - 0x9f - { "bcc", RelativeShort }, - { "sta", IDirectY }, - { "sta", IDirect }, - { "sta", IStackY }, - - { "sty", DirectX }, - { "sta", DirectX }, - { "stx", DirectY }, - { "sta", ILDirectY }, - - { "tya", Implied }, - { "sta", AddressY }, - { "txs", Implied }, - { "txy", Implied }, - - { "stz", Address }, - { "sta", AddressX }, - { "stz", AddressX }, - { "sta", LongX }, - - //0xa0 - 0xaf - { "ldy", IndexConstant }, - { "lda", IDirectX }, - { "ldx", IndexConstant }, - { "lda", Stack }, - - { "ldy", Direct }, - { "lda", Direct }, - { "ldx", Direct }, - { "lda", ILDirect }, - - { "tay", Implied }, - { "lda", AccumConstant }, - { "tax", Implied }, - { "plb", Implied }, - - { "ldy", Address }, - { "lda", Address }, - { "ldx", Address }, - { "lda", Long }, - - //0xb0 - 0xbf - { "bcs", RelativeShort }, - { "lda", IDirectY }, - { "lda", IDirect }, - { "lda", IStackY }, - - { "ldy", DirectX }, - { "lda", DirectX }, - { "ldx", DirectY }, - { "lda", ILDirectY }, - - { "clv", Implied }, - { "lda", AddressY }, - { "tsx", Implied }, - { "tyx", Implied }, - - { "ldy", AddressX }, - { "lda", AddressX }, - { "ldx", AddressY }, - { "lda", LongX }, - - //0xc0 - 0xcf - { "cpy", IndexConstant }, - { "cmp", IDirectX }, - { "rep", Constant }, - { "cmp", Stack }, - - { "cpy", Direct }, - { "cmp", Direct }, - { "dec", Direct }, - { "cmp", ILDirect }, - - { "iny", Implied }, - { "cmp", AccumConstant }, - { "dex", Implied }, - { "wai", Implied }, - - { "cpy", Address }, - { "cmp", Address }, - { "dec", Address }, - { "cmp", Long }, - - //0xd0 - 0xdf - { "bne", RelativeShort }, - { "cmp", IDirectY }, - { "cmp", IDirect }, - { "cmp", IStackY }, - - { "pei", IDirect }, - { "cmp", DirectX }, - { "dec", DirectX }, - { "cmp", ILDirectY }, - - { "cld", Implied }, - { "cmp", AddressY }, - { "phx", Implied }, - { "stp", Implied }, - - { "jmp", ILAddress }, - { "cmp", AddressX }, - { "dec", AddressX }, - { "cmp", LongX }, - - //0xe0 - 0xef - { "cpx", IndexConstant }, - { "sbc", IDirectX }, - { "sep", Constant }, - { "sbc", Stack }, - - { "cpx", Direct }, - { "sbc", Direct }, - { "inc", Direct }, - { "sbc", ILDirect }, - - { "inx", Implied }, - { "sbc", AccumConstant }, - { "nop", Implied }, - { "xba", Implied }, - - { "cpx", Address }, - { "sbc", Address }, - { "inc", Address }, - { "sbc", Long }, - - //0xf0 - 0xff - { "beq", RelativeShort }, - { "sbc", IDirectY }, - { "sbc", IDirect }, - { "sbc", IStackY }, - - { "pea", Address }, - { "sbc", DirectX }, - { "inc", DirectX }, - { "sbc", ILDirectY }, - - { "sed", Implied }, - { "sbc", AddressY }, - { "plx", Implied }, - { "xce", Implied }, - - { "jsr", IAddressX }, - { "sbc", AddressX }, - { "inc", AddressX }, - { "sbc", LongX }, -}; - -inline unsigned SNESCPU::getOpcodeLength(bool accum, bool index, uint8_t opcode) { - switch(opcodeInfo[opcode].mode) { default: - case Implied: return 1; - case Constant: return 2; - case AccumConstant: return 3 - accum; - case IndexConstant: return 3 - index; - case Direct: return 2; - case DirectX: return 2; - case DirectY: return 2; - case IDirect: return 2; - case IDirectX: return 2; - case IDirectY: return 2; - case ILDirect: return 2; - case ILDirectY: return 2; - case Address: return 3; - case AddressX: return 3; - case AddressY: return 3; - case IAddressX: return 3; - case ILAddress: return 3; - case PAddress: return 3; - case PIAddress: return 3; - case Long: return 4; - case LongX: return 4; - case Stack: return 2; - case IStackY: return 2; - case BlockMove: return 3; - case RelativeShort: return 2; - case RelativeLong: return 3; - } -} - -inline string SNESCPU::disassemble(unsigned pc, bool accum, bool index, uint8_t opcode, uint8_t pl, uint8_t ph, uint8_t pb) { - string name = opcodeInfo[opcode].name; - unsigned mode = opcodeInfo[opcode].mode; - - if(mode == Implied) return name; - if(mode == Constant) return { name, " #$", hex<2>(pl) }; - if(mode == AccumConstant) return { name, " #$", accum ? "" : hex<2>(ph), hex<2>(pl) }; - if(mode == IndexConstant) return { name, " #$", index ? "" : hex<2>(ph), hex<2>(pl) }; - if(mode == Direct) return { name, " $", hex<2>(pl) }; - if(mode == DirectX) return { name, " $", hex<2>(pl), ",x" }; - if(mode == DirectY) return { name, " $", hex<2>(pl), ",y" }; - if(mode == IDirect) return { name, " ($", hex<2>(pl), ")" }; - if(mode == IDirectX) return { name, " ($", hex<2>(pl), ",x)" }; - if(mode == IDirectY) return { name, " ($", hex<2>(pl), "),y" }; - if(mode == ILDirect) return { name, " [$", hex<2>(pl), "]" }; - if(mode == ILDirectY) return { name, " [$", hex<2>(pl), "],y" }; - if(mode == Address) return { name, " $", hex<2>(ph), hex<2>(pl) }; - if(mode == AddressX) return { name, " $", hex<2>(ph), hex<2>(pl), ",x" }; - if(mode == AddressY) return { name, " $", hex<2>(ph), hex<2>(pl), ",y" }; - if(mode == IAddressX) return { name, " ($", hex<2>(ph), hex<2>(pl), ",x)" }; - if(mode == ILAddress) return { name, " [$", hex<2>(ph), hex<2>(pl), "]" }; - if(mode == PAddress) return { name, " $", hex<2>(ph), hex<2>(pl) }; - if(mode == PIAddress) return { name, " ($", hex<2>(ph), hex<2>(pl), ")" }; - if(mode == Long) return { name, " $", hex<2>(pb), hex<2>(ph), hex<2>(pl) }; - if(mode == LongX) return { name, " $", hex<2>(pb), hex<2>(ph), hex<2>(pl), ",x" }; - if(mode == Stack) return { name, " $", hex<2>(pl), ",s" }; - if(mode == IStackY) return { name, " ($", hex<2>(pl), ",s),y" }; - if(mode == BlockMove) return { name, " $", hex<2>(ph), ",$", hex<2>(pl) }; - if(mode == RelativeShort) { - unsigned addr = (pc + 2) + (int8_t)(pl << 0); - return { name, " $", hex<4>(addr) }; - } - if(mode == RelativeLong) { - unsigned addr = (pc + 3) + (int16_t)((ph << 8) + (pl << 0)); - return { name, " $", hex<4>(addr) }; - } - - return ""; -} - -} - -#endif diff --git a/snespurify/phoenix/nall/snes/smp.hpp b/snespurify/phoenix/nall/snes/smp.hpp deleted file mode 100755 index 7a1ac47b..00000000 --- a/snespurify/phoenix/nall/snes/smp.hpp +++ /dev/null @@ -1,639 +0,0 @@ -#ifndef NALL_SNES_SMP_HPP -#define NALL_SNES_SMP_HPP - -namespace nall { - -struct SNESSMP { - enum : unsigned { - Implied, // - TVector, //0 - Direct, //$00 - DirectRelative, //$00,+/-$00 - ADirect, //a,$00 - AAbsolute, //a,$0000 - AIX, //a,(x) - AIDirectX, //a,($00+x) - AConstant, //a,#$00 - DirectDirect, //$00,$00 - CAbsoluteBit, //c,$0000:0 - Absolute, //$0000 - P, //p - AbsoluteA, //$0000,a - Relative, //+/-$00 - ADirectX, //a,$00+x - AAbsoluteX, //a,$0000+x - AAbsoluteY, //a,$0000+y - AIDirectY, //a,($00)+y - DirectConstant, //$00,#$00 - IXIY, //(x),(y) - DirectX, //$00+x - A, //a - X, //x - XAbsolute, //x,$0000 - IAbsoluteX, //($0000+x) - CNAbsoluteBit, //c,!$0000:0 - XDirect, //x,$00 - PVector, //$ff00 - YaDirect, //ya,$00 - XA, //x,a - YAbsolute, //y,$0000 - Y, //y - AX, //a,x - YDirect, //y,$00 - YConstant, //y,#$00 - XSp, //x,sp - YaX, //ya,x - IXPA, //(x)+,a - SpX, //sp,x - AIXP, //a,(x)+ - DirectA, //$00,a - IXA, //(x),a - IDirectXA, //($00+x),a - XConstant, //x,#$00 - AbsoluteX, //$0000,x - AbsoluteBitC, //$0000:0,c - DirectY, //$00,y - AbsoluteY, //$0000,y - Ya, //ya - DirectXA, //$00+x,a - AbsoluteXA, //$0000+x,a - AbsoluteYA, //$0000+y,a - IDirectYA, //($00)+y,a - DirectYX, //$00+y,x - DirectYa, //$00,ya - DirectXY, //$00+x,y - AY, //a,y - DirectXRelative, //$00+x,+/-$00 - XDirectY, //x,$00+y - YDirectX, //y,$00+x - YA, //y,a - YRelative, //y,+/-$00 - }; - - struct OpcodeInfo { - char name[6]; - unsigned mode; - }; - - static const OpcodeInfo opcodeInfo[256]; - - static unsigned getOpcodeLength(uint8_t opcode); - static string disassemble(uint16_t pc, uint8_t opcode, uint8_t pl, uint8_t ph); - static string disassemble(uint16_t pc, bool p, uint8_t opcode, uint8_t pl, uint8_t ph); -}; - -const SNESSMP::OpcodeInfo SNESSMP::opcodeInfo[256] = { - //0x00 - 0x0f - { "nop ", Implied }, - { "tcall", TVector }, - { "set0 ", Direct }, - { "bbs0 ", DirectRelative }, - - { "or ", ADirect }, - { "or ", AAbsolute }, - { "or ", AIX }, - { "or ", AIDirectX }, - - { "or ", AConstant }, - { "or ", DirectDirect }, - { "or1 ", CAbsoluteBit }, - { "asl ", Direct }, - - { "asl ", Absolute }, - { "push ", P }, - { "tset ", AbsoluteA }, - { "brk ", Implied }, - - //0x10 - 0x1f - { "bpl ", Relative }, - { "tcall", TVector }, - { "clr0 ", Direct }, - { "bbc0 ", DirectRelative }, - - { "or ", ADirectX }, - { "or ", AAbsoluteX }, - { "or ", AAbsoluteY }, - { "or ", AIDirectY }, - - { "or ", DirectConstant }, - { "or ", IXIY }, - { "decw ", Direct }, - { "asl ", DirectX }, - - { "asl ", A }, - { "dec ", X }, - { "cmp ", XAbsolute }, - { "jmp ", IAbsoluteX }, - - //0x20 - 0x2f - { "clrp ", Implied }, - { "tcall", TVector }, - { "set1 ", Direct }, - { "bbs1 ", DirectRelative }, - - { "and ", ADirect }, - { "and ", AAbsolute }, - { "and ", AIX }, - { "and ", AIDirectX }, - - { "and ", AConstant }, - { "and ", DirectDirect }, - { "or1 ", CNAbsoluteBit }, - { "rol ", Direct }, - - { "rol ", Absolute }, - { "push ", A }, - { "cbne ", DirectRelative }, - { "bra ", Relative }, - - //0x30 - 0x3f - { "bmi ", Relative }, - { "tcall", TVector }, - { "clr1 ", Direct }, - { "bbc1 ", DirectRelative }, - - { "and ", ADirectX }, - { "and ", AAbsoluteX }, - { "and ", AAbsoluteY }, - { "and ", AIDirectY }, - - { "and ", DirectConstant }, - { "and ", IXIY }, - { "incw ", Direct }, - { "rol ", DirectX }, - - { "rol ", A }, - { "inc ", X }, - { "cmp ", XDirect }, - { "call ", Absolute }, - - //0x40 - 0x4f - { "setp ", Implied }, - { "tcall", TVector }, - { "set2 ", Direct }, - { "bbs2 ", DirectRelative }, - - { "eor ", ADirect }, - { "eor ", AAbsolute }, - { "eor ", AIX }, - { "eor ", AIDirectX }, - - { "eor ", AConstant }, - { "eor ", DirectDirect }, - { "and1 ", CAbsoluteBit }, - { "lsr ", Direct }, - - { "lsr ", Absolute }, - { "push ", X }, - { "tclr ", AbsoluteA }, - { "pcall", PVector }, - - //0x50 - 0x5f - { "bvc ", Relative }, - { "tcall", TVector }, - { "clr2 ", Direct }, - { "bbc2 ", DirectRelative }, - - { "eor ", ADirectX }, - { "eor ", AAbsoluteX }, - { "eor ", AAbsoluteY }, - { "eor ", AIDirectY }, - - { "eor ", DirectConstant }, - { "eor ", IXIY }, - { "cmpw ", YaDirect }, - { "lsr ", DirectX }, - - { "lsr ", A }, - { "mov ", XA }, - { "cmp ", YAbsolute }, - { "jmp ", Absolute }, - - //0x60 - 0x6f - { "clrc ", Implied }, - { "tcall", TVector }, - { "set3 ", Direct }, - { "bbs3 ", DirectRelative }, - - { "cmp ", ADirect }, - { "cmp ", AAbsolute }, - { "cmp ", AIX }, - { "cmp ", AIDirectX }, - - { "cmp ", AConstant }, - { "cmp ", DirectDirect }, - { "and1 ", CNAbsoluteBit }, - { "ror ", Direct }, - - { "ror ", Absolute }, - { "push ", Y }, - { "dbnz ", DirectRelative }, - { "ret ", Implied }, - - //0x70 - 0x7f - { "bvs ", Relative }, - { "tcall", TVector }, - { "clr3 ", Direct }, - { "bbc3 ", DirectRelative }, - - { "cmp ", ADirectX }, - { "cmp ", AAbsoluteX }, - { "cmp ", AAbsoluteY }, - { "cmp ", AIDirectY }, - - { "cmp ", DirectConstant }, - { "cmp ", IXIY }, - { "addw ", YaDirect }, - { "ror ", DirectX }, - - { "ror ", A }, - { "mov ", AX }, - { "cmp ", YDirect }, - { "reti ", Implied }, - - //0x80 - 0x8f - { "setc ", Implied }, - { "tcall", TVector }, - { "set4 ", Direct }, - { "bbs4 ", DirectRelative }, - - { "adc ", ADirect }, - { "adc ", AAbsolute }, - { "adc ", AIX }, - { "adc ", AIDirectX }, - - { "adc ", AConstant }, - { "adc ", DirectDirect }, - { "eor1 ", CAbsoluteBit }, - { "dec ", Direct }, - - { "dec ", Absolute }, - { "mov ", YConstant }, - { "pop ", P }, - { "mov ", DirectConstant }, - - //0x90 - 0x9f - { "bcc ", Relative }, - { "tcall", TVector }, - { "clr4 ", Direct }, - { "bbc4 ", DirectRelative }, - - { "adc ", ADirectX }, - { "adc ", AAbsoluteX }, - { "adc ", AAbsoluteY }, - { "adc ", AIDirectY }, - - { "adc ", DirectRelative }, - { "adc ", IXIY }, - { "subw ", YaDirect }, - { "dec ", DirectX }, - - { "dec ", A }, - { "mov ", XSp }, - { "div ", YaX }, - { "xcn ", A }, - - //0xa0 - 0xaf - { "ei ", Implied }, - { "tcall", TVector }, - { "set5 ", Direct }, - { "bbs5 ", DirectRelative }, - - { "sbc ", ADirect }, - { "sbc ", AAbsolute }, - { "sbc ", AIX }, - { "sbc ", AIDirectX }, - - { "sbc ", AConstant }, - { "sbc ", DirectDirect }, - { "mov1 ", CAbsoluteBit }, - { "inc ", Direct }, - - { "inc ", Absolute }, - { "cmp ", YConstant }, - { "pop ", A }, - { "mov ", IXPA }, - - //0xb0 - 0xbf - { "bcs ", Relative }, - { "tcall", TVector }, - { "clr5 ", Direct }, - { "bbc5 ", DirectRelative }, - - { "sbc ", ADirectX }, - { "sbc ", AAbsoluteX }, - { "sbc ", AAbsoluteY }, - { "sbc ", AIDirectY }, - - { "sbc ", DirectConstant }, - { "sbc ", IXIY }, - { "movw ", YaDirect }, - { "inc ", DirectX }, - - { "inc ", A }, - { "mov ", SpX }, - { "das ", A }, - { "mov ", AIXP }, - - //0xc0 - 0xcf - { "di ", Implied }, - { "tcall", TVector }, - { "set6 ", Direct }, - { "bbs6 ", DirectRelative }, - - { "mov ", DirectA }, - { "mov ", AbsoluteA }, - { "mov ", IXA }, - { "mov ", IDirectXA }, - - { "cmp ", XConstant }, - { "mov ", AbsoluteX }, - { "mov1 ", AbsoluteBitC }, - { "mov ", DirectY }, - - { "mov ", AbsoluteY }, - { "mov ", XConstant }, - { "pop ", X }, - { "mul ", Ya }, - - //0xd0 - 0xdf - { "bne ", Relative }, - { "tcall", TVector }, - { "clr6 ", Relative }, - { "bbc6 ", DirectRelative }, - - { "mov ", DirectXA }, - { "mov ", AbsoluteXA }, - { "mov ", AbsoluteYA }, - { "mov ", IDirectYA }, - - { "mov ", DirectX }, - { "mov ", DirectYX }, - { "movw ", DirectYa }, - { "mov ", DirectXY }, - - { "dec ", Y }, - { "mov ", AY }, - { "cbne ", DirectXRelative }, - { "daa ", A }, - - //0xe0 - 0xef - { "clrv ", Implied }, - { "tcall", TVector }, - { "set7 ", Direct }, - { "bbs7 ", DirectRelative }, - - { "mov ", ADirect }, - { "mov ", AAbsolute }, - { "mov ", AIX }, - { "mov ", AIDirectX }, - - { "mov ", AConstant }, - { "mov ", XAbsolute }, - { "not1 ", CAbsoluteBit }, - { "mov ", YDirect }, - - { "mov ", YAbsolute }, - { "notc ", Implied }, - { "pop ", Y }, - { "sleep", Implied }, - - //0xf0 - 0xff - { "beq ", Relative }, - { "tcall", TVector }, - { "clr7 ", Direct }, - { "bbc7 ", DirectRelative }, - - { "mov ", ADirectX }, - { "mov ", AAbsoluteX }, - { "mov ", AAbsoluteY }, - { "mov ", AIDirectY }, - - { "mov ", XDirect }, - { "mov ", XDirectY }, - { "mov ", DirectDirect }, - { "mov ", YDirectX }, - - { "inc ", Y }, - { "mov ", YA }, - { "dbz ", YRelative }, - { "stop ", Implied }, -}; - -inline unsigned SNESSMP::getOpcodeLength(uint8_t opcode) { - switch(opcodeInfo[opcode].mode) { default: - case Implied: return 1; // - case TVector: return 1; //0 - case Direct: return 2; //$00 - case DirectRelative: return 3; //$00,+/-$00 - case ADirect: return 2; //a,$00 - case AAbsolute: return 3; //a,$0000 - case AIX: return 1; //a,(x) - case AIDirectX: return 2; //a,($00+x) - case AConstant: return 2; //a,#$00 - case DirectDirect: return 3; //$00,$00 - case CAbsoluteBit: return 3; //c,$0000:0 - case Absolute: return 3; //$0000 - case P: return 1; //p - case AbsoluteA: return 3; //$0000,a - case Relative: return 2; //+/-$00 - case ADirectX: return 2; //a,$00+x - case AAbsoluteX: return 3; //a,$0000+x - case AAbsoluteY: return 3; //a,$0000+y - case AIDirectY: return 2; //a,($00)+y - case DirectConstant: return 3; //$00,#$00 - case IXIY: return 1; //(x),(y) - case DirectX: return 2; //$00+x - case A: return 1; //a - case X: return 1; //x - case XAbsolute: return 3; //x,$0000 - case IAbsoluteX: return 3; //($0000+x) - case CNAbsoluteBit: return 3; //c,!$0000:0 - case XDirect: return 2; //x,$00 - case PVector: return 2; //$ff00 - case YaDirect: return 2; //ya,$00 - case XA: return 1; //x,a - case YAbsolute: return 3; //y,$0000 - case Y: return 1; //y - case AX: return 1; //a,x - case YDirect: return 2; //y,$00 - case YConstant: return 2; //y,#$00 - case XSp: return 1; //x,sp - case YaX: return 1; //ya,x - case IXPA: return 1; //(x)+,a - case SpX: return 1; //sp,x - case AIXP: return 1; //a,(x)+ - case DirectA: return 2; //$00,a - case IXA: return 1; //(x),a - case IDirectXA: return 2; //($00+x),a - case XConstant: return 2; //x,#$00 - case AbsoluteX: return 3; //$0000,x - case AbsoluteBitC: return 3; //$0000:0,c - case DirectY: return 2; //$00,y - case AbsoluteY: return 3; //$0000,y - case Ya: return 1; //ya - case DirectXA: return 2; //$00+x,a - case AbsoluteXA: return 3; //$0000+x,a - case AbsoluteYA: return 3; //$0000+y,a - case IDirectYA: return 2; //($00)+y,a - case DirectYX: return 2; //$00+y,x - case DirectYa: return 2; //$00,ya - case DirectXY: return 2; //$00+x,y - case AY: return 1; //a,y - case DirectXRelative: return 3; //$00+x,+/-$00 - case XDirectY: return 2; //x,$00+y - case YDirectX: return 2; //y,$00+x - case YA: return 1; //y,a - case YRelative: return 2; //y,+/-$00 - } -} - -inline string SNESSMP::disassemble(uint16_t pc, uint8_t opcode, uint8_t pl, uint8_t ph) { - string name = opcodeInfo[opcode].name; - unsigned mode = opcodeInfo[opcode].mode; - unsigned pa = (ph << 8) + pl; - - if(mode == Implied) return name; - if(mode == TVector) return { name, " ", opcode >> 4 }; - if(mode == Direct) return { name, " $", hex<2>(pl) }; - if(mode == DirectRelative) return { name, " $", hex<2>(pl), ",$", hex<4>(pc + 3 + (int8_t)ph) }; - if(mode == ADirect) return { name, " a,$", hex<2>(pl) }; - if(mode == AAbsolute) return { name, " a,$", hex<4>(pa) }; - if(mode == AIX) return { name, "a,(x)" }; - if(mode == AIDirectX) return { name, " a,($", hex<2>(pl), "+x)" }; - if(mode == AConstant) return { name, " a,#$", hex<2>(pl) }; - if(mode == DirectDirect) return { name, " $", hex<2>(ph), ",$", hex<2>(pl) }; - if(mode == CAbsoluteBit) return { name, " c,$", hex<4>(pa & 0x1fff), ":", pa >> 13 }; - if(mode == Absolute) return { name, " $", hex<4>(pa) }; - if(mode == P) return { name, " p" }; - if(mode == AbsoluteA) return { name, " $", hex<4>(pa), ",a" }; - if(mode == Relative) return { name, " $", hex<4>(pc + 2 + (int8_t)pl) }; - if(mode == ADirectX) return { name, " a,$", hex<2>(pl), "+x" }; - if(mode == AAbsoluteX) return { name, " a,$", hex<4>(pa), "+x" }; - if(mode == AAbsoluteY) return { name, " a,$", hex<4>(pa), "+y" }; - if(mode == AIDirectY) return { name, " a,($", hex<2>(pl), ")+y" }; - if(mode == DirectConstant) return { name, " $", hex<2>(ph), ",#$", hex<2>(pl) }; - if(mode == IXIY) return { name, " (x),(y)" }; - if(mode == DirectX) return { name, " $", hex<2>(pl), "+x" }; - if(mode == A) return { name, " a" }; - if(mode == X) return { name, " x" }; - if(mode == XAbsolute) return { name, " x,$", hex<4>(pa) }; - if(mode == IAbsoluteX) return { name, " ($", hex<4>(pa), "+x)" }; - if(mode == CNAbsoluteBit) return { name, " c,!$", hex<4>(pa & 0x1fff), ":", pa >> 13 }; - if(mode == XDirect) return { name, " x,$", hex<2>(pl) }; - if(mode == PVector) return { name, " $ff", hex<2>(pl) }; - if(mode == YaDirect) return { name, " ya,$", hex<2>(pl) }; - if(mode == XA) return { name, " x,a" }; - if(mode == YAbsolute) return { name, " y,$", hex<4>(pa) }; - if(mode == Y) return { name, " y" }; - if(mode == AX) return { name, " a,x" }; - if(mode == YDirect) return { name, " y,$", hex<2>(pl) }; - if(mode == YConstant) return { name, " y,#$", hex<2>(pl) }; - if(mode == XSp) return { name, " x,sp" }; - if(mode == YaX) return { name, " ya,x" }; - if(mode == IXPA) return { name, " (x)+,a" }; - if(mode == SpX) return { name, " sp,x" }; - if(mode == AIXP) return { name, " a,(x)+" }; - if(mode == DirectA) return { name, " $", hex<2>(pl), ",a" }; - if(mode == IXA) return { name, " (x),a" }; - if(mode == IDirectXA) return { name, " ($", hex<2>(pl), "+x),a" }; - if(mode == XConstant) return { name, " x,#$", hex<2>(pl) }; - if(mode == AbsoluteX) return { name, " $", hex<4>(pa), ",x" }; - if(mode == AbsoluteBitC) return { name, " $", hex<4>(pa & 0x1fff), ":", pa >> 13, ",c" }; - if(mode == DirectY) return { name, " $", hex<2>(pl), ",y" }; - if(mode == AbsoluteY) return { name, " $", hex<4>(pa), ",y" }; - if(mode == Ya) return { name, " ya" }; - if(mode == DirectXA) return { name, " $", hex<2>(pl), "+x,a" }; - if(mode == AbsoluteXA) return { name, " $", hex<4>(pa), "+x,a" }; - if(mode == AbsoluteYA) return { name, " $", hex<4>(pa), "+y,a" }; - if(mode == IDirectYA) return { name, " ($", hex<2>(pl), ")+y,a" }; - if(mode == DirectYX) return { name, " $", hex<2>(pl), "+y,x" }; - if(mode == DirectYa) return { name, " $", hex<2>(pl), ",ya" }; - if(mode == DirectXY) return { name, " $", hex<2>(pl), "+x,y" }; - if(mode == AY) return { name, " a,y" }; - if(mode == DirectXRelative) return { name, " $", hex<2>(pl), ",$", hex<4>(pc + 3 + (int8_t)ph) }; - if(mode == XDirectY) return { name, " x,$", hex<2>(pl), "+y" }; - if(mode == YDirectX) return { name, " y,$", hex<2>(pl), "+x" }; - if(mode == YA) return { name, " y,a" }; - if(mode == YRelative) return { name, " y,$", hex<4>(pc + 2 + (int8_t)pl) }; - - return ""; -} - -inline string SNESSMP::disassemble(uint16_t pc, bool p, uint8_t opcode, uint8_t pl, uint8_t ph) { - string name = opcodeInfo[opcode].name; - unsigned mode = opcodeInfo[opcode].mode; - unsigned pdl = (p << 8) + pl; - unsigned pdh = (p << 8) + ph; - unsigned pa = (ph << 8) + pl; - - if(mode == Implied) return name; - if(mode == TVector) return { name, " ", opcode >> 4 }; - if(mode == Direct) return { name, " $", hex<3>(pdl) }; - if(mode == DirectRelative) return { name, " $", hex<3>(pdl), ",$", hex<4>(pc + 3 + (int8_t)ph) }; - if(mode == ADirect) return { name, " a,$", hex<3>(pdl) }; - if(mode == AAbsolute) return { name, " a,$", hex<4>(pa) }; - if(mode == AIX) return { name, "a,(x)" }; - if(mode == AIDirectX) return { name, " a,($", hex<3>(pdl), "+x)" }; - if(mode == AConstant) return { name, " a,#$", hex<2>(pl) }; - if(mode == DirectDirect) return { name, " $", hex<3>(pdh), ",$", hex<3>(pdl) }; - if(mode == CAbsoluteBit) return { name, " c,$", hex<4>(pa & 0x1fff), ":", pa >> 13 }; - if(mode == Absolute) return { name, " $", hex<4>(pa) }; - if(mode == P) return { name, " p" }; - if(mode == AbsoluteA) return { name, " $", hex<4>(pa), ",a" }; - if(mode == Relative) return { name, " $", hex<4>(pc + 2 + (int8_t)pl) }; - if(mode == ADirectX) return { name, " a,$", hex<3>(pdl), "+x" }; - if(mode == AAbsoluteX) return { name, " a,$", hex<4>(pa), "+x" }; - if(mode == AAbsoluteY) return { name, " a,$", hex<4>(pa), "+y" }; - if(mode == AIDirectY) return { name, " a,($", hex<3>(pdl), ")+y" }; - if(mode == DirectConstant) return { name, " $", hex<3>(pdh), ",#$", hex<2>(pl) }; - if(mode == IXIY) return { name, " (x),(y)" }; - if(mode == DirectX) return { name, " $", hex<3>(pdl), "+x" }; - if(mode == A) return { name, " a" }; - if(mode == X) return { name, " x" }; - if(mode == XAbsolute) return { name, " x,$", hex<4>(pa) }; - if(mode == IAbsoluteX) return { name, " ($", hex<4>(pa), "+x)" }; - if(mode == CNAbsoluteBit) return { name, " c,!$", hex<4>(pa & 0x1fff), ":", pa >> 13 }; - if(mode == XDirect) return { name, " x,$", hex<3>(pdl) }; - if(mode == PVector) return { name, " $ff", hex<2>(pl) }; - if(mode == YaDirect) return { name, " ya,$", hex<3>(pdl) }; - if(mode == XA) return { name, " x,a" }; - if(mode == YAbsolute) return { name, " y,$", hex<4>(pa) }; - if(mode == Y) return { name, " y" }; - if(mode == AX) return { name, " a,x" }; - if(mode == YDirect) return { name, " y,$", hex<3>(pdl) }; - if(mode == YConstant) return { name, " y,#$", hex<2>(pl) }; - if(mode == XSp) return { name, " x,sp" }; - if(mode == YaX) return { name, " ya,x" }; - if(mode == IXPA) return { name, " (x)+,a" }; - if(mode == SpX) return { name, " sp,x" }; - if(mode == AIXP) return { name, " a,(x)+" }; - if(mode == DirectA) return { name, " $", hex<3>(pdl), ",a" }; - if(mode == IXA) return { name, " (x),a" }; - if(mode == IDirectXA) return { name, " ($", hex<3>(pdl), "+x),a" }; - if(mode == XConstant) return { name, " x,#$", hex<2>(pl) }; - if(mode == AbsoluteX) return { name, " $", hex<4>(pa), ",x" }; - if(mode == AbsoluteBitC) return { name, " $", hex<4>(pa & 0x1fff), ":", pa >> 13, ",c" }; - if(mode == DirectY) return { name, " $", hex<3>(pdl), ",y" }; - if(mode == AbsoluteY) return { name, " $", hex<4>(pa), ",y" }; - if(mode == Ya) return { name, " ya" }; - if(mode == DirectXA) return { name, " $", hex<3>(pdl), "+x,a" }; - if(mode == AbsoluteXA) return { name, " $", hex<4>(pa), "+x,a" }; - if(mode == AbsoluteYA) return { name, " $", hex<4>(pa), "+y,a" }; - if(mode == IDirectYA) return { name, " ($", hex<3>(pdl), ")+y,a" }; - if(mode == DirectYX) return { name, " $", hex<3>(pdl), "+y,x" }; - if(mode == DirectYa) return { name, " $", hex<3>(pdl), ",ya" }; - if(mode == DirectXY) return { name, " $", hex<3>(pdl), "+x,y" }; - if(mode == AY) return { name, " a,y" }; - if(mode == DirectXRelative) return { name, " $", hex<3>(pdl), ",$", hex<4>(pc + 3 + (int8_t)ph) }; - if(mode == XDirectY) return { name, " x,$", hex<3>(pdl), "+y" }; - if(mode == YDirectX) return { name, " y,$", hex<3>(pdl), "+x" }; - if(mode == YA) return { name, " y,a" }; - if(mode == YRelative) return { name, " y,$", hex<4>(pc + 2 + (int8_t)pl) }; - - return ""; -} - -} - -#endif diff --git a/snespurify/phoenix/nall/sort.hpp b/snespurify/phoenix/nall/sort.hpp deleted file mode 100755 index 23c317a5..00000000 --- a/snespurify/phoenix/nall/sort.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef NALL_SORT_HPP -#define NALL_SORT_HPP - -#include - -//class: merge sort -//average: O(n log n) -//worst: O(n log n) -//memory: O(n) -//stack: O(log n) -//stable?: yes - -//notes: -//there are two primary reasons for choosing merge sort -//over the (usually) faster quick sort*: -//1: it is a stable sort. -//2: it lacks O(n^2) worst-case overhead. -//(* which is also O(n log n) in the average case.) - -namespace nall { - template - void sort(T list[], unsigned length) { - if(length <= 1) return; //nothing to sort - - //use insertion sort to quickly sort smaller blocks - if(length < 64) { - for(unsigned i = 0; i < length; i++) { - unsigned min = i; - for(unsigned j = i + 1; j < length; j++) { - if(list[j] < list[min]) min = j; - } - if(min != i) swap(list[i], list[min]); - } - return; - } - - //split list in half and recursively sort both - unsigned middle = length / 2; - sort(list, middle); - sort(list + middle, length - middle); - - //left and right are sorted here; perform merge sort - T *buffer = new T[length]; - unsigned offset = 0; - unsigned left = 0; - unsigned right = middle; - while(left < middle && right < length) { - if(list[left] < list[right]) { - buffer[offset++] = list[left++]; - } else { - buffer[offset++] = list[right++]; - } - } - while(left < middle) buffer[offset++] = list[left++]; - while(right < length) buffer[offset++] = list[right++]; - - for(unsigned i = 0; i < length; i++) list[i] = buffer[i]; - delete[] buffer; - } -} - -#endif diff --git a/snespurify/phoenix/nall/static.hpp b/snespurify/phoenix/nall/static.hpp deleted file mode 100755 index 4acb9fd0..00000000 --- a/snespurify/phoenix/nall/static.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef NALL_STATIC_HPP -#define NALL_STATIC_HPP - -namespace nall { - template struct static_if { typedef T type; }; - template struct static_if { typedef F type; }; - template struct mp_static_if { typedef typename static_if::type type; }; - - template struct static_and { enum { value = false }; }; - template<> struct static_and { enum { value = true }; }; - template struct mp_static_and { enum { value = static_and::value }; }; - - template struct static_or { enum { value = false }; }; - template<> struct static_or { enum { value = true }; }; - template<> struct static_or { enum { value = true }; }; - template<> struct static_or { enum { value = true }; }; - template struct mp_static_or { enum { value = static_or::value }; }; -} - -#endif diff --git a/snespurify/phoenix/nall/stdint.hpp b/snespurify/phoenix/nall/stdint.hpp deleted file mode 100755 index d8b6c788..00000000 --- a/snespurify/phoenix/nall/stdint.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef NALL_STDINT_HPP -#define NALL_STDINT_HPP - -#include - -#if defined(_MSC_VER) - typedef signed char int8_t; - typedef signed short int16_t; - typedef signed int int32_t; - typedef signed long long int64_t; - typedef int64_t intmax_t; - #if defined(_WIN64) - typedef int64_t intptr_t; - #else - typedef int32_t intptr_t; - #endif - - typedef unsigned char uint8_t; - typedef unsigned short uint16_t; - typedef unsigned int uint32_t; - typedef unsigned long long uint64_t; - typedef uint64_t uintmax_t; - #if defined(_WIN64) - typedef uint64_t uintptr_t; - #else - typedef uint32_t uintptr_t; - #endif -#else - #include -#endif - -namespace nall { - static_assert(sizeof(int8_t) == 1, "int8_t is not of the correct size" ); - static_assert(sizeof(int16_t) == 2, "int16_t is not of the correct size"); - static_assert(sizeof(int32_t) == 4, "int32_t is not of the correct size"); - static_assert(sizeof(int64_t) == 8, "int64_t is not of the correct size"); - - static_assert(sizeof(uint8_t) == 1, "int8_t is not of the correct size" ); - static_assert(sizeof(uint16_t) == 2, "int16_t is not of the correct size"); - static_assert(sizeof(uint32_t) == 4, "int32_t is not of the correct size"); - static_assert(sizeof(uint64_t) == 8, "int64_t is not of the correct size"); -} - -#endif diff --git a/snespurify/phoenix/nall/string.hpp b/snespurify/phoenix/nall/string.hpp deleted file mode 100755 index 9acc2e9d..00000000 --- a/snespurify/phoenix/nall/string.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef NALL_STRING_HPP -#define NALL_STRING_HPP - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace nall { - template<> struct has_length { enum { value = true }; }; - template<> struct has_size { enum { value = true }; }; -} - -#endif diff --git a/snespurify/phoenix/nall/string/base.hpp b/snespurify/phoenix/nall/string/base.hpp deleted file mode 100755 index f6172c26..00000000 --- a/snespurify/phoenix/nall/string/base.hpp +++ /dev/null @@ -1,162 +0,0 @@ -#ifndef NALL_STRING_BASE_HPP -#define NALL_STRING_BASE_HPP - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace nall { - class string; - template inline const char* to_string(T); - - class string { - public: - inline void reserve(unsigned); - - template inline string& assign(Args&&... args); - template inline string& append(Args&&... args); - inline string& assign_(const char*); - inline string& append_(const char*); - - inline bool readfile(const string&); - - inline string& replace (const char*, const char*); - inline string& qreplace(const char*, const char*); - - inline unsigned length() const; - - inline bool equals(const char*) const; - inline bool iequals(const char*) const; - - inline bool wildcard(const char*) const; - inline bool iwildcard(const char*) const; - - inline bool beginswith(const char*) const; - inline bool ibeginswith(const char*) const; - inline bool endswith(const char*) const; - inline bool iendswith(const char*) const; - - inline string& lower(); - inline string& upper(); - inline string& transform(const char *before, const char *after); - - template inline string& ltrim(const char *key = " "); - template inline string& rtrim(const char *key = " "); - template inline string& trim (const char *key = " "); - - inline optional position(const char *key) const; - inline optional qposition(const char *key) const; - - template inline string& operator= (T value); - template inline string& operator<<(T value); - - inline operator const char*() const; - inline char* operator()(); - inline char& operator[](int); - - inline bool operator==(const char*) const; - inline bool operator!=(const char*) const; - inline bool operator< (const char*) const; - inline bool operator<=(const char*) const; - inline bool operator> (const char*) const; - inline bool operator>=(const char*) const; - - inline string& operator=(const string&); - inline string& operator=(string&&); - - template inline string(Args&&... args); - inline string(const string&); - inline string(string&&); - inline ~string(); - - protected: - char *data; - unsigned size; - - #if defined(QSTRING_H) - public: - inline operator QString() const; - #endif - }; - - class lstring : public linear_vector { - public: - template inline lstring& operator<<(T value); - - inline optional find(const char*) const; - template inline void split (const char*, const char*); - template inline void qsplit(const char*, const char*); - - lstring(); - lstring(std::initializer_list); - }; - - //compare.hpp - inline char chrlower(char c); - inline char chrupper(char c); - inline int stricmp(const char *str1, const char *str2); - inline bool wildcard(const char *str, const char *pattern); - inline bool iwildcard(const char *str, const char *pattern); - inline bool strbegin (const char *str, const char *key); - inline bool stribegin(const char *str, const char *key); - inline bool strend (const char *str, const char *key); - inline bool striend(const char *str, const char *key); - - //convert.hpp - inline char* strlower(char *str); - inline char* strupper(char *str); - inline char* strtr(char *dest, const char *before, const char *after); - inline uintmax_t hex (const char *str); - inline intmax_t integer(const char *str); - inline uintmax_t decimal(const char *str); - inline uintmax_t binary (const char *str); - inline double fp (const char *str); - - //math.hpp - inline bool strint (const char *str, int &result); - inline bool strmath(const char *str, int &result); - - //platform.hpp - inline string realpath(const char *name); - inline string userpath(); - inline string currentpath(); - - //strl.hpp - inline unsigned strlcpy(char *dest, const char *src, unsigned length); - inline unsigned strlcat(char *dest, const char *src, unsigned length); - - //strpos.hpp - inline optional strpos(const char *str, const char *key); - inline optional qstrpos(const char *str, const char *key); - - //trim.hpp - template inline char* ltrim(char *str, const char *key = " "); - template inline char* rtrim(char *str, const char *key = " "); - template inline char* trim (char *str, const char *key = " "); - - //utility.hpp - inline unsigned strlcpy(string &dest, const char *src, unsigned length); - inline unsigned strlcat(string &dest, const char *src, unsigned length); - inline string substr(const char *src, unsigned start = 0, unsigned length = 0); - - inline string integer(intmax_t value); - template inline string linteger(intmax_t value); - template inline string rinteger(intmax_t value); - inline string decimal(uintmax_t value); - template inline string ldecimal(uintmax_t value); - template inline string rdecimal(uintmax_t value); - template inline string hex(uintmax_t value); - template inline string binary(uintmax_t value); - inline unsigned fp(char *str, double value); - inline string fp(double value); - - //variadic.hpp - template inline void print(Args&&... args); -}; - -#endif diff --git a/snespurify/phoenix/nall/string/bsv.hpp b/snespurify/phoenix/nall/string/bsv.hpp deleted file mode 100755 index d4b919e0..00000000 --- a/snespurify/phoenix/nall/string/bsv.hpp +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef NALL_STRING_BSV_HPP -#define NALL_STRING_BSV_HPP - -//BSV parser -//version 0.01 - -namespace nall { - -inline string bsv_decode(const char *input) { - string output; - unsigned offset = 0; - while(*input) { - //illegal characters - if(*input == '}' ) return ""; - if(*input == '\r') return ""; - if(*input == '\n') return ""; - - //normal characters - if(*input != '{') { output[offset++] = *input++; continue; } - - //entities - if(strbegin(input, "{lf}")) { output[offset++] = '\n'; input += 4; continue; } - if(strbegin(input, "{lb}")) { output[offset++] = '{'; input += 4; continue; } - if(strbegin(input, "{rb}")) { output[offset++] = '}'; input += 4; continue; } - - //illegal entities - return ""; - } - output[offset] = 0; - return output; -} - -inline string bsv_encode(const char *input) { - string output; - unsigned offset = 0; - while(*input) { - //illegal characters - if(*input == '\r') return ""; - - if(*input == '\n') { - output[offset++] = '{'; - output[offset++] = 'l'; - output[offset++] = 'f'; - output[offset++] = '}'; - input++; - continue; - } - - if(*input == '{') { - output[offset++] = '{'; - output[offset++] = 'l'; - output[offset++] = 'b'; - output[offset++] = '}'; - input++; - continue; - } - - if(*input == '}') { - output[offset++] = '{'; - output[offset++] = 'r'; - output[offset++] = 'b'; - output[offset++] = '}'; - input++; - continue; - } - - output[offset++] = *input++; - } - output[offset] = 0; - return output; -} - -} - -#endif diff --git a/snespurify/phoenix/nall/string/cast.hpp b/snespurify/phoenix/nall/string/cast.hpp deleted file mode 100755 index 058fcdc1..00000000 --- a/snespurify/phoenix/nall/string/cast.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef NALL_STRING_CAST_HPP -#define NALL_STRING_CAST_HPP - -namespace nall { - -//this is needed, as C++0x does not support explicit template specialization inside classes -template<> inline const char* to_string (bool v) { return v ? "true" : "false"; } -template<> inline const char* to_string (signed int v) { static char temp[256]; snprintf(temp, 255, "%+d", v); return temp; } -template<> inline const char* to_string (unsigned int v) { static char temp[256]; snprintf(temp, 255, "%u", v); return temp; } -template<> inline const char* to_string (double v) { static char temp[256]; snprintf(temp, 255, "%f", v); return temp; } -template<> inline const char* to_string (char *v) { return v; } -template<> inline const char* to_string (const char *v) { return v; } -template<> inline const char* to_string (string v) { return v; } -template<> inline const char* to_string(const string &v) { return v; } - -template string& string::operator= (T value) { return assign(to_string(value)); } -template string& string::operator<<(T value) { return append(to_string(value)); } - -template lstring& lstring::operator<<(T value) { - operator[](size()).assign(to_string(value)); - return *this; -} - -#if defined(QSTRING_H) -template<> inline const char* to_string(QString v) { return v.toUtf8().constData(); } -template<> inline const char* to_string(const QString &v) { return v.toUtf8().constData(); } -string::operator QString() const { return QString::fromUtf8(*this); } -#endif - -} - -#endif diff --git a/snespurify/phoenix/nall/string/compare.hpp b/snespurify/phoenix/nall/string/compare.hpp deleted file mode 100755 index bce0895b..00000000 --- a/snespurify/phoenix/nall/string/compare.hpp +++ /dev/null @@ -1,110 +0,0 @@ -#ifndef NALL_STRING_COMPARE_HPP -#define NALL_STRING_COMPARE_HPP - -namespace nall { - -char chrlower(char c) { - return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c; -} - -char chrupper(char c) { - return (c >= 'a' && c <= 'z') ? c - ('a' - 'A') : c; -} - -int stricmp(const char *str1, const char *str2) { - while(*str1) { - if(chrlower(*str1) != chrlower(*str2)) break; - str1++, str2++; - } - return (int)chrlower(*str1) - (int)chrlower(*str2); -} - -bool wildcard(const char *s, const char *p) { - const char *cp = 0, *mp = 0; - while(*s && *p != '*') { - if(*p != '?' && *s != *p) return false; - p++, s++; - } - while(*s) { - if(*p == '*') { - if(!*++p) return true; - mp = p, cp = s + 1; - } else if(*p == '?' || *p == *s) { - p++, s++; - } else { - p = mp, s = cp++; - } - } - while(*p == '*') p++; - return !*p; -} - -bool iwildcard(const char *s, const char *p) { - const char *cp = 0, *mp = 0; - while(*s && *p != '*') { - if(*p != '?' && chrlower(*s) != chrlower(*p)) return false; - p++, s++; - } - while(*s) { - if(*p == '*') { - if(!*++p) return true; - mp = p, cp = s + 1; - } else if(*p == '?' || chrlower(*p) == chrlower(*s)) { - p++, s++; - } else { - p = mp, s = cp++; - } - } - while(*p == '*') p++; - return !*p; -} - -bool strbegin(const char *str, const char *key) { - int i, ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - return (!memcmp(str, key, ksl)); -} - -bool stribegin(const char *str, const char *key) { - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - for(int i = 0; i < ksl; i++) { - if(str[i] >= 'A' && str[i] <= 'Z') { - if(str[i] != key[i] && str[i]+0x20 != key[i])return false; - } else if(str[i] >= 'a' && str[i] <= 'z') { - if(str[i] != key[i] && str[i]-0x20 != key[i])return false; - } else { - if(str[i] != key[i])return false; - } - } - return true; -} - -bool strend(const char *str, const char *key) { - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - return (!memcmp(str + ssl - ksl, key, ksl)); -} - -bool striend(const char *str, const char *key) { - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - for(int i = ssl - ksl, z = 0; i < ssl; i++, z++) { - if(str[i] >= 'A' && str[i] <= 'Z') { - if(str[i] != key[z] && str[i]+0x20 != key[z])return false; - } else if(str[i] >= 'a' && str[i] <= 'z') { - if(str[i] != key[z] && str[i]-0x20 != key[z])return false; - } else { - if(str[i] != key[z])return false; - } - } - return true; -} - -} - -#endif diff --git a/snespurify/phoenix/nall/string/convert.hpp b/snespurify/phoenix/nall/string/convert.hpp deleted file mode 100755 index 603d2e0e..00000000 --- a/snespurify/phoenix/nall/string/convert.hpp +++ /dev/null @@ -1,125 +0,0 @@ -#ifndef NALL_STRING_CONVERT_HPP -#define NALL_STRING_CONVERT_HPP - -namespace nall { - -char* strlower(char *str) { - if(!str) return 0; - int i = 0; - while(str[i]) { - str[i] = chrlower(str[i]); - i++; - } - return str; -} - -char* strupper(char *str) { - if(!str) return 0; - int i = 0; - while(str[i]) { - str[i] = chrupper(str[i]); - i++; - } - return str; -} - -char* strtr(char *dest, const char *before, const char *after) { - if(!dest || !before || !after) return dest; - int sl = strlen(dest), bsl = strlen(before), asl = strlen(after); - - if(bsl != asl || bsl == 0) return dest; //patterns must be the same length for 1:1 replace - for(unsigned i = 0; i < sl; i++) { - for(unsigned l = 0; l < bsl; l++) { - if(dest[i] == before[l]) { - dest[i] = after[l]; - break; - } - } - } - - return dest; -} - -uintmax_t hex(const char *str) { - if(!str) return 0; - uintmax_t result = 0; - - //skip hex identifiers 0x and $, if present - if(*str == '0' && (*(str + 1) == 'X' || *(str + 1) == 'x')) str += 2; - else if(*str == '$') str++; - - while(*str) { - uint8_t x = *str++; - if(x >= '0' && x <= '9') x -= '0'; - else if(x >= 'A' && x <= 'F') x -= 'A' - 10; - else if(x >= 'a' && x <= 'f') x -= 'a' - 10; - else break; //stop at first invalid character - result = result * 16 + x; - } - - return result; -} - -intmax_t integer(const char *str) { - if(!str) return 0; - intmax_t result = 0; - bool negate = false; - - //check for sign - if(*str == '+') { - negate = false; - str++; - } else if(*str == '-') { - negate = true; - str++; - } - - while(*str) { - uint8_t x = *str++; - if(x >= '0' && x <= '9') x -= '0'; - else break; //stop at first invalid character - result = result * 10 + x; - } - - return !negate ? result : -result; -} - -uintmax_t decimal(const char *str) { - if(!str) return 0; - uintmax_t result = 0; - - while(*str) { - uint8_t x = *str++; - if(x >= '0' && x <= '9') x -= '0'; - else break; //stop at first invalid character - result = result * 10 + x; - } - - return result; -} - -uintmax_t binary(const char *str) { - if(!str) return 0; - uintmax_t result = 0; - - //skip bin identifiers 0b and %, if present - if(*str == '0' && (*(str + 1) == 'B' || *(str + 1) == 'b')) str += 2; - else if(*str == '%') str++; - - while(*str) { - uint8_t x = *str++; - if(x == '0' || x == '1') x -= '0'; - else break; //stop at first invalid character - result = result * 2 + x; - } - - return result; -} - -double fp(const char *str) { - return atof(str); -} - -} - -#endif diff --git a/snespurify/phoenix/nall/string/core.hpp b/snespurify/phoenix/nall/string/core.hpp deleted file mode 100755 index 4ffda4ee..00000000 --- a/snespurify/phoenix/nall/string/core.hpp +++ /dev/null @@ -1,145 +0,0 @@ -#ifndef NALL_STRING_CORE_HPP -#define NALL_STRING_CORE_HPP - -namespace nall { - -static void istring(string &output) { -} - -template -static void istring(string &output, const T &value, Args&&... args) { - output.append_(to_string(value)); - istring(output, std::forward(args)...); -} - -void string::reserve(unsigned size_) { - if(size_ > size) { - size = size_; - data = (char*)realloc(data, size + 1); - data[size] = 0; - } -} - -template string& string::assign(Args&&... args) { - *data = 0; - istring(*this, std::forward(args)...); - return *this; -} - -template string& string::append(Args&&... args) { - istring(*this, std::forward(args)...); - return *this; -} - -string& string::assign_(const char *s) { - unsigned length = strlen(s); - reserve(length); - strcpy(data, s); - return *this; -} - -string& string::append_(const char *s) { - unsigned length = strlen(data) + strlen(s); - reserve(length); - strcat(data, s); - return *this; -} - -string::operator const char*() const { - return data; -} - -char* string::operator()() { - return data; -} - -char& string::operator[](int index) { - reserve(index); - return data[index]; -} - -bool string::operator==(const char *str) const { return strcmp(data, str) == 0; } -bool string::operator!=(const char *str) const { return strcmp(data, str) != 0; } -bool string::operator< (const char *str) const { return strcmp(data, str) < 0; } -bool string::operator<=(const char *str) const { return strcmp(data, str) <= 0; } -bool string::operator> (const char *str) const { return strcmp(data, str) > 0; } -bool string::operator>=(const char *str) const { return strcmp(data, str) >= 0; } - -string& string::operator=(const string &value) { - assign(value); - return *this; -} - -string& string::operator=(string &&source) { - if(data) free(data); - size = source.size; - data = source.data; - source.data = 0; - source.size = 0; - return *this; -} - -template string::string(Args&&... args) { - size = 64; - data = (char*)malloc(size + 1); - *data = 0; - istring(*this, std::forward(args)...); -} - -string::string(const string &value) { - size = strlen(value); - data = strdup(value); -} - -string::string(string &&source) { - size = source.size; - data = source.data; - source.data = 0; -} - -string::~string() { - if(data) free(data); -} - -bool string::readfile(const string &filename) { - assign(""); - - #if !defined(_WIN32) - FILE *fp = fopen(filename, "rb"); - #else - FILE *fp = _wfopen(utf16_t(filename), L"rb"); - #endif - if(!fp) return false; - - fseek(fp, 0, SEEK_END); - unsigned size = ftell(fp); - rewind(fp); - char *fdata = new char[size + 1]; - unsigned unused = fread(fdata, 1, size, fp); - fclose(fp); - fdata[size] = 0; - assign(fdata); - delete[] fdata; - - return true; -} - -optional lstring::find(const char *key) const { - for(unsigned i = 0; i < size(); i++) { - if(operator[](i) == key) return { true, i }; - } - return { false, 0 }; -} - -inline lstring::lstring() { -} - -inline lstring::lstring(std::initializer_list list) { - for(const string *s = list.begin(); s != list.end(); ++s) { - operator<<(*s); - } -} - -} - -#endif diff --git a/snespurify/phoenix/nall/string/filename.hpp b/snespurify/phoenix/nall/string/filename.hpp deleted file mode 100755 index 93d605ae..00000000 --- a/snespurify/phoenix/nall/string/filename.hpp +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef NALL_FILENAME_HPP -#define NALL_FILENAME_HPP - -namespace nall { - -// "foo/bar.c" -> "foo/" -// "foo/" -> "foo/" -// "bar.c" -> "./" -inline string dir(char const *name) { - string result = name; - for(signed i = strlen(result); i >= 0; i--) { - if(result[i] == '/' || result[i] == '\\') { - result[i + 1] = 0; - break; - } - if(i == 0) result = "./"; - } - return result; -} - -// "foo/bar.c" -> "bar.c" -inline string notdir(char const *name) { - for(signed i = strlen(name); i >= 0; i--) { - if(name[i] == '/' || name[i] == '\\') { - name += i + 1; - break; - } - } - string result = name; - return result; -} - -// "foo/bar.c" -> "foo/bar" -inline string basename(char const *name) { - string result = name; - for(signed i = strlen(result); i >= 0; i--) { - if(result[i] == '/' || result[i] == '\\') { - //file has no extension - break; - } - if(result[i] == '.') { - result[i] = 0; - break; - } - } - return result; -} - -// "foo/bar.c" -> "c" -inline string extension(char const *name) { - for(signed i = strlen(name); i >= 0; i--) { - if(name[i] == '.') { - name += i + 1; - break; - } - } - string result = name; - return result; -} - -} - -#endif diff --git a/snespurify/phoenix/nall/string/math.hpp b/snespurify/phoenix/nall/string/math.hpp deleted file mode 100755 index ea8b99c8..00000000 --- a/snespurify/phoenix/nall/string/math.hpp +++ /dev/null @@ -1,164 +0,0 @@ -#ifndef NALL_STRING_MATH_HPP -#define NALL_STRING_MATH_HPP - -namespace nall { - -static int eval_integer(const char *&s) { - if(!*s) throw "unrecognized_integer"; - int value = 0, x = *s, y = *(s + 1); - - //hexadecimal - if(x == '0' && (y == 'X' || y == 'x')) { - s += 2; - while(true) { - if(*s >= '0' && *s <= '9') { value = value * 16 + (*s++ - '0'); continue; } - if(*s >= 'A' && *s <= 'F') { value = value * 16 + (*s++ - 'A' + 10); continue; } - if(*s >= 'a' && *s <= 'f') { value = value * 16 + (*s++ - 'a' + 10); continue; } - return value; - } - } - - //binary - if(x == '0' && (y == 'B' || y == 'b')) { - s += 2; - while(true) { - if(*s == '0' || *s == '1') { value = value * 2 + (*s++ - '0'); continue; } - return value; - } - } - - //octal (or decimal '0') - if(x == '0') { - s += 1; - while(true) { - if(*s >= '0' && *s <= '7') { value = value * 8 + (*s++ - '0'); continue; } - return value; - } - } - - //decimal - if(x >= '0' && x <= '9') { - while(true) { - if(*s >= '0' && *s <= '9') { value = value * 10 + (*s++ - '0'); continue; } - return value; - } - } - - //char - if(x == '\'' && y != '\'') { - s += 1; - while(true) { - value = value * 256 + *s++; - if(*s == '\'') { s += 1; return value; } - if(!*s) throw "mismatched_char"; - } - } - - throw "unrecognized_integer"; -} - -static int eval(const char *&s, int depth = 0) { - while(*s == ' ' || *s == '\t') s++; //trim whitespace - if(!*s) throw "unrecognized_token"; - int value = 0, x = *s, y = *(s + 1); - - if(*s == '(') { - value = eval(++s, 1); - if(*s++ != ')') throw "mismatched_group"; - } - - else if(x == '!') value = !eval(++s, 13); - else if(x == '~') value = ~eval(++s, 13); - else if(x == '+') value = +eval(++s, 13); - else if(x == '-') value = -eval(++s, 13); - - else if((x >= '0' && x <= '9') || x == '\'') value = eval_integer(s); - - else throw "unrecognized_token"; - - while(true) { - while(*s == ' ' || *s == '\t') s++; //trim whitespace - if(!*s) break; - x = *s, y = *(s + 1); - - if(depth >= 13) break; - if(x == '*') { value *= eval(++s, 13); continue; } - if(x == '/') { value /= eval(++s, 13); continue; } - if(x == '%') { value %= eval(++s, 13); continue; } - - if(depth >= 12) break; - if(x == '+') { value += eval(++s, 12); continue; } - if(x == '-') { value -= eval(++s, 12); continue; } - - if(depth >= 11) break; - if(x == '<' && y == '<') { value <<= eval(++++s, 11); continue; } - if(x == '>' && y == '>') { value >>= eval(++++s, 11); continue; } - - if(depth >= 10) break; - if(x == '<' && y == '=') { value = value <= eval(++++s, 10); continue; } - if(x == '>' && y == '=') { value = value >= eval(++++s, 10); continue; } - if(x == '<') { value = value < eval(++s, 10); continue; } - if(x == '>') { value = value > eval(++s, 10); continue; } - - if(depth >= 9) break; - if(x == '=' && y == '=') { value = value == eval(++++s, 9); continue; } - if(x == '!' && y == '=') { value = value != eval(++++s, 9); continue; } - - if(depth >= 8) break; - if(x == '&' && y != '&') { value = value & eval(++s, 8); continue; } - - if(depth >= 7) break; - if(x == '^' && y != '^') { value = value ^ eval(++s, 7); continue; } - - if(depth >= 6) break; - if(x == '|' && y != '|') { value = value | eval(++s, 6); continue; } - - if(depth >= 5) break; - if(x == '&' && y == '&') { value = eval(++++s, 5) && value; continue; } - - if(depth >= 4) break; - if(x == '^' && y == '^') { value = (!eval(++++s, 4) != !value); continue; } - - if(depth >= 3) break; - if(x == '|' && y == '|') { value = eval(++++s, 3) || value; continue; } - - if(x == '?') { - int lhs = eval(++s, 2); - if(*s != ':') throw "mismatched_ternary"; - int rhs = eval(++s, 2); - value = value ? lhs : rhs; - continue; - } - if(depth >= 2) break; - - if(depth > 0 && x == ')') break; - - throw "unrecognized_token"; - } - - return value; -} - -bool strint(const char *s, int &result) { - try { - result = eval_integer(s); - return true; - } catch(const char*) { - result = 0; - return false; - } -} - -bool strmath(const char *s, int &result) { - try { - result = eval(s); - return true; - } catch(const char*) { - result = 0; - return false; - } -} - -} - -#endif diff --git a/snespurify/phoenix/nall/string/platform.hpp b/snespurify/phoenix/nall/string/platform.hpp deleted file mode 100755 index 0deda430..00000000 --- a/snespurify/phoenix/nall/string/platform.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef NALL_STRING_PLATFORM_HPP -#define NALL_STRING_PLATFORM_HPP - -namespace nall { - -string currentpath() { - char path[PATH_MAX]; - if(::getcwd(path)) { - string result(path); - result.transform("\\", "/"); - if(result.endswith("/") == false) result.append("/"); - return result; - } - return "./"; -} - -string userpath() { - char path[PATH_MAX]; - if(::userpath(path)) { - string result(path); - result.transform("\\", "/"); - if(result.endswith("/") == false) result.append("/"); - return result; - } - return currentpath(); -} - -string realpath(const char *name) { - char path[PATH_MAX]; - if(::realpath(name, path)) { - string result(path); - result.transform("\\", "/"); - return result; - } - return userpath(); -} - -} - -#endif diff --git a/snespurify/phoenix/nall/string/replace.hpp b/snespurify/phoenix/nall/string/replace.hpp deleted file mode 100755 index db405a9b..00000000 --- a/snespurify/phoenix/nall/string/replace.hpp +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef NALL_STRING_REPLACE_HPP -#define NALL_STRING_REPLACE_HPP - -namespace nall { - -string& string::replace(const char *key, const char *token) { - int i, z, ksl = strlen(key), tsl = strlen(token), ssl = length(); - unsigned int replace_count = 0, size = ssl; - char *buffer; - - if(ksl <= ssl) { - if(tsl > ksl) { //the new string may be longer than the old string... - for(i = 0; i <= ssl - ksl;) { //so let's find out how big of a string we'll need... - if(!memcmp(data + i, key, ksl)) { - replace_count++; - i += ksl; - } else i++; - } - size = ssl + ((tsl - ksl) * replace_count); - reserve(size); - } - - buffer = new char[size + 1]; - for(i = z = 0; i < ssl;) { - if(i <= ssl - ksl) { - if(!memcmp(data + i, key, ksl)) { - memcpy(buffer + z, token, tsl); - z += tsl; - i += ksl; - } else buffer[z++] = data[i++]; - } else buffer[z++] = data[i++]; - } - buffer[z] = 0; - - assign(buffer); - delete[] buffer; - } - - return *this; -} - -string& string::qreplace(const char *key, const char *token) { - int i, l, z, ksl = strlen(key), tsl = strlen(token), ssl = length(); - unsigned int replace_count = 0, size = ssl; - uint8_t x; - char *buffer; - - if(ksl <= ssl) { - if(tsl > ksl) { - for(i = 0; i <= ssl - ksl;) { - x = data[i]; - if(x == '\"' || x == '\'') { - l = i; - i++; - while(data[i++] != x) { - if(i == ssl) { - i = l; - break; - } - } - } - if(!memcmp(data + i, key, ksl)) { - replace_count++; - i += ksl; - } else i++; - } - size = ssl + ((tsl - ksl) * replace_count); - reserve(size); - } - - buffer = new char[size + 1]; - for(i = z = 0; i < ssl;) { - x = data[i]; - if(x == '\"' || x == '\'') { - l = i++; - while(data[i] != x && i < ssl)i++; - if(i >= ssl)i = l; - else { - memcpy(buffer + z, data + l, i - l); - z += i - l; - } - } - if(i <= ssl - ksl) { - if(!memcmp(data + i, key, ksl)) { - memcpy(buffer + z, token, tsl); - z += tsl; - i += ksl; - replace_count++; - } else buffer[z++] = data[i++]; - } else buffer[z++] = data[i++]; - } - buffer[z] = 0; - - assign(buffer); - delete[] buffer; - } - - return *this; -} - -}; - -#endif diff --git a/snespurify/phoenix/nall/string/split.hpp b/snespurify/phoenix/nall/string/split.hpp deleted file mode 100755 index 8d3ca877..00000000 --- a/snespurify/phoenix/nall/string/split.hpp +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef NALL_STRING_SPLIT_HPP -#define NALL_STRING_SPLIT_HPP - -namespace nall { - -template void lstring::split(const char *key, const char *src) { - unsigned limit = Limit; - reset(); - - int ssl = strlen(src), ksl = strlen(key); - int lp = 0, split_count = 0; - - for(int i = 0; i <= ssl - ksl;) { - if(!memcmp(src + i, key, ksl)) { - strlcpy(operator[](split_count++), src + lp, i - lp + 1); - i += ksl; - lp = i; - if(!--limit) break; - } else i++; - } - - operator[](split_count++) = src + lp; -} - -template void lstring::qsplit(const char *key, const char *src) { - unsigned limit = Limit; - reset(); - - int ssl = strlen(src), ksl = strlen(key); - int lp = 0, split_count = 0; - - for(int i = 0; i <= ssl - ksl;) { - uint8_t x = src[i]; - - if(x == '\"' || x == '\'') { - int z = i++; //skip opening quote - while(i < ssl && src[i] != x) i++; - if(i >= ssl) i = z; //failed match, rewind i - else { - i++; //skip closing quote - continue; //restart in case next char is also a quote - } - } - - if(!memcmp(src + i, key, ksl)) { - strlcpy(operator[](split_count++), src + lp, i - lp + 1); - i += ksl; - lp = i; - if(!--limit) break; - } else i++; - } - - operator[](split_count++) = src + lp; -} - -}; - -#endif diff --git a/snespurify/phoenix/nall/string/strl.hpp b/snespurify/phoenix/nall/string/strl.hpp deleted file mode 100755 index 84c841fa..00000000 --- a/snespurify/phoenix/nall/string/strl.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef NALL_STRING_STRL_HPP -#define NALL_STRING_STRL_HPP - -namespace nall { - -//strlcpy, strlcat based on OpenBSD implementation by Todd C. Miller - -//return = strlen(src) -unsigned strlcpy(char *dest, const char *src, unsigned length) { - char *d = dest; - const char *s = src; - unsigned n = length; - - if(n) { - while(--n && (*d++ = *s++)); //copy as many bytes as possible, or until null terminator reached - } - - if(!n) { - if(length) *d = 0; - while(*s++); //traverse rest of s, so that s - src == strlen(src) - } - - return (s - src - 1); //return length of copied string, sans null terminator -} - -//return = strlen(src) + min(length, strlen(dest)) -unsigned strlcat(char *dest, const char *src, unsigned length) { - char *d = dest; - const char *s = src; - unsigned n = length; - - while(n-- && *d) d++; //find end of dest - unsigned dlength = d - dest; - n = length - dlength; //subtract length of dest from maximum string length - - if(!n) return dlength + strlen(s); - - while(*s) { - if(n != 1) { - *d++ = *s; - n--; - } - s++; - } - *d = 0; - - return dlength + (s - src); //return length of resulting string, sans null terminator -} - -} - -#endif diff --git a/snespurify/phoenix/nall/string/strpos.hpp b/snespurify/phoenix/nall/string/strpos.hpp deleted file mode 100755 index 1907a2f3..00000000 --- a/snespurify/phoenix/nall/string/strpos.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef NALL_STRING_STRPOS_HPP -#define NALL_STRING_STRPOS_HPP - -//usage example: -//if(auto pos = strpos(str, key)) print(pos(), "\n"); -//prints position of key within str, only if it is found - -namespace nall { - -optional strpos(const char *str, const char *key) { - unsigned ssl = strlen(str), ksl = strlen(key); - if(ksl > ssl) return { false, 0 }; - - for(unsigned i = 0; i <= ssl - ksl; i++) { - if(!memcmp(str + i, key, ksl)) return { true, i }; - } - - return { false, 0 }; -} - -optional qstrpos(const char *str, const char *key) { - unsigned ssl = strlen(str), ksl = strlen(key); - if(ksl > ssl) return { false, 0 }; - - for(unsigned i = 0; i <= ssl - ksl;) { - uint8_t x = str[i]; - if(x == '\"' || x == '\'') { - uint8_t z = i++; - while(str[i] != x && i < ssl) i++; - if(i >= ssl) i = z; - } - if(!memcmp(str + i, key, ksl)) return { true, i }; - i++; - } - - return { false, 0 }; -} - -} - -#endif diff --git a/snespurify/phoenix/nall/string/trim.hpp b/snespurify/phoenix/nall/string/trim.hpp deleted file mode 100755 index f5355d7d..00000000 --- a/snespurify/phoenix/nall/string/trim.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef NALL_STRING_TRIM_HPP -#define NALL_STRING_TRIM_HPP - -namespace nall { - -//limit defaults to zero, which will underflow on first compare; equivalent to no limit -template char* ltrim(char *str, const char *key) { - unsigned limit = Limit; - if(!key || !*key) return str; - while(strbegin(str, key)) { - char *dest = str, *src = str + strlen(key); - while(true) { - *dest = *src++; - if(!*dest) break; - dest++; - } - if(--limit == 0) break; - } - return str; -} - -template char* rtrim(char *str, const char *key) { - unsigned limit = Limit; - if(!key || !*key) return str; - while(strend(str, key)) { - str[strlen(str) - strlen(key)] = 0; - if(--limit == 0) break; - } - return str; -} - -template char* trim(char *str, const char *key) { - return ltrim(rtrim(str, key), key); -} - -} - -#endif diff --git a/snespurify/phoenix/nall/string/utility.hpp b/snespurify/phoenix/nall/string/utility.hpp deleted file mode 100755 index 8e6c1005..00000000 --- a/snespurify/phoenix/nall/string/utility.hpp +++ /dev/null @@ -1,255 +0,0 @@ -#ifndef NALL_STRING_UTILITY_HPP -#define NALL_STRING_UTILITY_HPP - -namespace nall { - -unsigned strlcpy(string &dest, const char *src, unsigned length) { - dest.reserve(length); - return strlcpy(dest(), src, length); -} - -unsigned strlcat(string &dest, const char *src, unsigned length) { - dest.reserve(length); - return strlcat(dest(), src, length); -} - -string substr(const char *src, unsigned start, unsigned length) { - string dest; - if(length == 0) { - //copy entire string - dest = src + start; - } else { - //copy partial string - strlcpy(dest, src + start, length + 1); - } - return dest; -} - -/* arithmetic <> string */ - -string integer(intmax_t value) { - bool negative = value < 0; - if(negative) value = abs(value); - - char buffer[64]; - unsigned size = 0; - - do { - unsigned n = value % 10; - buffer[size++] = '0' + n; - value /= 10; - } while(value); - buffer[size++] = negative ? '-' : '+'; - buffer[size] = 0; - - char result[size + 1]; - memset(result, '0', size); - result[size] = 0; - - for(signed x = size - 1, y = 0; x >= 0 && y < size; x--, y++) { - result[x] = buffer[y]; - } - - return (const char*)result; -} - -template string linteger(intmax_t value) { - bool negative = value < 0; - if(negative) value = abs(value); - - char buffer[64]; - unsigned size = 0; - - do { - unsigned n = value % 10; - buffer[size++] = '0' + n; - value /= 10; - } while(value); - buffer[size++] = negative ? '-' : '+'; - buffer[size] = 0; - - unsigned length = (length_ == 0 ? size : length_); - char result[length + 1]; - memset(result, ' ', length); - result[length] = 0; - - for(signed x = 0, y = size - 1; x < length && y >= 0; x++, y--) { - result[x] = buffer[y]; - } - - return (const char*)result; -} - -template string rinteger(intmax_t value) { - bool negative = value < 0; - if(negative) value = abs(value); - - char buffer[64]; - unsigned size = 0; - - do { - unsigned n = value % 10; - buffer[size++] = '0' + n; - value /= 10; - } while(value); - buffer[size++] = negative ? '-' : '+'; - buffer[size] = 0; - - unsigned length = (length_ == 0 ? size : length_); - char result[length + 1]; - memset(result, ' ', length); - result[length] = 0; - - for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) { - result[x] = buffer[y]; - } - - return (const char*)result; -} - -string decimal(uintmax_t value) { - char buffer[64]; - unsigned size = 0; - - do { - unsigned n = value % 10; - buffer[size++] = '0' + n; - value /= 10; - } while(value); - buffer[size] = 0; - - char result[size + 1]; - memset(result, '0', size); - result[size] = 0; - - for(signed x = size - 1, y = 0; x >= 0 && y < size; x--, y++) { - result[x] = buffer[y]; - } - - return (const char*)result; -} - -template string ldecimal(uintmax_t value) { - char buffer[64]; - unsigned size = 0; - - do { - unsigned n = value % 10; - buffer[size++] = '0' + n; - value /= 10; - } while(value); - buffer[size] = 0; - - unsigned length = (length_ == 0 ? size : length_); - char result[length + 1]; - memset(result, ' ', length); - result[length] = 0; - - for(signed x = 0, y = size - 1; x < length && y >= 0; x++, y--) { - result[x] = buffer[y]; - } - - return (const char*)result; -} - -template string rdecimal(uintmax_t value) { - char buffer[64]; - unsigned size = 0; - - do { - unsigned n = value % 10; - buffer[size++] = '0' + n; - value /= 10; - } while(value); - buffer[size] = 0; - - unsigned length = (length_ == 0 ? size : length_); - char result[length + 1]; - memset(result, ' ', length); - result[length] = 0; - - for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) { - result[x] = buffer[y]; - } - - return (const char*)result; -} - -template string hex(uintmax_t value) { - char buffer[64]; - unsigned size = 0; - - do { - unsigned n = value & 15; - buffer[size++] = n < 10 ? '0' + n : 'a' + n - 10; - value >>= 4; - } while(value); - - unsigned length = (length_ == 0 ? size : length_); - char result[length + 1]; - memset(result, '0', length); - result[length] = 0; - - for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) { - result[x] = buffer[y]; - } - - return (const char*)result; -} - -template string binary(uintmax_t value) { - char buffer[256]; - unsigned size = 0; - - do { - unsigned n = value & 1; - buffer[size++] = '0' + n; - value >>= 1; - } while(value); - - unsigned length = (length_ == 0 ? size : length_); - char result[length + 1]; - memset(result, '0', length); - result[length] = 0; - - for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) { - result[x] = buffer[y]; - } - - return (const char*)result; -} - -//using sprintf is certainly not the most ideal method to convert -//a double to a string ... but attempting to parse a double by -//hand, digit-by-digit, results in subtle rounding errors. -unsigned fp(char *str, double value) { - char buffer[256]; - sprintf(buffer, "%f", value); - - //remove excess 0's in fraction (2.500000 -> 2.5) - for(char *p = buffer; *p; p++) { - if(*p == '.') { - char *p = buffer + strlen(buffer) - 1; - while(*p == '0') { - if(*(p - 1) != '.') *p = 0; //... but not for eg 1.0 -> 1. - p--; - } - break; - } - } - - unsigned length = strlen(buffer); - if(str) strcpy(str, buffer); - return length + 1; -} - -string fp(double value) { - string temp; - temp.reserve(fp(0, value)); - fp(temp(), value); - return temp; -} - -} - -#endif diff --git a/snespurify/phoenix/nall/string/variadic.hpp b/snespurify/phoenix/nall/string/variadic.hpp deleted file mode 100755 index 6c027fc8..00000000 --- a/snespurify/phoenix/nall/string/variadic.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef NALL_STRING_VARIADIC_HPP -#define NALL_STRING_VARIADIC_HPP - -namespace nall { - -template inline void print(Args&&... args) { - printf("%s", (const char*)string(std::forward(args)...)); -} - -} - -#endif diff --git a/snespurify/phoenix/nall/string/wrapper.hpp b/snespurify/phoenix/nall/string/wrapper.hpp deleted file mode 100755 index eadf0a10..00000000 --- a/snespurify/phoenix/nall/string/wrapper.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef NALL_STRING_WRAPPER_HPP -#define NALL_STRING_WRAPPER_HPP - -namespace nall { - -unsigned string::length() const { return strlen(data); } - -bool string::equals(const char *str) const { return !strcmp(data, str); } -bool string::iequals(const char *str) const { return !stricmp(data, str); } - -bool string::wildcard(const char *str) const { return nall::wildcard(data, str); } -bool string::iwildcard(const char *str) const { return nall::iwildcard(data, str); } - -bool string::beginswith(const char *str) const { return strbegin(data, str); } -bool string::ibeginswith(const char *str) const { return stribegin(data, str); } - -bool string::endswith(const char *str) const { return strend(data, str); } -bool string::iendswith(const char *str) const { return striend(data, str); } - -string& string::lower() { nall::strlower(data); return *this; } -string& string::upper() { nall::strupper(data); return *this; } -string& string::transform(const char *before, const char *after) { nall::strtr(data, before, after); return *this; } - -template string& string::ltrim(const char *key) { nall::ltrim(data, key); return *this; } -template string& string::rtrim(const char *key) { nall::rtrim(data, key); return *this; } -template string& string::trim (const char *key) { nall::trim (data, key); return *this; } - -optional string::position(const char *key) const { return strpos(data, key); } -optional string::qposition(const char *key) const { return qstrpos(data, key); } - -} - -#endif diff --git a/snespurify/phoenix/nall/string/xml.hpp b/snespurify/phoenix/nall/string/xml.hpp deleted file mode 100755 index 185a89f9..00000000 --- a/snespurify/phoenix/nall/string/xml.hpp +++ /dev/null @@ -1,266 +0,0 @@ -#ifndef NALL_STRING_XML_HPP -#define NALL_STRING_XML_HPP - -//XML subset parser -//version 0.05 - -namespace nall { - -struct xml_attribute { - string name; - string content; - virtual string parse() const; -}; - -struct xml_element : xml_attribute { - string parse() const; - linear_vector attribute; - linear_vector element; - -protected: - void parse_doctype(const char *&data); - bool parse_head(string data); - bool parse_body(const char *&data); - friend xml_element xml_parse(const char *data); -}; - -inline string xml_attribute::parse() const { - string data; - unsigned offset = 0; - - const char *source = content; - while(*source) { - if(*source == '&') { - if(strbegin(source, "<")) { data[offset++] = '<'; source += 4; continue; } - if(strbegin(source, ">")) { data[offset++] = '>'; source += 4; continue; } - if(strbegin(source, "&")) { data[offset++] = '&'; source += 5; continue; } - if(strbegin(source, "'")) { data[offset++] = '\''; source += 6; continue; } - if(strbegin(source, """)) { data[offset++] = '"'; source += 6; continue; } - } - - //reject illegal characters - if(*source == '&') return ""; - if(*source == '<') return ""; - if(*source == '>') return ""; - - data[offset++] = *source++; - } - - data[offset] = 0; - return data; -} - -inline string xml_element::parse() const { - string data; - unsigned offset = 0; - - const char *source = content; - while(*source) { - if(*source == '&') { - if(strbegin(source, "<")) { data[offset++] = '<'; source += 4; continue; } - if(strbegin(source, ">")) { data[offset++] = '>'; source += 4; continue; } - if(strbegin(source, "&")) { data[offset++] = '&'; source += 5; continue; } - if(strbegin(source, "'")) { data[offset++] = '\''; source += 6; continue; } - if(strbegin(source, """)) { data[offset++] = '"'; source += 6; continue; } - } - - if(strbegin(source, "")) { - source += pos() + 3; - continue; - } else { - return ""; - } - } - - if(strbegin(source, "")) { - if(pos() - 9 > 0) { - string cdata = substr(source, 9, pos() - 9); - data << cdata; - offset += strlen(cdata); - } - source += 9 + offset + 3; - continue; - } else { - return ""; - } - } - - //reject illegal characters - if(*source == '&') return ""; - if(*source == '<') return ""; - if(*source == '>') return ""; - - data[offset++] = *source++; - } - - data[offset] = 0; - return data; -} - -inline void xml_element::parse_doctype(const char *&data) { - name = "!DOCTYPE"; - const char *content_begin = data; - - signed counter = 0; - while(*data) { - char value = *data++; - if(value == '<') counter++; - if(value == '>') counter--; - if(counter < 0) { - content = substr(content_begin, 0, data - content_begin - 1); - return; - } - } - throw "..."; -} - -inline bool xml_element::parse_head(string data) { - data.qreplace("\t", " "); - data.qreplace("\r", " "); - data.qreplace("\n", " "); - while(qstrpos(data, " ")) data.qreplace(" ", " "); - data.qreplace(" =", "="); - data.qreplace("= ", "="); - data.rtrim(); - - lstring part; - part.qsplit(" ", data); - - name = part[0]; - if(name == "") throw "..."; - - for(unsigned i = 1; i < part.size(); i++) { - lstring side; - side.qsplit("=", part[i]); - if(side.size() != 2) throw "..."; - - xml_attribute attr; - attr.name = side[0]; - attr.content = side[1]; - if(strbegin(attr.content, "\"") && strend(attr.content, "\"")) attr.content.trim<1>("\""); - else if(strbegin(attr.content, "'") && strend(attr.content, "'")) attr.content.trim<1>("'"); - else throw "..."; - attribute.append(attr); - } -} - -inline bool xml_element::parse_body(const char *&data) { - while(true) { - if(!*data) return false; - if(*data++ != '<') continue; - if(*data == '/') return false; - - if(strbegin(data, "!DOCTYPE") == true) { - parse_doctype(data); - return true; - } - - if(strbegin(data, "!--")) { - if(auto offset = strpos(data, "-->")) { - data += offset() + 3; - continue; - } else { - throw "..."; - } - } - - if(strbegin(data, "![CDATA[")) { - if(auto offset = strpos(data, "]]>")) { - data += offset() + 3; - continue; - } else { - throw "..."; - } - } - - auto offset = strpos(data, ">"); - if(!offset) throw "..."; - - string tag = substr(data, 0, offset()); - data += offset() + 1; - const char *content_begin = data; - - bool self_terminating = false; - - if(strend(tag, "?") == true) { - self_terminating = true; - tag.rtrim<1>("?"); - } else if(strend(tag, "/") == true) { - self_terminating = true; - tag.rtrim<1>("/"); - } - - parse_head(tag); - if(self_terminating) return true; - - while(*data) { - unsigned index = element.size(); - xml_element node; - if(node.parse_body(data) == false) { - if(*data == '/') { - signed length = data - content_begin - 1; - if(length > 0) content = substr(content_begin, 0, length); - - data++; - auto offset = strpos(data, ">"); - if(!offset) throw "..."; - - tag = substr(data, 0, offset()); - data += offset() + 1; - - tag.replace("\t", " "); - tag.replace("\r", " "); - tag.replace("\n", " "); - while(strpos(tag, " ")) tag.replace(" ", " "); - tag.rtrim(); - - if(name != tag) throw "..."; - return true; - } - } else { - element.append(node); - } - } - } -} - -//ensure there is only one root element -inline bool xml_validate(xml_element &document) { - unsigned root_counter = 0; - - for(unsigned i = 0; i < document.element.size(); i++) { - string &name = document.element[i].name; - if(strbegin(name, "?")) continue; - if(strbegin(name, "!")) continue; - if(++root_counter > 1) return false; - } - - return true; -} - -inline xml_element xml_parse(const char *data) { - xml_element self; - - try { - while(*data) { - xml_element node; - if(node.parse_body(data) == false) { - break; - } else { - self.element.append(node); - } - } - - if(xml_validate(self) == false) throw "..."; - return self; - } catch(const char*) { - xml_element empty; - return empty; - } -} - -} - -#endif diff --git a/snespurify/phoenix/nall/ups.hpp b/snespurify/phoenix/nall/ups.hpp deleted file mode 100755 index ffcdb2d7..00000000 --- a/snespurify/phoenix/nall/ups.hpp +++ /dev/null @@ -1,223 +0,0 @@ -#ifndef NALL_UPS_HPP -#define NALL_UPS_HPP - -#include -#include -#include -#include - -namespace nall { - -struct ups { - enum class result : unsigned { - unknown, - success, - patch_unwritable, - patch_invalid, - source_invalid, - target_invalid, - target_too_small, - patch_checksum_invalid, - source_checksum_invalid, - target_checksum_invalid, - }; - - function progress; - - result create( - const uint8_t *sourcedata, unsigned sourcelength, - const uint8_t *targetdata, unsigned targetlength, - const char *patchfilename - ) { - source_data = (uint8_t*)sourcedata, target_data = (uint8_t*)targetdata; - source_length = sourcelength, target_length = targetlength; - source_offset = target_offset = 0; - source_checksum = target_checksum = patch_checksum = ~0; - - if(patch_file.open(patchfilename, file::mode::write) == false) return result::patch_unwritable; - - patch_write('U'); - patch_write('P'); - patch_write('S'); - patch_write('1'); - encode(source_length); - encode(target_length); - - unsigned output_length = source_length > target_length ? source_length : target_length; - unsigned relative = 0; - for(unsigned offset = 0; offset < output_length;) { - uint8_t x = source_read(); - uint8_t y = target_read(); - - if(x == y) { - offset++; - continue; - } - - encode(offset++ - relative); - patch_write(x ^ y); - - while(true) { - if(offset >= output_length) { - patch_write(0x00); - break; - } - - x = source_read(); - y = target_read(); - offset++; - patch_write(x ^ y); - if(x == y) break; - } - - relative = offset; - } - - source_checksum = ~source_checksum; - target_checksum = ~target_checksum; - for(unsigned i = 0; i < 4; i++) patch_write(source_checksum >> (i * 8)); - for(unsigned i = 0; i < 4; i++) patch_write(target_checksum >> (i * 8)); - uint32_t patch_result_checksum = ~patch_checksum; - for(unsigned i = 0; i < 4; i++) patch_write(patch_result_checksum >> (i * 8)); - - patch_file.close(); - return result::success; - } - - result apply( - const uint8_t *patchdata, unsigned patchlength, - const uint8_t *sourcedata, unsigned sourcelength, - uint8_t *targetdata, unsigned &targetlength - ) { - patch_data = (uint8_t*)patchdata, source_data = (uint8_t*)sourcedata, target_data = targetdata; - patch_length = patchlength, source_length = sourcelength, target_length = targetlength; - patch_offset = source_offset = target_offset = 0; - patch_checksum = source_checksum = target_checksum = ~0; - - if(patch_length < 18) return result::patch_invalid; - if(patch_read() != 'U') return result::patch_invalid; - if(patch_read() != 'P') return result::patch_invalid; - if(patch_read() != 'S') return result::patch_invalid; - if(patch_read() != '1') return result::patch_invalid; - - unsigned source_read_length = decode(); - unsigned target_read_length = decode(); - - if(source_length != source_read_length && source_length != target_read_length) return result::source_invalid; - targetlength = (source_length == source_read_length ? target_read_length : source_read_length); - if(target_length < targetlength) return result::target_too_small; - target_length = targetlength; - - while(patch_offset < patch_length - 12) { - unsigned length = decode(); - while(length--) target_write(source_read()); - while(true) { - uint8_t patch_xor = patch_read(); - target_write(patch_xor ^ source_read()); - if(patch_xor == 0) break; - } - } - while(source_offset < source_length) target_write(source_read()); - while(target_offset < target_length) target_write(source_read()); - - uint32_t patch_read_checksum = 0, source_read_checksum = 0, target_read_checksum = 0; - for(unsigned i = 0; i < 4; i++) source_read_checksum |= patch_read() << (i * 8); - for(unsigned i = 0; i < 4; i++) target_read_checksum |= patch_read() << (i * 8); - uint32_t patch_result_checksum = ~patch_checksum; - source_checksum = ~source_checksum; - target_checksum = ~target_checksum; - for(unsigned i = 0; i < 4; i++) patch_read_checksum |= patch_read() << (i * 8); - - if(patch_result_checksum != patch_read_checksum) return result::patch_invalid; - if(source_checksum == source_read_checksum && source_length == source_read_length) { - if(target_checksum == target_read_checksum && target_length == target_read_length) return result::success; - return result::target_invalid; - } else if(source_checksum == target_read_checksum && source_length == target_read_length) { - if(target_checksum == source_read_checksum && target_length == source_read_length) return result::success; - return result::target_invalid; - } else { - return result::source_invalid; - } - } - -private: - uint8_t *patch_data, *source_data, *target_data; - unsigned patch_length, source_length, target_length; - unsigned patch_offset, source_offset, target_offset; - unsigned patch_checksum, source_checksum, target_checksum; - file patch_file; - - uint8_t patch_read() { - if(patch_offset < patch_length) { - uint8_t n = patch_data[patch_offset++]; - patch_checksum = crc32_adjust(patch_checksum, n); - return n; - } - return 0x00; - } - - uint8_t source_read() { - if(source_offset < source_length) { - uint8_t n = source_data[source_offset++]; - source_checksum = crc32_adjust(source_checksum, n); - return n; - } - return 0x00; - } - - uint8_t target_read() { - uint8_t result = 0x00; - if(target_offset < target_length) { - result = target_data[target_offset]; - target_checksum = crc32_adjust(target_checksum, result); - } - if(((target_offset++ & 255) == 0) && progress) { - progress(target_offset, source_length > target_length ? source_length : target_length); - } - return result; - } - - void patch_write(uint8_t n) { - patch_file.write(n); - patch_checksum = crc32_adjust(patch_checksum, n); - } - - void target_write(uint8_t n) { - if(target_offset < target_length) { - target_data[target_offset] = n; - target_checksum = crc32_adjust(target_checksum, n); - } - if(((target_offset++ & 255) == 0) && progress) { - progress(target_offset, source_length > target_length ? source_length : target_length); - } - } - - void encode(uint64_t offset) { - while(true) { - uint64_t x = offset & 0x7f; - offset >>= 7; - if(offset == 0) { - patch_write(0x80 | x); - break; - } - patch_write(x); - offset--; - } - } - - uint64_t decode() { - uint64_t offset = 0, shift = 1; - while(true) { - uint8_t x = patch_read(); - offset += (x & 0x7f) * shift; - if(x & 0x80) break; - shift <<= 7; - offset += shift; - } - return offset; - } -}; - -} - -#endif diff --git a/snespurify/phoenix/nall/utf8.hpp b/snespurify/phoenix/nall/utf8.hpp deleted file mode 100755 index f5597b85..00000000 --- a/snespurify/phoenix/nall/utf8.hpp +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef NALL_UTF8_HPP -#define NALL_UTF8_HPP - -//UTF-8 <> UTF-16 conversion -//used only for Win32; Linux, etc use UTF-8 internally - -#if defined(_WIN32) - -#undef UNICODE -#undef _WIN32_WINNT -#undef NOMINMAX -#define UNICODE -#define _WIN32_WINNT 0x0501 -#define NOMINMAX -#include -#undef interface - -namespace nall { - //UTF-8 to UTF-16 - class utf16_t { - public: - operator wchar_t*() { - return buffer; - } - - operator const wchar_t*() const { - return buffer; - } - - utf16_t(const char *s = "") { - if(!s) s = ""; - unsigned length = MultiByteToWideChar(CP_UTF8, 0, s, -1, 0, 0); - buffer = new wchar_t[length + 1](); - MultiByteToWideChar(CP_UTF8, 0, s, -1, buffer, length); - } - - ~utf16_t() { - delete[] buffer; - } - - private: - wchar_t *buffer; - }; - - //UTF-16 to UTF-8 - class utf8_t { - public: - operator char*() { - return buffer; - } - - operator const char*() const { - return buffer; - } - - utf8_t(const wchar_t *s = L"") { - if(!s) s = L""; - unsigned length = WideCharToMultiByte(CP_UTF8, 0, s, -1, 0, 0, (const char*)0, (BOOL*)0); - buffer = new char[length + 1](); - WideCharToMultiByte(CP_UTF8, 0, s, -1, buffer, length, (const char*)0, (BOOL*)0); - } - - ~utf8_t() { - delete[] buffer; - } - - utf8_t(const utf8_t&) = delete; - utf8_t& operator=(const utf8_t&) = delete; - - private: - char *buffer; - }; - - inline void utf8_args(int &argc, char **&argv) { - wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(), &argc); - argv = new char*[argc]; - for(unsigned i = 0; i < argc; i++) { - argv[i] = new char[_MAX_PATH]; - strcpy(argv[i], nall::utf8_t(wargv[i])); - } - } -} - -#endif //if defined(_WIN32) - -#endif diff --git a/snespurify/phoenix/nall/utility.hpp b/snespurify/phoenix/nall/utility.hpp deleted file mode 100755 index 60bda562..00000000 --- a/snespurify/phoenix/nall/utility.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef NALL_UTILITY_HPP -#define NALL_UTILITY_HPP - -#include -#include - -namespace nall { - template struct enable_if { typedef T type; }; - template struct enable_if {}; - template struct mp_enable_if : enable_if {}; - - template inline void swap(T &x, T &y) { - T temp(std::move(x)); - x = std::move(y); - y = std::move(temp); - } - - template struct base_from_member { - T value; - base_from_member(T value_) : value(value_) {} - }; - - template class optional { - bool valid; - T value; - public: - inline operator bool() const { return valid; } - inline const T& operator()() const { if(!valid) throw; return value; } - inline optional(bool valid, const T &value) : valid(valid), value(value) {} - }; - - template inline T* allocate(unsigned size, const T &value) { - T *array = new T[size]; - for(unsigned i = 0; i < size; i++) array[i] = value; - return array; - } -} - -#endif diff --git a/snespurify/phoenix/nall/varint.hpp b/snespurify/phoenix/nall/varint.hpp deleted file mode 100755 index 35649896..00000000 --- a/snespurify/phoenix/nall/varint.hpp +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef NALL_VARINT_HPP -#define NALL_VARINT_HPP - -#include -#include -#include - -namespace nall { - template class uint_t { - private: - unsigned data; - - public: - inline operator unsigned() const { return data; } - inline unsigned operator ++(int) { unsigned r = data; data = uclip(data + 1); return r; } - inline unsigned operator --(int) { unsigned r = data; data = uclip(data - 1); return r; } - inline unsigned operator ++() { return data = uclip(data + 1); } - inline unsigned operator --() { return data = uclip(data - 1); } - inline unsigned operator =(const unsigned i) { return data = uclip(i); } - inline unsigned operator |=(const unsigned i) { return data = uclip(data | i); } - inline unsigned operator ^=(const unsigned i) { return data = uclip(data ^ i); } - inline unsigned operator &=(const unsigned i) { return data = uclip(data & i); } - inline unsigned operator<<=(const unsigned i) { return data = uclip(data << i); } - inline unsigned operator>>=(const unsigned i) { return data = uclip(data >> i); } - inline unsigned operator +=(const unsigned i) { return data = uclip(data + i); } - inline unsigned operator -=(const unsigned i) { return data = uclip(data - i); } - inline unsigned operator *=(const unsigned i) { return data = uclip(data * i); } - inline unsigned operator /=(const unsigned i) { return data = uclip(data / i); } - inline unsigned operator %=(const unsigned i) { return data = uclip(data % i); } - - inline uint_t() : data(0) {} - inline uint_t(const unsigned i) : data(uclip(i)) {} - }; - - template class int_t { - private: - signed data; - - public: - inline operator signed() const { return data; } - inline signed operator ++(int) { signed r = data; data = sclip(data + 1); return r; } - inline signed operator --(int) { signed r = data; data = sclip(data - 1); return r; } - inline signed operator ++() { return data = sclip(data + 1); } - inline signed operator --() { return data = sclip(data - 1); } - inline signed operator =(const signed i) { return data = sclip(i); } - inline signed operator |=(const signed i) { return data = sclip(data | i); } - inline signed operator ^=(const signed i) { return data = sclip(data ^ i); } - inline signed operator &=(const signed i) { return data = sclip(data & i); } - inline signed operator<<=(const signed i) { return data = sclip(data << i); } - inline signed operator>>=(const signed i) { return data = sclip(data >> i); } - inline signed operator +=(const signed i) { return data = sclip(data + i); } - inline signed operator -=(const signed i) { return data = sclip(data - i); } - inline signed operator *=(const signed i) { return data = sclip(data * i); } - inline signed operator /=(const signed i) { return data = sclip(data / i); } - inline signed operator %=(const signed i) { return data = sclip(data % i); } - - inline int_t() : data(0) {} - inline int_t(const signed i) : data(sclip(i)) {} - }; - - class varuint_t { - private: - unsigned data; - unsigned mask; - - public: - inline operator unsigned() const { return data; } - inline unsigned operator ++(int) { unsigned r = data; data = (data + 1) & mask; return r; } - inline unsigned operator --(int) { unsigned r = data; data = (data - 1) & mask; return r; } - inline unsigned operator ++() { return data = (data + 1) & mask; } - inline unsigned operator --() { return data = (data - 1) & mask; } - inline unsigned operator =(const unsigned i) { return data = (i) & mask; } - inline unsigned operator |=(const unsigned i) { return data = (data | i) & mask; } - inline unsigned operator ^=(const unsigned i) { return data = (data ^ i) & mask; } - inline unsigned operator &=(const unsigned i) { return data = (data & i) & mask; } - inline unsigned operator<<=(const unsigned i) { return data = (data << i) & mask; } - inline unsigned operator>>=(const unsigned i) { return data = (data >> i) & mask; } - inline unsigned operator +=(const unsigned i) { return data = (data + i) & mask; } - inline unsigned operator -=(const unsigned i) { return data = (data - i) & mask; } - inline unsigned operator *=(const unsigned i) { return data = (data * i) & mask; } - inline unsigned operator /=(const unsigned i) { return data = (data / i) & mask; } - inline unsigned operator %=(const unsigned i) { return data = (data % i) & mask; } - - inline void bits(unsigned bits) { mask = (1U << (bits - 1)) + ((1U << (bits - 1)) - 1); data &= mask; } - inline varuint_t() : data(0), mask(~0U) {} - inline varuint_t(const unsigned i) : data(i), mask(~0U) {} - }; - - class varuintmax_t { - private: - uintmax_t data; - uintmax_t mask; - - public: - inline operator uintmax_t() const { return data; } - inline uintmax_t operator ++(int) { uintmax_t r = data; data = (data + 1) & mask; return r; } - inline uintmax_t operator --(int) { uintmax_t r = data; data = (data - 1) & mask; return r; } - inline uintmax_t operator ++() { return data = (data + 1) & mask; } - inline uintmax_t operator --() { return data = (data - 1) & mask; } - inline uintmax_t operator =(const uintmax_t i) { return data = (i) & mask; } - inline uintmax_t operator |=(const uintmax_t i) { return data = (data | i) & mask; } - inline uintmax_t operator ^=(const uintmax_t i) { return data = (data ^ i) & mask; } - inline uintmax_t operator &=(const uintmax_t i) { return data = (data & i) & mask; } - inline uintmax_t operator<<=(const uintmax_t i) { return data = (data << i) & mask; } - inline uintmax_t operator>>=(const uintmax_t i) { return data = (data >> i) & mask; } - inline uintmax_t operator +=(const uintmax_t i) { return data = (data + i) & mask; } - inline uintmax_t operator -=(const uintmax_t i) { return data = (data - i) & mask; } - inline uintmax_t operator *=(const uintmax_t i) { return data = (data * i) & mask; } - inline uintmax_t operator /=(const uintmax_t i) { return data = (data / i) & mask; } - inline uintmax_t operator %=(const uintmax_t i) { return data = (data % i) & mask; } - - inline void bits(unsigned bits) { mask = (1ULL << (bits - 1)) + ((1ULL << (bits - 1)) - 1); data &= mask; } - inline varuintmax_t() : data(0), mask(~0ULL) {} - inline varuintmax_t(const uintmax_t i) : data(i), mask(~0ULL) {} - }; -} - -#endif diff --git a/snespurify/phoenix/nall/vector.hpp b/snespurify/phoenix/nall/vector.hpp deleted file mode 100755 index c6ef24f2..00000000 --- a/snespurify/phoenix/nall/vector.hpp +++ /dev/null @@ -1,281 +0,0 @@ -#ifndef NALL_VECTOR_HPP -#define NALL_VECTOR_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace nall { - //linear_vector - //memory: O(capacity * 2) - // - //linear_vector uses placement new + manual destructor calls to create a - //contiguous block of memory for all objects. accessing individual elements - //is fast, though resizing the array incurs significant overhead. - //reserve() overhead is reduced from quadratic time to amortized constant time - //by resizing twice as much as requested. - // - //if objects hold memory address references to themselves (introspection), a - //valid copy constructor will be needed to keep pointers valid. - - template class linear_vector { - protected: - T *pool; - unsigned poolsize, objectsize; - - public: - unsigned size() const { return objectsize; } - unsigned capacity() const { return poolsize; } - - void reset() { - if(pool) { - for(unsigned i = 0; i < objectsize; i++) pool[i].~T(); - free(pool); - } - pool = 0; - poolsize = 0; - objectsize = 0; - } - - void reserve(unsigned newsize) { - newsize = bit::round(newsize); //round to nearest power of two (for amortized growth) - - T *poolcopy = (T*)calloc(newsize, sizeof(T)); - for(unsigned i = 0; i < min(objectsize, newsize); i++) new(poolcopy + i) T(pool[i]); - for(unsigned i = 0; i < objectsize; i++) pool[i].~T(); - free(pool); - pool = poolcopy; - poolsize = newsize; - objectsize = min(objectsize, newsize); - } - - void resize(unsigned newsize) { - if(newsize > poolsize) reserve(newsize); - - if(newsize < objectsize) { - //vector is shrinking; destroy excess objects - for(unsigned i = newsize; i < objectsize; i++) pool[i].~T(); - } else if(newsize > objectsize) { - //vector is expanding; allocate new objects - for(unsigned i = objectsize; i < newsize; i++) new(pool + i) T; - } - - objectsize = newsize; - } - - void append(const T data) { - if(objectsize + 1 > poolsize) reserve(objectsize + 1); - new(pool + objectsize++) T(data); - } - - template void insert(unsigned index, const U list) { - linear_vector merged; - for(unsigned i = 0; i < index; i++) merged.append(pool[i]); - foreach(item, list) merged.append(item); - for(unsigned i = index; i < objectsize; i++) merged.append(pool[i]); - operator=(merged); - } - - void insert(unsigned index, const T item) { - insert(index, linear_vector{ item }); - } - - void remove(unsigned index, unsigned count = 1) { - for(unsigned i = index; count + i < objectsize; i++) { - pool[i] = pool[count + i]; - } - if(count + index >= objectsize) resize(index); //every element >= index was removed - else resize(objectsize - count); - } - - inline T& operator[](unsigned index) { - if(index >= objectsize) resize(index + 1); - return pool[index]; - } - - inline const T& operator[](unsigned index) const { - if(index >= objectsize) throw "vector[] out of bounds"; - return pool[index]; - } - - //copy - inline linear_vector& operator=(const linear_vector &source) { - reset(); - reserve(source.capacity()); - resize(source.size()); - for(unsigned i = 0; i < source.size(); i++) operator[](i) = source.operator[](i); - return *this; - } - - linear_vector(const linear_vector &source) : pool(0), poolsize(0), objectsize(0) { - operator=(source); - } - - //move - inline linear_vector& operator=(linear_vector &&source) { - reset(); - pool = source.pool; - poolsize = source.poolsize; - objectsize = source.objectsize; - source.pool = 0; - source.reset(); - return *this; - } - - linear_vector(linear_vector &&source) : pool(0), poolsize(0), objectsize(0) { - operator=(std::move(source)); - } - - //construction - linear_vector() : pool(0), poolsize(0), objectsize(0) { - } - - linear_vector(std::initializer_list list) : pool(0), poolsize(0), objectsize(0) { - for(const T *p = list.begin(); p != list.end(); ++p) append(*p); - } - - ~linear_vector() { - reset(); - } - }; - - //pointer_vector - //memory: O(1) - // - //pointer_vector keeps an array of pointers to each vector object. this adds - //significant overhead to individual accesses, but allows for optimal memory - //utilization. - // - //by guaranteeing that the base memory address of each objects never changes, - //this avoids the need for an object to have a valid copy constructor. - - template class pointer_vector { - protected: - T **pool; - unsigned poolsize, objectsize; - - public: - unsigned size() const { return objectsize; } - unsigned capacity() const { return poolsize; } - - void reset() { - if(pool) { - for(unsigned i = 0; i < objectsize; i++) { if(pool[i]) delete pool[i]; } - free(pool); - } - pool = 0; - poolsize = 0; - objectsize = 0; - } - - void reserve(unsigned newsize) { - newsize = bit::round(newsize); //round to nearest power of two (for amortized growth) - - for(unsigned i = newsize; i < objectsize; i++) { - if(pool[i]) { delete pool[i]; pool[i] = 0; } - } - - pool = (T**)realloc(pool, newsize * sizeof(T*)); - for(unsigned i = poolsize; i < newsize; i++) pool[i] = 0; - poolsize = newsize; - objectsize = min(objectsize, newsize); - } - - void resize(unsigned newsize) { - if(newsize > poolsize) reserve(newsize); - - for(unsigned i = newsize; i < objectsize; i++) { - if(pool[i]) { delete pool[i]; pool[i] = 0; } - } - - objectsize = newsize; - } - - void append(const T data) { - if(objectsize + 1 > poolsize) reserve(objectsize + 1); - pool[objectsize++] = new T(data); - } - - template void insert(unsigned index, const U list) { - pointer_vector merged; - for(unsigned i = 0; i < index; i++) merged.append(*pool[i]); - foreach(item, list) merged.append(item); - for(unsigned i = index; i < objectsize; i++) merged.append(*pool[i]); - operator=(merged); - } - - void insert(unsigned index, const T item) { - insert(index, pointer_vector{ item }); - } - - void remove(unsigned index, unsigned count = 1) { - for(unsigned i = index; count + i < objectsize; i++) { - *pool[i] = *pool[count + i]; - } - if(count + index >= objectsize) resize(index); //every element >= index was removed - else resize(objectsize - count); - } - - inline T& operator[](unsigned index) { - if(index >= objectsize) resize(index + 1); - if(!pool[index]) pool[index] = new T; - return *pool[index]; - } - - inline const T& operator[](unsigned index) const { - if(index >= objectsize || !pool[index]) throw "vector[] out of bounds"; - return *pool[index]; - } - - //copy - inline pointer_vector& operator=(const pointer_vector &source) { - reset(); - reserve(source.capacity()); - resize(source.size()); - for(unsigned i = 0; i < source.size(); i++) operator[](i) = source.operator[](i); - return *this; - } - - pointer_vector(const pointer_vector &source) : pool(0), poolsize(0), objectsize(0) { - operator=(source); - } - - //move - inline pointer_vector& operator=(pointer_vector &&source) { - reset(); - pool = source.pool; - poolsize = source.poolsize; - objectsize = source.objectsize; - source.pool = 0; - source.reset(); - return *this; - } - - pointer_vector(pointer_vector &&source) : pool(0), poolsize(0), objectsize(0) { - operator=(std::move(source)); - } - - //construction - pointer_vector() : pool(0), poolsize(0), objectsize(0) { - } - - pointer_vector(std::initializer_list list) : pool(0), poolsize(0), objectsize(0) { - for(const T *p = list.begin(); p != list.end(); ++p) append(*p); - } - - ~pointer_vector() { - reset(); - } - }; - - template struct has_size> { enum { value = true }; }; - template struct has_size> { enum { value = true }; }; -} - -#endif diff --git a/snespurify/phoenix/phoenix.cpp b/snespurify/phoenix/phoenix.cpp index 28307897..77276e02 100755 --- a/snespurify/phoenix/phoenix.cpp +++ b/snespurify/phoenix/phoenix.cpp @@ -1,3 +1,6 @@ +#ifndef PHOENIX_CPP +#define PHOENIX_CPP + #if defined(PHOENIX_WINDOWS) #define UNICODE #define WINVER 0x0501 @@ -14,13 +17,16 @@ #include #include #elif defined(PHOENIX_GTK) - #define None X11None + #define None #define Window X11Window + #define X11None 0L #include + #include #include #include #include + #include #undef None #undef Window @@ -35,3 +41,5 @@ using namespace nall; namespace phoenix { #include "core/core.cpp" } + +#endif diff --git a/snespurify/phoenix/phoenix.hpp b/snespurify/phoenix/phoenix.hpp index aa0d94ab..bea075c1 100755 --- a/snespurify/phoenix/phoenix.hpp +++ b/snespurify/phoenix/phoenix.hpp @@ -1,3 +1,6 @@ +#ifndef PHOENIX_HPP +#define PHOENIX_HPP + #include #include #include @@ -11,3 +14,5 @@ namespace phoenix { #include "core/core.hpp" } + +#endif diff --git a/snespurify/phoenix/qt/font.cpp b/snespurify/phoenix/qt/font.cpp index f9c7acb7..4dc21c4b 100755 --- a/snespurify/phoenix/qt/font.cpp +++ b/snespurify/phoenix/qt/font.cpp @@ -20,6 +20,8 @@ void pFont::setUnderline(bool underline) { update(); } void pFont::constructor() { qtFont = new QFont; + font.setFamily("Sans"); + font.setSize(8); } void pFont::update() { diff --git a/snespurify/phoenix/qt/qt.cpp b/snespurify/phoenix/qt/qt.cpp index d971d04b..2eb69bdb 100755 --- a/snespurify/phoenix/qt/qt.cpp +++ b/snespurify/phoenix/qt/qt.cpp @@ -3,6 +3,7 @@ #include "settings.cpp" #include "font.cpp" +#include "timer.cpp" #include "message-window.cpp" #include "window.cpp" @@ -19,6 +20,7 @@ #include "widget/check-box.cpp" #include "widget/combo-box.cpp" #include "widget/hex-edit.cpp" +#include "widget/horizontal-scroll-bar.cpp" #include "widget/horizontal-slider.cpp" #include "widget/label.cpp" #include "widget/line-edit.cpp" @@ -26,6 +28,7 @@ #include "widget/progress-bar.cpp" #include "widget/radio-box.cpp" #include "widget/text-edit.cpp" +#include "widget/vertical-scroll-bar.cpp" #include "widget/vertical-slider.cpp" #include "widget/viewport.cpp" diff --git a/snespurify/phoenix/qt/qt.moc b/snespurify/phoenix/qt/qt.moc index 5105ee8f..80c33bee 100755 --- a/snespurify/phoenix/qt/qt.moc +++ b/snespurify/phoenix/qt/qt.moc @@ -1,7 +1,7 @@ /**************************************************************************** ** Meta object code from reading C++ file 'qt.moc.hpp' ** -** Created: Tue Mar 29 11:11:59 2011 +** Created: Mon Aug 8 04:51:19 2011 ** by: The Qt Meta Object Compiler version 62 (Qt 4.7.0) ** ** WARNING! All changes made in this file will be lost! @@ -16,6 +16,67 @@ #endif QT_BEGIN_MOC_NAMESPACE +static const uint qt_meta_data_pTimer[] = { + + // content: + 5, // revision + 0, // classname + 0, 0, // classinfo + 1, 14, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + // slots: signature, parameters, type, tag, flags + 8, 7, 7, 7, 0x0a, + + 0 // eod +}; + +static const char qt_meta_stringdata_pTimer[] = { + "pTimer\0\0onTimeout()\0" +}; + +const QMetaObject pTimer::staticMetaObject = { + { &QObject::staticMetaObject, qt_meta_stringdata_pTimer, + qt_meta_data_pTimer, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &pTimer::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *pTimer::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *pTimer::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_pTimer)) + return static_cast(const_cast< pTimer*>(this)); + if (!strcmp(_clname, "pObject")) + return static_cast< pObject*>(const_cast< pTimer*>(this)); + return QObject::qt_metacast(_clname); +} + +int pTimer::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QObject::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: onTimeout(); break; + default: ; + } + _id -= 1; + } + return _id; +} static const uint qt_meta_data_pWindow[] = { // content: @@ -545,6 +606,67 @@ int pHexEdit::qt_metacall(QMetaObject::Call _c, int _id, void **_a) } return _id; } +static const uint qt_meta_data_pHorizontalScrollBar[] = { + + // content: + 5, // revision + 0, // classname + 0, 0, // classinfo + 1, 14, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + // slots: signature, parameters, type, tag, flags + 22, 21, 21, 21, 0x0a, + + 0 // eod +}; + +static const char qt_meta_stringdata_pHorizontalScrollBar[] = { + "pHorizontalScrollBar\0\0onChange()\0" +}; + +const QMetaObject pHorizontalScrollBar::staticMetaObject = { + { &QObject::staticMetaObject, qt_meta_stringdata_pHorizontalScrollBar, + qt_meta_data_pHorizontalScrollBar, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &pHorizontalScrollBar::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *pHorizontalScrollBar::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *pHorizontalScrollBar::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_pHorizontalScrollBar)) + return static_cast(const_cast< pHorizontalScrollBar*>(this)); + if (!strcmp(_clname, "pWidget")) + return static_cast< pWidget*>(const_cast< pHorizontalScrollBar*>(this)); + return QObject::qt_metacast(_clname); +} + +int pHorizontalScrollBar::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QObject::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: onChange(); break; + default: ; + } + _id -= 1; + } + return _id; +} static const uint qt_meta_data_pHorizontalSlider[] = { // content: @@ -684,15 +806,16 @@ static const uint qt_meta_data_pListView[] = { // slots: signature, parameters, type, tag, flags 11, 10, 10, 10, 0x0a, - 24, 10, 10, 10, 0x0a, - 40, 35, 10, 10, 0x0a, + 29, 24, 10, 10, 0x0a, + 56, 24, 10, 10, 0x0a, 0 // eod }; static const char qt_meta_stringdata_pListView[] = { - "pListView\0\0onActivate()\0onChange()\0" - "item\0onTick(QTreeWidgetItem*)\0" + "pListView\0\0onActivate()\0item\0" + "onChange(QTreeWidgetItem*)\0" + "onTick(QTreeWidgetItem*)\0" }; const QMetaObject pListView::staticMetaObject = { @@ -727,7 +850,7 @@ int pListView::qt_metacall(QMetaObject::Call _c, int _id, void **_a) if (_c == QMetaObject::InvokeMetaMethod) { switch (_id) { case 0: onActivate(); break; - case 1: onChange(); break; + case 1: onChange((*reinterpret_cast< QTreeWidgetItem*(*)>(_a[1]))); break; case 2: onTick((*reinterpret_cast< QTreeWidgetItem*(*)>(_a[1]))); break; default: ; } @@ -857,6 +980,67 @@ int pTextEdit::qt_metacall(QMetaObject::Call _c, int _id, void **_a) } return _id; } +static const uint qt_meta_data_pVerticalScrollBar[] = { + + // content: + 5, // revision + 0, // classname + 0, 0, // classinfo + 1, 14, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + // slots: signature, parameters, type, tag, flags + 20, 19, 19, 19, 0x0a, + + 0 // eod +}; + +static const char qt_meta_stringdata_pVerticalScrollBar[] = { + "pVerticalScrollBar\0\0onChange()\0" +}; + +const QMetaObject pVerticalScrollBar::staticMetaObject = { + { &QObject::staticMetaObject, qt_meta_stringdata_pVerticalScrollBar, + qt_meta_data_pVerticalScrollBar, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &pVerticalScrollBar::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *pVerticalScrollBar::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *pVerticalScrollBar::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_pVerticalScrollBar)) + return static_cast(const_cast< pVerticalScrollBar*>(this)); + if (!strcmp(_clname, "pWidget")) + return static_cast< pWidget*>(const_cast< pVerticalScrollBar*>(this)); + return QObject::qt_metacast(_clname); +} + +int pVerticalScrollBar::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QObject::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: onChange(); break; + default: ; + } + _id -= 1; + } + return _id; +} static const uint qt_meta_data_pVerticalSlider[] = { // content: diff --git a/snespurify/phoenix/qt/qt.moc.hpp b/snespurify/phoenix/qt/qt.moc.hpp index d7466d6b..36416b46 100755 --- a/snespurify/phoenix/qt/qt.moc.hpp +++ b/snespurify/phoenix/qt/qt.moc.hpp @@ -56,6 +56,23 @@ struct pFont : public pObject { void update(); }; +struct pTimer : public QObject, public pObject { + Q_OBJECT + +public: + Timer &timer; + QTimer *qtTimer; + + void setEnabled(bool enabled); + void setInterval(unsigned milliseconds); + + pTimer(Timer &timer) : timer(timer) {} + void constructor(); + +public slots: + void onTimeout(); +}; + struct pMessageWindow : public pObject { static MessageWindow::Response information(Window &parent, const string &text, MessageWindow::Buttons buttons); static MessageWindow::Response question(Window &parent, const string &text, MessageWindow::Buttons buttons); @@ -84,10 +101,11 @@ public: void append(Layout &layout); void append(Menu &menu); void append(Widget &widget); + Color backgroundColor(); Geometry frameMargin(); bool focused(); Geometry geometry(); - void setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue); + void setBackgroundColor(const Color &color); void setFocused(); void setFullScreen(bool fullScreen); void setGeometry(const Geometry &geometry); @@ -313,6 +331,25 @@ public slots: void onScroll(); }; +struct pHorizontalScrollBar : public QObject, public pWidget { + Q_OBJECT + +public: + HorizontalScrollBar &horizontalScrollBar; + QScrollBar *qtScrollBar; + + Geometry minimumGeometry(); + unsigned position(); + void setLength(unsigned length); + void setPosition(unsigned position); + + pHorizontalScrollBar(HorizontalScrollBar &horizontalScrollBar) : pWidget(horizontalScrollBar), horizontalScrollBar(horizontalScrollBar) {} + void constructor(); + +public slots: + void onChange(); +}; + struct pHorizontalSlider : public QObject, public pWidget { Q_OBJECT @@ -389,7 +426,7 @@ public: public slots: void onActivate(); - void onChange(); + void onChange(QTreeWidgetItem *item); void onTick(QTreeWidgetItem *item); }; @@ -445,6 +482,25 @@ public slots: void onChange(); }; +struct pVerticalScrollBar : public QObject, public pWidget { + Q_OBJECT + +public: + VerticalScrollBar &verticalScrollBar; + QScrollBar *qtScrollBar; + + Geometry minimumGeometry(); + unsigned position(); + void setLength(unsigned length); + void setPosition(unsigned position); + + pVerticalScrollBar(VerticalScrollBar &verticalScrollBar) : pWidget(verticalScrollBar), verticalScrollBar(verticalScrollBar) {} + void constructor(); + +public slots: + void onChange(); +}; + struct pVerticalSlider : public QObject, public pWidget { Q_OBJECT diff --git a/snespurify/phoenix/qt/timer.cpp b/snespurify/phoenix/qt/timer.cpp new file mode 100755 index 00000000..eba78b5a --- /dev/null +++ b/snespurify/phoenix/qt/timer.cpp @@ -0,0 +1,21 @@ +void pTimer::setEnabled(bool enabled) { + if(enabled) { + qtTimer->start(); + } else { + qtTimer->stop(); + } +} + +void pTimer::setInterval(unsigned milliseconds) { + qtTimer->setInterval(milliseconds); +} + +void pTimer::constructor() { + qtTimer = new QTimer; + qtTimer->setInterval(0); + connect(qtTimer, SIGNAL(timeout()), SLOT(onTimeout())); +} + +void pTimer::onTimeout() { + if(timer.onTimeout) timer.onTimeout(); +} diff --git a/snespurify/phoenix/qt/widget/horizontal-scroll-bar.cpp b/snespurify/phoenix/qt/widget/horizontal-scroll-bar.cpp new file mode 100755 index 00000000..43f5c42f --- /dev/null +++ b/snespurify/phoenix/qt/widget/horizontal-scroll-bar.cpp @@ -0,0 +1,29 @@ +Geometry pHorizontalScrollBar::minimumGeometry() { + return { 0, 0, 0, 15 }; +} + +unsigned pHorizontalScrollBar::position() { + return qtScrollBar->value(); +} + +void pHorizontalScrollBar::setLength(unsigned length) { + length += length == 0; + qtScrollBar->setRange(0, length - 1); + qtScrollBar->setPageStep(length >> 3); +} + +void pHorizontalScrollBar::setPosition(unsigned position) { + qtScrollBar->setValue(position); +} + +void pHorizontalScrollBar::constructor() { + qtWidget = qtScrollBar = new QScrollBar(Qt::Horizontal); + qtScrollBar->setRange(0, 100); + qtScrollBar->setPageStep(101 >> 3); + connect(qtScrollBar, SIGNAL(valueChanged(int)), SLOT(onChange())); +} + +void pHorizontalScrollBar::onChange() { + horizontalScrollBar.state.position = position(); + if(horizontalScrollBar.onChange) horizontalScrollBar.onChange(); +} diff --git a/snespurify/phoenix/qt/widget/list-view.cpp b/snespurify/phoenix/qt/widget/list-view.cpp index fb295d5c..6566a94f 100755 --- a/snespurify/phoenix/qt/widget/list-view.cpp +++ b/snespurify/phoenix/qt/widget/list-view.cpp @@ -82,6 +82,7 @@ void pListView::setSelection(unsigned row) { locked = true; QTreeWidgetItem *item = qtListView->currentItem(); if(item) item->setSelected(false); + qtListView->setCurrentItem(0); auto items = qtListView->findItems("", Qt::MatchContains); for(unsigned n = 0; n < items.size(); n++) { if(items[n]->data(0, Qt::UserRole).toUInt() == row) { @@ -100,7 +101,7 @@ void pListView::constructor() { qtListView->setRootIsDecorated(false); connect(qtListView, SIGNAL(itemActivated(QTreeWidgetItem*, int)), SLOT(onActivate())); - connect(qtListView, SIGNAL(itemSelectionChanged()), SLOT(onChange())); + connect(qtListView, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), SLOT(onChange(QTreeWidgetItem*))); connect(qtListView, SIGNAL(itemChanged(QTreeWidgetItem*, int)), SLOT(onTick(QTreeWidgetItem*))); } @@ -108,7 +109,9 @@ void pListView::onActivate() { if(locked == false && listView.onActivate) listView.onActivate(); } -void pListView::onChange() { +void pListView::onChange(QTreeWidgetItem *item) { + //Qt bug workaround: clicking items with mouse does not mark items as selected + if(item) item->setSelected(true); listView.state.selected = selected(); if(listView.state.selected) listView.state.selection = selection(); if(locked == false && listView.onChange) listView.onChange(); diff --git a/snespurify/phoenix/qt/widget/vertical-scroll-bar.cpp b/snespurify/phoenix/qt/widget/vertical-scroll-bar.cpp new file mode 100755 index 00000000..a0638157 --- /dev/null +++ b/snespurify/phoenix/qt/widget/vertical-scroll-bar.cpp @@ -0,0 +1,29 @@ +Geometry pVerticalScrollBar::minimumGeometry() { + return { 0, 0, 15, 0 }; +} + +unsigned pVerticalScrollBar::position() { + return qtScrollBar->value(); +} + +void pVerticalScrollBar::setLength(unsigned length) { + length += length == 0; + qtScrollBar->setRange(0, length - 1); + qtScrollBar->setPageStep(length >> 3); +} + +void pVerticalScrollBar::setPosition(unsigned position) { + qtScrollBar->setValue(position); +} + +void pVerticalScrollBar::constructor() { + qtWidget = qtScrollBar = new QScrollBar(Qt::Vertical); + qtScrollBar->setRange(0, 100); + qtScrollBar->setPageStep(101 >> 3); + connect(qtScrollBar, SIGNAL(valueChanged(int)), SLOT(onChange())); +} + +void pVerticalScrollBar::onChange() { + verticalScrollBar.state.position = position(); + if(verticalScrollBar.onChange) verticalScrollBar.onChange(); +} diff --git a/snespurify/phoenix/qt/window.cpp b/snespurify/phoenix/qt/window.cpp index a11eb58b..7fa2bdff 100755 --- a/snespurify/phoenix/qt/window.cpp +++ b/snespurify/phoenix/qt/window.cpp @@ -18,6 +18,12 @@ void pWindow::append(Widget &widget) { widget.setVisible(widget.state.visible); } +Color pWindow::backgroundColor() { + if(window.state.backgroundColorOverride) return window.state.backgroundColor; + QColor color = qtWindow->palette().color(QPalette::ColorRole::Window); + return { (uint8_t)color.red(), (uint8_t)color.green(), (uint8_t)color.blue(), (uint8_t)color.alpha() }; +} + Geometry pWindow::frameMargin() { unsigned menuHeight = window.state.menuVisible ? qtMenu->height() : 0; unsigned statusHeight = window.state.statusVisible ? qtStatus->height() : 0; @@ -43,9 +49,9 @@ Geometry pWindow::geometry() { return window.state.geometry; } -void pWindow::setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue) { +void pWindow::setBackgroundColor(const Color &color) { QPalette palette; - palette.setColor(QPalette::Window, QColor(red, green, blue)); + palette.setColor(QPalette::Window, QColor(color.red, color.green, color.blue)); qtContainer->setPalette(palette); qtContainer->setAutoFillBackground(true); } diff --git a/snespurify/phoenix/reference/font.cpp b/snespurify/phoenix/reference/font.cpp index 9690c1d9..77d98f70 100755 --- a/snespurify/phoenix/reference/font.cpp +++ b/snespurify/phoenix/reference/font.cpp @@ -1,3 +1,7 @@ +Geometry pFont::geometry(const string &text) { + return { 0, 0, 0, 0 }; +} + void pFont::setBold(bool bold) { } diff --git a/snespurify/phoenix/reference/reference.cpp b/snespurify/phoenix/reference/reference.cpp index a70254b6..7d2262bc 100755 --- a/snespurify/phoenix/reference/reference.cpp +++ b/snespurify/phoenix/reference/reference.cpp @@ -1,6 +1,7 @@ #include "reference.hpp" #include "font.cpp" +#include "timer.cpp" #include "message-window.cpp" #include "window.cpp" @@ -13,9 +14,11 @@ #include "widget/widget.cpp" #include "widget/button.cpp" +#include "widget/canvas.cpp" #include "widget/check-box.cpp" #include "widget/combo-box.cpp" #include "widget/hex-edit.cpp" +#include "widget/horizontal-scroll-bar.cpp" #include "widget/horizontal-slider.cpp" #include "widget/label.cpp" #include "widget/line-edit.cpp" @@ -23,6 +26,7 @@ #include "widget/progress-bar.cpp" #include "widget/radio-box.cpp" #include "widget/text-edit.cpp" +#include "widget/vertical-scroll-bar.cpp" #include "widget/vertical-slider.cpp" #include "widget/viewport.cpp" diff --git a/snespurify/phoenix/reference/reference.hpp b/snespurify/phoenix/reference/reference.hpp index 5f8ebf59..d5872518 100755 --- a/snespurify/phoenix/reference/reference.hpp +++ b/snespurify/phoenix/reference/reference.hpp @@ -29,6 +29,7 @@ struct pOS : public pObject { struct pFont : public pObject { Font &font; + Geometry geometry(const string &text); void setBold(bool bold); void setFamily(const string &family); void setItalic(bool italic); @@ -39,6 +40,16 @@ struct pFont : public pObject { void constructor(); }; +struct pTimer : public pObject { + Timer &timer; + + void setEnabled(bool enabled); + void setInterval(unsigned milliseconds); + + pTimer(Timer &timer) : timer(timer) {} + void constructor(); +}; + struct pMessageWindow : public pObject { static MessageWindow::Response information(Window &parent, const string &text, MessageWindow::Buttons buttons); static MessageWindow::Response question(Window &parent, const string &text, MessageWindow::Buttons buttons); @@ -52,10 +63,11 @@ struct pWindow : public pObject { void append(Layout &layout); void append(Menu &menu); void append(Widget &widget); + Color backgroundColor(); bool focused(); Geometry frameMargin(); Geometry geometry(); - void setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue); + void setBackgroundColor(const Color &color); void setFocused(); void setFullScreen(bool fullScreen); void setGeometry(const Geometry &geometry); @@ -136,6 +148,8 @@ struct pWidget : public pObject { Widget &widget; bool enabled(); + Font& font(); + Geometry minimumGeometry(); void setEnabled(bool enabled); void setFocused(); void setFont(Font &font); @@ -155,6 +169,16 @@ struct pButton : public pWidget { void constructor(); }; +struct pCanvas : public pWidget { + Canvas &canvas; + + uint32_t* buffer(); + void update(); + + pCanvas(Canvas &canvas) : pWidget(canvas), canvas(canvas) {} + void constructor(); +}; + struct pCheckBox : public pWidget { CheckBox &checkBox; @@ -191,6 +215,17 @@ struct pHexEdit : public pWidget { void constructor(); }; +struct pHorizontalScrollBar : public pWidget { + HorizontalScrollBar &horizontalScrollBar; + + unsigned position(); + void setLength(unsigned length); + void setPosition(unsigned position); + + pHorizontalScrollBar(HorizontalScrollBar &horizontalScrollBar) : pWidget(horizontalScrollBar), horizontalScrollBar(horizontalScrollBar) {} + void constructor(); +}; + struct pHorizontalSlider : public pWidget { HorizontalSlider &horizontalSlider; @@ -277,6 +312,17 @@ struct pTextEdit : public pWidget { void constructor(); }; +struct pVerticalScrollBar : public pWidget { + VerticalScrollBar &verticalScrollBar; + + unsigned position(); + void setLength(unsigned length); + void setPosition(unsigned position); + + pVerticalScrollBar(VerticalScrollBar &verticalScrollBar) : pWidget(verticalScrollBar), verticalScrollBar(verticalScrollBar) {} + void constructor(); +}; + struct pVerticalSlider : public pWidget { VerticalSlider &verticalSlider; diff --git a/snespurify/phoenix/reference/timer.cpp b/snespurify/phoenix/reference/timer.cpp new file mode 100755 index 00000000..6cbe571a --- /dev/null +++ b/snespurify/phoenix/reference/timer.cpp @@ -0,0 +1,8 @@ +void pTimer::setEnabled(bool enabled) { +} + +void pTimer::setInterval(unsigned milliseconds) { +} + +void pTimer::constructor() { +} diff --git a/snespurify/phoenix/reference/widget/canvas.cpp b/snespurify/phoenix/reference/widget/canvas.cpp new file mode 100755 index 00000000..70295166 --- /dev/null +++ b/snespurify/phoenix/reference/widget/canvas.cpp @@ -0,0 +1,9 @@ +uint32_t* pCanvas::buffer() { + return 0; +} + +void pCanvas::update() { +} + +void pCanvas::constructor() { +} diff --git a/snespurify/phoenix/reference/widget/horizontal-scroll-bar.cpp b/snespurify/phoenix/reference/widget/horizontal-scroll-bar.cpp new file mode 100755 index 00000000..352b3393 --- /dev/null +++ b/snespurify/phoenix/reference/widget/horizontal-scroll-bar.cpp @@ -0,0 +1,12 @@ +unsigned pHorizontalScrollBar::position() { + return 0; +} + +void pHorizontalScrollBar::setLength(unsigned length) { +} + +void pHorizontalScrollBar::setPosition(unsigned position) { +} + +void pHorizontalScrollBar::constructor() { +} diff --git a/snespurify/phoenix/reference/widget/vertical-scroll-bar.cpp b/snespurify/phoenix/reference/widget/vertical-scroll-bar.cpp new file mode 100755 index 00000000..26795248 --- /dev/null +++ b/snespurify/phoenix/reference/widget/vertical-scroll-bar.cpp @@ -0,0 +1,12 @@ +unsigned pVerticalScrollBar::position() { + return 0; +} + +void pVerticalScrollBar::setLength(unsigned length) { +} + +void pVerticalScrollBar::setPosition(unsigned position) { +} + +void pVerticalScrollBar::constructor() { +} diff --git a/snespurify/phoenix/reference/widget/widget.cpp b/snespurify/phoenix/reference/widget/widget.cpp index 40387671..a7787587 100755 --- a/snespurify/phoenix/reference/widget/widget.cpp +++ b/snespurify/phoenix/reference/widget/widget.cpp @@ -2,6 +2,14 @@ bool pWidget::enabled() { return false; } +Font& pWidget::font() { + throw; +} + +Geometry pWidget::minimumGeometry() { + return { 0, 0, 0, 0 }; +} + void pWidget::setEnabled(bool enabled) { } diff --git a/snespurify/phoenix/reference/window.cpp b/snespurify/phoenix/reference/window.cpp index a31ce464..e9ceebb7 100755 --- a/snespurify/phoenix/reference/window.cpp +++ b/snespurify/phoenix/reference/window.cpp @@ -7,6 +7,10 @@ void pWindow::append(Menu &menu) { void pWindow::append(Widget &widget) { } +Color pWindow::backgroundColor() { + return { 0, 0, 0, 255 }; +} + bool pWindow::focused() { return false; } @@ -19,7 +23,7 @@ Geometry pWindow::geometry() { return { 0, 0, 0, 0 }; } -void pWindow::setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue) { +void pWindow::setBackgroundColor(const Color &color) { } void pWindow::setFocused() { diff --git a/snespurify/phoenix/sync.sh b/snespurify/phoenix/sync.sh index b51e3b40..40ee3d98 100755 --- a/snespurify/phoenix/sync.sh +++ b/snespurify/phoenix/sync.sh @@ -6,3 +6,4 @@ synchronize() { } synchronize "nall" +rm -r nall/test diff --git a/snespurify/phoenix/windows/font.cpp b/snespurify/phoenix/windows/font.cpp index 60d417ee..4153cc65 100755 --- a/snespurify/phoenix/windows/font.cpp +++ b/snespurify/phoenix/windows/font.cpp @@ -46,4 +46,6 @@ void pFont::setUnderline(bool underline) { void pFont::constructor() { hfont = Font_createFont("Tahoma", 8, false, false, false); + font.setFamily("Tahoma"); + font.setSize(8); } diff --git a/snespurify/phoenix/windows/timer.cpp b/snespurify/phoenix/windows/timer.cpp new file mode 100755 index 00000000..8e2b3216 --- /dev/null +++ b/snespurify/phoenix/windows/timer.cpp @@ -0,0 +1,31 @@ +static linear_vector timers; + +static void CALLBACK Timer_timeoutProc(HWND hwnd, UINT msg, UINT_PTR timerID, DWORD time) { + foreach(timer, timers) { + if(timer->htimer == timerID) { + if(timer->timer.onTimeout) timer->timer.onTimeout(); + return; + } + } +} + +void pTimer::setEnabled(bool enabled) { + if(htimer) { + KillTimer(NULL, htimer); + htimer = 0; + } + + if(enabled == true) { + htimer = SetTimer(NULL, 0U, timer.state.milliseconds, Timer_timeoutProc); + } +} + +void pTimer::setInterval(unsigned milliseconds) { + //destroy and recreate timer if interval changed + setEnabled(timer.state.enabled); +} + +void pTimer::constructor() { + timers.append(this); + htimer = 0; +} diff --git a/snespurify/phoenix/windows/widget/horizontal-scroll-bar.cpp b/snespurify/phoenix/windows/widget/horizontal-scroll-bar.cpp new file mode 100755 index 00000000..cdf93056 --- /dev/null +++ b/snespurify/phoenix/windows/widget/horizontal-scroll-bar.cpp @@ -0,0 +1,33 @@ +Geometry pHorizontalScrollBar::minimumGeometry() { + return { 0, 0, 0, 18 }; +} + +unsigned pHorizontalScrollBar::position() { + return GetScrollPos(hwnd, SB_CTL); +} + +void pHorizontalScrollBar::setLength(unsigned length) { + length += (length == 0); + SetScrollRange(hwnd, SB_CTL, 0, length - 1, TRUE); + horizontalScrollBar.setPosition(0); +} + +void pHorizontalScrollBar::setPosition(unsigned position) { return; + SetScrollPos(hwnd, SB_CTL, position, TRUE); +} + +void pHorizontalScrollBar::constructor() { + setParent(Window::None); +} + +void pHorizontalScrollBar::setParent(Window &parent) { + if(hwnd) DestroyWindow(hwnd); + hwnd = CreateWindow( + L"SCROLLBAR", L"", WS_CHILD | WS_VISIBLE | WS_TABSTOP | SBS_HORZ, + 0, 0, 0, 0, parent.p.hwnd, (HMENU)id, GetModuleHandle(0), 0 + ); + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&horizontalScrollBar); + unsigned position = horizontalScrollBar.state.position; + setLength(horizontalScrollBar.state.length); + setPosition(position); +} diff --git a/snespurify/phoenix/windows/widget/horizontal-slider.cpp b/snespurify/phoenix/windows/widget/horizontal-slider.cpp index c660be1e..5359921c 100755 --- a/snespurify/phoenix/windows/widget/horizontal-slider.cpp +++ b/snespurify/phoenix/windows/widget/horizontal-slider.cpp @@ -28,6 +28,7 @@ void pHorizontalSlider::setParent(Window &parent) { 0, 0, 0, 0, parent.p.hwnd, (HMENU)id, GetModuleHandle(0), 0 ); SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&horizontalSlider); + unsigned position = horizontalSlider.state.position; setLength(horizontalSlider.state.length); - setPosition(horizontalSlider.state.position); + setPosition(position); } diff --git a/snespurify/phoenix/windows/widget/list-view.cpp b/snespurify/phoenix/windows/widget/list-view.cpp index 484193a1..92a4f751 100755 --- a/snespurify/phoenix/windows/widget/list-view.cpp +++ b/snespurify/phoenix/windows/widget/list-view.cpp @@ -13,8 +13,6 @@ void pListView::append(const lstring &list) { utf16_t wtext(text); ListView_SetItemText(hwnd, row, n, wtext); } - //workaround: when there is only one column, the horizontal scrollbar will always appear without this - if(listView.state.headerText.size() <= 1) ListView_SetColumnWidth(hwnd, 0, LVSCW_AUTOSIZE_USEHEADER); } void pListView::autoSizeColumns() { @@ -32,7 +30,6 @@ void pListView::modify(unsigned row, const lstring &list) { utf16_t wtext(text); ListView_SetItemText(hwnd, row, n, wtext); } - if(listView.state.headerText.size() <= 1) ListView_SetColumnWidth(hwnd, 0, LVSCW_AUTOSIZE_USEHEADER); } void pListView::reset() { @@ -110,6 +107,7 @@ void pListView::setSelection(unsigned row) { void pListView::constructor() { lostFocus = false; setParent(Window::None); + listView.setHeaderText(""); } void pListView::setGeometry(const Geometry &geometry) { diff --git a/snespurify/phoenix/windows/widget/vertical-scroll-bar.cpp b/snespurify/phoenix/windows/widget/vertical-scroll-bar.cpp new file mode 100755 index 00000000..991c9746 --- /dev/null +++ b/snespurify/phoenix/windows/widget/vertical-scroll-bar.cpp @@ -0,0 +1,33 @@ +Geometry pVerticalScrollBar::minimumGeometry() { + return { 0, 0, 18, 0 }; +} + +unsigned pVerticalScrollBar::position() { + return GetScrollPos(hwnd, SB_CTL); +} + +void pVerticalScrollBar::setLength(unsigned length) { + length += (length == 0); + SetScrollRange(hwnd, SB_CTL, 0, length - 1, TRUE); + verticalScrollBar.setPosition(0); +} + +void pVerticalScrollBar::setPosition(unsigned position) { + SetScrollPos(hwnd, SB_CTL, position, TRUE); +} + +void pVerticalScrollBar::constructor() { + setParent(Window::None); +} + +void pVerticalScrollBar::setParent(Window &parent) { + if(hwnd) DestroyWindow(hwnd); + hwnd = CreateWindow( + L"SCROLLBAR", L"", WS_CHILD | WS_VISIBLE | SBS_VERT, + 0, 0, 0, 0, parent.p.hwnd, (HMENU)id, GetModuleHandle(0), 0 + ); + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&verticalScrollBar); + unsigned position = verticalScrollBar.state.position; + setLength(verticalScrollBar.state.length); + setPosition(position); +} diff --git a/snespurify/phoenix/windows/widget/vertical-slider.cpp b/snespurify/phoenix/windows/widget/vertical-slider.cpp index 8c170cdf..8fa8e569 100755 --- a/snespurify/phoenix/windows/widget/vertical-slider.cpp +++ b/snespurify/phoenix/windows/widget/vertical-slider.cpp @@ -1,5 +1,5 @@ Geometry pVerticalSlider::minimumGeometry() { - return { 0, 0, 25, 0 }; + return { 0, 0, 0, 25 }; } unsigned pVerticalSlider::position() { @@ -28,6 +28,7 @@ void pVerticalSlider::setParent(Window &parent) { 0, 0, 0, 0, parent.p.hwnd, (HMENU)id, GetModuleHandle(0), 0 ); SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&verticalSlider); + unsigned position = verticalSlider.state.position; setLength(verticalSlider.state.length); - setPosition(verticalSlider.state.position); + setPosition(position); } diff --git a/snespurify/phoenix/windows/window.cpp b/snespurify/phoenix/windows/window.cpp index 1961b410..3955168d 100755 --- a/snespurify/phoenix/windows/window.cpp +++ b/snespurify/phoenix/windows/window.cpp @@ -16,6 +16,12 @@ void pWindow::append(Widget &widget) { widget.p.setParent(window); } +Color pWindow::backgroundColor() { + if(window.state.backgroundColorOverride) return window.state.backgroundColor; + DWORD color = GetSysColor(COLOR_3DFACE); + return { (uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color >> 0), 255 }; +} + bool pWindow::focused() { return (GetForegroundWindow() == hwnd); } @@ -36,8 +42,16 @@ Geometry pWindow::frameMargin() { Geometry pWindow::geometry() { Geometry margin = frameMargin(); + RECT rc; - GetWindowRect(hwnd, &rc); + if(IsIconic(hwnd)) { + //GetWindowRect returns -32000(x),-32000(y) when window is minimized + WINDOWPLACEMENT wp; + GetWindowPlacement(hwnd, &wp); + rc = wp.rcNormalPosition; + } else { + GetWindowRect(hwnd, &rc); + } signed x = rc.left + margin.x; signed y = rc.top + margin.y; @@ -47,9 +61,9 @@ Geometry pWindow::geometry() { return { x, y, width, height }; } -void pWindow::setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue) { +void pWindow::setBackgroundColor(const Color &color) { if(brush) DeleteObject(brush); - brushColor = RGB(red, green, blue); + brushColor = RGB(color.red, color.green, color.blue); brush = CreateSolidBrush(brushColor); } diff --git a/snespurify/phoenix/windows/windows.cpp b/snespurify/phoenix/windows/windows.cpp index 4c3596a4..565099e4 100755 --- a/snespurify/phoenix/windows/windows.cpp +++ b/snespurify/phoenix/windows/windows.cpp @@ -2,6 +2,7 @@ #include "object.cpp" #include "font.cpp" +#include "timer.cpp" #include "message-window.cpp" #include "window.cpp" @@ -18,6 +19,7 @@ #include "widget/check-box.cpp" #include "widget/combo-box.cpp" #include "widget/hex-edit.cpp" +#include "widget/horizontal-scroll-bar.cpp" #include "widget/horizontal-slider.cpp" #include "widget/label.cpp" #include "widget/line-edit.cpp" @@ -25,6 +27,7 @@ #include "widget/progress-bar.cpp" #include "widget/radio-box.cpp" #include "widget/text-edit.cpp" +#include "widget/vertical-scroll-bar.cpp" #include "widget/vertical-slider.cpp" #include "widget/viewport.cpp" @@ -174,7 +177,7 @@ void pOS::initialize() { WNDCLASS wc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; - wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); + wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); wc.hCursor = LoadCursor(0, IDC_ARROW); wc.hIcon = LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(2)); wc.hInstance = GetModuleHandle(0); @@ -198,7 +201,7 @@ void pOS::initialize() { wc.cbClsExtra = 0; wc.cbWndExtra = 0; - wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); + wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); wc.hCursor = LoadCursor(0, IDC_ARROW); wc.hIcon = LoadIcon(0, IDI_APPLICATION); wc.hInstance = GetModuleHandle(0); @@ -407,11 +410,58 @@ static LRESULT CALLBACK OS_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM case WM_HSCROLL: case WM_VSCROLL: { - unsigned id = LOWORD(wparam); - HWND control = GetDlgItem(window.p.hwnd, id); - if(control == 0) break; - Object *object = (Object*)GetWindowLongPtr(control, GWLP_USERDATA); + Object *object = 0; + if(lparam) { + object = (Object*)GetWindowLongPtr((HWND)lparam, GWLP_USERDATA); + } else { + unsigned id = LOWORD(wparam); + HWND control = GetDlgItem(window.p.hwnd, id); + if(control == 0) break; + object = (Object*)GetWindowLongPtr(control, GWLP_USERDATA); + } if(object == 0) break; + + if(dynamic_cast(object) + || dynamic_cast(object)) { + SCROLLINFO info; + memset(&info, 0, sizeof(SCROLLINFO)); + info.cbSize = sizeof(SCROLLINFO); + info.fMask = SIF_ALL; + GetScrollInfo((HWND)lparam, SB_CTL, &info); + + switch(LOWORD(wparam)) { + case SB_LEFT: info.nPos = info.nMin; break; + case SB_RIGHT: info.nPos = info.nMax; break; + case SB_LINELEFT: info.nPos--; break; + case SB_LINERIGHT: info.nPos++; break; + case SB_PAGELEFT: info.nPos -= info.nMax >> 3; break; + case SB_PAGERIGHT: info.nPos += info.nMax >> 3; break; + case SB_THUMBTRACK: info.nPos = info.nTrackPos; break; + } + + info.fMask = SIF_POS; + SetScrollInfo((HWND)lparam, SB_CTL, &info, TRUE); + + //Windows may clamp position to scrollbar range + GetScrollInfo((HWND)lparam, SB_CTL, &info); + + if(dynamic_cast(object)) { + HorizontalScrollBar &horizontalScrollBar = (HorizontalScrollBar&)*object; + if(horizontalScrollBar.state.position != info.nPos) { + horizontalScrollBar.state.position = info.nPos; + horizontalScrollBar.onChange(); + } + } else { + VerticalScrollBar &verticalScrollBar = (VerticalScrollBar&)*object; + if(verticalScrollBar.state.position != info.nPos) { + verticalScrollBar.state.position = info.nPos; + verticalScrollBar.onChange(); + } + } + + return TRUE; + } + if(dynamic_cast(object)) { HorizontalSlider &horizontalSlider = (HorizontalSlider&)*object; if(horizontalSlider.state.position != horizontalSlider.position()) { diff --git a/snespurify/phoenix/windows/windows.hpp b/snespurify/phoenix/windows/windows.hpp index 70933131..1cc92696 100755 --- a/snespurify/phoenix/windows/windows.hpp +++ b/snespurify/phoenix/windows/windows.hpp @@ -49,6 +49,17 @@ struct pFont : public pObject { void constructor(); }; +struct pTimer : public pObject { + Timer &timer; + UINT_PTR htimer; + + void setEnabled(bool enabled); + void setInterval(unsigned milliseconds); + + pTimer(Timer &timer) : timer(timer) {} + void constructor(); +}; + struct pMessageWindow : public pObject { static MessageWindow::Response information(Window &parent, const string &text, MessageWindow::Buttons buttons); static MessageWindow::Response question(Window &parent, const string &text, MessageWindow::Buttons buttons); @@ -67,10 +78,11 @@ struct pWindow : public pObject { void append(Layout &layout); void append(Menu &menu); void append(Widget &widget); + Color backgroundColor(); bool focused(); Geometry frameMargin(); Geometry geometry(); - void setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue); + void setBackgroundColor(const Color &color); void setFocused(); void setFullScreen(bool fullScreen); void setGeometry(const Geometry &geometry); @@ -239,6 +251,19 @@ struct pHexEdit : public pWidget { void setParent(Window &parent); }; +struct pHorizontalScrollBar : public pWidget { + HorizontalScrollBar &horizontalScrollBar; + + Geometry minimumGeometry(); + unsigned position(); + void setLength(unsigned length); + void setPosition(unsigned position); + + pHorizontalScrollBar(HorizontalScrollBar &horizontalScrollBar) : pWidget(horizontalScrollBar), horizontalScrollBar(horizontalScrollBar) {} + void constructor(); + void setParent(Window &parent); +}; + struct pHorizontalSlider : public pWidget { HorizontalSlider &horizontalSlider; @@ -339,6 +364,19 @@ struct pTextEdit : public pWidget { void setParent(Window &parent); }; +struct pVerticalScrollBar : public pWidget { + VerticalScrollBar &verticalScrollBar; + + Geometry minimumGeometry(); + unsigned position(); + void setLength(unsigned length); + void setPosition(unsigned position); + + pVerticalScrollBar(VerticalScrollBar &verticalScrollBar) : pWidget(verticalScrollBar), verticalScrollBar(verticalScrollBar) {} + void constructor(); + void setParent(Window &parent); +}; + struct pVerticalSlider : public pWidget { VerticalSlider &verticalSlider; diff --git a/snespurify/snespurify.cpp b/snespurify/snespurify.cpp index 4f07d05e..46ea6c6e 100755 --- a/snespurify/snespurify.cpp +++ b/snespurify/snespurify.cpp @@ -1,319 +1,400 @@ -#include -#include -#include -#include -#include -#include -#include -#include -using namespace nall; +#include "snespurify.hpp" -#include -using namespace phoenix; +MainWindow mainWindow; -static const char applicationTitle[] = "snespurify v10"; - -struct Application : Window { - Font font; - VerticalLayout layout; - HorizontalLayout pathLayout; - Label pathLabel; - LineEdit pathBox; - Button pathScan; - Button pathBrowse; - ListView fileList; - HorizontalLayout controlLayout; - Button selectAll; - Button unselectAll; - Widget spacer; - Button fixSelected; - - struct FileInfo { - string filename; - string problem; - string solution; - }; - linear_vector fileInfo; - lstring errors; - - void main(); - void enable(bool); - void scan(); - void scan(const string &pathname); - void analyze(const string &filename); - void repair(); -} application; - -void Application::main() { - #if defined(PLATFORM_WIN) - font.setFamily("Tahoma"); +void MainWindow::create() { font.setSize(8); - #else - font.setFamily("Sans"); - font.setSize(8); - #endif - setTitle(applicationTitle); - setGeometry({ 128, 128, 600, 360 }); setWidgetFont(font); + setTitle("SNES Purify v11"); - pathLabel.setText("Path to scan:"); - pathScan.setText("Scan"); - pathBrowse.setText("Browse ..."); - fileList.setHeaderText("Filename", "Problem", "Solution"); - fileList.setHeaderVisible(); - fileList.setCheckable(); - selectAll.setText("Select All"); - unselectAll.setText("Clear All"); - fixSelected.setText("Correct"); + navigationLabel.setText("Path to scan:"); + navigationScan.setEnabled(false); + navigationScan.setText("Scan"); + navigationBrowse.setText("Browse ..."); + + listView.setHeaderText("Filename", "Problem"); + listView.setHeaderVisible(); + listView.setCheckable(); + + controlSelectAll.setText("Select All"); + controlClearAll.setText("Clear All"); + controlDeleteFiles.setText("Delete ZIP, IPS, UPS files after conversion"); + controlCorrect.setEnabled(false); + controlCorrect.setText("Correct"); layout.setMargin(5); - pathLayout.append(pathLabel, 0, 0, 5); - pathLayout.append(pathBox, ~0, 0, 5); - pathLayout.append(pathScan, 80, 0, 5); - pathLayout.append(pathBrowse, 80, 0 ); - layout.append(pathLayout, 5); - layout.append(fileList, ~0, ~0, 5); - controlLayout.append(selectAll, 80, 0, 5); - controlLayout.append(unselectAll, 80, 0, 5); - controlLayout.append(spacer, ~0, 0, 5); - controlLayout.append(fixSelected, 80, 0 ); - layout.append(controlLayout ); + navigationLayout.append(navigationLabel, 0, 0, 5); + navigationLayout.append(navigationPath, ~0, 0, 5); + navigationLayout.append(navigationScan, 80, 0, 5); + navigationLayout.append(navigationBrowse, 80, 0); + layout.append(navigationLayout, 5); + layout.append(listView, ~0, ~0, 5); + controlLayout.append(controlSelectAll, 80, 0, 5); + controlLayout.append(controlClearAll, 80, 0, 5); + controlLayout.append(controlDeleteFiles, 0, 0, 5); + controlLayout.append(spacer, ~0, 0); + controlLayout.append(controlCorrect, 80, 0); + layout.append(controlLayout); append(layout); onClose = &OS::quit; - pathBox.onActivate = pathScan.onTick = { &Application::scan, this }; - - pathBrowse.onTick = []() { - string pathname = OS::folderSelect(application, ""); - if(pathname != "") application.pathBox.setText(pathname); + navigationPath.onChange = [this] { + navigationScan.setEnabled(navigationPath.text() != ""); }; - selectAll.onTick = []() { - unsigned count = application.fileInfo.size(); - for(unsigned i = 0; i < count; i++) application.fileList.setChecked(i, true); + navigationPath.onActivate = navigationScan.onTick = { &MainWindow::onScan, this }; + + navigationBrowse.onTick = [this] { + string path = OS::folderSelect(*this, ""); + if(path != "") { + navigationPath.setText(path); + navigationScan.setEnabled(true); + navigationScan.onTick(); + } }; - unselectAll.onTick = []() { - unsigned count = application.fileInfo.size(); - for(unsigned i = 0; i < count; i++) application.fileList.setChecked(i, false); + controlSelectAll.onTick = [this] { + for(unsigned n = 0; n < fileList.size(); n++) listView.setChecked(n, true); }; - fixSelected.onTick = { &Application::repair, this }; + controlClearAll.onTick = [this] { + for(unsigned n = 0; n < fileList.size(); n++) listView.setChecked(n, false); + }; + controlCorrect.onTick = { &MainWindow::onCorrect, this }; + + setGeometry({ 128, 128, 640, 360 }); setVisible(); } -//don't allow actions to be taken while files are being scanned or fixed -void Application::enable(bool state) { - if(state == false) { - setTitle({ applicationTitle, " - working ..." }); - } else { - setTitle(applicationTitle); - } +void MainWindow::onScan() { + string path = navigationPath.text(); + path.transform("\\", "/"); + if(path.endswith("/") == false) path.append("/"); - pathBox.setEnabled(state); - pathScan.setEnabled(state); - pathBrowse.setEnabled(state); - fileList.setEnabled(state); - selectAll.setEnabled(state); - unselectAll.setEnabled(state); - fixSelected.setEnabled(state); -} - -void Application::scan() { - fileInfo.reset(); + listView.reset(); fileList.reset(); - - string pathname = pathBox.text(); - if(pathname == "") { - MessageWindow::information(application, "Please specify a directory to scan"); - return; + onScanFolder(path); + foreach(file, fileList) { + listView.append(notdir(file.name), file.problem); } - pathname.transform("\\", "/"); - if(pathname.endswith("/") == false) pathname.append("/"); - if(directory::exists(pathname) == false) { - MessageWindow::warning(application, "Specified directory does not exist"); - return; - } - - enable(false); - scan(pathname); - enable(true); - - if(fileInfo.size() == 0) { - MessageWindow::information(application, "All files are correct"); - return; - } - - unsigned counter = 0; - foreach(info, fileInfo) { - fileList.append(notdir(info.filename), info.problem, info.solution); - fileList.setChecked(counter++, true); - } - fileList.autoSizeColumns(); + controlSelectAll.onTick(); + listView.autoSizeColumns(); + controlCorrect.setEnabled(fileList.size() > 0); } -void Application::scan(const string &pathname) { - lstring files = directory::files(pathname); - foreach(file, files) { - OS::processEvents(); - analyze({ pathname, file }); +void MainWindow::onScanFolder(const string &path) { + lstring contents = directory::contents(path); + foreach(filename, contents) { + if(filename.endswith("/")) onScanFolder({ path, filename }); + else analyzeFile({ path, filename }); } - - //recursion - lstring folders = directory::folders(pathname); - foreach(folder, folders) scan({ pathname, folder }); } -void Application::analyze(const string &filename) { - if(file::exists(filename) == false) return; +void MainWindow::analyzeFile(const string &filename) { + File file; + file.name = filename; - if(filename.iendswith(".sfc") || filename.iendswith(".bs") || filename.iendswith(".st") - || filename.iendswith(".gb") || filename.iendswith(".gbc") || filename.iendswith(".sgb") - || filename.iendswith(".smc") || filename.iendswith(".swc") || filename.iendswith(".fig") || filename.iendswith(".ufo") - || filename.iendswith(".gd3") || filename.iendswith(".gd7") || filename.iendswith(".dx2") || filename.iendswith(".mgd") - || filename.iendswith(".mgh") || filename.iendswith(".048") || filename.iendswith(".058") || filename.iendswith(".068") - || filename.iendswith(".078") || filename.iendswith(".usa") || filename.iendswith(".eur") || filename.iendswith(".jap") - || filename.iendswith(".aus") || filename.iendswith(".bsx") - ) { - filemap map(filename, filemap::mode::read); - unsigned filesize = map.size(); - SNESCartridge information(map.data(), filesize); + if(filename.iendswith(".zip")) { + //verify there is exactly one SNES image inside the archive + zip archive; + if(archive.open(filename)) { + unsigned fileCount = 0, archiveFileSize = 0; + string archiveFileName; + foreach(archiveFile, archive.file) if(isImageName(archiveFile.name)) { + //make sure file isn't already decompressed + string basename = { nall::basename(filename), correctExtension(archiveFile.name) }; + if(file::exists(basename)) { fileCount = 0; break; } //zero fileCount to prevent multi-archive repeated extractions - //note: the ordering of rules is very important - switch(information.type) { - case SNESCartridge::TypeNormal: - case SNESCartridge::TypeBsxSlotted: - case SNESCartridge::TypeBsxBios: - case SNESCartridge::TypeSufamiTurboBios: - case SNESCartridge::TypeSuperGameBoy1Bios: - case SNESCartridge::TypeSuperGameBoy2Bios: { - if((filesize & 0x7fff) == 512) { - FileInfo info; - info.filename = filename; - info.problem = "Copier header present"; - info.solution = "Remove copier header"; - fileInfo.append(info); - } - - if(filename.endswith(".sfc") == false) { - FileInfo info; - info.filename = filename; - info.problem = "Wrong file extension"; - info.solution = "Rename to .sfc"; - fileInfo.append(info); - } - - break; + fileCount++; + archiveFileName = archiveFile.name; + archiveFileSize = archiveFile.size; } - - case SNESCartridge::TypeBsx: { - if((filesize & 0x7fff) == 512) { - FileInfo info; - info.filename = filename; - info.problem = "Copier header present"; - info.solution = "Remove copier header"; - fileInfo.append(info); + archive.close(); + if(fileCount == 1) { + file.problem.append("Compressed with ZIP; "); + if(isSnesImageName(archiveFileName) && (archiveFileSize & 0x7fff) == 512) { + file.problem.append("Contains copier header; "); } - - if(filename.endswith(".bs") == false) { - FileInfo info; - info.filename = filename; - info.problem = "Wrong file extension"; - info.solution = "Rename to .bs"; - fileInfo.append(info); - } - - break; - } - - case SNESCartridge::TypeSufamiTurbo: { - if((filesize & 0x7fff) == 512) { - FileInfo info; - info.filename = filename; - info.problem = "Copier header present"; - info.solution = "Remove copier header"; - fileInfo.append(info); - } - - if(filename.endswith(".st") == false) { - FileInfo info; - info.filename = filename; - info.problem = "Wrong file extension"; - info.solution = "Rename to .st"; - fileInfo.append(info); - } - - break; - } - - case SNESCartridge::TypeGameBoy: { - if(filename.endswith(".gb") == false && filename.endswith(".gbc") == false && filename.endswith(".sgb") == false) { - FileInfo info; - info.filename = filename; - info.problem = "Wrong file extension"; - info.solution = "Rename to .gb"; - fileInfo.append(info); - } - - break; } } } + + if(isBadImageName(filename)) { + file.problem.append("Incorrect extension; "); + } + + if(isSnesImageName(filename) && (file::size(filename) & 0x7fff) == 512) { + file.problem.append("Contains copier header; "); + } + + if((isImageName(filename) || filename.iendswith(".zip")) && !file::exists({ nall::basename(filename), ".bps" })) { + if(file::exists({ nall::basename(filename), ".ups" })) { + file.problem.append("Deprecated UPS patch; "); + } else if(file::exists({ nall::basename(filename), ".ips" })) { + file.problem.append("Deprecated IPS patch; "); + } + } + + file.problem.rtrim<1>("; "); + if(file.problem != "") fileList.append(file); } -void Application::repair() { - enable(false); +bool MainWindow::isSnesCartImageName(const string &filename) { + if(filename.iendswith(".sfc")) return true; + if(filename.iendswith(".048")) return true; + if(filename.iendswith(".058")) return true; + if(filename.iendswith(".068")) return true; + if(filename.iendswith(".078")) return true; + if(filename.iendswith(".aus")) return true; + if(filename.iendswith(".dx2")) return true; + if(filename.iendswith(".eur")) return true; + if(filename.iendswith(".fig")) return true; + if(filename.iendswith(".gd3")) return true; + if(filename.iendswith(".gd7")) return true; + if(filename.iendswith(".jap")) return true; + if(filename.iendswith(".mgd")) return true; + if(filename.iendswith(".mgh")) return true; + if(filename.iendswith(".smc")) return true; + if(filename.iendswith(".swc")) return true; + if(filename.iendswith(".ufo")) return true; + if(filename.iendswith(".usa")) return true; + return false; +} + +bool MainWindow::isSnesBsImageName(const string &filename) { + if(filename.iendswith(".bs")) return true; + if(filename.iendswith(".bsx")) return true; + return false; +} + +bool MainWindow::isSnesStImageName(const string &filename) { + if(filename.iendswith(".st")) return true; + return false; +} + +bool MainWindow::isSnesImageName(const string &filename) { + if(isSnesCartImageName(filename)) return true; + if(isSnesBsImageName(filename)) return true; + if(isSnesStImageName(filename)) return true; + return false; +} + +bool MainWindow::isGameBoyClassicImageName(const string &filename) { + if(filename.iendswith(".gb")) return true; + if(filename.iendswith(".sgb")) return true; + return false; +} + +bool MainWindow::isGameBoyColorImageName(const string &filename) { + if(filename.iendswith(".gbc")) return true; + return false; +} + +bool MainWindow::isGameBoyImageName(const string &filename) { + if(isGameBoyClassicImageName(filename)) return true; + if(isGameBoyColorImageName(filename)) return true; + return false; +} + +bool MainWindow::isImageName(const string &filename) { + if(isSnesImageName(filename)) return true; + if(isGameBoyImageName(filename)) return true; + return false; +} + +bool MainWindow::isGoodImageName(const string &filename) { + if(filename.endswith(".sfc")) return true; + if(filename.endswith(".bs")) return true; + if(filename.endswith(".st")) return true; + if(filename.endswith(".gb")) return true; + if(filename.endswith(".gbc")) return true; + return false; +} + +bool MainWindow::isBadImageName(const string &filename) { + return (isGoodImageName(filename) == false && isImageName(filename) == true); +} + +string MainWindow::correctExtension(const string &filename) { + if(isSnesCartImageName(filename)) return ".sfc"; + if(isSnesBsImageName(filename)) return ".bs"; + if(isSnesStImageName(filename)) return ".st"; + if(isGameBoyClassicImageName(filename)) return ".gb"; + if(isGameBoyColorImageName(filename)) return ".gbc"; + return { ".", extension(filename) }; //should never occur +} + +void MainWindow::onCorrect() { + navigationPath.setEnabled(false); + navigationScan.setEnabled(false); + navigationBrowse.setEnabled(false); + listView.setEnabled(false); + controlSelectAll.setEnabled(false); + controlClearAll.setEnabled(false); + controlDeleteFiles.setEnabled(false); + controlCorrect.setEnabled(false); + OS::processEvents(); + + MessageWindow::information(*this, + "Corrections may take a long time to complete.\n" + "The GUI will be unresponsive during this time, so please be patient.\n" + "You will be notified when all corrections have been completed." + ); + OS::processEvents(); + errors.reset(); - - for(unsigned n = 0; n < fileInfo.size(); n++) { - if(fileList.checked(n) == false) continue; - OS::processEvents(); - - FileInfo &info = fileInfo[n]; - if(info.solution == "Remove copier header") { - file fp; - if(fp.open(info.filename, file::mode::read)) { - unsigned size = fp.size(); - uint8_t *data = new uint8_t[size]; - fp.read(data, size); - fp.close(); - if(fp.open(info.filename, file::mode::write)) { - fp.write(data + 512, size - 512); - fp.close(); - } - } - } else if(info.solution == "Rename to .sfc") { - rename(info.filename, string(nall::basename(info.filename), ".sfc")); - } else if(info.solution == "Rename to .bs") { - rename(info.filename, string(nall::basename(info.filename), ".bs")); - } else if(info.solution == "Rename to .st") { - rename(info.filename, string(nall::basename(info.filename), ".st")); - } else if(info.solution == "Rename to .gb") { - rename(info.filename, string(nall::basename(info.filename), ".gb")); - } + foreach(file, fileList, n) { + if(listView.checked(n) == false) continue; + if(file.problem.position("Compressed with ZIP")) problemDecompressZip(file); + if(file.problem.position("Incorrect extension")) problemCorrectExtension(file); + if(file.problem.position("Deprecated UPS patch")) problemCreatePatchFromUPS(file); + if(file.problem.position("Deprecated IPS patch")) problemCreatePatchFromIPS(file); + if(file.problem.position("Contains copier header")) problemRemoveCopierHeader(file); } if(errors.size() == 0) { - MessageWindow::information(application, "Selected problems have been corrected"); + MessageWindow::information(*this, "Corrections completed!"); } else { - string output; - for(unsigned i = 0; i < 3 && i < errors.size(); i++) output.append(string(errors[i], "\n")); - if(errors.size() > 3) output.append("\n(too many errors to show ...)"); - MessageWindow::information(application, { - "Selected problems have been corrected, but there were errors:\n\n", - output + file fp; + if(fp.open({ navigationPath.text(), "errors.txt" }, file::mode::write)) { + foreach(error, errors) fp.print(error, "\n"); + fp.close(); + } + MessageWindow::information(*this, { + "Corrections completed, but there were errors.\n" + "Please see ", navigationPath.text(), "errors.txt for more details.\n" }); } - - fileInfo.reset(); + listView.reset(); + listView.autoSizeColumns(); fileList.reset(); - enable(true); + + navigationPath.setEnabled(true); + navigationScan.setEnabled(true); + navigationBrowse.setEnabled(true); + listView.setEnabled(true); + controlSelectAll.setEnabled(true); + controlClearAll.setEnabled(true); + controlDeleteFiles.setEnabled(true); +} + +void MainWindow::problemDecompressZip(File &item) { + zip archive; + if(archive.open(item.name)) { + foreach(archiveFile, archive.file) { + if(isImageName(archiveFile.name)) { + uint8_t *data; + unsigned size; + if(archive.extract(archiveFile, data, size)) { + string targetFileName = { nall::basename(item.name), correctExtension(archiveFile.name) }; + if(file::write(targetFileName, data, size) == false) { + errors.append({ "Failed to write file: ", item.name }); + } else { + if(controlDeleteFiles.checked()) unlink(item.name); + item.name = targetFileName; + } + } else { + errors.append({ "Failed to decompress file: ", item.name }); + } + break; + } + } + } +} + +void MainWindow::problemCorrectExtension(File &item) { + string filename = { nall::basename(item.name), correctExtension(item.name) }; + if(rename(item.name, filename) == -1) { + errors.append({ "Failed to rename file: ", item.name }); + } else { + item.name = filename; + } +} + +void MainWindow::problemCreatePatchFromUPS(File &item) { + string upsPatchName = { nall::basename(item.name), ".ups" }; + string bpsPatchName = { nall::basename(item.name), ".bps" }; + ups oldPatch; + filemap patchFile, sourceFile; + patchFile.open(upsPatchName, filemap::mode::read); + sourceFile.open(item.name, filemap::mode::read); + uint8_t *targetData = 0; + unsigned targetSize = 0; + oldPatch.apply(patchFile.data(), patchFile.size(), sourceFile.data(), sourceFile.size(), targetData, targetSize); + targetData = new uint8_t[targetSize]; + if(oldPatch.apply(patchFile.data(), patchFile.size(), sourceFile.data(), sourceFile.size(), targetData, targetSize) + == ups::result::success) { + bpslinear newPatch; + newPatch.source(item.name); + newPatch.target(targetData, targetSize); + if(newPatch.create(bpsPatchName)) { + patchFile.close(); + if(controlDeleteFiles.checked()) unlink(upsPatchName); + } else { + errors.append({ "Failed to create BPS patch: ", bpsPatchName }); + } + } else { + errors.append({ "Invalid UPS patch: ", upsPatchName }); + } +} + +void MainWindow::problemCreatePatchFromIPS(File &item) { + string ipsPatchName = { nall::basename(item.name), ".ips" }; + string bpsPatchName = { nall::basename(item.name), ".bps" }; + ips oldPatch; + oldPatch.source(item.name); + oldPatch.modify(ipsPatchName); + if(oldPatch.apply()) { + bpslinear newPatch; + newPatch.source(item.name); + newPatch.target(oldPatch.data, oldPatch.size); + if(newPatch.create(bpsPatchName)) { + if(controlDeleteFiles.checked()) unlink(ipsPatchName); + } else { + errors.append({ "Failed to create BPS patch: ", bpsPatchName }); + } + } else { + errors.append({ "Invalid IPS patch: ", ipsPatchName }); + } +} + +/* +void MainWindow::problemCreateUpsPatch(File &item) { + string ipsPatchName = { nall::basename(item.name), ".ips" }; + ips oldPatch; + oldPatch.source(item.name); + oldPatch.modify(ipsPatchName); + if(oldPatch.apply()) { + ups newPatch; + if(newPatch.create( + oldPatch.sourceData, oldPatch.sourceSize, + oldPatch.data, oldPatch.size, + string(nall::basename(item.name), ".ups") + ) != ups::result::success) { + errors.append({ "Failed to convert IPS patch: ", ipsPatchName }); + } else { + if(controlDeleteFiles.checked()) unlink(ipsPatchName); + } + } +} +*/ + +void MainWindow::problemRemoveCopierHeader(File &item) { + uint8_t *data; + unsigned size; + if(file::read(item.name, data, size)) { + if((size & 0x7fff) == 512) { + if(file::write(item.name, data + 512, size - 512) == false) { + errors.append({ "Failed to write file: ", item.name }); + } + } + } } int main() { - application.main(); + mainWindow.create(); OS::main(); return 0; } diff --git a/snespurify/snespurify.hpp b/snespurify/snespurify.hpp new file mode 100755 index 00000000..aaea968a --- /dev/null +++ b/snespurify/snespurify.hpp @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include +#include +#include +#include +using namespace nall; +using namespace phoenix; + +struct MainWindow : public Window { + Font font; + VerticalLayout layout; + HorizontalLayout navigationLayout; + Label navigationLabel; + LineEdit navigationPath; + Button navigationScan; + Button navigationBrowse; + ListView listView; + HorizontalLayout controlLayout; + Button controlSelectAll; + Button controlClearAll; + CheckBox controlDeleteFiles; + Widget spacer; + Button controlCorrect; + + void create(); + void onScan(); + void onScanFolder(const string &path); + void analyzeFile(const string &filename); + + bool isSnesCartImageName(const string &filename); + bool isSnesBsImageName(const string &filename); + bool isSnesStImageName(const string &filename); + bool isSnesImageName(const string &filename); + bool isGameBoyClassicImageName(const string &filename); + bool isGameBoyColorImageName(const string &filename); + bool isGameBoyImageName(const string &filename); + bool isImageName(const string &filename); + bool isGoodImageName(const string &filename); + bool isBadImageName(const string &filename); + string correctExtension(const string &filename); + + struct File { + string name; + string problem; + }; + linear_vector fileList; + lstring errors; + + void onCorrect(); + void problemDecompressZip(File &file); + void problemCorrectExtension(File &file); + void problemCreatePatchFromUPS(File &file); + void problemCreatePatchFromIPS(File &file); + void problemRemoveCopierHeader(File &file); +}; diff --git a/snespurify/sync.sh b/snespurify/sync.sh index 288f98ad..cc469553 100755 --- a/snespurify/sync.sh +++ b/snespurify/sync.sh @@ -7,5 +7,7 @@ synchronize() { synchronize "nall" synchronize "phoenix" -rm -r nall/test -rm -r phoenix/test* + +test -d nall/test && rm -r nall/test +test -d phoenix/nall && rm -r phoenix/nall +test -d phoenix/test && rm -r phoenix/test