Update to ananke v01 release.

byuu says:

This updated anake fixes all of the reported game issues thus far.
This commit is contained in:
Tim Allen 2013-01-17 22:14:58 +11:00
parent 6ac67c260b
commit 8d88337e28
23 changed files with 314 additions and 115 deletions

3
.gitignore vendored
View File

@ -1,5 +1,2 @@
purify/*.o
purify/purify
purify/analyze-gba
ananke/ananke.o
ananke/libananke.so

View File

@ -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

View File

@ -36,6 +36,7 @@ struct Ananke {
void copyFamicomSaves(const string &pathname);
string createFamicomHeuristic(vector<uint8_t> &buffer);
string openFamicom(vector<uint8_t> &buffer);
string syncFamicom(const string &pathname);
//super-famicom.cpp
void copySuperFamicomSaves(const string &pathname);
@ -43,30 +44,36 @@ struct Ananke {
string createSuperFamicomHeuristic(vector<uint8_t> &buffer);
void createSuperFamicomHeuristicFirmware(vector<uint8_t> &buffer, const string &pathname, bool firmware_appended);
string openSuperFamicom(vector<uint8_t> &buffer);
string syncSuperFamicom(const string &pathname);
//sufami-turbo.cpp
void copySufamiTurboSaves(const string &pathname);
string createSufamiTurboDatabase(vector<uint8_t> &buffer, Markup::Node &document, const string &manifest);
string createSufamiTurboHeuristic(vector<uint8_t> &buffer);
string openSufamiTurbo(vector<uint8_t> &buffer);
string syncSufamiTurbo(const string &pathname);
//bsx-satellaview.cpp
string createBsxSatellaviewDatabase(vector<uint8_t> &buffer, Markup::Node &document, const string &manifest);
string createBsxSatellaviewHeuristic(vector<uint8_t> &buffer);
string openBsxSatellaview(vector<uint8_t> &buffer);
string syncBsxSatellaview(const string &pathname);
//game-boy.cpp
void copyGameBoySaves(const string &pathname);
string createGameBoyHeuristic(vector<uint8_t> &buffer);
string openGameBoy(vector<uint8_t> &buffer);
string syncGameBoy(const string &pathname);
//game-boy-advance.cpp
void copyGameBoyAdvanceSaves(const string &pathname);
string createGameBoyAdvanceHeuristic(vector<uint8_t> &buffer);
string openGameBoyAdvance(vector<uint8_t> &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);
}

View File

@ -17,7 +17,7 @@ string Ananke::createBsxSatellaviewDatabase(vector<uint8_t> &buffer, Markup::Nod
file::write({pathname, "manifest.bml"}, markup);
file::write({pathname, "program.rom"}, buffer);
return "";
return pathname;
}
string Ananke::createBsxSatellaviewHeuristic(vector<uint8_t> &buffer) {
@ -37,7 +37,7 @@ string Ananke::createBsxSatellaviewHeuristic(vector<uint8_t> &buffer) {
});
file::write({pathname, "program.rom"}, buffer);
return "";
return pathname;
}
string Ananke::openBsxSatellaview(vector<uint8_t> &buffer) {
@ -58,3 +58,11 @@ string Ananke::openBsxSatellaview(vector<uint8_t> &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);
}

View File

@ -1,6 +1,6 @@
string BsxSatellaview = R"(
database revision=2013-01-14
database revision=2013-01-16
release
cartridge

View File

@ -1,6 +1,6 @@
string SufamiTurbo = R"(
database revision=2013-01-14
database revision=2013-01-16
release
cartridge linkable

View File

@ -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:

View File

@ -30,3 +30,10 @@ string Ananke::createFamicomHeuristic(vector<uint8_t> &buffer) {
string Ananke::openFamicom(vector<uint8_t> &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 "";
}

View File

@ -35,3 +35,22 @@ string Ananke::createGameBoyAdvanceHeuristic(vector<uint8_t> &buffer) {
string Ananke::openGameBoyAdvance(vector<uint8_t> &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;
}

View File

@ -37,3 +37,22 @@ string Ananke::createGameBoyHeuristic(vector<uint8_t> &buffer) {
string Ananke::openGameBoy(vector<uint8_t> &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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -5,12 +5,6 @@
//example: property<owner>::readonly<type> 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<foo>::readonly<bool> x;
@ -50,8 +44,6 @@
namespace nall {
template<typename C> struct property {
template<typename T> struct traits { typedef T type; };
template<typename T> 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<C>::type;
friend C;
};
template<typename T> struct writeonly {
@ -73,7 +65,7 @@ namespace nall {
T* operator->() { return &value; }
operator T&() { return value; }
T value;
friend class traits<C>::type;
friend C;
};
template<typename T> struct readwrite {

View File

@ -30,6 +30,7 @@
#include <nall/string/cstring.hpp>
#include <nall/string/datetime.hpp>
#include <nall/string/filename.hpp>
#include <nall/string/format.hpp>
#include <nall/string/math-fixed-point.hpp>
#include <nall/string/math-floating-point.hpp>
#include <nall/string/platform.hpp>

View File

@ -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<typename... Args> 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<unsigned limit = 0> inline string& ltrim(const char *key = " ");
template<unsigned limit = 0> 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<signed precision = 0, char padchar = ' '> inline string format(const string &value);
template<signed precision = 0, char padchar = '0'> inline string hex(uintmax_t value);
template<signed precision = 0, char padchar = '0'> inline string octal(uintmax_t value);
template<signed precision = 0, char padchar = '0'> 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<unsigned length = 0, char padding = ' '> inline string integer(intmax_t value);
template<unsigned length = 0, char padding = ' '> inline string linteger(intmax_t value);
template<unsigned length = 0, char padding = ' '> inline string decimal(uintmax_t value);
template<unsigned length = 0, char padding = ' '> inline string ldecimal(uintmax_t value);
template<unsigned length = 0, char padding = '0'> inline string hex(uintmax_t value);
template<unsigned length = 0, char padding = '0'> inline string binary(uintmax_t value);
inline unsigned fp(char *str, long double value);
inline string fp(long double value);

View File

@ -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 {

View File

@ -0,0 +1,73 @@
#ifdef NALL_STRING_INTERNAL_HPP
namespace nall {
template<signed precision, char padchar> 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<signed precision, char padchar> 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<precision, padchar>(buffer);
}
template<signed precision, char padchar> 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<precision, padchar>(buffer);
}
template<signed precision, char padchar> 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<precision, padchar>(buffer);
}
}
#endif

View File

@ -201,50 +201,6 @@ template<unsigned length_, char padding> string ldecimal(uintmax_t value) {
return (const char*)result;
}
template<unsigned length_, char padding> 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<unsigned length_, char padding> 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.

View File

@ -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<unsigned limit> string& string::ltrim(const char *key) { nall::ltrim<limit>(data, key); return *this; }
template<unsigned limit> string& string::rtrim(const char *key) { nall::rtrim<limit>(data, key); return *this; }

1
ananke/obj/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.o

View File

@ -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 :=

View File

@ -26,7 +26,7 @@ string Ananke::createSufamiTurboDatabase(vector<uint8_t> &buffer, Markup::Node &
file::write({pathname, "program.rom"}, buffer);
copySufamiTurboSaves(pathname);
return "";
return pathname;
}
string Ananke::createSufamiTurboHeuristic(vector<uint8_t> &buffer) {
@ -48,7 +48,7 @@ string Ananke::createSufamiTurboHeuristic(vector<uint8_t> &buffer) {
file::write({pathname, "program.rom"}, buffer);
copySufamiTurboSaves(pathname);
return "";
return pathname;
}
string Ananke::openSufamiTurbo(vector<uint8_t> &buffer) {
@ -69,3 +69,18 @@ string Ananke::openSufamiTurbo(vector<uint8_t> &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;
}

View File

@ -137,3 +137,74 @@ string Ananke::openSuperFamicom(vector<uint8_t> &buffer) {
return createSuperFamicomHeuristic(buffer);
}
string Ananke::syncSuperFamicom(const string &pathname) {
vector<uint8_t> 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;
}