diff --git a/SConstruct b/SConstruct index fac8552a..e099a1c3 100644 --- a/SConstruct +++ b/SConstruct @@ -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']: diff --git a/src/SConscript b/src/SConscript index 21b4c31b..1621e570 100644 --- a/src/SConscript +++ b/src/SConscript @@ -12,6 +12,7 @@ file.cpp filter.cpp ines.cpp input.cpp +lua-engine.cpp netplay.cpp nsf.cpp palette.cpp diff --git a/src/movie.cpp b/src/movie.cpp index 4f755989..81f2ed1a 100644 --- a/src/movie.cpp +++ b/src/movie.cpp @@ -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 } } } diff --git a/src/utils/xstring.cpp b/src/utils/xstring.cpp index ce284d79..98ef1cdf 100644 --- a/src/utils/xstring.cpp +++ b/src/utils/xstring.cpp @@ -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>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> 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>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='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='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 @@ -482,4 +563,4 @@ std::string readNullTerminatedAscii(std::istream* is) else ret += (char)c; } return ret; -} \ No newline at end of file +} diff --git a/src/utils/xstring.h b/src/utils/xstring.h index 3beb5d98..c4cb9a89 100644 --- a/src/utils/xstring.h +++ b/src/utils/xstring.h @@ -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 tokenize_str(const std::string & str,const std::string & delims); void splitpath(const char* path, char* drv, char* dir, char* name, char* ext);