diff --git a/.gitignore b/.gitignore index 841da7a3..0423bfef 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,2 @@ -purify/*.o purify/purify -purify/analyze-gba -ananke/ananke.o ananke/libananke.so diff --git a/ananke/Makefile b/ananke/Makefile index 4dced73c..46d0160e 100644 --- a/ananke/Makefile +++ b/ananke/Makefile @@ -3,25 +3,22 @@ include phoenix/Makefile path := /usr/local/lib flags := -I. -O3 -fomit-frame-pointer -ifeq ($(arch),win32) - flags := -m32 $(flags) -endif all: - $(cpp) $(flags) -fPIC -o ananke.o -c ananke.cpp + $(cpp) $(flags) -fPIC -o obj/ananke.o -c ananke.cpp ifeq ($(platform),x) - $(cpp) $(flags) -shared -Wl,-soname,libananke.so.1 -o libananke.so ananke.o + $(cpp) $(flags) -shared -Wl,-soname,libananke.so.1 -o libananke.so obj/ananke.o else ifeq ($(platform),win) - $(cpp) $(flags) -fPIC -o phoenix.o -c phoenix/phoenix.cpp $(phoenixflags) - $(cpp) $(flags) -shared -o phoenix.dll phoenix.o $(phoenixlink) - $(cpp) $(flags) -shared -o ananke.dll ananke.o -L. -lphoenix + $(cpp) $(flags) -fPIC -o obj/phoenix.o -c phoenix/phoenix.cpp $(phoenixflags) + $(cpp) $(flags) -shared -o phoenix.dll obj/phoenix.o $(phoenixlink) + $(cpp) $(flags) -shared -o ananke.dll obj/ananke.o -L. -lphoenix endif resource: force sourcery resource/resource.bml resource/resource.cpp resource/resource.hpp clean: - -@$(call delete,*.o) + -@$(call delete,obj/*.o) -@$(call delete,*.so) install: uninstall diff --git a/ananke/ananke.cpp b/ananke/ananke.cpp index 31a594cd..75a1f4f6 100644 --- a/ananke/ananke.cpp +++ b/ananke/ananke.cpp @@ -36,6 +36,7 @@ struct Ananke { void copyFamicomSaves(const string &pathname); string createFamicomHeuristic(vector &buffer); string openFamicom(vector &buffer); + string syncFamicom(const string &pathname); //super-famicom.cpp void copySuperFamicomSaves(const string &pathname); @@ -43,30 +44,36 @@ struct Ananke { string createSuperFamicomHeuristic(vector &buffer); void createSuperFamicomHeuristicFirmware(vector &buffer, const string &pathname, bool firmware_appended); string openSuperFamicom(vector &buffer); + string syncSuperFamicom(const string &pathname); //sufami-turbo.cpp void copySufamiTurboSaves(const string &pathname); string createSufamiTurboDatabase(vector &buffer, Markup::Node &document, const string &manifest); string createSufamiTurboHeuristic(vector &buffer); string openSufamiTurbo(vector &buffer); + string syncSufamiTurbo(const string &pathname); //bsx-satellaview.cpp string createBsxSatellaviewDatabase(vector &buffer, Markup::Node &document, const string &manifest); string createBsxSatellaviewHeuristic(vector &buffer); string openBsxSatellaview(vector &buffer); + string syncBsxSatellaview(const string &pathname); //game-boy.cpp void copyGameBoySaves(const string &pathname); string createGameBoyHeuristic(vector &buffer); string openGameBoy(vector &buffer); + string syncGameBoy(const string &pathname); //game-boy-advance.cpp void copyGameBoyAdvanceSaves(const string &pathname); string createGameBoyAdvanceHeuristic(vector &buffer); string openGameBoyAdvance(vector &buffer); + string syncGameBoyAdvance(const string &pathname); static bool supported(const string &filename); string open(string filename = ""); + string sync(string pathname); }; #include "resource/resource.cpp" @@ -132,6 +139,17 @@ string Ananke::open(string filename) { return ""; } +string Ananke::sync(string pathname) { + if(pathname.endswith(".fc/")) return syncFamicom(pathname); + if(pathname.endswith(".sfc/")) return syncSuperFamicom(pathname); + if(pathname.endswith(".st/")) return syncSufamiTurbo(pathname); + if(pathname.endswith(".bs/")) return syncBsxSatellaview(pathname); + if(pathname.endswith(".gb/")) return syncGameBoy(pathname); + if(pathname.endswith(".gbc/")) return syncGameBoy(pathname); + if(pathname.endswith(".gba/")) return syncGameBoyAdvance(pathname); + return ""; +} + extern "C" string ananke_browse(const string &filename) { Ananke ananke; return ananke.open(); @@ -141,3 +159,8 @@ extern "C" string ananke_open(const string &filename) { Ananke ananke; return ananke.open(filename); } + +extern "C" string ananke_sync(const string &pathname) { + Ananke ananke; + return ananke.sync(pathname); +} diff --git a/ananke/bsx-satellaview.cpp b/ananke/bsx-satellaview.cpp index 4ebc7bf7..559fcd3c 100644 --- a/ananke/bsx-satellaview.cpp +++ b/ananke/bsx-satellaview.cpp @@ -17,7 +17,7 @@ string Ananke::createBsxSatellaviewDatabase(vector &buffer, Markup::Nod file::write({pathname, "manifest.bml"}, markup); file::write({pathname, "program.rom"}, buffer); - return ""; + return pathname; } string Ananke::createBsxSatellaviewHeuristic(vector &buffer) { @@ -37,7 +37,7 @@ string Ananke::createBsxSatellaviewHeuristic(vector &buffer) { }); file::write({pathname, "program.rom"}, buffer); - return ""; + return pathname; } string Ananke::openBsxSatellaview(vector &buffer) { @@ -58,3 +58,11 @@ string Ananke::openBsxSatellaview(vector &buffer) { return createBsxSatellaviewHeuristic(buffer); } + +string Ananke::syncBsxSatellaview(const string &pathname) { + auto buffer = file::read({pathname, "program.rom"}); + if(buffer.size() == 0) return ""; + + directory::remove(pathname); + return openBsxSatellaview(buffer); +} diff --git a/ananke/database/bsx-satellaview.hpp b/ananke/database/bsx-satellaview.hpp index 0b51bdc2..4ff0fd7b 100644 --- a/ananke/database/bsx-satellaview.hpp +++ b/ananke/database/bsx-satellaview.hpp @@ -1,6 +1,6 @@ string BsxSatellaview = R"( -database revision=2013-01-14 +database revision=2013-01-16 release cartridge diff --git a/ananke/database/sufami-turbo.hpp b/ananke/database/sufami-turbo.hpp index d3d505e5..bc0d02dd 100644 --- a/ananke/database/sufami-turbo.hpp +++ b/ananke/database/sufami-turbo.hpp @@ -1,6 +1,6 @@ string SufamiTurbo = R"( -database revision=2013-01-14 +database revision=2013-01-16 release cartridge linkable diff --git a/ananke/database/super-famicom.hpp b/ananke/database/super-famicom.hpp index c6f8b713..7daa7840 100644 --- a/ananke/database/super-famicom.hpp +++ b/ananke/database/super-famicom.hpp @@ -1,6 +1,6 @@ string SuperFamicom = R"( -database revision=2013-01-14 +database revision=2013-01-16 release cartridge region=NTSC @@ -208,10 +208,10 @@ release board type=LJ3M revision=01 rom name=program.rom size=0x600000 ram name=save.ram size=0x2000 - map id=rom address=00-3f:8000-ffff offset=0x400000 - map id=rom address=40-7d:0000-ffff offset=0x400000 - map id=rom address=80-bf:8000-ffff offset=0x000000 mask=0xc00000 - map id=rom address=c0-ff:0000-ffff offset=0x000000 mask=0xc00000 + map id=rom address=00-3f:8000-ffff base=0x400000 + map id=rom address=40-7d:0000-ffff base=0x400000 + map id=rom address=80-bf:8000-ffff mask=0xc00000 + map id=rom address=c0-ff:0000-ffff mask=0xc00000 map id=ram address=80-bf:6000-7fff mask=0xe000 information title: テイルズ オブ ファンタジア diff --git a/ananke/famicom.cpp b/ananke/famicom.cpp index 00f945e0..6bcd6f20 100644 --- a/ananke/famicom.cpp +++ b/ananke/famicom.cpp @@ -30,3 +30,10 @@ string Ananke::createFamicomHeuristic(vector &buffer) { string Ananke::openFamicom(vector &buffer) { return createFamicomHeuristic(buffer); } + +//this currently cannot work: +//game folders discard iNES header required for heuristic detection +//a games database of all commercial Famicom software will be required +string Ananke::syncFamicom(const string &pathname) { + return ""; +} diff --git a/ananke/game-boy-advance.cpp b/ananke/game-boy-advance.cpp index 30b93f59..af55a40f 100644 --- a/ananke/game-boy-advance.cpp +++ b/ananke/game-boy-advance.cpp @@ -35,3 +35,22 @@ string Ananke::createGameBoyAdvanceHeuristic(vector &buffer) { string Ananke::openGameBoyAdvance(vector &buffer) { return createGameBoyAdvanceHeuristic(buffer); } + +string Ananke::syncGameBoyAdvance(const string &pathname) { + auto buffer = file::read({pathname, "program.rom"}); + if(buffer.size() == 0) return ""; + + auto save = file::read({pathname, "save.ram"}); + if(save.size() == 0) save = file::read({pathname, "save.rwm"}); + + auto rtc = file::read({pathname, "rtc.ram"}); + if(rtc.size() == 0) rtc = file::read({pathname, "rtc.rwm"}); + + directory::remove(pathname); + string outputPath = openGameBoyAdvance(buffer); + + if(save.size()) file::write({outputPath, "save.ram"}, save); + if(rtc.size()) file::write({outputPath, "rtc.ram"}, rtc); + + return outputPath; +} diff --git a/ananke/game-boy.cpp b/ananke/game-boy.cpp index 3daca00c..a06b2234 100644 --- a/ananke/game-boy.cpp +++ b/ananke/game-boy.cpp @@ -37,3 +37,22 @@ string Ananke::createGameBoyHeuristic(vector &buffer) { string Ananke::openGameBoy(vector &buffer) { return createGameBoyHeuristic(buffer); } + +string Ananke::syncGameBoy(const string &pathname) { + auto buffer = file::read({pathname, "program.rom"}); + if(buffer.size() == 0) return ""; + + auto save = file::read({pathname, "save.ram"}); + if(save.size() == 0) save = file::read({pathname, "save.rwm"}); + + auto rtc = file::read({pathname, "rtc.ram"}); + if(rtc.size() == 0) rtc = file::read({pathname, "rtc.rwm"}); + + directory::remove(pathname); + string outputPath = openGameBoy(buffer); + + if(save.size()) file::write({outputPath, "save.ram"}, save); + if(rtc.size()) file::write({outputPath, "rtc.ram"}, rtc); + + return outputPath; +} diff --git a/ananke/heuristics/super-famicom.hpp b/ananke/heuristics/super-famicom.hpp index d5efaabf..afea54b5 100644 --- a/ananke/heuristics/super-famicom.hpp +++ b/ananke/heuristics/super-famicom.hpp @@ -91,10 +91,10 @@ struct SuperFamicomCartridge { bool has_bsx_slot; bool has_superfx; bool has_sa1; - bool has_srtc; + bool has_sharprtc; + bool has_epsonrtc; bool has_sdd1; bool has_spc7110; - bool has_spc7110rtc; bool has_cx4; bool has_dsp1; bool has_dsp2; @@ -128,7 +128,7 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size) if(type == TypeSuperGameBoy1Bios || type == TypeSuperGameBoy2Bios) { markup.append( " rom name=program.rom size=0x", hex(rom_size), "\n" - " map id=rom address=00-7f,80-ff:8000-ffff\n" + " map id=rom address=00-7f,80-ff:8000-ffff mask=0x8000\n" " icd2 revision=1\n" " rom name=sgb.boot.rom size=0x100\n" " map id=io address=00-3f,80-bf:6000-7fff\n" @@ -244,10 +244,10 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size) " ram name=save.ram size=0x", hex(ram_size), "\n" ); markup.append( - " map id=rom address=00-3f:8000-ffff offset=0x400000\n" - " map id=rom address=40-7f:0000-ffff offset=0x400000\n" - " map id=rom address=80-bf:8000-ffff offset=0x000000 mask=0xc00000\n" - " map id=rom address=c0-ff:0000-ffff offset=0x000000 mask=0xc00000\n" + " map id=rom address=00-3f:8000-ffff base=0x400000\n" + " map id=rom address=40-7f:0000-ffff base=0x400000\n" + " map id=rom address=80-bf:8000-ffff mask=0xc00000\n" + " map id=rom address=c0-ff:0000-ffff mask=0xc00000\n" ); if(ram_size > 0) markup.append( " map id=ram address=20-3f,a0-bf:6000-7fff mask=0xe000\n" @@ -301,10 +301,10 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size) markup.append( " rom name=program.rom size=0x", hex(rom_size), "\n" " ram name=save.ram size=0x", hex(ram_size), "\n" - " map id=rom address=00-1f:8000-ffff offset=0x000000 mask=0x8000\n" - " map id=rom address=20-3f:8000-ffff offset=0x100000 mask=0x8000\n" - " map id=rom address=80-9f:8000-ffff offset=0x200000 mask=0x8000\n" - " map id=rom address=a0-bf:8000-ffff offset=0x100000 mask=0x8000\n" + " map id=rom address=00-1f:8000-ffff base=0x000000 mask=0x8000\n" + " map id=rom address=20-3f:8000-ffff base=0x100000 mask=0x8000\n" + " map id=rom address=80-9f:8000-ffff base=0x200000 mask=0x8000\n" + " map id=rom address=a0-bf:8000-ffff base=0x100000 mask=0x8000\n" " map id=ram address=70-7f,f0-ff:0000-7fff\n" " bsxslot\n" " map id=rom address=c0-ef:0000-ffff\n" @@ -351,15 +351,7 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size) ); } - if(has_spc7110rtc) { - markup.append( - " epsonrtc\n" - " ram name=rtc.ram size=0x10\n" - " map id=io address=00-3f,80-bf:4840-4842\n" - ); - } - - if(has_srtc) { + if(has_sharprtc) { markup.append( " sharprtc\n" " ram name=rtc.ram size=0x10\n" @@ -367,6 +359,14 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size) ); } + if(has_epsonrtc) { + markup.append( + " epsonrtc\n" + " ram name=rtc.ram size=0x10\n" + " map id=io address=00-3f,80-bf:4840-4842\n" + ); + } + if(has_obc1) { markup.append( " obc1\n" @@ -431,7 +431,7 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size) " rom id=program name=dsp4.program.rom size=0x1800\n" " rom id=data name=dsp4.data.rom size=0x800\n" " ram id=data size=0x200\n" - " map address=30-3f,b0-bf:8000-ffff select=0x4000\n" + " map id=io address=30-3f,b0-bf:8000-ffff select=0x4000\n" ); if((size & 0x7fff) == 0x2000) { firmware_appended = true; @@ -495,10 +495,10 @@ void SuperFamicomCartridge::read_header(const uint8_t *data, unsigned size) { has_bsx_slot = false; has_superfx = false; has_sa1 = false; - has_srtc = false; + has_sharprtc = false; + has_epsonrtc = false; has_sdd1 = false; has_spc7110 = false; - has_spc7110rtc = false; has_cx4 = false; has_dsp1 = false; has_dsp2 = false; @@ -645,7 +645,7 @@ void SuperFamicomCartridge::read_header(const uint8_t *data, unsigned size) { } if(mapperid == 0x35 && rom_type == 0x55) { - has_srtc = true; + has_sharprtc = true; } if(mapperid == 0x32 && (rom_type == 0x43 || rom_type == 0x45)) { @@ -654,7 +654,7 @@ void SuperFamicomCartridge::read_header(const uint8_t *data, unsigned size) { if(mapperid == 0x3a && (rom_type == 0xf5 || rom_type == 0xf9)) { has_spc7110 = true; - has_spc7110rtc = (rom_type == 0xf9); + has_epsonrtc = (rom_type == 0xf9); mapper = SPC7110ROM; } diff --git a/ananke/nall/Makefile b/ananke/nall/Makefile index bbc4b029..9929d101 100644 --- a/ananke/nall/Makefile +++ b/ananke/nall/Makefile @@ -45,7 +45,12 @@ ifeq ($(compiler),) endif c := $(compiler) -std=gnu99 -cpp := $(subst cc,++,$(compiler)) -std=gnu++0x +cpp := $(subst cc,++,$(compiler)) -std=gnu++11 + +ifeq ($(arch),x86) + c := $(c) -m32 + cpp := $(cpp) -m32 +endif ifeq ($(prefix),) prefix := /usr/local diff --git a/ananke/nall/property.hpp b/ananke/nall/property.hpp index 665afcad..1ddb5c9b 100644 --- a/ananke/nall/property.hpp +++ b/ananke/nall/property.hpp @@ -5,12 +5,6 @@ //example: property::readonly implies that only owner has full //access to type; and all other code has readonly access. // -//this code relies on extended friend semantics from C++0x to work, as it -//declares a friend class via a template paramter. it also exploits a bug in -//G++ 4.x to work even in C++98 mode. -// -//if compiling elsewhere, simply remove the friend class and private semantics - //property can be used either of two ways: //struct foo { // property::readonly x; @@ -50,8 +44,6 @@ namespace nall { template struct property { - template struct traits { typedef T type; }; - template struct readonly { const T* operator->() const { return &value; } const T& operator()() const { return value; } @@ -61,7 +53,7 @@ namespace nall { operator T&() { return value; } const T& operator=(const T& value_) { return value = value_; } T value; - friend class traits::type; + friend C; }; template struct writeonly { @@ -73,7 +65,7 @@ namespace nall { T* operator->() { return &value; } operator T&() { return value; } T value; - friend class traits::type; + friend C; }; template struct readwrite { diff --git a/ananke/nall/string.hpp b/ananke/nall/string.hpp index 82c1bbb1..82b7cde4 100644 --- a/ananke/nall/string.hpp +++ b/ananke/nall/string.hpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include diff --git a/ananke/nall/string/base.hpp b/ananke/nall/string/base.hpp index 85645c7f..abf21735 100644 --- a/ananke/nall/string/base.hpp +++ b/ananke/nall/string/base.hpp @@ -28,6 +28,8 @@ namespace nall { inline static string datetime(); inline void reserve(unsigned); + inline void resize(unsigned); + inline void clear(char); inline bool empty() const; template inline string& assign(Args&&... args); @@ -64,6 +66,7 @@ namespace nall { inline string& qlower(); inline string& qupper(); inline string& transform(const char *before, const char *after); + inline string& reverse(); template inline string& ltrim(const char *key = " "); template inline string& rtrim(const char *key = " "); @@ -159,6 +162,12 @@ namespace nall { inline char* qstrupper(char *str); inline char* strtr(char *dest, const char *before, const char *after); + //format.hpp + template inline string format(const string &value); + template inline string hex(uintmax_t value); + template inline string octal(uintmax_t value); + template inline string binary(uintmax_t value); + //math.hpp inline bool strint(const char *str, int &result); inline bool strmath(const char *str, int &result); @@ -200,12 +209,11 @@ namespace nall { inline char* integer(char *result, intmax_t value); inline char* decimal(char *result, uintmax_t value); + //these functions are deprecated, use format() instead: template inline string integer(intmax_t value); template inline string linteger(intmax_t value); template inline string decimal(uintmax_t value); template inline string ldecimal(uintmax_t value); - template inline string hex(uintmax_t value); - template inline string binary(uintmax_t value); inline unsigned fp(char *str, long double value); inline string fp(long double value); diff --git a/ananke/nall/string/core.hpp b/ananke/nall/string/core.hpp index d843e2fd..64c9250d 100644 --- a/ananke/nall/string/core.hpp +++ b/ananke/nall/string/core.hpp @@ -12,11 +12,18 @@ static void istring(string &output, const T &value, Args&&... args) { } void string::reserve(unsigned size_) { - if(size_ > size) { - size = size_; - data = (char*)realloc(data, size + 1); - data[size] = 0; - } + if(size_ > size) resize(size_); +} + +void string::resize(unsigned size_) { + size = size_; + data = (char*)realloc(data, size + 1); + data[size] = 0; +} + +void string::clear(char c) { + for(unsigned n = 0; n < size; n++) data[n] = c; + data[size] = 0; } bool string::empty() const { diff --git a/ananke/nall/string/format.hpp b/ananke/nall/string/format.hpp new file mode 100644 index 00000000..599021d1 --- /dev/null +++ b/ananke/nall/string/format.hpp @@ -0,0 +1,73 @@ +#ifdef NALL_STRING_INTERNAL_HPP + +namespace nall { + +template string format(const string &value) { + if(precision == 0) return value; + + bool padright = precision >= 0; + unsigned padding = abs(precision); + + unsigned length = value.length(); + if(padding <= length) { + if(padright) return substr(value, length - padding); + else return substr(value, 0, padding); + } + + string buffer; + buffer.resize(padding); + buffer.clear(padchar); + + memcpy(buffer() + (padright ? padding - length : 0), value, length); + return buffer; +} + +template string hex(uintmax_t value) { + string buffer; + buffer.resize(sizeof(uintmax_t) * 2); + + unsigned size = 0; + do { + unsigned n = value & 15; + buffer[size++] = n < 10 ? '0' + n : 'a' + n - 10; + value >>= 4; + } while(value); + buffer[size] = 0; + buffer.reverse(); + + return format(buffer); +} + +template string octal(uintmax_t value) { + string buffer; + buffer.resize(sizeof(uintmax_t) * 3); + + unsigned size = 0; + do { + buffer[size++] = '0' + (value & 7); + value >>= 3; + } while(value); + buffer[size] = 0; + buffer.reverse(); + + return format(buffer); +} + +template string binary(uintmax_t value) { + string buffer; + buffer.resize(sizeof(uintmax_t) * 8); + + unsigned size = 0; + do { + buffer[size++] = '0' + (value & 1); + value >>= 1; + } while(value); + buffer[size] = 0; + buffer.reverse(); + + return format(buffer); +} + +} + +#endif diff --git a/ananke/nall/string/utility.hpp b/ananke/nall/string/utility.hpp index 0225e4fe..657383f8 100644 --- a/ananke/nall/string/utility.hpp +++ b/ananke/nall/string/utility.hpp @@ -201,50 +201,6 @@ template string ldecimal(uintmax_t value) { return (const char*)result; } -template string hex(uintmax_t value) { - char buffer[64]; - unsigned size = 0; - - do { - unsigned n = value & 15; - buffer[size++] = n < 10 ? '0' + n : 'a' + n - 10; - value >>= 4; - } while(value); - - unsigned length = (length_ == 0 ? size : length_); - char result[length + 1]; - memset(result, padding, length); - result[length] = 0; - - for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) { - result[x] = buffer[y]; - } - - return (const char*)result; -} - -template string binary(uintmax_t value) { - char buffer[256]; - unsigned size = 0; - - do { - unsigned n = value & 1; - buffer[size++] = '0' + n; - value >>= 1; - } while(value); - - unsigned length = (length_ == 0 ? size : length_); - char result[length + 1]; - memset(result, padding, length); - result[length] = 0; - - for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) { - result[x] = buffer[y]; - } - - return (const char*)result; -} - //using sprintf is certainly not the most ideal method to convert //a double to a string ... but attempting to parse a double by //hand, digit-by-digit, results in subtle rounding errors. diff --git a/ananke/nall/string/wrapper.hpp b/ananke/nall/string/wrapper.hpp index 9d62915b..08aa98b3 100644 --- a/ananke/nall/string/wrapper.hpp +++ b/ananke/nall/string/wrapper.hpp @@ -27,6 +27,11 @@ string& string::upper() { nall::strupper(data); return *this; } string& string::qlower() { nall::qstrlower(data); return *this; } string& string::qupper() { nall::qstrupper(data); return *this; } string& string::transform(const char *before, const char *after) { nall::strtr(data, before, after); return *this; } +string& string::reverse() { + unsigned length = strlen(data), pivot = length >> 1; + for(signed x = 0, y = length - 1; x < pivot && y >= 0; x++, y--) std::swap(data[x], data[y]); + return *this; +} template string& string::ltrim(const char *key) { nall::ltrim(data, key); return *this; } template string& string::rtrim(const char *key) { nall::rtrim(data, key); return *this; } diff --git a/ananke/obj/.gitignore b/ananke/obj/.gitignore new file mode 100644 index 00000000..5761abcf --- /dev/null +++ b/ananke/obj/.gitignore @@ -0,0 +1 @@ +*.o diff --git a/ananke/phoenix/Makefile b/ananke/phoenix/Makefile index b98ccfdd..d1c9d981 100644 --- a/ananke/phoenix/Makefile +++ b/ananke/phoenix/Makefile @@ -15,11 +15,6 @@ ifeq ($(platform),x) else ifeq ($(platform),win) phoenixflags := -DPHOENIX_WINDOWS phoenixlink := -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32 -lshlwapi - - ifeq ($(arch),win32) - phoenixflags := -m32 $(phoenixflags) - phoenixlink := -m32 $(phoenixlink) - endif else phoenixflags := -DPHOENIX_REFERENCE phoenixlink := diff --git a/ananke/sufami-turbo.cpp b/ananke/sufami-turbo.cpp index 15e304a8..722d2847 100644 --- a/ananke/sufami-turbo.cpp +++ b/ananke/sufami-turbo.cpp @@ -26,7 +26,7 @@ string Ananke::createSufamiTurboDatabase(vector &buffer, Markup::Node & file::write({pathname, "program.rom"}, buffer); copySufamiTurboSaves(pathname); - return ""; + return pathname; } string Ananke::createSufamiTurboHeuristic(vector &buffer) { @@ -48,7 +48,7 @@ string Ananke::createSufamiTurboHeuristic(vector &buffer) { file::write({pathname, "program.rom"}, buffer); copySufamiTurboSaves(pathname); - return ""; + return pathname; } string Ananke::openSufamiTurbo(vector &buffer) { @@ -69,3 +69,18 @@ string Ananke::openSufamiTurbo(vector &buffer) { return createSufamiTurboHeuristic(buffer); } + +string Ananke::syncSufamiTurbo(const string &pathname) { + auto buffer = file::read({pathname, "program.rom"}); + if(buffer.size() == 0) return ""; + + auto save = file::read({pathname, "save.ram"}); + if(save.size() == 0) save = file::read({pathname, "save.rwm"}); + + directory::remove(pathname); + string outputPath = openSufamiTurbo(buffer); + + if(save.size()) file::write({outputPath, "save.ram"}, save); + + return outputPath; +} diff --git a/ananke/super-famicom.cpp b/ananke/super-famicom.cpp index da991fb8..89872fb7 100644 --- a/ananke/super-famicom.cpp +++ b/ananke/super-famicom.cpp @@ -137,3 +137,74 @@ string Ananke::openSuperFamicom(vector &buffer) { return createSuperFamicomHeuristic(buffer); } + +string Ananke::syncSuperFamicom(const string &pathname) { + vector buffer; + + auto append = [&](string filename) { + filename = {pathname, filename}; + auto data = file::read(filename); + if(data.size() == 0) return; //file does not exist + + unsigned position = buffer.size(); + buffer.resize(buffer.size() + data.size()); + memcpy(buffer.data() + position, data.data(), data.size()); + }; + + append("program.rom"); + append("data.rom"); + + append("dsp1.rom"); + append("dsp1.program.rom"); + append("dsp1.data.rom"); + + append("dsp1b.rom"); + append("dsp1b.program.rom"); + append("dsp1b.data.rom"); + + append("dsp2.rom"); + append("dsp2.program.rom"); + append("dsp2.data.rom"); + + append("dsp3.rom"); + append("dsp3.program.rom"); + append("dsp3.data.rom"); + + append("dsp4.rom"); + append("dsp4.program.rom"); + append("dsp4.data.rom"); + + append("st010.rom"); + append("st010.program.rom"); + append("st010.data.rom"); + + append("st011.rom"); + append("st011.program.rom"); + append("st011.data.rom"); + + append("st018.rom"); + append("st018.program.rom"); + append("st018.data.rom"); + + append("cx4.rom"); + append("cx4.data.rom"); + + append("sgb.rom"); + append("sgb.boot.rom"); + + if(buffer.size() == 0) return ""; + + auto save = file::read({pathname, "save.ram"}); + if(save.size() == 0) save = file::read({pathname, "save.rwm"}); + + auto rtc = file::read({pathname, "rtc.ram"}); + if(rtc.size() == 0) rtc= file::read({pathname, "rtc.rwm"}); + + directory::remove(pathname); + string outputPath = openSuperFamicom(buffer); + + if(save.size()) file::write({outputPath, "save.ram"}, save); + if(rtc.size()) file::write({outputPath, "rtc.ram"}, save); + + return outputPath; +}