mirror of https://github.com/bsnes-emu/bsnes.git
Update to v080r04 release.
byuu says: Adds nall/inflate.hpp and nall/unzip.hpp. Updates nall/resource.hpp to encode and decode using ZIP/deflate files, rather than a much simpler (and less powerful) LZSS implementation. Cuts the bsnes-logo.hpp file from 270KB to 130KB, and the binary overhead from 80KB to 35KB.
This commit is contained in:
parent
8276700381
commit
f38af85e0a
File diff suppressed because it is too large
Load Diff
|
@ -1,75 +0,0 @@
|
||||||
#ifndef NALL_DICTIONARY_HPP
|
|
||||||
#define NALL_DICTIONARY_HPP
|
|
||||||
|
|
||||||
#include <nall/array.hpp>
|
|
||||||
#include <nall/string.hpp>
|
|
||||||
#include <nall/utility.hpp>
|
|
||||||
|
|
||||||
namespace nall {
|
|
||||||
class dictionary {
|
|
||||||
public:
|
|
||||||
string operator[](const char *input) {
|
|
||||||
for(unsigned i = 0; i < index_input.size(); i++) {
|
|
||||||
if(index_input[i] == input) return index_output[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
//no match, use input; remove input identifier, if one exists
|
|
||||||
if(strbegin(input, "{{")) {
|
|
||||||
if(auto pos = strpos(input, "}}")) {
|
|
||||||
string temp = substr(input, pos() + 2);
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return input;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool import(const char *filename) {
|
|
||||||
string data;
|
|
||||||
if(data.readfile(filename) == false) return false;
|
|
||||||
data.ltrim<1>("\xef\xbb\xbf"); //remove UTF-8 marker, if it exists
|
|
||||||
data.replace("\r", "");
|
|
||||||
|
|
||||||
lstring line;
|
|
||||||
line.split("\n", data);
|
|
||||||
for(unsigned i = 0; i < line.size(); i++) {
|
|
||||||
lstring part;
|
|
||||||
//format: "Input" = "Output"
|
|
||||||
part.qsplit("=", line[i]);
|
|
||||||
if(part.size() != 2) continue;
|
|
||||||
|
|
||||||
//remove whitespace
|
|
||||||
part[0].trim();
|
|
||||||
part[1].trim();
|
|
||||||
|
|
||||||
//remove quotes
|
|
||||||
part[0].trim<1>("\"");
|
|
||||||
part[1].trim<1>("\"");
|
|
||||||
|
|
||||||
unsigned n = index_input.size();
|
|
||||||
index_input[n] = part[0];
|
|
||||||
index_output[n] = part[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset() {
|
|
||||||
index_input.reset();
|
|
||||||
index_output.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
~dictionary() {
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
dictionary& operator=(const dictionary&) = delete;
|
|
||||||
dictionary(const dictionary&) = delete;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
lstring index_input;
|
|
||||||
lstring index_output;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -0,0 +1,169 @@
|
||||||
|
#ifndef NALL_HTTP_HPP
|
||||||
|
#define NALL_HTTP_HPP
|
||||||
|
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#else
|
||||||
|
#include <windows.h>
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <nall/platform.hpp>
|
||||||
|
#include <nall/string.hpp>
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
|
||||||
|
struct http {
|
||||||
|
string hostname;
|
||||||
|
addrinfo *serverinfo;
|
||||||
|
int serversocket;
|
||||||
|
string header;
|
||||||
|
|
||||||
|
inline void download(const string &path, uint8_t *&data, unsigned &size) {
|
||||||
|
data = 0;
|
||||||
|
size = 0;
|
||||||
|
|
||||||
|
send({
|
||||||
|
"GET ", path, " HTTP/1.1\n"
|
||||||
|
"Host: ", hostname, "\n"
|
||||||
|
"\n"
|
||||||
|
});
|
||||||
|
|
||||||
|
header = downloadHeader();
|
||||||
|
downloadContent(data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool connect(string host, unsigned port) {
|
||||||
|
hostname = host;
|
||||||
|
|
||||||
|
addrinfo hints;
|
||||||
|
memset(&hints, 0, sizeof(addrinfo));
|
||||||
|
hints.ai_family = AF_UNSPEC;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_flags = AI_PASSIVE;
|
||||||
|
|
||||||
|
int status = getaddrinfo(hostname, string(port), &hints, &serverinfo);
|
||||||
|
if(status != 0) return false;
|
||||||
|
|
||||||
|
serversocket = socket(serverinfo->ai_family, serverinfo->ai_socktype, serverinfo->ai_protocol);
|
||||||
|
if(serversocket == -1) return false;
|
||||||
|
|
||||||
|
int result = ::connect(serversocket, serverinfo->ai_addr, serverinfo->ai_addrlen);
|
||||||
|
if(result == -1) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool send(const string &data) {
|
||||||
|
return send((const uint8_t*)(const char*)data, data.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool send(const uint8_t *data, unsigned size) {
|
||||||
|
while(size) {
|
||||||
|
int length = ::send(serversocket, data, size, 0);
|
||||||
|
if(length == -1) return false;
|
||||||
|
data += length;
|
||||||
|
size -= length;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline string downloadHeader() {
|
||||||
|
string output;
|
||||||
|
do {
|
||||||
|
char buffer[2];
|
||||||
|
int length = recv(serversocket, buffer, 1, 0);
|
||||||
|
if(length <= 0) return output;
|
||||||
|
buffer[1] = 0;
|
||||||
|
output.append(buffer);
|
||||||
|
} while(output.endswith("\r\n\r\n") == false);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline string downloadChunkLength() {
|
||||||
|
string output;
|
||||||
|
do {
|
||||||
|
char buffer[2];
|
||||||
|
int length = recv(serversocket, buffer, 1, 0);
|
||||||
|
if(length <= 0) return output;
|
||||||
|
buffer[1] = 0;
|
||||||
|
output.append(buffer);
|
||||||
|
} while(output.endswith("\r\n") == false);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void downloadContent(uint8_t *&data, unsigned &size) {
|
||||||
|
unsigned capacity = 0;
|
||||||
|
|
||||||
|
if(header.position("Transfer-Encoding: chunked")) {
|
||||||
|
while(true) {
|
||||||
|
unsigned length = hex(downloadChunkLength());
|
||||||
|
if(length == 0) break;
|
||||||
|
capacity += length;
|
||||||
|
data = (uint8_t*)realloc(data, capacity);
|
||||||
|
|
||||||
|
char buffer[length];
|
||||||
|
while(length) {
|
||||||
|
int packetlength = recv(serversocket, buffer, length, 0);
|
||||||
|
if(packetlength <= 0) break;
|
||||||
|
memcpy(data + size, buffer, packetlength);
|
||||||
|
size += packetlength;
|
||||||
|
length -= packetlength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if(auto position = header.position("Content-Length: ")) {
|
||||||
|
unsigned length = decimal((const char*)header + position() + 16);
|
||||||
|
while(length) {
|
||||||
|
char buffer[256];
|
||||||
|
int packetlength = recv(serversocket, buffer, min(256, length), 0);
|
||||||
|
if(packetlength <= 0) break;
|
||||||
|
capacity += packetlength;
|
||||||
|
data = (uint8_t*)realloc(data, capacity);
|
||||||
|
memcpy(data + size, buffer, packetlength);
|
||||||
|
size += packetlength;
|
||||||
|
length -= packetlength;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while(true) {
|
||||||
|
char buffer[256];
|
||||||
|
int packetlength = recv(serversocket, buffer, 256, 0);
|
||||||
|
if(packetlength <= 0) break;
|
||||||
|
capacity += packetlength;
|
||||||
|
data = (uint8_t*)realloc(data, capacity);
|
||||||
|
memcpy(data + size, buffer, packetlength);
|
||||||
|
size += packetlength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data = (uint8_t*)realloc(data, capacity + 1);
|
||||||
|
data[capacity] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void disconnect() {
|
||||||
|
close(serversocket);
|
||||||
|
freeaddrinfo(serverinfo);
|
||||||
|
serverinfo = 0;
|
||||||
|
serversocket = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline http() {
|
||||||
|
#ifdef _WIN32
|
||||||
|
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
if(sock == INVALID_SOCKET && WSAGetLastError() == WSANOTINITIALISED) {
|
||||||
|
WSADATA wsaData;
|
||||||
|
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
|
||||||
|
WSACleanup();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else close(sock);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,357 @@
|
||||||
|
#ifndef NALL_INFLATE_HPP
|
||||||
|
#define NALL_INFLATE_HPP
|
||||||
|
|
||||||
|
#include <setjmp.h>
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
|
||||||
|
namespace puff {
|
||||||
|
inline int puff(
|
||||||
|
unsigned char *dest, unsigned long *destlen,
|
||||||
|
unsigned char *source, unsigned long *sourcelen
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool inflate(
|
||||||
|
uint8_t *target, unsigned targetLength,
|
||||||
|
const uint8_t *source, unsigned sourceLength
|
||||||
|
) {
|
||||||
|
unsigned long tl = targetLength, sl = sourceLength;
|
||||||
|
return puff::puff((unsigned char*)target, &tl, (unsigned char*)source, &sl) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace puff {
|
||||||
|
|
||||||
|
//zlib/contrib/puff.c
|
||||||
|
//version 2.1*
|
||||||
|
//author: Mark Adler
|
||||||
|
//license: zlib
|
||||||
|
//ported by: byuu
|
||||||
|
|
||||||
|
//* I have corrected a bug in fixed(), where it was accessing uninitialized
|
||||||
|
// memory: calling construct() with lencode prior to initializing lencode.count
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MAXBITS = 15,
|
||||||
|
MAXLCODES = 286,
|
||||||
|
MAXDCODES = 30,
|
||||||
|
FIXLCODES = 288,
|
||||||
|
MAXCODES = MAXLCODES + MAXDCODES,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct state {
|
||||||
|
unsigned char *out;
|
||||||
|
unsigned long outlen;
|
||||||
|
unsigned long outcnt;
|
||||||
|
|
||||||
|
unsigned char *in;
|
||||||
|
unsigned long inlen;
|
||||||
|
unsigned long incnt;
|
||||||
|
int bitbuf;
|
||||||
|
int bitcnt;
|
||||||
|
|
||||||
|
jmp_buf env;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct huffman {
|
||||||
|
short *count;
|
||||||
|
short *symbol;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline int bits(state *s, int need) {
|
||||||
|
long val;
|
||||||
|
|
||||||
|
val = s->bitbuf;
|
||||||
|
while(s->bitcnt < need) {
|
||||||
|
if(s->incnt == s->inlen) longjmp(s->env, 1);
|
||||||
|
val |= (long)(s->in[s->incnt++]) << s->bitcnt;
|
||||||
|
s->bitcnt += 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
s->bitbuf = (int)(val >> need);
|
||||||
|
s->bitcnt -= need;
|
||||||
|
|
||||||
|
return (int)(val & ((1L << need) - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int stored(state *s) {
|
||||||
|
unsigned len;
|
||||||
|
|
||||||
|
s->bitbuf = 0;
|
||||||
|
s->bitcnt = 0;
|
||||||
|
|
||||||
|
if(s->incnt + 4 > s->inlen) return 2;
|
||||||
|
len = s->in[s->incnt++];
|
||||||
|
len |= s->in[s->incnt++] << 8;
|
||||||
|
if(s->in[s->incnt++] != (~len & 0xff) ||
|
||||||
|
s->in[s->incnt++] != ((~len >> 8) & 0xff)
|
||||||
|
) return 2;
|
||||||
|
|
||||||
|
if(s->incnt + len > s->inlen) return 2;
|
||||||
|
if(s->out != 0) {
|
||||||
|
if(s->outcnt + len > s->outlen) return 1;
|
||||||
|
while(len--) s->out[s->outcnt++] = s->in[s->incnt++];
|
||||||
|
} else {
|
||||||
|
s->outcnt += len;
|
||||||
|
s->incnt += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int decode(state *s, huffman *h) {
|
||||||
|
int len, code, first, count, index, bitbuf, left;
|
||||||
|
short *next;
|
||||||
|
|
||||||
|
bitbuf = s->bitbuf;
|
||||||
|
left = s->bitcnt;
|
||||||
|
code = first = index = 0;
|
||||||
|
len = 1;
|
||||||
|
next = h->count + 1;
|
||||||
|
while(true) {
|
||||||
|
while(left--) {
|
||||||
|
code |= bitbuf & 1;
|
||||||
|
bitbuf >>= 1;
|
||||||
|
count = *next++;
|
||||||
|
if(code - count < first) {
|
||||||
|
s->bitbuf = bitbuf;
|
||||||
|
s->bitcnt = (s->bitcnt - len) & 7;
|
||||||
|
return h->symbol[index + (code - first)];
|
||||||
|
}
|
||||||
|
index += count;
|
||||||
|
first += count;
|
||||||
|
first <<= 1;
|
||||||
|
code <<= 1;
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
left = (MAXBITS + 1) - len;
|
||||||
|
if(left == 0) break;
|
||||||
|
if(s->incnt == s->inlen) longjmp(s->env, 1);
|
||||||
|
bitbuf = s->in[s->incnt++];
|
||||||
|
if(left > 8) left = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -10;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int construct(huffman *h, short *length, int n) {
|
||||||
|
int symbol, len, left;
|
||||||
|
short offs[MAXBITS + 1];
|
||||||
|
|
||||||
|
for(len = 0; len <= MAXBITS; len++) h->count[len] = 0;
|
||||||
|
for(symbol = 0; symbol < n; symbol++) h->count[length[symbol]]++;
|
||||||
|
if(h->count[0] == n) return 0;
|
||||||
|
|
||||||
|
left = 1;
|
||||||
|
for(len = 1; len <= MAXBITS; len++) {
|
||||||
|
left <<= 1;
|
||||||
|
left -= h->count[len];
|
||||||
|
if(left < 0) return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
offs[1] = 0;
|
||||||
|
for(len = 1; len < MAXBITS; len++) offs[len + 1] = offs[len] + h->count[len];
|
||||||
|
|
||||||
|
for(symbol = 0; symbol < n; symbol++) {
|
||||||
|
if(length[symbol] != 0) h->symbol[offs[length[symbol]]++] = symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int codes(state *s, huffman *lencode, huffman *distcode) {
|
||||||
|
int symbol, len;
|
||||||
|
unsigned dist;
|
||||||
|
static const short lens[29] = {
|
||||||
|
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
|
||||||
|
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
|
||||||
|
};
|
||||||
|
static const short lext[29] = {
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
|
||||||
|
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
|
||||||
|
};
|
||||||
|
static const short dists[30] = {
|
||||||
|
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
|
||||||
|
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
|
||||||
|
8193, 12289, 16385, 24577
|
||||||
|
};
|
||||||
|
static const short dext[30] = {
|
||||||
|
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
|
||||||
|
7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
|
||||||
|
12, 12, 13, 13
|
||||||
|
};
|
||||||
|
|
||||||
|
do {
|
||||||
|
symbol = decode(s, lencode);
|
||||||
|
if(symbol < 0) return symbol;
|
||||||
|
if(symbol < 256) {
|
||||||
|
if(s->out != 0) {
|
||||||
|
if(s->outcnt == s->outlen) return 1;
|
||||||
|
s->out[s->outcnt] = symbol;
|
||||||
|
}
|
||||||
|
s->outcnt++;
|
||||||
|
} else if(symbol > 256) {
|
||||||
|
symbol -= 257;
|
||||||
|
if(symbol >= 29) return -10;
|
||||||
|
len = lens[symbol] + bits(s, lext[symbol]);
|
||||||
|
|
||||||
|
symbol = decode(s, distcode);
|
||||||
|
if(symbol < 0) return symbol;
|
||||||
|
dist = dists[symbol] + bits(s, dext[symbol]);
|
||||||
|
#ifndef INFLATE_ALLOW_INVALID_DISTANCE_TOO_FAR
|
||||||
|
if(dist > s->outcnt) return -11;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(s->out != 0) {
|
||||||
|
if(s->outcnt + len > s->outlen) return 1;
|
||||||
|
while(len--) {
|
||||||
|
s->out[s->outcnt] =
|
||||||
|
#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOO_FAR
|
||||||
|
dist > s->outcnt ? 0 :
|
||||||
|
#endif
|
||||||
|
s->out[s->outcnt - dist];
|
||||||
|
s->outcnt++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
s->outcnt += len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while(symbol != 256);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int fixed(state *s) {
|
||||||
|
static int virgin = 1;
|
||||||
|
static short lencnt[MAXBITS + 1], lensym[FIXLCODES];
|
||||||
|
static short distcnt[MAXBITS + 1], distsym[MAXDCODES];
|
||||||
|
static huffman lencode, distcode;
|
||||||
|
|
||||||
|
if(virgin) {
|
||||||
|
int symbol = 0;
|
||||||
|
short lengths[FIXLCODES];
|
||||||
|
|
||||||
|
lencode.count = lencnt;
|
||||||
|
lencode.symbol = lensym;
|
||||||
|
distcode.count = distcnt;
|
||||||
|
distcode.symbol = distsym;
|
||||||
|
|
||||||
|
for(; symbol < 144; symbol++) lengths[symbol] = 8;
|
||||||
|
for(; symbol < 256; symbol++) lengths[symbol] = 9;
|
||||||
|
for(; symbol < 280; symbol++) lengths[symbol] = 7;
|
||||||
|
for(; symbol < FIXLCODES; symbol++) lengths[symbol] = 8;
|
||||||
|
construct(&lencode, lengths, FIXLCODES);
|
||||||
|
|
||||||
|
for(symbol = 0; symbol < MAXDCODES; symbol++) lengths[symbol] = 5;
|
||||||
|
construct(&distcode, lengths, MAXDCODES);
|
||||||
|
|
||||||
|
virgin = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return codes(s, &lencode, &distcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int dynamic(state *s) {
|
||||||
|
int nlen, ndist, ncode, index, err;
|
||||||
|
short lengths[MAXCODES];
|
||||||
|
short lencnt[MAXBITS + 1], lensym[MAXLCODES];
|
||||||
|
short distcnt[MAXBITS + 1], distsym[MAXDCODES];
|
||||||
|
huffman lencode, distcode;
|
||||||
|
static const short order[19] = {
|
||||||
|
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
|
||||||
|
};
|
||||||
|
|
||||||
|
lencode.count = lencnt;
|
||||||
|
lencode.symbol = lensym;
|
||||||
|
distcode.count = distcnt;
|
||||||
|
distcode.symbol = distsym;
|
||||||
|
|
||||||
|
nlen = bits(s, 5) + 257;
|
||||||
|
ndist = bits(s, 5) + 1;
|
||||||
|
ncode = bits(s, 4) + 4;
|
||||||
|
if(nlen > MAXLCODES || ndist > MAXDCODES) return -3;
|
||||||
|
|
||||||
|
for(index = 0; index < ncode; index++) lengths[order[index]] = bits(s, 3);
|
||||||
|
for(; index < 19; index++) lengths[order[index]] = 0;
|
||||||
|
|
||||||
|
err = construct(&lencode, lengths, 19);
|
||||||
|
if(err != 0) return -4;
|
||||||
|
|
||||||
|
index = 0;
|
||||||
|
while(index < nlen + ndist) {
|
||||||
|
int symbol, len;
|
||||||
|
|
||||||
|
symbol = decode(s, &lencode);
|
||||||
|
if(symbol < 16) {
|
||||||
|
lengths[index++] = symbol;
|
||||||
|
} else {
|
||||||
|
len = 0;
|
||||||
|
if(symbol == 16) {
|
||||||
|
if(index == 0) return -5;
|
||||||
|
len = lengths[index - 1];
|
||||||
|
symbol = 3 + bits(s, 2);
|
||||||
|
} else if(symbol == 17) {
|
||||||
|
symbol = 3 + bits(s, 3);
|
||||||
|
} else {
|
||||||
|
symbol = 11 + bits(s, 7);
|
||||||
|
}
|
||||||
|
if(index + symbol > nlen + ndist) return -6;
|
||||||
|
while(symbol--) lengths[index++] = len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lengths[256] == 0) return -9;
|
||||||
|
|
||||||
|
err = construct(&lencode, lengths, nlen);
|
||||||
|
if(err < 0 || (err > 0 && nlen - lencode.count[0] != 1)) return -7;
|
||||||
|
|
||||||
|
err = construct(&distcode, lengths + nlen, ndist);
|
||||||
|
if(err < 0 || (err > 0 && ndist - distcode.count[0] != 1)) return -8;
|
||||||
|
|
||||||
|
return codes(s, &lencode, &distcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int puff(
|
||||||
|
unsigned char *dest, unsigned long *destlen,
|
||||||
|
unsigned char *source, unsigned long *sourcelen
|
||||||
|
) {
|
||||||
|
state s;
|
||||||
|
int last, type, err;
|
||||||
|
|
||||||
|
s.out = dest;
|
||||||
|
s.outlen = *destlen;
|
||||||
|
s.outcnt = 0;
|
||||||
|
|
||||||
|
s.in = source;
|
||||||
|
s.inlen = *sourcelen;
|
||||||
|
s.incnt = 0;
|
||||||
|
s.bitbuf = 0;
|
||||||
|
s.bitcnt = 0;
|
||||||
|
|
||||||
|
if(setjmp(s.env) != 0) {
|
||||||
|
err = 2;
|
||||||
|
} else {
|
||||||
|
do {
|
||||||
|
last = bits(&s, 1);
|
||||||
|
type = bits(&s, 2);
|
||||||
|
err = type == 0 ? stored(&s)
|
||||||
|
: type == 1 ? fixed(&s)
|
||||||
|
: type == 2 ? dynamic(&s)
|
||||||
|
: -1;
|
||||||
|
if(err != 0) break;
|
||||||
|
} while(!last);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(err <= 0) {
|
||||||
|
*destlen = s.outcnt;
|
||||||
|
*sourcelen = s.incnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -67,6 +67,7 @@
|
||||||
#define rmdir _rmdir
|
#define rmdir _rmdir
|
||||||
#define usleep(n) Sleep(n / 1000)
|
#define usleep(n) Sleep(n / 1000)
|
||||||
#define vsnprintf _vsnprintf
|
#define vsnprintf _vsnprintf
|
||||||
|
static int close(int sock) { return closesocket(sock); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//================
|
//================
|
||||||
|
|
|
@ -2,30 +2,26 @@
|
||||||
#define NALL_RESOURCE_HPP
|
#define NALL_RESOURCE_HPP
|
||||||
|
|
||||||
#include <nall/file.hpp>
|
#include <nall/file.hpp>
|
||||||
#include <nall/lzss.hpp>
|
#include <nall/unzip.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
struct resource {
|
struct resource {
|
||||||
|
//create resource with "zip -9 resource.zip resource"
|
||||||
static bool encode(const char *outputFilename, const char *inputFilename) {
|
static bool encode(const char *outputFilename, const char *inputFilename) {
|
||||||
file fp;
|
file fp;
|
||||||
if(fp.open(inputFilename, file::mode::read) == false) return false;
|
if(fp.open(inputFilename, file::mode::read) == false) return false;
|
||||||
unsigned inputSize = fp.size();
|
unsigned size = fp.size();
|
||||||
uint8_t *inputData = new uint8_t[inputSize];
|
uint8_t *data = new uint8_t[size];
|
||||||
fp.read(inputData, inputSize);
|
fp.read(data, size);
|
||||||
fp.close();
|
fp.close();
|
||||||
|
|
||||||
unsigned outputSize;
|
|
||||||
uint8_t *outputData;
|
|
||||||
lzss::encode(outputData, outputSize, inputData, inputSize);
|
|
||||||
|
|
||||||
fp.open(outputFilename, file::mode::write);
|
fp.open(outputFilename, file::mode::write);
|
||||||
fp.print("static const unsigned size = ", inputSize, ";\n");
|
fp.print("static const uint8_t data[", size, "] = {\n");
|
||||||
fp.print("static const uint8_t data[", outputSize, "] = {\n");
|
uint8_t *p = data;
|
||||||
uint8_t *p = outputData;
|
while(size) {
|
||||||
while(outputSize) {
|
|
||||||
fp.print(" ");
|
fp.print(" ");
|
||||||
for(unsigned n = 0; n < 32 && outputSize; n++, outputSize--) {
|
for(unsigned n = 0; n < 32 && size; n++, size--) {
|
||||||
fp.print((unsigned)*p++, ",");
|
fp.print((unsigned)*p++, ",");
|
||||||
}
|
}
|
||||||
fp.print("\n");
|
fp.print("\n");
|
||||||
|
@ -33,17 +29,23 @@ struct resource {
|
||||||
fp.print("};\n");
|
fp.print("};\n");
|
||||||
fp.close();
|
fp.close();
|
||||||
|
|
||||||
delete[] inputData;
|
delete[] data;
|
||||||
delete[] outputData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
unsigned size;
|
unsigned size;
|
||||||
|
|
||||||
bool decode(const uint8_t *inputData, unsigned outputSize) {
|
//extract first file from ZIP archive
|
||||||
|
bool decode(const uint8_t *cdata, unsigned csize) {
|
||||||
if(data) delete[] data;
|
if(data) delete[] data;
|
||||||
lzss::decode(data, inputData, size = outputSize);
|
|
||||||
return true;
|
unzip archive;
|
||||||
|
if(archive.open(cdata, csize) == false) return false;
|
||||||
|
if(archive.file.size() == 0) return false;
|
||||||
|
bool result = archive.extract(archive.file[0], data, size);
|
||||||
|
archive.close();
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
resource() : data(0), size(0) {
|
resource() : data(0), size(0) {
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
g++-4.5 -std=gnu++0x -O3 -fomit-frame-pointer -s -o test test.cpp -I../..
|
|
|
@ -1,44 +0,0 @@
|
||||||
#include <nall/any.hpp>
|
|
||||||
#include <nall/array.hpp>
|
|
||||||
#include <nall/base64.hpp>
|
|
||||||
#include <nall/concept.hpp>
|
|
||||||
#include <nall/config.hpp>
|
|
||||||
#include <nall/dictionary.hpp>
|
|
||||||
#include <nall/directory.hpp>
|
|
||||||
#include <nall/dl.hpp>
|
|
||||||
#include <nall/file.hpp>
|
|
||||||
#include <nall/filemap.hpp>
|
|
||||||
#include <nall/foreach.hpp>
|
|
||||||
#include <nall/function.hpp>
|
|
||||||
#include <nall/input.hpp>
|
|
||||||
#include <nall/lzss.hpp>
|
|
||||||
#include <nall/priorityqueue.hpp>
|
|
||||||
#include <nall/public_cast.hpp>
|
|
||||||
#include <nall/reference_array.hpp>
|
|
||||||
#include <nall/resource.hpp>
|
|
||||||
#include <nall/serializer.hpp>
|
|
||||||
#include <nall/stack.hpp>
|
|
||||||
#include <nall/static.hpp>
|
|
||||||
#include <nall/stdint.hpp>
|
|
||||||
#include <nall/string.hpp>
|
|
||||||
#include <nall/utility.hpp>
|
|
||||||
#include <nall/varint.hpp>
|
|
||||||
#include <nall/vector.hpp>
|
|
||||||
#include <nall/snes/cpu.hpp>
|
|
||||||
#include <nall/snes/smp.hpp>
|
|
||||||
#include <nall/snes/cartridge.hpp>
|
|
||||||
#include <nall/gameboy/cartridge.hpp>
|
|
||||||
using namespace nall;
|
|
||||||
|
|
||||||
#include "bsnes-logo.hpp"
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
// resource::encode("bsnes-logo.hpp", "bsnes-logo.bmp");
|
|
||||||
resource logo;
|
|
||||||
logo.decode(data, size);
|
|
||||||
file fp;
|
|
||||||
fp.open("output.bmp", file::mode::write);
|
|
||||||
fp.write(logo.data, logo.size);
|
|
||||||
fp.close();
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -0,0 +1,124 @@
|
||||||
|
#ifndef NALL_UNZIP_HPP
|
||||||
|
#define NALL_UNZIP_HPP
|
||||||
|
|
||||||
|
#include <nall/filemap.hpp>
|
||||||
|
#include <nall/inflate.hpp>
|
||||||
|
#include <nall/string.hpp>
|
||||||
|
#include <nall/vector.hpp>
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
|
||||||
|
struct unzip {
|
||||||
|
struct File {
|
||||||
|
string name;
|
||||||
|
const uint8_t *data;
|
||||||
|
unsigned size;
|
||||||
|
unsigned csize;
|
||||||
|
unsigned cmode; //0 = uncompressed, 8 = deflate
|
||||||
|
unsigned crc32;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool open(const char *filename) {
|
||||||
|
close();
|
||||||
|
if(fm.open(filename, filemap::mode::read) == false) return false;
|
||||||
|
if(open(fm.data(), fm.size()) == false) {
|
||||||
|
fm.close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool open(const uint8_t *data, unsigned size) {
|
||||||
|
if(size < 22) return false;
|
||||||
|
|
||||||
|
filedata = data;
|
||||||
|
filesize = size;
|
||||||
|
|
||||||
|
file.reset();
|
||||||
|
|
||||||
|
const uint8_t *footer = data + size - 22;
|
||||||
|
const uint8_t *directory = data + read(footer + 16, 4);
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
unsigned signature = read(directory + 0, 4);
|
||||||
|
if(signature != 0x02014b50) break;
|
||||||
|
|
||||||
|
File file;
|
||||||
|
file.cmode = read(directory + 10, 2);
|
||||||
|
file.crc32 = read(directory + 16, 4);
|
||||||
|
file.csize = read(directory + 20, 4);
|
||||||
|
file.size = read(directory + 24, 4);
|
||||||
|
|
||||||
|
unsigned namelength = read(directory + 28, 2);
|
||||||
|
unsigned extralength = read(directory + 30, 2);
|
||||||
|
unsigned commentlength = read(directory + 32, 2);
|
||||||
|
|
||||||
|
char *filename = new char[namelength + 1];
|
||||||
|
memcpy(filename, directory + 46, namelength);
|
||||||
|
filename[namelength] = 0;
|
||||||
|
file.name = filename;
|
||||||
|
delete[] filename;
|
||||||
|
|
||||||
|
unsigned offset = read(directory + 42, 4);
|
||||||
|
unsigned offsetNL = read(data + offset + 26, 2);
|
||||||
|
unsigned offsetEL = read(data + offset + 28, 2);
|
||||||
|
file.data = data + offset + 30 + offsetNL + offsetEL;
|
||||||
|
|
||||||
|
directory += 46 + namelength + extralength + commentlength;
|
||||||
|
|
||||||
|
this->file.append(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool extract(File &file, uint8_t *&data, unsigned &size) {
|
||||||
|
data = 0, size = 0;
|
||||||
|
|
||||||
|
if(file.cmode == 0) {
|
||||||
|
size = file.size;
|
||||||
|
data = new uint8_t[size];
|
||||||
|
memcpy(data, file.data, size);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(file.cmode == 8) {
|
||||||
|
size = file.size;
|
||||||
|
data = new uint8_t[size];
|
||||||
|
if(inflate(data, size, file.data, file.csize) == false) {
|
||||||
|
delete[] data;
|
||||||
|
size = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void close() {
|
||||||
|
if(fm.open()) fm.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
~unzip() {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
filemap fm;
|
||||||
|
const uint8_t *filedata;
|
||||||
|
unsigned filesize;
|
||||||
|
|
||||||
|
unsigned read(const uint8_t *data, unsigned size) {
|
||||||
|
unsigned result = 0, shift = 0;
|
||||||
|
while(size--) { result |= *data++ << shift; shift += 8; }
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
linear_vector<File> file;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,7 +1,7 @@
|
||||||
namespace SNES {
|
namespace SNES {
|
||||||
namespace Info {
|
namespace Info {
|
||||||
static const char Name[] = "bsnes";
|
static const char Name[] = "bsnes";
|
||||||
static const char Version[] = "080.03";
|
static const char Version[] = "080.04";
|
||||||
static const unsigned SerializerVersion = 21;
|
static const unsigned SerializerVersion = 21;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ synchronize "phoenix"
|
||||||
|
|
||||||
test -d libco/doc && rm -r libco/doc
|
test -d libco/doc && rm -r libco/doc
|
||||||
test -d libco/test && rm -r libco/test
|
test -d libco/test && rm -r libco/test
|
||||||
|
test -d nall/test && rm -r nall/test
|
||||||
test -d ruby/_test && rm -r ruby/_test
|
test -d ruby/_test && rm -r ruby/_test
|
||||||
test -d phoenix/nall && rm -r phoenix/nall
|
test -d phoenix/nall && rm -r phoenix/nall
|
||||||
test -d phoenix/test && rm -r phoenix/test
|
test -d phoenix/test && rm -r phoenix/test
|
||||||
|
|
|
@ -23,7 +23,7 @@ void AboutWindow::create() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AboutWindow::show() {
|
void AboutWindow::show() {
|
||||||
logo.decode(bsnesLogoData, bsnesLogoSize);
|
logo.decode(bsnesLogoData, sizeof bsnesLogoData);
|
||||||
setVisible();
|
setVisible();
|
||||||
uint32_t *buffer = canvas.buffer();
|
uint32_t *buffer = canvas.buffer();
|
||||||
for(unsigned y = 0; y < 180; y++) {
|
for(unsigned y = 0; y < 180; y++) {
|
||||||
|
|
Loading…
Reference in New Issue