o cleanup
This commit is contained in:
63
tools/bsnes/lib/nall/Makefile.string
Executable file
63
tools/bsnes/lib/nall/Makefile.string
Executable file
@@ -0,0 +1,63 @@
|
||||
# Makefile.string
|
||||
# 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] +=
|
||||
|
||||
#####
|
||||
# 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,)
|
||||
23
tools/bsnes/lib/nall/algorithm.hpp
Executable file
23
tools/bsnes/lib/nall/algorithm.hpp
Executable file
@@ -0,0 +1,23 @@
|
||||
#ifndef NALL_ALGORITHM_HPP
|
||||
#define NALL_ALGORITHM_HPP
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
namespace nall {
|
||||
template<typename T, typename U> T min(const T& t, const U& u) {
|
||||
return t < u ? t : u;
|
||||
}
|
||||
|
||||
template<typename T, typename U> T max(const T& t, const U& u) {
|
||||
return t > u ? t : u;
|
||||
}
|
||||
|
||||
//pseudo-random number generator
|
||||
inline unsigned prng() {
|
||||
static unsigned n = 0;
|
||||
return n = (n >> 1) ^ (((n & 1) - 1) & 0xedb88320);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
74
tools/bsnes/lib/nall/any.hpp
Executable file
74
tools/bsnes/lib/nall/any.hpp
Executable file
@@ -0,0 +1,74 @@
|
||||
#ifndef NALL_ANY_HPP
|
||||
#define NALL_ANY_HPP
|
||||
|
||||
#include <typeinfo>
|
||||
#include <nall/static.hpp>
|
||||
#include <nall/traits.hpp>
|
||||
|
||||
namespace nall {
|
||||
class any {
|
||||
public:
|
||||
bool empty() const { return container; }
|
||||
const std::type_info& type() const { return container ? container->type() : typeid(void); }
|
||||
|
||||
template<typename T> any& operator=(const T& value_) {
|
||||
typedef typename static_if<
|
||||
is_array<T>::value,
|
||||
typename remove_extent<typename add_const<T>::type>::type*,
|
||||
T
|
||||
>::type auto_t;
|
||||
|
||||
if(type() == typeid(auto_t)) {
|
||||
static_cast<holder<auto_t>*>(container)->value = (auto_t)value_;
|
||||
} else {
|
||||
if(container) delete container;
|
||||
container = new holder<auto_t>((auto_t)value_);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
any() : container(0) {}
|
||||
template<typename T> any(const T& value_) : container(0) { operator=(value_); }
|
||||
|
||||
private:
|
||||
struct placeholder {
|
||||
virtual const std::type_info& type() const = 0;
|
||||
} *container;
|
||||
|
||||
template<typename T> struct holder : placeholder {
|
||||
T value;
|
||||
const std::type_info& type() const { return typeid(T); }
|
||||
holder(const T& value_) : value(value_) {}
|
||||
};
|
||||
|
||||
template<typename T> friend T any_cast(any&);
|
||||
template<typename T> friend T any_cast(const any&);
|
||||
template<typename T> friend T* any_cast(any*);
|
||||
template<typename T> friend const T* any_cast(const any*);
|
||||
};
|
||||
|
||||
template<typename T> T any_cast(any &value) {
|
||||
typedef typename remove_reference<T>::type nonref;
|
||||
if(value.type() != typeid(nonref)) throw;
|
||||
return static_cast<any::holder<nonref>*>(value.container)->value;
|
||||
}
|
||||
|
||||
template<typename T> T any_cast(const any &value) {
|
||||
typedef const typename remove_reference<T>::type nonref;
|
||||
if(value.type() != typeid(nonref)) throw;
|
||||
return static_cast<any::holder<nonref>*>(value.container)->value;
|
||||
}
|
||||
|
||||
template<typename T> T* any_cast(any *value) {
|
||||
if(!value || value->type() != typeid(T)) return 0;
|
||||
return &static_cast<any::holder<T>*>(value->container)->value;
|
||||
}
|
||||
|
||||
template<typename T> const T* any_cast(const any *value) {
|
||||
if(!value || value->type() != typeid(T)) return 0;
|
||||
return &static_cast<any::holder<T>*>(value->container)->value;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
94
tools/bsnes/lib/nall/array.hpp
Executable file
94
tools/bsnes/lib/nall/array.hpp
Executable file
@@ -0,0 +1,94 @@
|
||||
#ifndef NALL_ARRAY_HPP
|
||||
#define NALL_ARRAY_HPP
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <nall/algorithm.hpp>
|
||||
#include <nall/bit.hpp>
|
||||
|
||||
namespace nall {
|
||||
//dynamic vector array
|
||||
//neither constructor nor destructor is ever invoked;
|
||||
//thus, this should only be used for POD objects.
|
||||
template<typename T> 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 add(const T data) {
|
||||
operator[](buffersize) = data;
|
||||
}
|
||||
|
||||
signed find(const T data) {
|
||||
for(unsigned i = 0; i < size(); i++) if(pool[i] == data) return i;
|
||||
return -1; //not found
|
||||
}
|
||||
|
||||
void clear() {
|
||||
memset(pool, 0, buffersize * sizeof(T));
|
||||
}
|
||||
|
||||
array() {
|
||||
pool = 0;
|
||||
poolsize = 0;
|
||||
buffersize = 0;
|
||||
}
|
||||
|
||||
~array() { reset(); }
|
||||
|
||||
array(const array &source) : pool(0) {
|
||||
operator=(source);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
92
tools/bsnes/lib/nall/base64.hpp
Executable file
92
tools/bsnes/lib/nall/base64.hpp
Executable file
@@ -0,0 +1,92 @@
|
||||
#ifndef NALL_BASE64_HPP
|
||||
#define NALL_BASE64_HPP
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <nall/new.hpp>
|
||||
#include <nall/stdint.hpp>
|
||||
|
||||
namespace nall {
|
||||
class base64 {
|
||||
public:
|
||||
static bool encode(char *&output, const uint8_t* input, unsigned inlength) {
|
||||
output = new(zeromemory) 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(zeromemory) 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
|
||||
51
tools/bsnes/lib/nall/bit.hpp
Executable file
51
tools/bsnes/lib/nall/bit.hpp
Executable file
@@ -0,0 +1,51 @@
|
||||
#ifndef NALL_BIT_HPP
|
||||
#define NALL_BIT_HPP
|
||||
|
||||
namespace nall {
|
||||
template<int bits> inline unsigned uclamp(const unsigned x) {
|
||||
enum { y = (1U << bits) - 1 };
|
||||
return y + ((x - y) & -(x < y)); //min(x, y);
|
||||
}
|
||||
|
||||
template<int bits> inline unsigned uclip(const unsigned x) {
|
||||
enum { m = (1U << bits) - 1 };
|
||||
return (x & m);
|
||||
}
|
||||
|
||||
template<int bits> 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<int bits> 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<typename T> inline T lowest(const T x) {
|
||||
return x & -x;
|
||||
}
|
||||
|
||||
//clear_lowest(0b1110) == 0b1100
|
||||
template<typename T> inline T clear_lowest(const T x) {
|
||||
return x & (x - 1);
|
||||
}
|
||||
|
||||
//set_lowest(0b0101) == 0b0111
|
||||
template<typename T> 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
|
||||
124
tools/bsnes/lib/nall/config.hpp
Executable file
124
tools/bsnes/lib/nall/config.hpp
Executable file
@@ -0,0 +1,124 @@
|
||||
#ifndef NALL_CONFIG_HPP
|
||||
#define NALL_CONFIG_HPP
|
||||
|
||||
#include <nall/file.hpp>
|
||||
#include <nall/string.hpp>
|
||||
#include <nall/vector.hpp>
|
||||
|
||||
namespace nall {
|
||||
namespace configuration_traits {
|
||||
template<typename T> struct is_boolean { enum { value = false }; };
|
||||
template<> struct is_boolean<bool> { enum { value = true }; };
|
||||
|
||||
template<typename T> struct is_signed { enum { value = false }; };
|
||||
template<> struct is_signed<signed> { enum { value = true }; };
|
||||
|
||||
template<typename T> struct is_unsigned { enum { value = false }; };
|
||||
template<> struct is_unsigned<unsigned> { enum { value = true }; };
|
||||
|
||||
template<typename T> struct is_double { enum { value = false }; };
|
||||
template<> struct is_double<double> { enum { value = true }; };
|
||||
|
||||
template<typename T> struct is_string { enum { value = false }; };
|
||||
template<> struct is_string<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 = strsigned(s); break;
|
||||
case unsigned_t: *(unsigned*)data = strunsigned(s); break;
|
||||
case double_t: *(double*)data = strdouble(s); break;
|
||||
case string_t: trim(s, "\""); *(string*)data = s; break;
|
||||
}
|
||||
}
|
||||
};
|
||||
vector<item_t> list;
|
||||
|
||||
template<typename T>
|
||||
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<T>::value) list[n].type = boolean_t;
|
||||
else if(configuration_traits::is_signed<T>::value) list[n].type = signed_t;
|
||||
else if(configuration_traits::is_unsigned<T>::value) list[n].type = unsigned_t;
|
||||
else if(configuration_traits::is_double<T>::value) list[n].type = double_t;
|
||||
else if(configuration_traits::is_string<T>::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++) {
|
||||
int position = qstrpos(line[i], "#");
|
||||
if(position >= 0) line[i][position] = 0;
|
||||
if(qstrpos(line[i], " = ") < 0) continue;
|
||||
|
||||
lstring part;
|
||||
part.qsplit(" = ", line[i]);
|
||||
trim(part[0]);
|
||||
trim(part[1]);
|
||||
|
||||
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
|
||||
66
tools/bsnes/lib/nall/crc32.hpp
Executable file
66
tools/bsnes/lib/nall/crc32.hpp
Executable file
@@ -0,0 +1,66 @@
|
||||
#ifndef NALL_CRC32_HPP
|
||||
#define NALL_CRC32_HPP
|
||||
|
||||
#include <nall/stdint.hpp>
|
||||
|
||||
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
|
||||
30
tools/bsnes/lib/nall/detect.hpp
Executable file
30
tools/bsnes/lib/nall/detect.hpp
Executable file
@@ -0,0 +1,30 @@
|
||||
#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)
|
||||
#define ARCH_MSB
|
||||
#endif
|
||||
|
||||
#endif
|
||||
73
tools/bsnes/lib/nall/dictionary.hpp
Executable file
73
tools/bsnes/lib/nall/dictionary.hpp
Executable file
@@ -0,0 +1,73 @@
|
||||
#ifndef NALL_DICTIONARY_HPP
|
||||
#define NALL_DICTIONARY_HPP
|
||||
|
||||
#include <nall/array.hpp>
|
||||
#include <nall/string.hpp>
|
||||
#include <nall/utility.hpp>
|
||||
|
||||
namespace nall {
|
||||
class dictionary : noncopyable {
|
||||
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, "{{")) {
|
||||
int pos = strpos(input, "}}");
|
||||
if(pos >= 0) {
|
||||
string temp = substr(input, pos + 2);
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
bool import(const char *filename) {
|
||||
string data;
|
||||
if(data.readfile(filename) == false) return false;
|
||||
ltrim_once(data, "\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
|
||||
trim(part[0]);
|
||||
trim(part[1]);
|
||||
|
||||
//remove quotes
|
||||
trim_once(part[0], "\"");
|
||||
trim_once(part[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();
|
||||
}
|
||||
|
||||
protected:
|
||||
lstring index_input;
|
||||
lstring index_output;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
38
tools/bsnes/lib/nall/endian.hpp
Executable file
38
tools/bsnes/lib/nall/endian.hpp
Executable file
@@ -0,0 +1,38 @@
|
||||
#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
|
||||
218
tools/bsnes/lib/nall/file.hpp
Executable file
218
tools/bsnes/lib/nall/file.hpp
Executable file
@@ -0,0 +1,218 @@
|
||||
#ifndef NALL_FILE_HPP
|
||||
#define NALL_FILE_HPP
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <nall/stdint.hpp>
|
||||
#include <nall/utf8.hpp>
|
||||
#include <nall/utility.hpp>
|
||||
|
||||
namespace nall {
|
||||
class file : noncopyable {
|
||||
public:
|
||||
enum FileMode { mode_read, mode_write, mode_readwrite, mode_writeread };
|
||||
enum SeekMode { seek_absolute, seek_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++);
|
||||
}
|
||||
|
||||
void print(const char *string) {
|
||||
if(!string) return;
|
||||
while(*string) write(*string++);
|
||||
}
|
||||
|
||||
void flush() {
|
||||
buffer_flush();
|
||||
fflush(fp);
|
||||
}
|
||||
|
||||
void seek(int offset, SeekMode mode = seek_absolute) {
|
||||
if(!fp) return; //file not open
|
||||
buffer_flush();
|
||||
|
||||
uintmax_t req_offset = file_offset;
|
||||
switch(mode) {
|
||||
case seek_absolute: req_offset = offset; break;
|
||||
case seek_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 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;
|
||||
}
|
||||
|
||||
bool open() {
|
||||
return fp;
|
||||
}
|
||||
|
||||
bool open(const char *fn, FileMode 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();
|
||||
}
|
||||
|
||||
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;
|
||||
FileMode 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
|
||||
190
tools/bsnes/lib/nall/filemap.hpp
Executable file
190
tools/bsnes/lib/nall/filemap.hpp
Executable file
@@ -0,0 +1,190 @@
|
||||
#ifndef NALL_FILEMAP_HPP
|
||||
#define NALL_FILEMAP_HPP
|
||||
|
||||
#include <nall/stdint.hpp>
|
||||
#include <nall/utf8.hpp>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
namespace nall {
|
||||
class filemap {
|
||||
public:
|
||||
enum filemode { mode_read, mode_write, mode_readwrite, mode_writeread };
|
||||
|
||||
bool open(const char *filename, filemode mode) { return p_open(filename, mode); }
|
||||
void close() { return p_close(); }
|
||||
unsigned size() const { return p_size; }
|
||||
uint8_t* handle() { return p_handle; }
|
||||
const uint8_t* handle() const { return p_handle; }
|
||||
filemap() : p_size(0), p_handle(0) { p_ctor(); }
|
||||
~filemap() { p_dtor(); }
|
||||
|
||||
private:
|
||||
unsigned p_size;
|
||||
uint8_t *p_handle;
|
||||
|
||||
#if defined(_WIN32)
|
||||
//=============
|
||||
//MapViewOfFile
|
||||
//=============
|
||||
|
||||
HANDLE p_filehandle, p_maphandle;
|
||||
|
||||
bool p_open(const char *filename, filemode 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_open(const char *filename, filemode 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);
|
||||
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
|
||||
184
tools/bsnes/lib/nall/function.hpp
Executable file
184
tools/bsnes/lib/nall/function.hpp
Executable file
@@ -0,0 +1,184 @@
|
||||
#ifndef NALL_FUNCTION_HPP
|
||||
#define NALL_FUNCTION_HPP
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
//prologue
|
||||
|
||||
#define TN typename
|
||||
|
||||
namespace nall {
|
||||
template<typename T> class function;
|
||||
}
|
||||
|
||||
//parameters = 0
|
||||
|
||||
#define cat(n) n
|
||||
#define TL typename R
|
||||
#define PL
|
||||
#define CL
|
||||
|
||||
#include "function.hpp"
|
||||
|
||||
//parameters = 1
|
||||
|
||||
#define cat(n) , n
|
||||
#define TL TN R, TN P1
|
||||
#define PL P1 p1
|
||||
#define CL p1
|
||||
|
||||
#include "function.hpp"
|
||||
|
||||
//parameters = 2
|
||||
|
||||
#define cat(n) , n
|
||||
#define TL TN R, TN P1, TN P2
|
||||
#define PL P1 p1, P2 p2
|
||||
#define CL p1, p2
|
||||
|
||||
#include "function.hpp"
|
||||
|
||||
//parameters = 3
|
||||
|
||||
#define cat(n) , n
|
||||
#define TL TN R, TN P1, TN P2, TN P3
|
||||
#define PL P1 p1, P2 p2, P3 p3
|
||||
#define CL p1, p2, p3
|
||||
|
||||
#include "function.hpp"
|
||||
|
||||
//parameters = 4
|
||||
|
||||
#define cat(n) , n
|
||||
#define TL TN R, TN P1, TN P2, TN P3, TN P4
|
||||
#define PL P1 p1, P2 p2, P3 p3, P4 p4
|
||||
#define CL p1, p2, p3, p4
|
||||
|
||||
#include "function.hpp"
|
||||
|
||||
//parameters = 5
|
||||
|
||||
#define cat(n) , n
|
||||
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5
|
||||
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5
|
||||
#define CL p1, p2, p3, p4, p5
|
||||
|
||||
#include "function.hpp"
|
||||
|
||||
//parameters = 6
|
||||
|
||||
#define cat(n) , n
|
||||
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5, TN P6
|
||||
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6
|
||||
#define CL p1, p2, p3, p4, p5, p6
|
||||
|
||||
#include "function.hpp"
|
||||
|
||||
//parameters = 7
|
||||
|
||||
#define cat(n) , n
|
||||
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5, TN P6, TN P7
|
||||
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7
|
||||
#define CL p1, p2, p3, p4, p5, p6, p7
|
||||
|
||||
#include "function.hpp"
|
||||
|
||||
//parameters = 8
|
||||
|
||||
#define cat(n) , n
|
||||
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5, TN P6, TN P7, TN P8
|
||||
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8
|
||||
#define CL p1, p2, p3, p4, p5, p6, p7, p8
|
||||
|
||||
#include "function.hpp"
|
||||
|
||||
//epilogue
|
||||
|
||||
#undef TN
|
||||
#define NALL_FUNCTION_T
|
||||
|
||||
#elif !defined(NALL_FUNCTION_T)
|
||||
|
||||
//function implementation template class
|
||||
|
||||
namespace nall {
|
||||
template<TL>
|
||||
class function<R (PL)> {
|
||||
private:
|
||||
struct base1 { virtual void func1(PL) {} };
|
||||
struct base2 { virtual void func2(PL) {} };
|
||||
struct derived : base1, virtual base2 {};
|
||||
|
||||
struct data_t {
|
||||
R (*fn_call)(const data_t& cat(PL));
|
||||
union {
|
||||
R (*fn_global)(PL);
|
||||
struct {
|
||||
R (derived::*fn_member)(PL);
|
||||
void *object;
|
||||
};
|
||||
};
|
||||
} data;
|
||||
|
||||
static R fn_call_global(const data_t &d cat(PL)) {
|
||||
return d.fn_global(CL);
|
||||
}
|
||||
|
||||
template<typename C>
|
||||
static R fn_call_member(const data_t &d cat(PL)) {
|
||||
return (((C*)d.object)->*((R (C::*&)(PL))d.fn_member))(CL);
|
||||
}
|
||||
|
||||
public:
|
||||
R operator()(PL) const { return data.fn_call(data cat(CL)); }
|
||||
operator bool() const { return data.fn_call; }
|
||||
|
||||
function() { data.fn_call = 0; }
|
||||
|
||||
function(R (*fn)(PL)) {
|
||||
data.fn_call = &fn_call_global;
|
||||
data.fn_global = fn;
|
||||
}
|
||||
|
||||
template<typename C>
|
||||
function(R (C::*fn)(PL), C *obj) {
|
||||
data.fn_call = &fn_call_member<C>;
|
||||
(R (C::*&)(PL))data.fn_member = fn;
|
||||
assert(sizeof data.fn_member >= sizeof fn);
|
||||
data.object = obj;
|
||||
}
|
||||
|
||||
template<typename C>
|
||||
function(R (C::*fn)(PL) const, C *obj) {
|
||||
data.fn_call = &fn_call_member<C>;
|
||||
(R (C::*&)(PL))data.fn_member = (R (C::*&)(PL))fn;
|
||||
assert(sizeof data.fn_member >= sizeof fn);
|
||||
data.object = obj;
|
||||
}
|
||||
|
||||
function &operator=(const function &source) { memcpy(&data, &source.data, sizeof(data_t)); return *this; }
|
||||
function(const function &source) { memcpy(&data, &source.data, sizeof(data_t)); }
|
||||
};
|
||||
|
||||
template<TL>
|
||||
function<R (PL)> bind(R (*fn)(PL)) {
|
||||
return function<R (PL)>(fn);
|
||||
}
|
||||
|
||||
template<typename C, TL>
|
||||
function<R (PL)> bind(R (C::*fn)(PL), C *obj) {
|
||||
return function<R (PL)>(fn, obj);
|
||||
}
|
||||
|
||||
template<typename C, TL>
|
||||
function<R (PL)> bind(R (C::*fn)(PL) const, C *obj) {
|
||||
return function<R (PL)>(fn, obj);
|
||||
}
|
||||
}
|
||||
|
||||
#undef cat
|
||||
#undef TL
|
||||
#undef PL
|
||||
#undef CL
|
||||
|
||||
#endif
|
||||
263
tools/bsnes/lib/nall/input.hpp
Executable file
263
tools/bsnes/lib/nall/input.hpp
Executable file
@@ -0,0 +1,263 @@
|
||||
#ifndef NALL_INPUT_HPP
|
||||
#define NALL_INPUT_HPP
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <nall/stdint.hpp>
|
||||
|
||||
namespace nall {
|
||||
enum { input_none = 0 };
|
||||
|
||||
template<int number = -1> struct keyboard {
|
||||
enum {
|
||||
none = keyboard<number - 1>::limit,
|
||||
escape, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12,
|
||||
print_screen, scroll_lock, pause, tilde,
|
||||
num_1, num_2, num_3, num_4, num_5, num_6, num_7, num_8, num_9, num_0,
|
||||
dash, equal, backspace,
|
||||
insert, delete_, home, end, page_up, page_down,
|
||||
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,
|
||||
lbracket, rbracket, backslash, semicolon, apostrophe, comma, period, slash,
|
||||
pad_1, pad_2, pad_3, pad_4, pad_5, pad_6, pad_7, pad_8, pad_9, pad_0,
|
||||
point, enter, add, subtract, multiply, divide,
|
||||
num_lock, caps_lock,
|
||||
up, down, left, right,
|
||||
tab, return_, spacebar,
|
||||
lctrl, rctrl, lalt, ralt, lshift, rshift, lsuper, rsuper, menu,
|
||||
limit,
|
||||
};
|
||||
};
|
||||
|
||||
template<> struct keyboard<-1> {
|
||||
enum { count = 16 };
|
||||
enum {
|
||||
none,
|
||||
escape, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12,
|
||||
print_screen, scroll_lock, pause, tilde,
|
||||
num_1, num_2, num_3, num_4, num_5, num_6, num_7, num_8, num_9, num_0,
|
||||
dash, equal, backspace,
|
||||
insert, delete_, home, end, page_up, page_down,
|
||||
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,
|
||||
lbracket, rbracket, backslash, semicolon, apostrophe, comma, period, slash,
|
||||
pad_1, pad_2, pad_3, pad_4, pad_5, pad_6, pad_7, pad_8, pad_9, pad_0,
|
||||
point, enter, add, subtract, multiply, divide,
|
||||
num_lock, caps_lock,
|
||||
up, down, left, right,
|
||||
tab, return_, spacebar,
|
||||
lctrl, rctrl, lalt, ralt, lshift, rshift, lsuper, rsuper, menu,
|
||||
length, //number of syms per keyboard
|
||||
limit = 0,
|
||||
};
|
||||
|
||||
static uint16_t index(unsigned keyboard_number, unsigned keyboard_enum) {
|
||||
if(keyboard_number >= count) return input_none;
|
||||
return limit + keyboard_number * length + keyboard_enum;
|
||||
}
|
||||
};
|
||||
|
||||
template<int number = -1> struct mouse {
|
||||
enum { buttons = 8 };
|
||||
enum {
|
||||
none = mouse<number - 1>::limit,
|
||||
x, y, z,
|
||||
button,
|
||||
limit = button + buttons,
|
||||
};
|
||||
};
|
||||
|
||||
template<> struct mouse<-1> {
|
||||
enum { count = 16, buttons = 8 };
|
||||
enum {
|
||||
none,
|
||||
x, y, z,
|
||||
button,
|
||||
length = button + buttons - none, //number of syms per mouse
|
||||
limit = keyboard<keyboard<>::count - 1>::limit,
|
||||
};
|
||||
|
||||
static uint16_t index(unsigned mouse_number, unsigned mouse_enum) {
|
||||
if(mouse_number >= count) return input_none;
|
||||
return limit + mouse_number * length + mouse_enum;
|
||||
}
|
||||
};
|
||||
|
||||
template<int number = -1> struct joypad {
|
||||
enum { hats = 8, axes = 32, buttons = 96 };
|
||||
enum {
|
||||
none = joypad<number - 1>::limit,
|
||||
hat,
|
||||
axis = hat + hats,
|
||||
button = axis + axes,
|
||||
limit = button + buttons,
|
||||
};
|
||||
};
|
||||
|
||||
template<> struct joypad<-1> {
|
||||
enum { count = 16, hats = 8, axes = 32, buttons = 96 };
|
||||
enum { hat_center = 0, hat_up = 1, hat_right = 2, hat_down = 4, hat_left = 8 };
|
||||
enum {
|
||||
none,
|
||||
hat,
|
||||
axis = hat + hats,
|
||||
button = axis + axes,
|
||||
length = button + buttons - none, //number of syms per joypad
|
||||
limit = mouse<mouse<>::count - 1>::limit,
|
||||
};
|
||||
|
||||
static uint16_t index(unsigned joypad_number, unsigned joypad_enum) {
|
||||
if(joypad_number >= count) return input_none;
|
||||
return limit + joypad_number * length + joypad_enum;
|
||||
}
|
||||
};
|
||||
|
||||
enum { input_limit = joypad<joypad<>::count - 1>::limit };
|
||||
|
||||
static const char keysym[][64] = {
|
||||
"none",
|
||||
"escape", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12",
|
||||
"print_screen", "scroll_lock", "pause", "tilde",
|
||||
"num_1", "num_2", "num_3", "num_4", "num_5", "num_6", "num_7", "num_8", "num_9", "num_0",
|
||||
"dash", "equal", "backspace",
|
||||
"insert", "delete", "home", "end", "page_up", "page_down",
|
||||
"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",
|
||||
"lbracket", "rbracket", "backslash", "semicolon", "apostrophe", "comma", "period", "slash",
|
||||
"pad_1", "pad_2", "pad_3", "pad_4", "pad_5", "pad_6", "pad_7", "pad_8", "pad_9", "pad_0",
|
||||
"point", "enter", "add", "subtract", "multiply", "divide",
|
||||
"num_lock", "caps_lock",
|
||||
"up", "down", "left", "right",
|
||||
"tab", "return", "spacebar",
|
||||
"lctrl", "rctrl", "lalt", "ralt", "lshift", "rshift", "lsuper", "rsuper", "menu",
|
||||
"limit",
|
||||
};
|
||||
|
||||
static const char* input_find(uint16_t key) {
|
||||
static char buffer[64];
|
||||
|
||||
for(unsigned k = 0; k < keyboard<>::count; k++) {
|
||||
if(key >= keyboard<>::index(k, keyboard<>::none) && key < keyboard<>::index(k, keyboard<>::length)) {
|
||||
sprintf(buffer, "keyboard%.2d.%s", k, keysym[key - keyboard<>::index(k, keyboard<>::none)]);
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned m = 0; m < mouse<>::count; m++) {
|
||||
if(key == mouse<>::index(m, mouse<>::x)) { sprintf(buffer, "mouse%.2d.x", m); return buffer; }
|
||||
if(key == mouse<>::index(m, mouse<>::y)) { sprintf(buffer, "mouse%.2d.y", m); return buffer; }
|
||||
if(key == mouse<>::index(m, mouse<>::z)) { sprintf(buffer, "mouse%.2d.z", m); return buffer; }
|
||||
|
||||
if(key >= mouse<>::index(m, mouse<>::button + 0)
|
||||
&& key < mouse<>::index(m, mouse<>::button + mouse<>::buttons)) {
|
||||
sprintf(buffer, "mouse%.2d.button%.2d", m, key - mouse<>::index(m, mouse<>::button));
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned j = 0; j < joypad<>::count; j++) {
|
||||
if(key >= joypad<>::index(j, joypad<>::hat + 0)
|
||||
&& key < joypad<>::index(j, joypad<>::hat + joypad<>::hats)) {
|
||||
sprintf(buffer, "joypad%.2d.hat%.2d", j, key - joypad<>::index(j, joypad<>::hat));
|
||||
return buffer;
|
||||
}
|
||||
|
||||
if(key >= joypad<>::index(j, joypad<>::axis + 0)
|
||||
&& key < joypad<>::index(j, joypad<>::axis + joypad<>::axes)) {
|
||||
sprintf(buffer, "joypad%.2d.axis%.2d", j, key - joypad<>::index(j, joypad<>::axis));
|
||||
return buffer;
|
||||
}
|
||||
|
||||
if(key >= joypad<>::index(j, joypad<>::button + 0)
|
||||
&& key < joypad<>::index(j, joypad<>::button + joypad<>::buttons)) {
|
||||
sprintf(buffer, "joypad%.2d.button%.2d", j, key - joypad<>::index(j, joypad<>::button));
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
return "none";
|
||||
}
|
||||
|
||||
static char* input_find(char *out, uint16_t key) {
|
||||
strcpy(out, input_find(key));
|
||||
return out;
|
||||
}
|
||||
|
||||
static uint16_t input_find(const char *key) {
|
||||
if(!memcmp(key, "keyboard", 8)) {
|
||||
key += 8;
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t k = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(k >= keyboard<>::count) return input_none;
|
||||
key += 2;
|
||||
|
||||
if(*key++ != '.') return input_none;
|
||||
|
||||
for(unsigned i = 0; i < keyboard<>::length; i++) {
|
||||
if(!strcmp(key, keysym[i])) return keyboard<>::index(k, i);
|
||||
}
|
||||
}
|
||||
|
||||
if(!memcmp(key, "mouse", 5)) {
|
||||
key += 5;
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t m = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(m >= mouse<>::count) return input_none;
|
||||
key += 2;
|
||||
|
||||
if(!strcmp(key, ".x")) return mouse<>::index(m, mouse<>::x);
|
||||
if(!strcmp(key, ".y")) return mouse<>::index(m, mouse<>::y);
|
||||
if(!strcmp(key, ".z")) return mouse<>::index(m, mouse<>::z);
|
||||
|
||||
if(!memcmp(key, ".button", 7)) {
|
||||
key += 7;
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t button = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(button >= mouse<>::buttons) return input_none;
|
||||
return mouse<>::index(m, mouse<>::button + button);
|
||||
}
|
||||
|
||||
return input_none;
|
||||
}
|
||||
|
||||
if(!memcmp(key, "joypad", 6)) {
|
||||
key += 6;
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t j = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(j >= joypad<>::count) return input_none;
|
||||
key += 2;
|
||||
|
||||
if(!memcmp(key, ".hat", 4)) {
|
||||
key += 4;
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t hat = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(hat >= joypad<>::hats) return input_none;
|
||||
return joypad<>::index(j, joypad<>::hat + hat);
|
||||
}
|
||||
|
||||
if(!memcmp(key, ".axis", 5)) {
|
||||
key += 5;
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t axis = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(axis >= joypad<>::axes) return input_none;
|
||||
return joypad<>::index(j, joypad<>::axis + axis);
|
||||
}
|
||||
|
||||
if(!memcmp(key, ".button", 7)) {
|
||||
key += 7;
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t button = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(button >= joypad<>::buttons) return input_none;
|
||||
return joypad<>::index(j, joypad<>::button + button);
|
||||
}
|
||||
|
||||
return input_none;
|
||||
}
|
||||
|
||||
return input_none;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
81
tools/bsnes/lib/nall/lzss.hpp
Executable file
81
tools/bsnes/lib/nall/lzss.hpp
Executable file
@@ -0,0 +1,81 @@
|
||||
#ifndef NALL_LZSS_HPP
|
||||
#define NALL_LZSS_HPP
|
||||
|
||||
#include <nall/array.hpp>
|
||||
#include <nall/new.hpp>
|
||||
#include <nall/stdint.hpp>
|
||||
|
||||
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
|
||||
36
tools/bsnes/lib/nall/moduloarray.hpp
Executable file
36
tools/bsnes/lib/nall/moduloarray.hpp
Executable file
@@ -0,0 +1,36 @@
|
||||
#ifndef NALL_MODULO_HPP
|
||||
#define NALL_MODULO_HPP
|
||||
|
||||
#include <nall/new.hpp>
|
||||
|
||||
namespace nall {
|
||||
template<typename T, int size> 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;
|
||||
}
|
||||
|
||||
modulo_array() {
|
||||
buffer = new(zeromemory) T[size * 3];
|
||||
}
|
||||
|
||||
~modulo_array() {
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
private:
|
||||
T *buffer;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
25
tools/bsnes/lib/nall/new.hpp
Executable file
25
tools/bsnes/lib/nall/new.hpp
Executable file
@@ -0,0 +1,25 @@
|
||||
#ifndef NALL_NEW_HPP
|
||||
#define NALL_NEW_HPP
|
||||
|
||||
#include <string.h>
|
||||
#include <new>
|
||||
#include <nall/stdint.hpp>
|
||||
|
||||
namespace nall {
|
||||
struct zeromemory_t {};
|
||||
static zeromemory_t zeromemory;
|
||||
}
|
||||
|
||||
inline void* operator new[](size_t size, const nall::zeromemory_t&) throw(std::bad_alloc) {
|
||||
void *p = new uint8_t[size];
|
||||
memset(p, 0, size);
|
||||
return p;
|
||||
}
|
||||
|
||||
inline void* operator new[](size_t size, const std::nothrow_t&, const nall::zeromemory_t&) throw() {
|
||||
void *p = new(std::nothrow) uint8_t[size];
|
||||
if(p) memset(p, 0, size);
|
||||
return p;
|
||||
}
|
||||
|
||||
#endif
|
||||
75
tools/bsnes/lib/nall/platform.hpp
Executable file
75
tools/bsnes/lib/nall/platform.hpp
Executable file
@@ -0,0 +1,75 @@
|
||||
#ifndef NALL_PLATFORM_HPP
|
||||
#define NALL_PLATFORM_HPP
|
||||
|
||||
//=========================
|
||||
//standard platform headers
|
||||
//=========================
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <io.h>
|
||||
#include <direct.h>
|
||||
#include <shlobj.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
#include <sys/stat.h>
|
||||
#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 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 __attribute__((always_inline))
|
||||
#elif defined(_MSC_VER)
|
||||
#define noinline __declspec(noinline)
|
||||
#define inline inline
|
||||
#define alwaysinline __forceinline
|
||||
#else
|
||||
#define noinline
|
||||
#define inline inline
|
||||
#define alwaysinline inline
|
||||
#endif
|
||||
|
||||
#endif
|
||||
94
tools/bsnes/lib/nall/priorityqueue.hpp
Executable file
94
tools/bsnes/lib/nall/priorityqueue.hpp
Executable file
@@ -0,0 +1,94 @@
|
||||
#ifndef NALL_PRIORITYQUEUE_HPP
|
||||
#define NALL_PRIORITYQUEUE_HPP
|
||||
|
||||
#include <limits>
|
||||
#include <nall/function.hpp>
|
||||
#include <nall/utility.hpp>
|
||||
|
||||
namespace nall {
|
||||
template<typename type_t> 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<typename type_t> class priority_queue : noncopyable {
|
||||
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<unsigned>::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;
|
||||
}
|
||||
|
||||
priority_queue(unsigned size, function<void (type_t)> callback_ = &priority_queue_nocallback<type_t>)
|
||||
: callback(callback_) {
|
||||
heap = new heap_t[size];
|
||||
reset();
|
||||
}
|
||||
|
||||
~priority_queue() {
|
||||
delete[] heap;
|
||||
}
|
||||
|
||||
private:
|
||||
function<void (type_t)> callback;
|
||||
unsigned basecounter;
|
||||
unsigned heapsize;
|
||||
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<unsigned>::max() >> 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
45
tools/bsnes/lib/nall/property.hpp
Executable file
45
tools/bsnes/lib/nall/property.hpp
Executable file
@@ -0,0 +1,45 @@
|
||||
#ifndef NALL_PROPERTY_HPP
|
||||
#define NALL_PROPERTY_HPP
|
||||
|
||||
//nall::property implements a variable container that disallows write access
|
||||
//to non-derived objects. This requires use of property::set(), as C++ lacks
|
||||
//the ability to make this implementation completely transparent.
|
||||
|
||||
namespace nall {
|
||||
class property {
|
||||
public:
|
||||
template<typename T> class property_t;
|
||||
|
||||
protected:
|
||||
template<typename T> T& get(property_t<T>&);
|
||||
template<typename T> property_t<T>& set(property_t<T>&, const T);
|
||||
|
||||
public:
|
||||
template<typename T>
|
||||
class property_t {
|
||||
public:
|
||||
const T& operator()() const { return value; }
|
||||
property_t() : value() {}
|
||||
property_t(const T value_) : value(value_) {}
|
||||
|
||||
protected:
|
||||
T value;
|
||||
operator T&() { return value; }
|
||||
property_t& operator=(const T newValue) { value = newValue; return *this; }
|
||||
friend T& property::get<T>(property_t<T>&);
|
||||
friend property_t<T>& property::set<T>(property_t<T>&, const T);
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
T& property::get(property::property_t<T> &p) {
|
||||
return p.operator T&();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
property::property_t<T>& property::set(property::property_t<T> &p, const T value) {
|
||||
return p.operator=(value);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
80
tools/bsnes/lib/nall/serial.hpp
Executable file
80
tools/bsnes/lib/nall/serial.hpp
Executable file
@@ -0,0 +1,80 @@
|
||||
#ifndef NALL_SERIAL_HPP
|
||||
#define NALL_SERIAL_HPP
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <nall/stdint.hpp>
|
||||
|
||||
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) {
|
||||
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);
|
||||
attr.c_cflag |= (CS8 | CREAD | CLOCAL);
|
||||
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
|
||||
62
tools/bsnes/lib/nall/sort.hpp
Executable file
62
tools/bsnes/lib/nall/sort.hpp
Executable file
@@ -0,0 +1,62 @@
|
||||
#ifndef NALL_SORT_HPP
|
||||
#define NALL_SORT_HPP
|
||||
|
||||
#include <nall/utility.hpp>
|
||||
|
||||
//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<typename T>
|
||||
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
|
||||
17
tools/bsnes/lib/nall/static.hpp
Executable file
17
tools/bsnes/lib/nall/static.hpp
Executable file
@@ -0,0 +1,17 @@
|
||||
#ifndef NALL_STATIC_HPP
|
||||
#define NALL_STATIC_HPP
|
||||
|
||||
namespace nall {
|
||||
template<bool condition> struct static_assert;
|
||||
template<> struct static_assert<true> {};
|
||||
|
||||
template<bool condition, typename true_type, typename false_type> struct static_if {
|
||||
typedef true_type type;
|
||||
};
|
||||
|
||||
template<typename true_type, typename false_type> struct static_if<false, true_type, false_type> {
|
||||
typedef false_type type;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
44
tools/bsnes/lib/nall/stdint.hpp
Executable file
44
tools/bsnes/lib/nall/stdint.hpp
Executable file
@@ -0,0 +1,44 @@
|
||||
#ifndef NALL_STDINT_HPP
|
||||
#define NALL_STDINT_HPP
|
||||
|
||||
#include <nall/static.hpp>
|
||||
|
||||
#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 <stdint.h>
|
||||
#endif
|
||||
|
||||
namespace nall {
|
||||
static static_assert<sizeof(int8_t) == 1> int8_t_assert;
|
||||
static static_assert<sizeof(int16_t) == 2> int16_t_assert;
|
||||
static static_assert<sizeof(int32_t) == 4> int32_t_assert;
|
||||
static static_assert<sizeof(int64_t) == 8> int64_t_assert;
|
||||
|
||||
static static_assert<sizeof(uint8_t) == 1> uint8_t_assert;
|
||||
static static_assert<sizeof(uint16_t) == 2> uint16_t_assert;
|
||||
static static_assert<sizeof(uint32_t) == 4> uint32_t_assert;
|
||||
static static_assert<sizeof(uint64_t) == 8> uint64_t_assert;
|
||||
}
|
||||
|
||||
#endif
|
||||
24
tools/bsnes/lib/nall/string.cpp
Executable file
24
tools/bsnes/lib/nall/string.cpp
Executable file
@@ -0,0 +1,24 @@
|
||||
#ifndef NALL_STRING_CPP
|
||||
#define NALL_STRING_CPP
|
||||
|
||||
#include <math.h>
|
||||
#include <nall/algorithm.hpp>
|
||||
#include <nall/static.hpp>
|
||||
#include <nall/utf8.hpp>
|
||||
|
||||
#include <nall/string.hpp>
|
||||
#include <nall/string/compare.cpp>
|
||||
#include <nall/string/convert.cpp>
|
||||
#include <nall/string/match.cpp>
|
||||
#include <nall/string/math.cpp>
|
||||
#include <nall/string/strl.cpp>
|
||||
#include <nall/string/trim.cpp>
|
||||
#include <nall/string/utility.cpp>
|
||||
|
||||
namespace nall {
|
||||
#include <nall/string/core.cpp>
|
||||
#include <nall/string/replace.cpp>
|
||||
#include <nall/string/split.cpp>
|
||||
}
|
||||
|
||||
#endif
|
||||
175
tools/bsnes/lib/nall/string.hpp
Executable file
175
tools/bsnes/lib/nall/string.hpp
Executable file
@@ -0,0 +1,175 @@
|
||||
#ifndef NALL_STRING_HPP
|
||||
#define NALL_STRING_HPP
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <nall/stdint.hpp>
|
||||
#include <nall/vector.hpp>
|
||||
|
||||
//===============
|
||||
//libc extensions
|
||||
//===============
|
||||
|
||||
//compare.cpp
|
||||
char chrlower(char c);
|
||||
char chrupper(char c);
|
||||
|
||||
int stricmp(const char *dest, const char *src);
|
||||
|
||||
int strpos (const char *str, const char *key);
|
||||
int qstrpos(const char *str, const char *key);
|
||||
|
||||
bool strbegin (const char *str, const char *key);
|
||||
bool stribegin(const char *str, const char *key);
|
||||
|
||||
bool strend (const char *str, const char *key);
|
||||
bool striend(const char *str, const char *key);
|
||||
|
||||
//convert.cpp
|
||||
char* strlower(char *str);
|
||||
char* strupper(char *str);
|
||||
|
||||
char* strtr(char *dest, const char *before, const char *after);
|
||||
|
||||
uintmax_t strhex (const char *str);
|
||||
intmax_t strsigned (const char *str);
|
||||
uintmax_t strunsigned(const char *str);
|
||||
uintmax_t strbin (const char *str);
|
||||
double strdouble (const char *str);
|
||||
|
||||
size_t strhex (char *str, uintmax_t value, size_t length = 0);
|
||||
size_t strsigned (char *str, intmax_t value, size_t length = 0);
|
||||
size_t strunsigned(char *str, uintmax_t value, size_t length = 0);
|
||||
size_t strbin (char *str, uintmax_t value, size_t length = 0);
|
||||
size_t strdouble (char *str, double value, size_t length = 0);
|
||||
|
||||
//match.cpp
|
||||
bool match(const char *pattern, const char *str);
|
||||
|
||||
//math.cpp
|
||||
bool strint (const char *str, int &result);
|
||||
bool strmath(const char *str, int &result);
|
||||
|
||||
//strl.cpp
|
||||
size_t strlcpy(char *dest, const char *src, size_t length);
|
||||
size_t strlcat(char *dest, const char *src, size_t length);
|
||||
|
||||
//trim.cpp
|
||||
char* ltrim(char *str, const char *key = " ");
|
||||
char* rtrim(char *str, const char *key = " ");
|
||||
char* trim (char *str, const char *key = " ");
|
||||
|
||||
char* ltrim_once(char *str, const char *key = " ");
|
||||
char* rtrim_once(char *str, const char *key = " ");
|
||||
char* trim_once (char *str, const char *key = " ");
|
||||
|
||||
//================
|
||||
//string + lstring
|
||||
//================
|
||||
|
||||
namespace nall {
|
||||
class string;
|
||||
template<typename T> inline string to_string(T);
|
||||
|
||||
class string {
|
||||
public:
|
||||
void reserve(size_t);
|
||||
unsigned length() const;
|
||||
|
||||
string& assign(const char*);
|
||||
string& append(const char*);
|
||||
template<typename T> string& operator= (T value) { return assign(to_string<T>(value)); }
|
||||
template<typename T> string& operator<<(T value) { return append(to_string<T>(value)); }
|
||||
|
||||
operator const char*() const;
|
||||
char* operator()();
|
||||
char& operator[](int);
|
||||
|
||||
bool operator==(const char*) const;
|
||||
bool operator!=(const char*) const;
|
||||
bool operator< (const char*) const;
|
||||
bool operator<=(const char*) const;
|
||||
bool operator> (const char*) const;
|
||||
bool operator>=(const char*) const;
|
||||
|
||||
string();
|
||||
string(const char*);
|
||||
string(const string&);
|
||||
string& operator=(const string&);
|
||||
~string();
|
||||
|
||||
//core.cpp
|
||||
bool readfile(const char*);
|
||||
|
||||
//replace.cpp
|
||||
string& replace (const char*, const char*);
|
||||
string& qreplace(const char*, const char*);
|
||||
|
||||
protected:
|
||||
char *data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
class lstring : public vector<string> {
|
||||
public:
|
||||
template<typename T> lstring& operator<<(T value) {
|
||||
operator[](size()).assign(to_string<T>(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
//core.cpp
|
||||
int find(const char*);
|
||||
|
||||
//split.cpp
|
||||
void split (const char*, const char*, unsigned = 0);
|
||||
void qsplit(const char*, const char*, unsigned = 0);
|
||||
};
|
||||
}
|
||||
|
||||
//=====================
|
||||
//string<>libc wrappers
|
||||
//=====================
|
||||
|
||||
size_t strlcpy(nall::string &dest, const char *src, size_t length);
|
||||
size_t strlcat(nall::string &dest, const char *src, size_t length);
|
||||
|
||||
nall::string& strlower(nall::string &str);
|
||||
nall::string& strupper(nall::string &str);
|
||||
|
||||
nall::string& strtr(nall::string &dest, const char *before, const char *after);
|
||||
|
||||
nall::string& ltrim(nall::string &str, const char *key = " ");
|
||||
nall::string& rtrim(nall::string &str, const char *key = " ");
|
||||
nall::string& trim (nall::string &str, const char *key = " ");
|
||||
|
||||
nall::string& ltrim_once(nall::string &str, const char *key = " ");
|
||||
nall::string& rtrim_once(nall::string &str, const char *key = " ");
|
||||
nall::string& trim_once (nall::string &str, const char *key = " ");
|
||||
|
||||
//==============
|
||||
//misc functions
|
||||
//==============
|
||||
|
||||
nall::string substr(const char *src, size_t start = 0, size_t length = 0);
|
||||
|
||||
nall::string strhex (uintmax_t value);
|
||||
nall::string strsigned (intmax_t value);
|
||||
nall::string strunsigned(uintmax_t value);
|
||||
nall::string strbin (uintmax_t value);
|
||||
nall::string strdouble (double value);
|
||||
|
||||
namespace nall {
|
||||
//this is needed, as C++98 does not support explicit template specialization inside classes;
|
||||
//redundant memory allocation should hopefully be avoided via compiler optimizations.
|
||||
template<> inline string to_string<bool> (bool v) { return v ? "true" : "false"; }
|
||||
template<> inline string to_string<signed int> (signed int v) { return strsigned(v); }
|
||||
template<> inline string to_string<unsigned int> (unsigned int v) { return strunsigned(v); }
|
||||
template<> inline string to_string<double> (double v) { return strdouble(v); }
|
||||
template<> inline string to_string<char*> (char *v) { return v; }
|
||||
template<> inline string to_string<const char*> (const char *v) { return v; }
|
||||
template<> inline string to_string<string> (string v) { return v; }
|
||||
template<> inline string to_string<const string&>(const string &v) { return v; }
|
||||
}
|
||||
|
||||
#endif
|
||||
99
tools/bsnes/lib/nall/string/compare.cpp
Executable file
99
tools/bsnes/lib/nall/string/compare.cpp
Executable file
@@ -0,0 +1,99 @@
|
||||
#ifdef NALL_STRING_CPP
|
||||
|
||||
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 *dest, const char *src) {
|
||||
while(*dest) {
|
||||
if(chrlower(*dest) != chrlower(*src)) break;
|
||||
dest++;
|
||||
src++;
|
||||
}
|
||||
|
||||
return (int)chrlower(*dest) - (int)chrlower(*src);
|
||||
}
|
||||
|
||||
int strpos(const char *str, const char *key) {
|
||||
int ssl = strlen(str), ksl = strlen(key);
|
||||
|
||||
if(ksl > ssl) return -1;
|
||||
for(int i = 0; i <= ssl - ksl; i++) {
|
||||
if(!memcmp(str + i, key, ksl)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int qstrpos(const char *str, const char *key) {
|
||||
int ssl = strlen(str), ksl = strlen(key);
|
||||
|
||||
if(ksl > ssl) return -1;
|
||||
for(int 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 i;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
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
|
||||
284
tools/bsnes/lib/nall/string/convert.cpp
Executable file
284
tools/bsnes/lib/nall/string/convert.cpp
Executable file
@@ -0,0 +1,284 @@
|
||||
#ifdef NALL_STRING_CPP
|
||||
|
||||
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 strhex(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 strsigned(const char *str) {
|
||||
if(!str) return 0;
|
||||
intmax_t result = 0;
|
||||
bool negate = false;
|
||||
|
||||
//check for negation
|
||||
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 strunsigned(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 strbin(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 strdouble(const char *str) {
|
||||
if(!str) return 0.0;
|
||||
bool negate = false;
|
||||
|
||||
//check for negation
|
||||
if(*str == '-') {
|
||||
negate = true;
|
||||
str++;
|
||||
}
|
||||
|
||||
intmax_t result_integral = 0;
|
||||
while(*str) {
|
||||
uint8_t x = *str++;
|
||||
if(x >= '0' && x <= '9') x -= '0';
|
||||
else if(x == '.') break; //break loop and read fractional part
|
||||
else return (double)result_integral; //invalid value, assume no fractional part
|
||||
result_integral = result_integral * 10 + x;
|
||||
}
|
||||
|
||||
intmax_t result_fractional = 0;
|
||||
while(*str) {
|
||||
uint8_t x = *str++;
|
||||
if(x >= '0' && x <= '9') x -= '0';
|
||||
else break; //stop at first invalid character
|
||||
result_fractional = result_fractional * 10 + x;
|
||||
}
|
||||
|
||||
//calculate fractional portion
|
||||
double result = (double)result_fractional;
|
||||
while((uintmax_t)result > 0) result /= 10.0;
|
||||
result += (double)result_integral;
|
||||
|
||||
return !negate ? result : -result;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
size_t strhex(char *str, uintmax_t value, size_t length /* = 0 */) {
|
||||
if(length == 0) length -= 1U; //"infinite" length
|
||||
size_t initial_length = length;
|
||||
|
||||
//count number of digits in value
|
||||
int digits_integral = 1;
|
||||
uintmax_t digits_integral_ = value;
|
||||
while(digits_integral_ /= 16) digits_integral++;
|
||||
|
||||
int digits = digits_integral;
|
||||
if(!str) return digits + 1; //only computing required length?
|
||||
|
||||
length = nall::min(digits, length - 1);
|
||||
str += length; //seek to end of target string
|
||||
*str = 0; //set null terminator
|
||||
|
||||
while(length--) {
|
||||
uint8_t x = value % 16;
|
||||
value /= 16;
|
||||
*--str = x < 10 ? (x + '0') : (x + 'a' - 10); //iterate backwards to write string
|
||||
}
|
||||
|
||||
return nall::min(initial_length, digits + 1);
|
||||
}
|
||||
|
||||
size_t strsigned(char *str, intmax_t value_, size_t length /* = 0 */) {
|
||||
if(length == 0) length = -1U; //"infinite" length
|
||||
size_t initial_length = length;
|
||||
|
||||
bool negate = value_ < 0;
|
||||
uintmax_t value = value_ >= 0 ? value_ : -value_;
|
||||
|
||||
//count number of digits in value
|
||||
int digits_integral = 1;
|
||||
uintmax_t digits_integral_ = value;
|
||||
while(digits_integral_ /= 10) digits_integral++;
|
||||
|
||||
int digits = (negate ? 1 : 0) + digits_integral;
|
||||
if(!str) return digits + 1; //only computing required length?
|
||||
|
||||
length = nall::min(digits, length - 1);
|
||||
str += length; //seek to end of target string
|
||||
*str = 0; //set null terminator
|
||||
while(length && digits_integral--) {
|
||||
uint8_t x = '0' + (value % 10);
|
||||
value /= 10;
|
||||
*--str = x; //iterate backwards to write string
|
||||
length--;
|
||||
}
|
||||
|
||||
if(length && negate) {
|
||||
*--str = '-';
|
||||
}
|
||||
|
||||
return nall::min(initial_length, digits + 1);
|
||||
}
|
||||
|
||||
size_t strunsigned(char *str, uintmax_t value, size_t length /* = 0 */) {
|
||||
if(length == 0) length = -1U; //"infinite" length
|
||||
size_t initial_length = length;
|
||||
|
||||
//count number of digits in value
|
||||
int digits_integral = 1;
|
||||
uintmax_t digits_integral_ = value;
|
||||
while(digits_integral_ /= 10) digits_integral++;
|
||||
|
||||
int digits = digits_integral;
|
||||
if(!str) return digits_integral + 1; //only computing required length?
|
||||
|
||||
length = nall::min(digits, length - 1);
|
||||
str += length; //seek to end of target string
|
||||
*str = 0; //set null terminator
|
||||
|
||||
while(length--) {
|
||||
uint8_t x = '0' + (value % 10);
|
||||
value /= 10;
|
||||
*--str = x; //iterate backwards to write string
|
||||
}
|
||||
|
||||
return nall::min(initial_length, digits + 1);
|
||||
}
|
||||
|
||||
size_t strbin(char *str, uintmax_t value, size_t length /* = 0 */) {
|
||||
if(length == 0) length = -1U; //"infinite" length
|
||||
size_t initial_length = length;
|
||||
|
||||
//count number of digits in value
|
||||
int digits_integral = 1;
|
||||
uintmax_t digits_integral_ = value;
|
||||
while(digits_integral_ /= 2) digits_integral++;
|
||||
|
||||
int digits = digits_integral;
|
||||
if(!str) return digits + 1; //only computing required length?
|
||||
|
||||
length = nall::min(digits, length - 1);
|
||||
str += length; //seek to end of target string
|
||||
*str = 0; //set null terminator
|
||||
|
||||
while(length--) {
|
||||
uint8_t x = '0' + (value % 2);
|
||||
value /= 2;
|
||||
*--str = x; //iterate backwards to write string
|
||||
}
|
||||
|
||||
return nall::min(initial_length, digits + 1);
|
||||
}
|
||||
|
||||
//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.
|
||||
//
|
||||
//note: length parameter is currently ignored.
|
||||
//it remains for consistency and possible future support.
|
||||
size_t strdouble(char *str, double value, size_t length /* = 0 */) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
length = strlen(buffer);
|
||||
if(str) strcpy(str, buffer);
|
||||
return length + 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
103
tools/bsnes/lib/nall/string/core.cpp
Executable file
103
tools/bsnes/lib/nall/string/core.cpp
Executable file
@@ -0,0 +1,103 @@
|
||||
#ifdef NALL_STRING_CPP
|
||||
|
||||
void string::reserve(size_t size_) {
|
||||
if(size_ > size) {
|
||||
size = size_;
|
||||
data = (char*)realloc(data, size + 1);
|
||||
data[size] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned string::length() const {
|
||||
return strlen(data);
|
||||
}
|
||||
|
||||
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() {
|
||||
size = 64;
|
||||
data = (char*)malloc(size + 1);
|
||||
*data = 0;
|
||||
}
|
||||
|
||||
string::string(const char *value) {
|
||||
size = strlen(value);
|
||||
data = strdup(value);
|
||||
}
|
||||
|
||||
string::string(const string &value) {
|
||||
size = strlen(value);
|
||||
data = strdup(value);
|
||||
}
|
||||
|
||||
string& string::operator=(const string &value) {
|
||||
assign(value);
|
||||
}
|
||||
|
||||
string::~string() {
|
||||
free(data);
|
||||
}
|
||||
|
||||
bool string::readfile(const char *filename) {
|
||||
assign("");
|
||||
|
||||
#if !defined(_WIN32)
|
||||
FILE *fp = fopen(filename, "rb");
|
||||
#else
|
||||
FILE *fp = _wfopen(nall::utf16_t(filename), L"rb");
|
||||
#endif
|
||||
if(!fp) return false;
|
||||
|
||||
fseek(fp, 0, SEEK_END);
|
||||
size_t 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;
|
||||
}
|
||||
|
||||
int lstring::find(const char *key) {
|
||||
for(unsigned i = 0; i < size(); i++) {
|
||||
if(operator[](i) == key) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
71
tools/bsnes/lib/nall/string/match.cpp
Executable file
71
tools/bsnes/lib/nall/string/match.cpp
Executable file
@@ -0,0 +1,71 @@
|
||||
#ifdef NALL_STRING_CPP
|
||||
|
||||
bool match(const char *p, const char *s) {
|
||||
const char *p_ = 0, *s_ = 0;
|
||||
|
||||
for(;;) {
|
||||
if(!*s) {
|
||||
while(*p == '*') p++;
|
||||
return !*p;
|
||||
}
|
||||
|
||||
//wildcard match
|
||||
if(*p == '*') {
|
||||
p_ = p++, s_ = s;
|
||||
continue;
|
||||
}
|
||||
|
||||
//any match
|
||||
if(*p == '?') {
|
||||
p++, s++;
|
||||
continue;
|
||||
}
|
||||
|
||||
//ranged match
|
||||
if(*p == '{') {
|
||||
#define pattern(name_, rule_) \
|
||||
if(strbegin(p, name_)) { \
|
||||
if(rule_) { \
|
||||
p += sizeof(name_) - 1, s++; \
|
||||
continue; \
|
||||
} \
|
||||
goto failure; \
|
||||
}
|
||||
|
||||
pattern("{alpha}", (*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z'))
|
||||
pattern("{alphanumeric}", (*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z') || (*s >= '0' && *s <= '9'))
|
||||
pattern("{binary}", (*s == '0' || *s == '1'))
|
||||
pattern("{hex}", (*s >= '0' && *s <= '9') || (*s >= 'A' && *s <= 'F') || (*s >= 'a' && *s <= 'f'))
|
||||
pattern("{lowercase}", (*s >= 'a' && *s <= 'z'))
|
||||
pattern("{numeric}", (*s >= '0' && *s <= '9'))
|
||||
pattern("{uppercase}", (*s >= 'A' && *s <= 'Z'))
|
||||
pattern("{whitespace}", (*s == ' ' || *s == '\t'))
|
||||
|
||||
#undef pattern
|
||||
goto failure;
|
||||
}
|
||||
|
||||
//reserved character match
|
||||
if(*p == '\\') {
|
||||
p++;
|
||||
//fallthrough
|
||||
}
|
||||
|
||||
//literal match
|
||||
if(*p == *s) {
|
||||
p++, *s++;
|
||||
continue;
|
||||
}
|
||||
|
||||
//attempt wildcard rematch
|
||||
failure:
|
||||
if(p_) {
|
||||
p = p_, s = s_ + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
159
tools/bsnes/lib/nall/string/math.cpp
Executable file
159
tools/bsnes/lib/nall/string/math.cpp
Executable file
@@ -0,0 +1,159 @@
|
||||
#ifdef NALL_STRING_CPP
|
||||
|
||||
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
|
||||
98
tools/bsnes/lib/nall/string/replace.cpp
Executable file
98
tools/bsnes/lib/nall/string/replace.cpp
Executable file
@@ -0,0 +1,98 @@
|
||||
#ifdef NALL_STRING_CPP
|
||||
|
||||
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
|
||||
51
tools/bsnes/lib/nall/string/split.cpp
Executable file
51
tools/bsnes/lib/nall/string/split.cpp
Executable file
@@ -0,0 +1,51 @@
|
||||
#ifdef NALL_STRING_CPP
|
||||
|
||||
void lstring::split(const char *key, const char *src, unsigned 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;
|
||||
}
|
||||
|
||||
void lstring::qsplit(const char *key, const char *src, unsigned 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
|
||||
47
tools/bsnes/lib/nall/string/strl.cpp
Executable file
47
tools/bsnes/lib/nall/string/strl.cpp
Executable file
@@ -0,0 +1,47 @@
|
||||
#ifdef NALL_STRING_CPP
|
||||
|
||||
//strlcpy, strlcat based on OpenBSD implementation by Todd C. Miller
|
||||
|
||||
//return = strlen(src)
|
||||
size_t strlcpy(char *dest, const char *src, size_t length) {
|
||||
char *d = dest;
|
||||
const char *s = src;
|
||||
size_t 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))
|
||||
size_t strlcat(char *dest, const char *src, size_t length) {
|
||||
char *d = dest;
|
||||
const char *s = src;
|
||||
size_t n = length;
|
||||
|
||||
while(n-- && *d) d++; //find end of dest
|
||||
size_t 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
|
||||
35
tools/bsnes/lib/nall/string/trim.cpp
Executable file
35
tools/bsnes/lib/nall/string/trim.cpp
Executable file
@@ -0,0 +1,35 @@
|
||||
#ifdef NALL_STRING_CPP
|
||||
|
||||
char* ltrim(char *str, const char *key) {
|
||||
if(!key || !*key) return str;
|
||||
while(strbegin(str, key)) strcpy(str, str + strlen(key));
|
||||
return str;
|
||||
}
|
||||
|
||||
char* rtrim(char *str, const char *key) {
|
||||
if(!key || !*key) return str;
|
||||
while(strend(str, key)) str[strlen(str) - strlen(key)] = 0;
|
||||
return str;
|
||||
}
|
||||
|
||||
char* trim(char *str, const char *key) {
|
||||
return ltrim(rtrim(str, key), key);
|
||||
}
|
||||
|
||||
char* ltrim_once(char *str, const char *key) {
|
||||
if(!key || !*key) return str;
|
||||
if(strbegin(str, key)) strcpy(str, str + strlen(key));
|
||||
return str;
|
||||
}
|
||||
|
||||
char* rtrim_once(char *str, const char *key) {
|
||||
if(!key || !*key) return str;
|
||||
if(strend(str, key)) str[strlen(str) - strlen(key)] = 0;
|
||||
return str;
|
||||
}
|
||||
|
||||
char* trim_once(char *str, const char *key) {
|
||||
return ltrim_once(rtrim_once(str, key), key);
|
||||
}
|
||||
|
||||
#endif
|
||||
74
tools/bsnes/lib/nall/string/utility.cpp
Executable file
74
tools/bsnes/lib/nall/string/utility.cpp
Executable file
@@ -0,0 +1,74 @@
|
||||
#ifdef NALL_STRING_CPP
|
||||
|
||||
size_t strlcpy(nall::string &dest, const char *src, size_t length) {
|
||||
dest.reserve(length);
|
||||
return strlcpy(dest(), src, length);
|
||||
}
|
||||
|
||||
size_t strlcat(nall::string &dest, const char *src, size_t length) {
|
||||
dest.reserve(length);
|
||||
return strlcat(dest(), src, length);
|
||||
}
|
||||
|
||||
nall::string substr(const char *src, size_t start, size_t length) {
|
||||
nall::string dest;
|
||||
if(length == 0) {
|
||||
//copy entire string
|
||||
dest = src + start;
|
||||
} else {
|
||||
//copy partial string
|
||||
strlcpy(dest, src + start, length + 1);
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* very simplistic wrappers to return nall::string& instead of char* type */
|
||||
|
||||
nall::string& strlower(nall::string &str) { strlower(str()); return str; }
|
||||
nall::string& strupper(nall::string &str) { strupper(str()); return str; }
|
||||
nall::string& strtr(nall::string &dest, const char *before, const char *after) { strtr(dest(), before, after); return dest; }
|
||||
nall::string& ltrim(nall::string &str, const char *key) { ltrim(str(), key); return str; }
|
||||
nall::string& rtrim(nall::string &str, const char *key) { rtrim(str(), key); return str; }
|
||||
nall::string& trim (nall::string &str, const char *key) { trim (str(), key); return str; }
|
||||
nall::string& ltrim_once(nall::string &str, const char *key) { ltrim_once(str(), key); return str; }
|
||||
nall::string& rtrim_once(nall::string &str, const char *key) { rtrim_once(str(), key); return str; }
|
||||
nall::string& trim_once (nall::string &str, const char *key) { trim_once (str(), key); return str; }
|
||||
|
||||
/* arithmetic <> string */
|
||||
|
||||
nall::string strhex(uintmax_t value) {
|
||||
nall::string temp;
|
||||
temp.reserve(strhex(0, value));
|
||||
strhex(temp(), value);
|
||||
return temp;
|
||||
}
|
||||
|
||||
nall::string strsigned(intmax_t value) {
|
||||
nall::string temp;
|
||||
temp.reserve(strsigned(0, value));
|
||||
strsigned(temp(), value);
|
||||
return temp;
|
||||
}
|
||||
|
||||
nall::string strunsigned(uintmax_t value) {
|
||||
nall::string temp;
|
||||
temp.reserve(strunsigned(0, value));
|
||||
strunsigned(temp(), value);
|
||||
return temp;
|
||||
}
|
||||
|
||||
nall::string strbin(uintmax_t value) {
|
||||
nall::string temp;
|
||||
temp.reserve(strbin(0, value));
|
||||
strbin(temp(), value);
|
||||
return temp;
|
||||
}
|
||||
|
||||
nall::string strdouble(double value) {
|
||||
nall::string temp;
|
||||
temp.reserve(strdouble(0, value));
|
||||
strdouble(temp(), value);
|
||||
return temp;
|
||||
}
|
||||
|
||||
#endif
|
||||
94
tools/bsnes/lib/nall/traits.hpp
Executable file
94
tools/bsnes/lib/nall/traits.hpp
Executable file
@@ -0,0 +1,94 @@
|
||||
#ifndef NALL_TRAITS_HPP
|
||||
#define NALL_TRAITS_HPP
|
||||
|
||||
namespace nall {
|
||||
//==
|
||||
//is
|
||||
//==
|
||||
|
||||
template<typename T> struct is_integral { enum { value = false }; };
|
||||
template<> struct is_integral<bool> { enum { value = true }; };
|
||||
template<> struct is_integral<char> { enum { value = true }; };
|
||||
template<> struct is_integral<signed char> { enum { value = true }; };
|
||||
template<> struct is_integral<unsigned char> { enum { value = true }; };
|
||||
template<> struct is_integral<wchar_t> { enum { value = true }; };
|
||||
template<> struct is_integral<short> { enum { value = true }; };
|
||||
template<> struct is_integral<unsigned short> { enum { value = true }; };
|
||||
template<> struct is_integral<long> { enum { value = true }; };
|
||||
template<> struct is_integral<unsigned long> { enum { value = true }; };
|
||||
template<> struct is_integral<long long> { enum { value = true }; };
|
||||
template<> struct is_integral<unsigned long long> { enum { value = true }; };
|
||||
template<> struct is_integral<int> { enum { value = true }; };
|
||||
template<> struct is_integral<unsigned int> { enum { value = true }; };
|
||||
|
||||
template<typename T> struct is_floating_point { enum { value = false }; };
|
||||
template<> struct is_floating_point<float> { enum { value = true }; };
|
||||
template<> struct is_floating_point<double> { enum { value = true }; };
|
||||
template<> struct is_floating_point<long double> { enum { value = true }; };
|
||||
|
||||
template<typename T> struct is_void { enum { value = false }; };
|
||||
template<> struct is_void<void> { enum { value = true }; };
|
||||
|
||||
template<typename T> struct is_arithmetic {
|
||||
enum { value = is_integral<T>::value || is_floating_point<T>::value };
|
||||
};
|
||||
|
||||
template<typename T> struct is_fundamental {
|
||||
enum { value = is_integral<T>::value || is_floating_point<T>::value || is_void<T>::value };
|
||||
};
|
||||
|
||||
template<typename T> struct is_compound {
|
||||
enum { value = !is_fundamental<T>::value };
|
||||
};
|
||||
|
||||
template<typename T> struct is_array { enum { value = false }; };
|
||||
template<typename T> struct is_array<T[]> { enum { value = true }; };
|
||||
template<typename T, int N> struct is_array<T[N]> { enum { value = true }; };
|
||||
|
||||
template<typename T> struct is_const { enum { value = false }; };
|
||||
template<typename T> struct is_const<const T> { enum { value = true }; };
|
||||
template<typename T> struct is_const<const T&> { enum { value = true }; };
|
||||
|
||||
template<typename T> struct is_pointer { enum { value = false }; };
|
||||
template<typename T> struct is_pointer<T*> { enum { value = true }; };
|
||||
|
||||
template<typename T> struct is_reference { enum { value = false }; };
|
||||
template<typename T> struct is_reference<T&> { enum { value = true }; };
|
||||
|
||||
template<typename T, typename U> struct is_same { enum { value = false }; };
|
||||
template<typename T> struct is_same<T, T> { enum { value = true }; };
|
||||
|
||||
//===
|
||||
//add
|
||||
//===
|
||||
|
||||
template<typename T> struct add_const { typedef const T type; };
|
||||
template<typename T> struct add_const<const T> { typedef const T type; };
|
||||
template<typename T> struct add_const<const T&> { typedef const T& type; };
|
||||
|
||||
template<typename T> struct add_pointer { typedef T* type; };
|
||||
template<typename T> struct add_pointer<T*> { typedef T** type; };
|
||||
|
||||
template<typename T> struct add_reference { typedef T& type; };
|
||||
template<typename T> struct add_reference<T&> { typedef T& type; };
|
||||
|
||||
//======
|
||||
//remove
|
||||
//======
|
||||
|
||||
template<typename T> struct remove_const { typedef T type; };
|
||||
template<typename T> struct remove_const<const T> { typedef T type; };
|
||||
template<typename T> struct remove_const<const T&> { typedef T type; };
|
||||
|
||||
template<typename T> struct remove_extent { typedef T type; };
|
||||
template<typename T> struct remove_extent<T[]> { typedef T type; };
|
||||
template<typename T, int N> struct remove_extent<T[N]> { typedef T type; };
|
||||
|
||||
template<typename T> struct remove_pointer { typedef T type; };
|
||||
template<typename T> struct remove_pointer<T*> { typedef T type; };
|
||||
|
||||
template<typename T> struct remove_reference { typedef T type; };
|
||||
template<typename T> struct remove_reference<T&> { typedef T type; };
|
||||
}
|
||||
|
||||
#endif
|
||||
191
tools/bsnes/lib/nall/ups.hpp
Executable file
191
tools/bsnes/lib/nall/ups.hpp
Executable file
@@ -0,0 +1,191 @@
|
||||
#ifndef NALL_UPS_HPP
|
||||
#define NALL_UPS_HPP
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <nall/algorithm.hpp>
|
||||
#include <nall/crc32.hpp>
|
||||
#include <nall/file.hpp>
|
||||
#include <nall/new.hpp>
|
||||
#include <nall/stdint.hpp>
|
||||
|
||||
namespace nall {
|
||||
class ups {
|
||||
public:
|
||||
enum result {
|
||||
ok,
|
||||
patch_unreadable,
|
||||
patch_unwritable,
|
||||
patch_invalid,
|
||||
input_invalid,
|
||||
output_invalid,
|
||||
patch_crc32_invalid,
|
||||
input_crc32_invalid,
|
||||
output_crc32_invalid,
|
||||
};
|
||||
|
||||
ups::result create(const char *patch_fn, const uint8_t *x_data, unsigned x_size, const uint8_t *y_data, unsigned y_size) {
|
||||
if(!fp.open(patch_fn, file::mode_write)) return patch_unwritable;
|
||||
|
||||
crc32 = ~0;
|
||||
uint32_t x_crc32 = crc32_calculate(x_data, x_size);
|
||||
uint32_t y_crc32 = crc32_calculate(y_data, y_size);
|
||||
|
||||
//header
|
||||
write('U');
|
||||
write('P');
|
||||
write('S');
|
||||
write('1');
|
||||
encptr(x_size);
|
||||
encptr(y_size);
|
||||
|
||||
//body
|
||||
unsigned max_size = max(x_size, y_size);
|
||||
unsigned relative = 0;
|
||||
for(unsigned i = 0; i < max_size;) {
|
||||
uint8_t x = i < x_size ? x_data[i] : 0x00;
|
||||
uint8_t y = i < y_size ? y_data[i] : 0x00;
|
||||
|
||||
if(x == y) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
encptr(i++ - relative);
|
||||
write(x ^ y);
|
||||
|
||||
while(true) {
|
||||
if(i >= max_size) {
|
||||
write(0x00);
|
||||
break;
|
||||
}
|
||||
|
||||
x = i < x_size ? x_data[i] : 0x00;
|
||||
y = i < y_size ? y_data[i] : 0x00;
|
||||
i++;
|
||||
write(x ^ y);
|
||||
if(x == y) break;
|
||||
}
|
||||
|
||||
relative = i;
|
||||
}
|
||||
|
||||
//footer
|
||||
for(unsigned i = 0; i < 4; i++) write(x_crc32 >> (i << 3));
|
||||
for(unsigned i = 0; i < 4; i++) write(y_crc32 >> (i << 3));
|
||||
uint32_t p_crc32 = ~crc32;
|
||||
for(unsigned i = 0; i < 4; i++) write(p_crc32 >> (i << 3));
|
||||
|
||||
fp.close();
|
||||
return ok;
|
||||
}
|
||||
|
||||
ups::result apply(const uint8_t *p_data, unsigned p_size, const uint8_t *x_data, unsigned x_size, uint8_t *&y_data, unsigned &y_size) {
|
||||
if(p_size < 18) return patch_invalid;
|
||||
p_buffer = p_data;
|
||||
|
||||
crc32 = ~0;
|
||||
|
||||
//header
|
||||
if(read() != 'U') return patch_invalid;
|
||||
if(read() != 'P') return patch_invalid;
|
||||
if(read() != 'S') return patch_invalid;
|
||||
if(read() != '1') return patch_invalid;
|
||||
|
||||
unsigned px_size = decptr();
|
||||
unsigned py_size = decptr();
|
||||
|
||||
//mirror
|
||||
if(x_size != px_size && x_size != py_size) return input_invalid;
|
||||
y_size = (x_size == px_size) ? py_size : px_size;
|
||||
y_data = new(zeromemory) uint8_t[y_size];
|
||||
|
||||
for(unsigned i = 0; i < x_size && i < y_size; i++) y_data[i] = x_data[i];
|
||||
for(unsigned i = x_size; i < y_size; i++) y_data[i] = 0x00;
|
||||
|
||||
//body
|
||||
unsigned relative = 0;
|
||||
while(p_buffer < p_data + p_size - 12) {
|
||||
relative += decptr();
|
||||
|
||||
while(true) {
|
||||
uint8_t x = read();
|
||||
if(x && relative < y_size) {
|
||||
uint8_t y = relative < x_size ? x_data[relative] : 0x00;
|
||||
y_data[relative] = x ^ y;
|
||||
}
|
||||
relative++;
|
||||
if(!x) break;
|
||||
}
|
||||
}
|
||||
|
||||
//footer
|
||||
unsigned px_crc32 = 0, py_crc32 = 0, pp_crc32 = 0;
|
||||
for(unsigned i = 0; i < 4; i++) px_crc32 |= read() << (i << 3);
|
||||
for(unsigned i = 0; i < 4; i++) py_crc32 |= read() << (i << 3);
|
||||
uint32_t p_crc32 = ~crc32;
|
||||
for(unsigned i = 0; i < 4; i++) pp_crc32 |= read() << (i << 3);
|
||||
|
||||
uint32_t x_crc32 = crc32_calculate(x_data, x_size);
|
||||
uint32_t y_crc32 = crc32_calculate(y_data, y_size);
|
||||
|
||||
if(px_size != py_size) {
|
||||
if(x_size == px_size && x_crc32 != px_crc32) return input_crc32_invalid;
|
||||
if(x_size == py_size && x_crc32 != py_crc32) return input_crc32_invalid;
|
||||
if(y_size == px_size && y_crc32 != px_crc32) return output_crc32_invalid;
|
||||
if(y_size == py_size && y_crc32 != py_crc32) return output_crc32_invalid;
|
||||
} else {
|
||||
if(x_crc32 != px_crc32 && x_crc32 != py_crc32) return input_crc32_invalid;
|
||||
if(y_crc32 != px_crc32 && y_crc32 != py_crc32) return output_crc32_invalid;
|
||||
if(x_crc32 == y_crc32 && px_crc32 != py_crc32) return output_crc32_invalid;
|
||||
if(x_crc32 != y_crc32 && px_crc32 == py_crc32) return output_crc32_invalid;
|
||||
}
|
||||
|
||||
if(p_crc32 != pp_crc32) return patch_crc32_invalid;
|
||||
return ok;
|
||||
}
|
||||
|
||||
private:
|
||||
file fp;
|
||||
uint32_t crc32;
|
||||
const uint8_t *p_buffer;
|
||||
|
||||
uint8_t read() {
|
||||
uint8_t n = *p_buffer++;
|
||||
crc32 = crc32_adjust(crc32, n);
|
||||
return n;
|
||||
}
|
||||
|
||||
void write(uint8_t n) {
|
||||
fp.write(n);
|
||||
crc32 = crc32_adjust(crc32, n);
|
||||
}
|
||||
|
||||
void encptr(uint64_t offset) {
|
||||
while(true) {
|
||||
uint64_t x = offset & 0x7f;
|
||||
offset >>= 7;
|
||||
if(offset == 0) {
|
||||
write(0x80 | x);
|
||||
break;
|
||||
}
|
||||
write(x);
|
||||
offset--;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t decptr() {
|
||||
uint64_t offset = 0, shift = 1;
|
||||
while(true) {
|
||||
uint8_t x = read();
|
||||
offset += (x & 0x7f) * shift;
|
||||
if(x & 0x80) break;
|
||||
shift <<= 7;
|
||||
offset += shift;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
71
tools/bsnes/lib/nall/utf8.hpp
Executable file
71
tools/bsnes/lib/nall/utf8.hpp
Executable file
@@ -0,0 +1,71 @@
|
||||
#ifndef NALL_UTF8_HPP
|
||||
#define NALL_UTF8_HPP
|
||||
|
||||
#include <nall/new.hpp>
|
||||
|
||||
//UTF-8 <> UTF-16 conversion
|
||||
//used only for Win32; Linux, etc use UTF-8 internally
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#undef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
|
||||
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(zeromemory) 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(zeromemory) char[length + 1];
|
||||
WideCharToMultiByte(CP_UTF8, 0, s, -1, buffer, length, (const char*)0, (BOOL*)0);
|
||||
}
|
||||
|
||||
~utf8_t() {
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
private:
|
||||
char *buffer;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //if defined(_WIN32)
|
||||
|
||||
#endif
|
||||
29
tools/bsnes/lib/nall/utility.hpp
Executable file
29
tools/bsnes/lib/nall/utility.hpp
Executable file
@@ -0,0 +1,29 @@
|
||||
#ifndef NALL_UTILITY_HPP
|
||||
#define NALL_UTILITY_HPP
|
||||
|
||||
namespace nall {
|
||||
template<typename T>
|
||||
inline void swap(T &x, T &y) {
|
||||
T temp(x);
|
||||
x = y;
|
||||
y = temp;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct base_from_member {
|
||||
T value;
|
||||
base_from_member(T value_) : value(value_) {}
|
||||
};
|
||||
|
||||
class noncopyable {
|
||||
protected:
|
||||
noncopyable() {}
|
||||
~noncopyable() {}
|
||||
|
||||
private:
|
||||
noncopyable(const noncopyable&);
|
||||
const noncopyable& operator=(const noncopyable&);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
92
tools/bsnes/lib/nall/varint.hpp
Executable file
92
tools/bsnes/lib/nall/varint.hpp
Executable file
@@ -0,0 +1,92 @@
|
||||
#ifndef NALL_VARINT_HPP
|
||||
#define NALL_VARINT_HPP
|
||||
|
||||
#include <nall/bit.hpp>
|
||||
#include <nall/static.hpp>
|
||||
#include <nall/traits.hpp>
|
||||
|
||||
namespace nall {
|
||||
template<unsigned bits> class uint_t {
|
||||
private:
|
||||
enum { bytes = (bits + 7) >> 3 }; //minimum number of bytes needed to store value
|
||||
typedef typename static_if<
|
||||
sizeof(int) >= bytes,
|
||||
unsigned int,
|
||||
typename static_if<
|
||||
sizeof(long) >= bytes,
|
||||
unsigned long,
|
||||
typename static_if<
|
||||
sizeof(long long) >= bytes,
|
||||
unsigned long long,
|
||||
void
|
||||
>::type
|
||||
>::type
|
||||
>::type T;
|
||||
static_assert<!is_void<T>::value> uint_assert;
|
||||
T data;
|
||||
|
||||
public:
|
||||
inline operator T() const { return data; }
|
||||
inline T operator ++(int) { T r = data; data = uclip<bits>(data + 1); return r; }
|
||||
inline T operator --(int) { T r = data; data = uclip<bits>(data - 1); return r; }
|
||||
inline T operator ++() { return data = uclip<bits>(data + 1); }
|
||||
inline T operator --() { return data = uclip<bits>(data - 1); }
|
||||
inline T operator =(const T i) { return data = uclip<bits>(i); }
|
||||
inline T operator |=(const T i) { return data = uclip<bits>(data | i); }
|
||||
inline T operator ^=(const T i) { return data = uclip<bits>(data ^ i); }
|
||||
inline T operator &=(const T i) { return data = uclip<bits>(data & i); }
|
||||
inline T operator<<=(const T i) { return data = uclip<bits>(data << i); }
|
||||
inline T operator>>=(const T i) { return data = uclip<bits>(data >> i); }
|
||||
inline T operator +=(const T i) { return data = uclip<bits>(data + i); }
|
||||
inline T operator -=(const T i) { return data = uclip<bits>(data - i); }
|
||||
inline T operator *=(const T i) { return data = uclip<bits>(data * i); }
|
||||
inline T operator /=(const T i) { return data = uclip<bits>(data / i); }
|
||||
inline T operator %=(const T i) { return data = uclip<bits>(data % i); }
|
||||
|
||||
inline uint_t() : data(0) {}
|
||||
inline uint_t(const T i) : data(uclip<bits>(i)) {}
|
||||
};
|
||||
|
||||
template<unsigned bits> class int_t {
|
||||
private:
|
||||
enum { bytes = (bits + 7) >> 3 }; //minimum number of bytes needed to store value
|
||||
typedef typename static_if<
|
||||
sizeof(int) >= bytes,
|
||||
signed int,
|
||||
typename static_if<
|
||||
sizeof(long) >= bytes,
|
||||
signed long,
|
||||
typename static_if<
|
||||
sizeof(long long) >= bytes,
|
||||
signed long long,
|
||||
void
|
||||
>::type
|
||||
>::type
|
||||
>::type T;
|
||||
static_assert<!is_void<T>::value> int_assert;
|
||||
T data;
|
||||
|
||||
public:
|
||||
inline operator T() const { return data; }
|
||||
inline T operator ++(int) { T r = data; data = sclip<bits>(data + 1); return r; }
|
||||
inline T operator --(int) { T r = data; data = sclip<bits>(data - 1); return r; }
|
||||
inline T operator ++() { return data = sclip<bits>(data + 1); }
|
||||
inline T operator --() { return data = sclip<bits>(data - 1); }
|
||||
inline T operator =(const T i) { return data = sclip<bits>(i); }
|
||||
inline T operator |=(const T i) { return data = sclip<bits>(data | i); }
|
||||
inline T operator ^=(const T i) { return data = sclip<bits>(data ^ i); }
|
||||
inline T operator &=(const T i) { return data = sclip<bits>(data & i); }
|
||||
inline T operator<<=(const T i) { return data = sclip<bits>(data << i); }
|
||||
inline T operator>>=(const T i) { return data = sclip<bits>(data >> i); }
|
||||
inline T operator +=(const T i) { return data = sclip<bits>(data + i); }
|
||||
inline T operator -=(const T i) { return data = sclip<bits>(data - i); }
|
||||
inline T operator *=(const T i) { return data = sclip<bits>(data * i); }
|
||||
inline T operator /=(const T i) { return data = sclip<bits>(data / i); }
|
||||
inline T operator %=(const T i) { return data = sclip<bits>(data % i); }
|
||||
|
||||
inline int_t() : data(0) {}
|
||||
inline int_t(const T i) : data(sclip<bits>(i)) {}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
162
tools/bsnes/lib/nall/vector.hpp
Executable file
162
tools/bsnes/lib/nall/vector.hpp
Executable file
@@ -0,0 +1,162 @@
|
||||
#ifndef NALL_VECTOR_HPP
|
||||
#define NALL_VECTOR_HPP
|
||||
|
||||
#include <new>
|
||||
#include <nall/algorithm.hpp>
|
||||
#include <nall/bit.hpp>
|
||||
#include <nall/utility.hpp>
|
||||
|
||||
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<typename T> class linear_vector : noncopyable {
|
||||
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*)malloc(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 add(const T data) {
|
||||
if(objectsize + 1 > poolsize) reserve(objectsize + 1);
|
||||
new(pool + objectsize++) T(data);
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
linear_vector() : pool(0), poolsize(0), objectsize(0) {}
|
||||
~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<typename T> class pointer_vector : noncopyable {
|
||||
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 add(const T data) {
|
||||
if(objectsize + 1 > poolsize) reserve(objectsize + 1);
|
||||
pool[objectsize++] = new T(data);
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
pointer_vector() : pool(0), poolsize(0), objectsize(0) {}
|
||||
~pointer_vector() { reset(); }
|
||||
};
|
||||
|
||||
//default vector type
|
||||
template<typename T> class vector : public linear_vector<T> {};
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user