patch from bisquit to make savestates more efficient

also worked on the build system to accomidate for lua
This commit is contained in:
punkrockguy318 2008-07-24 03:01:39 +00:00
parent 71c98f6600
commit cbb5c8bc90
5 changed files with 134 additions and 46 deletions

View File

@ -48,6 +48,9 @@ else:
if not conf.CheckLib('z', autoadd=1):
print 'Did not find libz or z.lib, exiting!'
Exit(1)
if not conf.CheckLib('lua5.1', autoadd=1):
print 'Did not find liblua5.1 or lua5.1.lib, exiting!'
Exit(1)
if conf.CheckFunc('asprintf'):
conf.env.Append(CCFLAGS = " -DHAVE_ASPRINTF")
if env['OPENGL'] and conf.CheckLibWithHeader('GL', 'GL/gl.h', 'c++', autoadd=1):
@ -55,13 +58,14 @@ else:
conf.env.Append(CPPDEFINES = ['PSS_STYLE=1'])
# parse SDL cflags/libs
env.ParseConfig('sdl-config --cflags --libs')
env.ParseConfig('echo "-I/usr/include/lua5.1/ -llua5.1"')
env = conf.Finish()
# Build for this system's endianness, if not overriden
#if env.has_key('LSB_FIRST'):
# if env['LSB_FIRST']:
# env.Append(CPPDEFINES = ['LSB_FIRST'])
elif sys.byteorder == 'little' or env['PLATFORM'] == 'win32':
if sys.byteorder == 'little' or env['PLATFORM'] == 'win32':
env.Append(CPPDEFINES = ['LSB_FIRST'])
if env['FRAMESKIP']:

View File

@ -12,6 +12,7 @@ file.cpp
filter.cpp
ines.cpp
input.cpp
lua-engine.cpp
netplay.cpp
nsf.cpp
palette.cpp

View File

@ -343,11 +343,12 @@ void MovieData::installValue(std::string& key, std::string& val)
comments.push_back(val);
else if(key == "savestate")
{
int len = HexStringToBytesLength(val);
int len = Base64StringToBytesLength(val);
if(len == -1) len = HexStringToBytesLength(val); // wasn't base64, try hex
if(len >= 1)
{
savestate.resize(len);
StringToBytes(val,&savestate[0],len);
StringToBytes(val,&savestate[0],len); // decodes either base64 or hex
}
}
}

View File

@ -191,54 +191,153 @@ int str_replace(char *str, char *search, char *replace) {
return j;
}
static const struct Base64Table
{
Base64Table()
{
size_t a=0;
for(a=0; a<256; ++a) data[a] = 0xFF; // mark everything as invalid by default
// create value->ascii mapping
a=0;
for(unsigned char c='A'; c<='Z'; ++c) data[a++] = c; // 0..25
for(unsigned char c='a'; c<='z'; ++c) data[a++] = c; // 26..51
for(unsigned char c='0'; c<='9'; ++c) data[a++] = c; // 52..61
data[62] = '+'; // 62
data[63] = '/'; // 63
// create ascii->value mapping (but due to overlap, write it to highbit region)
for(a=0; a<64; ++a) data[data[a]^0x80] = a; //
data[((unsigned char)'=') ^ 0x80] = 0;
}
unsigned char operator[] (size_t pos) const { return data[pos]; }
private:
unsigned char data[256];
} Base64Table;
///Converts the provided data to a string in a standard, user-friendly, round-trippable format
std::string BytesToString(void* data, int len)
std::string BytesToString(const void* data, int len)
{
char temp[16];
if(len==1) {
sprintf(temp,"%d",*(unsigned char*)data);
sprintf(temp,"%d",*(const unsigned char*)data);
return temp;
} else if(len==2) {
sprintf(temp,"%d",*(unsigned short*)data);
sprintf(temp,"%d",*(const unsigned short*)data);
return temp;
} else if(len==4) {
sprintf(temp,"%d",*(unsigned int*)data);
sprintf(temp,"%d",*(const unsigned int*)data);
return temp;
}
std::string ret;
ret.resize(len*2+2);
char* str= (char*)ret.c_str();
str[0] = '0';
str[1] = 'x';
str += 2;
for(int i=0;i<len;i++)
if(1) // use base64
{
int a = (((unsigned char*)data)[i]>>4);
int b = (((unsigned char*)data)[i])&15;
if(a>9) a += 'A'-10;
else a += '0';
if(b>9) b += 'A'-10;
else b += '0';
str[i*2] = a;
str[i*2+1] = b;
const unsigned char* src = (const unsigned char*)data;
ret = "base64:";
for(int n; len > 0; len -= n)
{
unsigned char input[3] = {0,0,0};
for(n=0; n<3 && n<len; ++n)
input[n] = *src++;
unsigned char output[4] =
{
Base64Table[ input[0] >> 2 ],
Base64Table[ ((input[0] & 0x03) << 4) | (input[1] >> 4) ],
n<2 ? '=' : Base64Table[ ((input[1] & 0x0F) << 2) | (input[2] >> 6) ],
n<3 ? '=' : Base64Table[ input[2] & 0x3F ]
};
ret.append(output, output+4);
}
}
else // use hex
{
ret.resize(len*2+2);
ret[0] = '0';
ret[1] = 'x';
for(int i=0;i<len;i++)
{
int a = (((const unsigned char*)data)[i]>>4);
int b = (((const unsigned char*)data)[i])&15;
if(a>9) a += 'A'-10;
else a += '0';
if(b>9) b += 'A'-10;
else b += '0';
ret[2+i*2] = a;
ret[2+i*2+1] = b;
}
}
return ret;
}
///returns -1 if this is not a hex string
int HexStringToBytesLength(std::string& str)
int HexStringToBytesLength(const std::string& str)
{
if(str.size()>2 && str[0] == '0' && toupper(str[1]) == 'X')
return str.size()/2-1;
else return -1;
}
int Base64StringToBytesLength(const std::string& str)
{
if(str.size() < 7 || (str.size()-7) % 4 || str.substr(0,7) != "base64:") return -1;
size_t c = (str.size() - 7) / 4;
if(str[str.size()-1] == '=') { --c;
if(str[str.size()-2] == '=') --c; }
return c;
}
///parses a string in the same format as BytesToString
///returns true if success.
bool StringToBytes(std::string& str, void* data, int len)
bool StringToBytes(const std::string& str, void* data, int len)
{
if(str.substr(0,7) == "base64:")
{
// base64
unsigned char* tgt = (unsigned char*)data;
int pos = 7, remain = str.size() - pos;
while(remain > 0 && len > 0)
{
unsigned char input[4], converted[4];
for(int i=0; i<4; ++i)
{
if(pos >= remain && i > 0) return false; // invalid data
input[i] = str[pos++];
if(input[i] & 0x80) return false; // illegal character
converted[i] = Base64Table[input[i]^0x80];
if(converted[i] & 0x80) return false; // illegal character
}
unsigned char outpacket[3] =
{
(converted[0] << 2) | (converted[1] >> 4),
(converted[1] << 4) | (converted[2] >> 2),
(converted[2] << 6) | (converted[3])
};
int outlen = (input[2] == '=') ? 1 : (input[3] == '=' ? 2 : 3);
if(outlen > len) outlen = len;
memcpy(tgt, outpacket, outlen);
tgt += outlen;
}
}
if(str.size()>2 && str[0] == '0' && toupper(str[1]) == 'X')
goto hex;
{
// hex
int amt = len;
int bytesAvailable = str.size()/2;
if(bytesAvailable < amt)
amt = bytesAvailable;
const char* cstr = str.c_str()+2;
for(int i=0;i<amt;i++) {
char a = toupper(cstr[i*2]);
char b = toupper(cstr[i*2+1]);
if(a>='A') a=a-'A'+10;
else a-='0';
if(b>='A') b=b-'A'+10;
else b-='0';
unsigned char val = ((unsigned char)a<<4)|(unsigned char)b;
((unsigned char*)data)[i] = val;
}
return true;
}
if(len==1) {
int x = atoi(str.c_str());
@ -255,24 +354,6 @@ bool StringToBytes(std::string& str, void* data, int len)
}
//we can't handle it
return false;
hex:
int amt = len;
int bytesAvailable = str.size()/2;
if(bytesAvailable < amt)
amt = bytesAvailable;
const char* cstr = str.c_str()+2;
for(int i=0;i<amt;i++) {
char a = toupper(cstr[i*2]);
char b = toupper(cstr[i*2+1]);
if(a>='A') a=a-'A'+10;
else a-='0';
if(b>='A') b=b-'A'+10;
else b-='0';
unsigned char val = ((unsigned char)a<<4)|(unsigned char)b;
((unsigned char*)data)[i] = val;
}
return true;
}
#include <string>
@ -482,4 +563,4 @@ std::string readNullTerminatedAscii(std::istream* is)
else ret += (char)c;
}
return ret;
}
}

View File

@ -44,9 +44,10 @@ int str_strip(char *str, int flags);
int chr_replace(char *str, char search, char replace);
int str_replace(char *str, char *search, char *replace);
int HexStringToBytesLength(std::string& str);
std::string BytesToString(void* data, int len);
bool StringToBytes(std::string& str, void* data, int len);
int HexStringToBytesLength(const std::string& str);
int Base64StringToBytesLength(const std::string& str);
std::string BytesToString(const void* data, int len);
bool StringToBytes(const std::string& str, void* data, int len);
std::vector<std::string> tokenize_str(const std::string & str,const std::string & delims);
void splitpath(const char* path, char* drv, char* dir, char* name, char* ext);