Update to ananke v00r02 release.

byuu says:

This should be basically final now.

Works with all media types (nes, sfc, gb, gbc, gba, bs, st), strips
headers, can use internal or external firmware, imports saves on first
run.

Added a custom file dialog. It seems both GTK+ and Windows XP have
(un)intelligent file sorting, which puts eg "ActRaiser 2 (NA)" before
"ActRaiser (NA)". So, screw 'em.
This commit is contained in:
Tim Allen 2012-12-24 16:48:23 +11:00
parent 019fc1a2c6
commit 85f2e9a6d4
24 changed files with 13615 additions and 6648 deletions

View File

@ -8,14 +8,15 @@ all:
$(cpp) $(flags) -fPIC -o ananke.o -c ananke.cpp $(cpp) $(flags) -fPIC -o ananke.o -c ananke.cpp
$(cpp) $(flags) -shared -Wl,-soname,libananke.so.1 -o libananke.so ananke.o $(cpp) $(flags) -shared -Wl,-soname,libananke.so.1 -o libananke.so ananke.o
resource: force
sourcery resource/resource.bml resource/resource.cpp resource/resource.hpp
clean: clean:
-@$(call delete,*.o) -@$(call delete,*.o)
-@$(call delete,*.so) -@$(call delete,*.so)
install: uninstall install: uninstall
if [ ! -d ~/.config/ananke ]; then mkdir ~/.config/ananke; fi if [ ! -d ~/.config/ananke ]; then mkdir ~/.config/ananke; fi
if [ -d ~/.config/ananke/database ]; then rm -r ~/.config/ananke/database; fi
cp -r database ~/.config/ananke/database
sudo cp libananke.so $(path)/libananke.so.1 sudo cp libananke.so $(path)/libananke.so.1
sudo ln -s $(path)/libananke.so.1 $(path)/libananke.so sudo ln -s $(path)/libananke.so.1 $(path)/libananke.so

View File

@ -1,11 +1,18 @@
#include <nall/nall.hpp> #include <nall/nall.hpp>
#include <nall/beat/patch.hpp> #include <nall/beat/patch.hpp>
#include <nall/emulation/famicom.hpp>
#include <nall/emulation/super-famicom.hpp> #include <nall/emulation/super-famicom.hpp>
#include <nall/emulation/game-boy.hpp>
#include <nall/emulation/game-boy-advance.hpp>
using namespace nall; using namespace nall;
#include <phoenix/phoenix.hpp> #include <phoenix/phoenix.hpp>
using namespace phoenix; using namespace phoenix;
namespace Database {
#include "database/super-famicom.hpp"
};
struct Ananke { struct Ananke {
#include "configuration.cpp" #include "configuration.cpp"
@ -23,40 +30,72 @@ struct Ananke {
//patch.cpp //patch.cpp
void applyBeatPatch(vector<uint8_t> &buffer); void applyBeatPatch(vector<uint8_t> &buffer);
//famicom.cpp
void copyFamicomSaves(const string &pathname);
string createFamicomHeuristic(vector<uint8_t> &buffer);
string openFamicom(vector<uint8_t> &buffer);
//super-famicom.cpp //super-famicom.cpp
void copySuperFamicomSaves(const string &pathname);
string createSuperFamicomDatabase(vector<uint8_t> &buffer, Markup::Node &document, const string &manifest); string createSuperFamicomDatabase(vector<uint8_t> &buffer, Markup::Node &document, const string &manifest);
string createSuperFamicomHeuristic(vector<uint8_t> &buffer); 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 openSuperFamicom(vector<uint8_t> &buffer);
string open(string filename = "") { //game-boy.cpp
if(filename.empty()) filename = DialogWindow::fileOpen(Window::none(), config.path); void copyGameBoySaves(const string &pathname);
if(filename.empty()) return ""; string createGameBoyHeuristic(vector<uint8_t> &buffer);
string openGameBoy(vector<uint8_t> &buffer);
information.path = dir(filename);
information.name = notdir(filename);
config.path = information.path; //remember last used directory
vector<uint8_t> buffer;
if(filename.endswith(".zip")) {
information.archive = filename;
buffer = extractROM();
} else {
buffer = file::read(filename);
}
if(buffer.size() == 0) return ""; //failed to read file
applyBeatPatch(buffer);
if(information.name.endswith(".sfc")) return openSuperFamicom(buffer);
return "";
}
//game-boy-advance.cpp
void copyGameBoyAdvanceSaves(const string &pathname);
string createGameBoyAdvanceHeuristic(vector<uint8_t> &buffer);
string openGameBoyAdvance(vector<uint8_t> &buffer);
string open(string filename = "");
}; };
#include "resource/resource.cpp"
#include "file-dialog.cpp"
#include "archive.cpp" #include "archive.cpp"
#include "patch.cpp" #include "patch.cpp"
#include "famicom.cpp"
#include "super-famicom.cpp" #include "super-famicom.cpp"
#include "game-boy.cpp"
#include "game-boy-advance.cpp"
FileDialog *fileDialog = nullptr;
string Ananke::open(string filename) {
if(filename.empty()) {
if(!fileDialog) fileDialog = new FileDialog;
fileDialog->setPath(config.path);
filename = fileDialog->open();
}
if(filename.empty()) return "";
information.path = dir(filename);
information.name = notdir(filename);
config.path = information.path; //remember last used directory
vector<uint8_t> buffer;
if(filename.endswith(".zip")) {
information.archive = filename;
buffer = extractROM();
} else {
buffer = file::read(filename);
}
if(buffer.size() == 0) return ""; //failed to read file
applyBeatPatch(buffer);
if(information.name.endswith(".fc") || information.name.endswith(".nes")) return openFamicom(buffer);
if(information.name.endswith(".sfc") || information.name.endswith(".smc")) return openSuperFamicom(buffer);
if(information.name.endswith(".gb") || information.name.endswith(".gbc")) return openGameBoy(buffer);
if(information.name.endswith(".gba")) return openGameBoyAdvance(buffer);
return "";
}
extern "C" string ananke_browse(const string &filename) { extern "C" string ananke_browse(const string &filename) {
Ananke ananke; Ananke ananke;

View File

@ -2,7 +2,12 @@ vector<uint8_t> Ananke::extractROM() {
unzip archive; unzip archive;
if(archive.open(information.archive)) { if(archive.open(information.archive)) {
for(auto &file : archive.file) { for(auto &file : archive.file) {
if(file.name.endswith(".sfc")) { if(
file.name.endswith(".fc") || file.name.endswith(".nes")
|| file.name.endswith(".sfc") || file.name.endswith(".smc")
|| file.name.endswith(".gb") || file.name.endswith(".gbc")
|| file.name.endswith(".gba")
) {
information.name = notdir(file.name); information.name = notdir(file.name);
return archive.extract(file); return archive.extract(file);
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

31
ananke/famicom.cpp Normal file
View File

@ -0,0 +1,31 @@
void Ananke::copyFamicomSaves(const string &pathname) {
if(!file::exists({pathname, "save.ram"})) {
if(file::exists({information.path, nall::basename(information.name), ".sav"})) {
file::copy({information.path, nall::basename(information.name), ".srm"}, {pathname, "save.ram"});
}
}
}
string Ananke::createFamicomHeuristic(vector<uint8_t> &buffer) {
string pathname = {
userpath(), "Emulation/Famicom/",
nall::basename(information.name),
" (!).fc/"
};
directory::create(pathname);
FamicomCartridge info(buffer.data(), buffer.size());
string markup = info.markup();
if(!information.manifest.empty()) markup = information.manifest; //override with embedded beat manifest, if one exists
file::write({pathname, "manifest.bml"}, markup);
file::write({pathname, "program.rom"}, buffer.data() + 16, info.prgrom);
if(info.chrrom > 0) file::write({pathname, "character.rom"}, buffer.data() + 16 + info.prgrom, info.chrrom);
copyFamicomSaves(pathname);
return pathname;
}
string Ananke::openFamicom(vector<uint8_t> &buffer) {
return createFamicomHeuristic(buffer);
}

109
ananke/file-dialog.cpp Normal file
View File

@ -0,0 +1,109 @@
struct FileDialog : Window {
VerticalLayout layout;
HorizontalLayout pathLayout;
LineEdit pathEdit;
Button homeButton;
Button upButton;
ListView fileList;
HorizontalLayout controlLayout;
Widget spacer;
Button openButton;
string open() {
setModal();
setVisible();
fileList.setFocused();
filename = "";
dialogActive = true;
while(dialogActive) {
OS::processEvents();
if(Keyboard::pressed(Keyboard::Scancode::Escape)) onClose();
}
return filename;
}
void setPath(const string &path) {
pathname = string{path}.transform("\\", "/");
if(pathname.empty()) pathname = userpath();
if(pathname.endswith("/") == false) pathname.append("/");
pathEdit.setText(pathname);
fileList.reset();
filenameList.reset();
lstring folders = directory::ifolders(pathname);
for(auto &folder : folders) {
fileList.append(string{folder}.rtrim<1>("/"));
fileList.setImage(filenameList.size(), 0, {resource::folder, sizeof resource::folder});
filenameList.append({pathname, folder});
}
lstring files = directory::ifiles(pathname);
for(auto &file : files) {
fileList.append(file);
fileList.setImage(filenameList.size(), 0, {resource::file, sizeof resource::file});
filenameList.append({pathname, file});
}
fileList.setSelection(0);
fileList.setSelected();
fileList.setFocused();
}
FileDialog() {
setGeometry({64, 64, 480, 600});
setTitle("Load Image");
layout.setMargin(5);
homeButton.setImage({resource::home, sizeof resource::home});
upButton.setImage({resource::up, sizeof resource::up});
openButton.setText("Open");
append(layout);
layout.append(pathLayout, {~0, 0}, 5);
pathLayout.append(pathEdit, {~0, 0}, 5);
pathLayout.append(homeButton, {28, 28}, 5);
pathLayout.append(upButton, {28, 28});
layout.append(fileList, {~0, ~0}, 5);
layout.append(controlLayout, {~0, 0});
controlLayout.append(spacer, {~0, 0});
controlLayout.append(openButton, {80, 0});
pathEdit.onActivate = [&] {
string path = pathEdit.text();
setPath(path);
};
homeButton.onActivate = [&] {
setPath(userpath());
};
upButton.onActivate = [&] {
setPath(parentdir(pathname));
};
fileList.onActivate = openButton.onActivate = [&] {
if(fileList.selected() == false) return;
string name = filenameList(fileList.selection());
if(name.empty()) return;
if(name.endswith("/")) return setPath(name);
filename = name;
onClose();
};
onClose = [&] {
dialogActive = false;
setModal(false);
setVisible(false);
};
}
private:
bool dialogActive;
string pathname;
string filename;
lstring filenameList;
};

View File

@ -0,0 +1,36 @@
void Ananke::copyGameBoyAdvanceSaves(const string &pathname) {
if(!file::exists({pathname, "save.ram"})) {
if(file::exists({information.path, nall::basename(information.name), ".sav"})) {
file::copy({information.path, nall::basename(information.name), ".sav"}, {pathname, "save.ram"});
}
}
if(!file::exists({pathname, "rtc.ram"})) {
if(file::exists({information.path, nall::basename(information.name), ".rtc"})) {
file::copy({information.path, nall::basename(information.name), ".rtc"}, {pathname, "rtc.ram"});
}
}
}
string Ananke::createGameBoyAdvanceHeuristic(vector<uint8_t> &buffer) {
string pathname = {
userpath(), "Emulation/Game Boy Advance/",
nall::basename(information.name),
" (!).gba/"
};
directory::create(pathname);
GameBoyAdvanceCartridge info(buffer.data(), buffer.size());
string markup = info.markup;
if(!information.manifest.empty()) markup = information.manifest; //override with embedded beat manifest, if one exists
file::write({pathname, "manifest.bml"}, markup);
file::write({pathname, "program.rom"}, buffer);
copyGameBoyAdvanceSaves(pathname);
return pathname;
}
string Ananke::openGameBoyAdvance(vector<uint8_t> &buffer) {
return createGameBoyAdvanceHeuristic(buffer);
}

38
ananke/game-boy.cpp Normal file
View File

@ -0,0 +1,38 @@
void Ananke::copyGameBoySaves(const string &pathname) {
if(!file::exists({pathname, "save.ram"})) {
if(file::exists({information.path, nall::basename(information.name), ".sav"})) {
file::copy({information.path, nall::basename(information.name), ".sav"}, {pathname, "save.ram"});
}
}
if(!file::exists({pathname, "rtc.ram"})) {
if(file::exists({information.path, nall::basename(information.name), ".rtc"})) {
file::copy({information.path, nall::basename(information.name), ".rtc"}, {pathname, "rtc.ram"});
}
}
}
string Ananke::createGameBoyHeuristic(vector<uint8_t> &buffer) {
GameBoyCartridge info(buffer.data(), buffer.size());
string pathname = {
userpath(),
"Emulation/Game Boy/",
nall::basename(information.name),
" (!).", (info.info.cgb ? "gbc" : "gb"), "/"
};
directory::create(pathname);
string markup = info.markup;
if(!information.manifest.empty()) markup = information.manifest; //override with embedded beat manifest, if one exists
file::write({pathname, "manifest.bml"}, info.markup);
file::write({pathname, "program.rom"}, buffer);
copyGameBoySaves(pathname);
return pathname;
}
string Ananke::openGameBoy(vector<uint8_t> &buffer) {
return createGameBoyHeuristic(buffer);
}

View File

@ -21,9 +21,53 @@ struct directory {
static bool create(const string &pathname, unsigned permissions = 0755); //recursive static bool create(const string &pathname, unsigned permissions = 0755); //recursive
static bool remove(const string &pathname); //recursive static bool remove(const string &pathname); //recursive
static bool exists(const string &pathname); static bool exists(const string &pathname);
static lstring folders(const string &pathname, const string &pattern = "*");
static lstring files(const string &pathname, const string &pattern = "*"); static lstring folders(const string &pathname, const string &pattern = "*") {
static lstring contents(const string &pathname, const string &pattern = "*"); lstring folders = directory::ufolders(pathname, pattern);
folders.sort();
return folders;
}
static lstring files(const string &pathname, const string &pattern = "*") {
lstring files = directory::ufiles(pathname, pattern);
files.sort();
return files;
}
static lstring contents(const string &pathname, const string &pattern = "*") {
lstring folders = directory::ufolders(pathname); //pattern search of contents should only filter files
lstring files = directory::ufiles(pathname, pattern);
folders.sort();
files.sort();
for(auto &file : files) folders.append(file);
return folders;
}
static lstring ifolders(const string &pathname, const string &pattern = "*") {
lstring folders = ufolders(pathname, pattern);
folders.isort();
return folders;
}
static lstring ifiles(const string &pathname, const string &pattern = "*") {
lstring files = ufiles(pathname, pattern);
files.isort();
return files;
}
static lstring icontents(const string &pathname, const string &pattern = "*") {
lstring folders = directory::ufolders(pathname); //pattern search of contents should only filter files
lstring files = directory::ufiles(pathname, pattern);
folders.isort();
files.isort();
for(auto &file : files) folders.append(file);
return folders;
}
private:
//internal functions; these return unsorted lists
static lstring ufolders(const string &pathname, const string &pattern = "*");
static lstring ufiles(const string &pathname, const string &pattern = "*");
}; };
#if defined(PLATFORM_WINDOWS) #if defined(PLATFORM_WINDOWS)
@ -55,7 +99,7 @@ struct directory {
return (result & FILE_ATTRIBUTE_DIRECTORY); return (result & FILE_ATTRIBUTE_DIRECTORY);
} }
inline lstring directory::folders(const string &pathname, const string &pattern) { inline lstring directory::ufolders(const string &pathname, const string &pattern) {
lstring list; lstring list;
string path = pathname; string path = pathname;
path.transform("/", "\\"); path.transform("/", "\\");
@ -81,12 +125,11 @@ struct directory {
} }
FindClose(handle); FindClose(handle);
} }
if(list.size() > 0) list.sort();
for(auto &name : list) name.append("/"); //must append after sorting for(auto &name : list) name.append("/"); //must append after sorting
return list; return list;
} }
inline lstring directory::files(const string &pathname, const string &pattern) { inline lstring directory::ufiles(const string &pathname, const string &pattern) {
lstring list; lstring list;
string path = pathname; string path = pathname;
path.transform("/", "\\"); path.transform("/", "\\");
@ -108,16 +151,8 @@ struct directory {
} }
FindClose(handle); FindClose(handle);
} }
if(list.size() > 0) list.sort();
return list; return list;
} }
inline lstring directory::contents(const string &pathname, const string &pattern) {
lstring folders = directory::folders(pathname); //pattern search of contents() should only filter files
lstring files = directory::files(pathname, pattern);
for(auto &file : files) folders.append(file);
return folders;
}
#else #else
inline bool directory::create(const string &pathname, unsigned permissions) { inline bool directory::create(const string &pathname, unsigned permissions) {
string path; string path;
@ -146,7 +181,7 @@ struct directory {
return true; return true;
} }
inline lstring directory::folders(const string &pathname, const string &pattern) { inline lstring directory::ufolders(const string &pathname, const string &pattern) {
lstring list; lstring list;
DIR *dp; DIR *dp;
struct dirent *ep; struct dirent *ep;
@ -161,12 +196,11 @@ struct directory {
} }
closedir(dp); closedir(dp);
} }
if(list.size() > 0) list.sort();
for(auto &name : list) name.append("/"); //must append after sorting for(auto &name : list) name.append("/"); //must append after sorting
return list; return list;
} }
inline lstring directory::files(const string &pathname, const string &pattern) { inline lstring directory::ufiles(const string &pathname, const string &pattern) {
lstring list; lstring list;
DIR *dp; DIR *dp;
struct dirent *ep; struct dirent *ep;
@ -181,16 +215,8 @@ struct directory {
} }
closedir(dp); closedir(dp);
} }
if(list.size() > 0) list.sort();
return list; return list;
} }
inline lstring directory::contents(const string &pathname, const string &pattern) {
lstring folders = directory::folders(pathname); //pattern search of contents() should only filter files
lstring files = directory::files(pathname, pattern);
for(auto &file : files) folders.append(file);
return folders;
}
#endif #endif
} }

View File

@ -27,8 +27,6 @@ FamicomCartridge::FamicomCartridge(const uint8_t *data, unsigned size) {
if(data[2] != 'S') return; if(data[2] != 'S') return;
if(data[3] != 26) return; if(data[3] != 26) return;
markup.append("<?xml version='1.0' encoding='UTF-8'?>\n");
mapper = ((data[7] >> 4) << 4) | (data[6] >> 4); mapper = ((data[7] >> 4) << 4) | (data[6] >> 4);
mirror = ((data[6] & 0x08) >> 2) | (data[6] & 0x01); mirror = ((data[6] & 0x08) >> 2) | (data[6] & 0x01);
prgrom = data[4] * 0x4000; prgrom = data[4] * 0x4000;
@ -36,145 +34,138 @@ FamicomCartridge::FamicomCartridge(const uint8_t *data, unsigned size) {
prgram = 0u; prgram = 0u;
chrram = chrrom == 0u ? 8192u : 0u; chrram = chrrom == 0u ? 8192u : 0u;
markup.append("<cartridge sha256='", sha256(data, size), "'>\n"); markup.append("cartridge\n");
switch(mapper) { switch(mapper) {
default: default:
markup.append(" <board type='NES-NROM-256'/>\n"); markup.append(" board type=NES-NROM-256\n");
markup.append(" <mirror mode='", mirror == 0 ? "horizontal" : "vertical", "'/>\n"); markup.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
break; break;
case 1: case 1:
markup.append(" <board type='NES-SXROM'/>\n"); markup.append(" board type=NES-SXROM\n");
markup.append(" <chip type='MMC1B2'/>\n"); markup.append(" chip type=MMC1B2\n");
prgram = 8192; prgram = 8192;
break; break;
case 2: case 2:
markup.append(" <board type='NES-UOROM'/>\n"); markup.append(" board type=NES-UOROM\n");
markup.append(" <mirror mode='", mirror == 0 ? "horizontal" : "vertical", "'/>\n"); markup.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
break; break;
case 3: case 3:
markup.append(" <board type='NES-CNROM'/>\n"); markup.append(" board type=NES-CNROM\n");
markup.append(" <mirror mode='", mirror == 0 ? "horizontal" : "vertical", "'/>\n"); markup.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
break; break;
case 4: case 4:
//MMC3 //MMC3
markup.append(" <board type='NES-TLROM'/>\n"); markup.append(" board type=NES-TLROM\n");
markup.append(" <chip type='MMC3B'/>\n"); markup.append(" chip type=MMC3B\n");
prgram = 8192; prgram = 8192;
//MMC6 //MMC6
//markup.append(" <board type='NES-HKROM'/>\n"); //markup.append(" board type=NES-HKROM\n");
//markup.append(" <chip type='MMC6'/>\n"); //markup.append(" chip type=MMC6n");
//prgram = 1024; //prgram = 1024;
break; break;
case 5: case 5:
markup.append(" <board type='NES-ELROM'/>\n"); markup.append(" board type=NES-ELROM\n");
markup.append(" <chip type='MMC5'/>\n"); markup.append(" chip type=MMC5\n");
prgram = 65536; prgram = 65536;
break; break;
case 7: case 7:
markup.append(" <board type='NES-AOROM'/>\n"); markup.append(" board type=NES-AOROM\n");
break; break;
case 9: case 9:
markup.append(" <board type='NES-PNROM'/>\n"); markup.append(" board type=NES-PNROM\n");
markup.append(" <chip type='MMC2'/>\n"); markup.append(" chip type=MMC2\n");
prgram = 8192; prgram = 8192;
break; break;
case 10: case 10:
markup.append(" <board type='NES-FKROM'/>\n"); markup.append(" board type=NES-FKROM\n");
markup.append(" <chip type='MMC4'/>\n"); markup.append(" chip type=MMC4\n");
prgram = 8192; prgram = 8192;
break; break;
case 16: case 16:
markup.append(" <board type='BANDAI-FCG'/>\n"); markup.append(" board type=BANDAI-FCG\n");
markup.append(" <chip type='LZ93D50'/>\n"); markup.append(" chip type=LZ93D50\n");
break; break;
case 21: case 21:
case 23: case 23:
case 25: case 25:
//VRC4 //VRC4
markup.append(" <board type='KONAMI-VRC-4'/>\n"); markup.append(" board type=KONAMI-VRC-4\n");
markup.append(" <chip type='VRC4'>\n"); markup.append(" chip type=VRC4\n");
markup.append(" <pinout a0='1' a1='0'/>\n"); markup.append(" pinout a0=1 a1=0\n");
markup.append(" </chip>\n");
prgram = 8192; prgram = 8192;
break; break;
case 22: case 22:
//VRC2 //VRC2
markup.append(" <board type='KONAMI-VRC-2'/>\n"); markup.append(" board type=KONAMI-VRC-2\n");
markup.append(" <chip type='VRC2'>\n"); markup.append(" chip type=VRC2\n");
markup.append(" <pinout a0='0' a1='1'/>\n"); markup.append(" pinout a0=0 a1=1\n");
markup.append(" </chip>\n");
break; break;
case 24: case 24:
markup.append(" <board type='KONAMI-VRC-6'/>\n"); markup.append(" board type=KONAMI-VRC-6\n");
markup.append(" <chip type='VRC6'/>\n"); markup.append(" chip type=VRC6\n");
break; break;
case 26: case 26:
markup.append(" <board type='KONAMI-VRC-6'/>\n"); markup.append(" board type=KONAMI-VRC-6\n");
markup.append(" <chip type='VRC6'/>\n"); markup.append(" chip type=VRC6\n");
prgram = 8192; prgram = 8192;
break; break;
case 34: case 34:
markup.append(" <board type='NES-BNROM'/>\n"); markup.append(" board type=NES-BNROM\n");
markup.append(" <mirror mode='", mirror == 0 ? "horizontal" : "vertical", "'/>\n"); markup.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
break; break;
case 66: case 66:
markup.append(" <board type='NES-GNROM'/>\n"); markup.append(" board type=NES-GNROM\n");
markup.append(" <mirror mode='", mirror == 0 ? "horizontal" : "vertical", "'/>\n"); markup.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
break; break;
case 69: case 69:
markup.append(" <board type='SUNSOFT-5B'/>\n"); markup.append(" board type=SUNSOFT-5B\n");
markup.append(" <chip type='5B'/>\n"); markup.append(" chip type=5B\n");
prgram = 8192; prgram = 8192;
break; break;
case 73: case 73:
markup.append(" <board type='KONAMI-VRC-3'/>\n"); markup.append(" board type=KONAMI-VRC-3\n");
markup.append(" <chip type='VRC3'/>\n"); markup.append(" chip type=VRC3\n");
markup.append(" <mirror mode='", mirror == 0 ? "horizontal" : "vertical", "'/>\n"); markup.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
prgram = 8192; prgram = 8192;
break; break;
case 75: case 75:
markup.append(" <board type='KONAMI-VRC-1'/>\n"); markup.append(" board type=KONAMI-VRC-1\n");
markup.append(" <chip type='VRC1'/>\n"); markup.append(" chip type=VRC1\n");
break; break;
case 85: case 85:
markup.append(" <board type='KONAMI-VRC-7/'>\n"); markup.append(" board type=KONAMI-VRC-7\n");
markup.append(" <chip type='VRC7'/>\n"); markup.append(" chip type=VRC7\n");
prgram = 8192; prgram = 8192;
break; break;
} }
markup.append(" <prg>\n"); markup.append(" prg\n");
if(prgrom) markup.append(" <rom name='program.rom' size='0x", hex(prgrom), "'/>\n"); if(prgrom) markup.append(" rom name=program.rom size=0x", hex(prgrom), "\n");
if(prgram) markup.append(" <ram name='save.ram' size='0x", hex(prgram), "'/>\n"); if(prgram) markup.append(" ram name=save.ram size=0x", hex(prgram), "\n");
markup.append(" </prg>\n");
markup.append(" <chr>\n"); markup.append(" chr\n");
if(chrrom) markup.append(" <rom name='character.rom' size='0x", hex(chrrom), "'/>\n"); if(chrrom) markup.append(" rom name=character.rom size=0x", hex(chrrom), "\n");
if(chrram) markup.append(" <ram size='0x", hex(chrram), "'/>\n"); if(chrram) markup.append(" ram size=0x", hex(chrram), "\n");
markup.append(" </chr>\n");
markup.append("</cartridge>\n");
markup.transform("'", "\"");
} }
} }

View File

@ -46,21 +46,16 @@ GameBoyAdvanceCartridge::GameBoyAdvanceCartridge(const uint8_t *data, unsigned s
identifiers = list.concatenate(","); identifiers = list.concatenate(",");
markup = ""; markup = "";
markup.append("cartridge\n");
markup.append("<?xml version='1.0' encoding='UTF-8'?>\n"); markup.append(" rom name=program.rom size=0x", hex(size), "\n");
markup.append("<cartridge sha256='", sha256(data, size), "'>\n");
markup.append(" <rom name='program.rom' size='0x", hex(size), "'/>\n");
if(0); if(0);
else if(identifiers.beginswith("SRAM_V" )) markup.append(" <ram name='save.ram' type='SRAM' size='0x8000'/>\n"); else if(identifiers.beginswith("SRAM_V" )) markup.append(" ram name=save.ram type=SRAM size=0x8000\n");
else if(identifiers.beginswith("SRAM_F_V" )) markup.append(" <ram name='save.ram' type='FRAM' size='0x8000'/>\n"); else if(identifiers.beginswith("SRAM_F_V" )) markup.append(" ram name=save.ram type=FRAM size=0x8000\n");
else if(identifiers.beginswith("EEPROM_V" )) markup.append(" <ram name='save.ram' type='EEPROM' size='0x0'/>\n"); else if(identifiers.beginswith("EEPROM_V" )) markup.append(" ram name=save.ram type=EEPROM size=0x0\n");
else if(identifiers.beginswith("FLASH_V" )) markup.append(" <ram name='save.ram' type='FlashROM' size='0x10000'/>\n"); else if(identifiers.beginswith("FLASH_V" )) markup.append(" ram name=save.ram type=FlashROM size=0x10000\n");
else if(identifiers.beginswith("FLASH512_V")) markup.append(" <ram name='save.ram' type='FlashROM' size='0x10000'/>\n"); else if(identifiers.beginswith("FLASH512_V")) markup.append(" ram name=save.ram type=FlashROM size=0x10000\n");
else if(identifiers.beginswith("FLASH1M_V" )) markup.append(" <ram name='save.ram' type='FlashROM' size='0x20000'/>\n"); else if(identifiers.beginswith("FLASH1M_V" )) markup.append(" ram name=save.ram type=FlashROM size=0x20000\n");
if(identifiers.empty() == false) markup.append(" <!-- detected: ", identifiers, " -->\n"); //if(identifiers.empty() == false) markup.append(" #detected: ", identifiers, "\n");
markup.append("</cartridge>\n");
markup.transform("'", "\"");
} }
} }

View File

@ -108,13 +108,11 @@ GameBoyCartridge::GameBoyCartridge(uint8_t *romdata, unsigned romsize) {
if(info.mapper == "MBC2") info.ramsize = 512; //512 x 4-bit if(info.mapper == "MBC2") info.ramsize = 512; //512 x 4-bit
markup = "<?xml version='1.0' encoding='UTF-8'?>\n"; markup = "";
markup.append("<cartridge>\n"); markup.append("cartridge\n");
markup.append(" <board type='", info.mapper, "'/>\n"); markup.append(" board type=", info.mapper, "\n");
markup.append(" <rom name='program.rom' size='0x", hex(romsize), "'/>\n"); markup.append(" rom name=program.rom size=0x", hex(romsize), "\n");
if(info.ramsize > 0) markup.append(" <ram name='save.ram' size='0x", hex(info.ramsize), "'/>\n"); if(info.ramsize > 0) markup.append(" ram name=save.ram size=0x", hex(info.ramsize), "\n");
markup.append("</cartridge>\n");
markup.transform("'", "\"");
} }
} }

View File

@ -76,10 +76,11 @@ struct SuperFamicomCartridge {
DSP1HiROM, DSP1HiROM,
}; };
bool loaded; //is a base cartridge inserted? bool loaded; //is a base cartridge inserted?
unsigned crc32; //crc32 of all cartridges (base+slot(s)) unsigned crc32; //crc32 of all cartridges (base+slot(s))
unsigned rom_size; unsigned rom_size;
unsigned ram_size; unsigned ram_size;
bool firmware_appended; //true if firmware is appended to end of ROM data
Mode mode; Mode mode;
Type type; Type type;
@ -106,6 +107,8 @@ struct SuperFamicomCartridge {
}; };
SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size) { SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size) {
firmware_appended = false;
//skip copier header //skip copier header
if((size & 0x7fff) == 512) data += 512, size -= 512; if((size & 0x7fff) == 512) data += 512, size -= 512;
@ -122,35 +125,49 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
const char *range = (rom_size > 0x200000) || (ram_size > 32 * 1024) ? "0000-7fff" : "0000-ffff"; const char *range = (rom_size > 0x200000) || (ram_size > 32 * 1024) ? "0000-7fff" : "0000-ffff";
markup.append("cartridge region=", region == NTSC ? "NTSC" : "PAL", "\n"); markup.append("cartridge region=", region == NTSC ? "NTSC" : "PAL", "\n");
if(type == TypeSuperGameBoy1Bios || type == TypeSuperGameBoy2Bios) markup.append( if(type == TypeSuperGameBoy1Bios || type == TypeSuperGameBoy2Bios) {
" rom name=program.rom size=0x", hex(rom_size), "\n" markup.append(
" map id=rom address=00-7f,80-ff:8000-ffff\n" " rom name=program.rom size=0x", hex(rom_size), "\n"
" icd2 revision=1\n" " map id=rom address=00-7f,80-ff:8000-ffff\n"
" rom name=boot.rom size=0x100\n" " icd2 revision=1\n"
" map id=io address=00-3f,80-bf:6000-7fff\n" " rom name=boot.rom size=0x100\n"
); " map id=io address=00-3f,80-bf:6000-7fff\n"
);
if((rom_size & 0x7fff) == 0x100) {
firmware_appended = true;
rom_size -= 0x100;
}
}
else if(has_cx4) markup.append( else if(has_cx4) {
" hitachidsp model=HG51B169 frequency=20000000\n" markup.append(
" rom id=program name=program.rom size=0x", hex(rom_size), "\n" " hitachidsp model=HG51B169 frequency=20000000\n"
" rom id=data name=cx4.data.rom size=0xc00\n" " rom id=program name=program.rom size=0x", hex(rom_size), "\n"
" ram id=data size=0xc00\n" " rom id=data name=cx4.data.rom size=0xc00\n"
" map id=io address=00-3f,80-bf:6000-7fff\n" " ram id=data size=0xc00\n"
" map id=rom address=00-7f,80-ff:8000-ffff mask=0x8000\n" " map id=io address=00-3f,80-bf:6000-7fff\n"
" map id=ram address=70-77:0000-7fff\n" " map id=rom address=00-7f,80-ff:8000-ffff mask=0x8000\n"
); " map id=ram address=70-77:0000-7fff\n"
);
if((rom_size & 0x7fff) == 0xc00) {
firmware_appended = true;
rom_size -= 0xc00;
}
}
else if(has_spc7110) markup.append( else if(has_spc7110) {
" spc7110\n" markup.append(
" rom id=program name=program.rom size=0x100000\n" " spc7110\n"
" rom id=data name=data.rom size=0x", hex(rom_size - 0x100000), "\n" " rom id=program name=program.rom size=0x100000\n"
" ram name=save.ram size=0x", hex(ram_size), "\n" " rom id=data name=data.rom size=0x", hex(rom_size - 0x100000), "\n"
" map id=io address=00-3f,80-bf:4800-483f\n" " ram name=save.ram size=0x", hex(ram_size), "\n"
" map id=io address=50:0000-ffff\n" " map id=io address=00-3f,80-bf:4800-483f\n"
" map id=rom address=00-3f,80-bf:8000-ffff\n" " map id=io address=50:0000-ffff\n"
" map id=rom address=c0-ff:0000-ffff\n" " map id=rom address=00-3f,80-bf:8000-ffff\n"
" map id=ram address=00-3f,80-bf:6000-7fff mask=0xe000\n" " map id=rom address=c0-ff:0000-ffff\n"
); " map id=ram address=00-3f,80-bf:6000-7fff mask=0xe000\n"
);
}
else if(has_sdd1) { else if(has_sdd1) {
markup.append( markup.append(
@ -280,69 +297,83 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
); );
} }
else if(mapper == BSCLoROM) markup.append( else if(mapper == BSCLoROM) {
" rom name=program.rom size=0x", hex(rom_size), "\n" markup.append(
" ram name=save.ram size=0x", hex(ram_size), "\n" " rom name=program.rom size=0x", hex(rom_size), "\n"
" map id=rom address=00-1f:8000-ffff offset=0x000000 mask=0x8000\n" " ram name=save.ram size=0x", hex(ram_size), "\n"
" map id=rom address=20-3f:8000-ffff offset=0x100000 mask=0x8000\n" " map id=rom address=00-1f:8000-ffff offset=0x000000 mask=0x8000\n"
" map id=rom address=80-9f:8000-ffff offset=0x200000 mask=0x8000\n" " map id=rom address=20-3f:8000-ffff offset=0x100000 mask=0x8000\n"
" map id=rom address=a0-bf:8000-ffff offset=0x100000 mask=0x8000\n" " map id=rom address=80-9f:8000-ffff offset=0x200000 mask=0x8000\n"
" map id=ram address=70-7f,f0-ff:0000-7fff\n" " map id=rom address=a0-bf:8000-ffff offset=0x100000 mask=0x8000\n"
" bsxslot\n" " map id=ram address=70-7f,f0-ff:0000-7fff\n"
" map id=rom address=c0-ef:0000-ffff\n" " bsxslot\n"
); " map id=rom address=c0-ef:0000-ffff\n"
);
}
else if(mapper == BSCHiROM) markup.append( else if(mapper == BSCHiROM) {
" rom name=program.rom size=0x", hex(rom_size), "\n" markup.append(
" ram name=save.ram size=0x", hex(ram_size), "\n" " rom name=program.rom size=0x", hex(rom_size), "\n"
" map id=rom address=00-1f,80-9f:8000-ffff\n" " ram name=save.ram size=0x", hex(ram_size), "\n"
" map id=rom address=40-5f,c0-df:0000-ffff\n" " map id=rom address=00-1f,80-9f:8000-ffff\n"
" map id=ram address=20-3f,a0-bf:6000-7fff\n" " map id=rom address=40-5f,c0-df:0000-ffff\n"
" bsxslot\n" " map id=ram address=20-3f,a0-bf:6000-7fff\n"
" map id=rom address=20-3f,a0-bf:8000-ffff\n" " bsxslot\n"
" map id=rom address=60-7f,e0-ff:0000-ffff\n" " map id=rom address=20-3f,a0-bf:8000-ffff\n"
); " map id=rom address=60-7f,e0-ff:0000-ffff\n"
);
}
else if(mapper == BSXROM) markup.append( else if(mapper == BSXROM) {
" bsx\n" markup.append(
" rom name=program.rom size=0x", hex(rom_size), "\n" " bsx\n"
" ram id=save name=save.ram size=0x", hex(ram_size), "\n" " rom name=program.rom size=0x", hex(rom_size), "\n"
" ram id=download name=bsx.ram size=0x40000\n" " ram id=save name=save.ram size=0x", hex(ram_size), "\n"
" map id=io address=00-3f,80-bf:5000-5fff\n" " ram id=download name=bsx.ram size=0x40000\n"
" map id=rom address=00-3f,80-bf:8000-ffff\n" " map id=io address=00-3f,80-bf:5000-5fff\n"
" map id=rom address=40-7f,c0-ff:0000-ffff\n" " map id=rom address=00-3f,80-bf:8000-ffff\n"
" map id=ram address=20-3f:6000-7fff\n" " map id=rom address=40-7f,c0-ff:0000-ffff\n"
); " map id=ram address=20-3f:6000-7fff\n"
);
}
else if(mapper == STROM) markup.append( else if(mapper == STROM) {
" rom name=program.rom size=0x", hex(rom_size), "\n" markup.append(
" map id=rom address='00-1f,80-9f:8000-ffff mask=0x8000\n" " rom name=program.rom size=0x", hex(rom_size), "\n"
" sufamiturbo\n" " map id=rom address='00-1f,80-9f:8000-ffff mask=0x8000\n"
" slot id=A\n" " sufamiturbo\n"
" map id=rom address=20-3f,a0-bf:8000-ffff mask=0x8000\n" " slot id=A\n"
" map id=ram address=60-63,e0-e3:8000-ffff\n" " map id=rom address=20-3f,a0-bf:8000-ffff mask=0x8000\n"
" slot id=B\n" " map id=ram address=60-63,e0-e3:8000-ffff\n"
" map id=rom address=40-5f,c0-df:8000-ffff mask=0x8000\n" " slot id=B\n"
" map id=ram address=70-73,f0-f3:8000-ffff\n" " map id=rom address=40-5f,c0-df:8000-ffff mask=0x8000\n"
); " map id=ram address=70-73,f0-f3:8000-ffff\n"
);
}
if(has_spc7110rtc) markup.append( if(has_spc7110rtc) {
" epsonrtc\n" markup.append(
" ram name=rtc.ram size=0x10\n" " epsonrtc\n"
" map id=io address=00-3f,80-bf:4840-4842\n" " ram name=rtc.ram size=0x10\n"
); " map id=io address=00-3f,80-bf:4840-4842\n"
);
}
if(has_srtc) markup.append( if(has_srtc) {
" sharprtc\n" markup.append(
" ram name=rtc.ram size=0x10\n" " sharprtc\n"
" map id=io address=00-3f,80-bf:2800-2801\n" " ram name=rtc.ram size=0x10\n"
); " map id=io address=00-3f,80-bf:2800-2801\n"
);
}
if(has_obc1) markup.append( if(has_obc1) {
" obc1\n" markup.append(
" ram name=save.ram size=0x2000\n" " obc1\n"
" map id=io address=00-3f,80-bf:6000-7fff\n" " ram name=save.ram size=0x2000\n"
); " map id=io address=00-3f,80-bf:6000-7fff\n"
);
}
if(has_dsp1) { if(has_dsp1) {
markup.append( markup.append(
@ -360,57 +391,97 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
if(dsp1_mapper == DSP1HiROM) markup.append( if(dsp1_mapper == DSP1HiROM) markup.append(
" map id=io address=00-1f,80-9f:6000-7fff select=0x1000\n" " map id=io address=00-1f,80-9f:6000-7fff select=0x1000\n"
); );
if((size & 0x7fff) == 0x2000) {
firmware_appended = true;
rom_size -= 0x2000;
}
} }
if(has_dsp2) markup.append( if(has_dsp2) {
" necdsp model=uPD7725 frequency=8000000\n" markup.append(
" rom id=program name=dsp2.program.rom size=0x1800\n" " necdsp model=uPD7725 frequency=8000000\n"
" rom id=data name=dsp2.data.rom size=0x800\n" " rom id=program name=dsp2.program.rom size=0x1800\n"
" ram id=data size=0x200\n" " rom id=data name=dsp2.data.rom size=0x800\n"
" map id=io address=20-3f,a0-bf:8000-ffff select=0x4000\n" " ram id=data size=0x200\n"
); " map id=io address=20-3f,a0-bf:8000-ffff select=0x4000\n"
);
if((size & 0x7fff) == 0x2000) {
firmware_appended = true;
rom_size -= 0x2000;
}
}
if(has_dsp3) markup.append( if(has_dsp3) {
" necdsp model=uPD7725 frequency=8000000\n" markup.append(
" rom id=program name=dsp3.program.rom size=0x1800\n" " necdsp model=uPD7725 frequency=8000000\n"
" rom id=data name=dsp3.data.rom size=0x800\n" " rom id=program name=dsp3.program.rom size=0x1800\n"
" ram id=data size=0x200\n" " rom id=data name=dsp3.data.rom size=0x800\n"
" map id=io address=20-3f,a0-bf:8000-ffff select=0x4000\n" " ram id=data size=0x200\n"
); " map id=io address=20-3f,a0-bf:8000-ffff select=0x4000\n"
);
if((size & 0x7fff) == 0x2000) {
firmware_appended = true;
rom_size -= 0x2000;
}
}
if(has_dsp4) markup.append( if(has_dsp4) {
" necdsp model=uPD7725 frequency=8000000\n" markup.append(
" rom id=program name=dsp4.program.rom size=0x1800\n" " necdsp model=uPD7725 frequency=8000000\n"
" rom id=data name=dsp4.data.rom size=0x800\n" " rom id=program name=dsp4.program.rom size=0x1800\n"
" ram id=data size=0x200\n" " rom id=data name=dsp4.data.rom size=0x800\n"
" map address=30-3f,b0-bf:8000-ffff select=0x4000\n" " ram id=data size=0x200\n"
); " map address=30-3f,b0-bf:8000-ffff select=0x4000\n"
);
if((size & 0x7fff) == 0x2000) {
firmware_appended = true;
rom_size -= 0x2000;
}
}
if(has_st010) markup.append( if(has_st010) {
" necdsp model=uPD96050 frequency=11000000\n" markup.append(
" rom id=program name=st010.program.rom size=0xc000\n" " necdsp model=uPD96050 frequency=11000000\n"
" rom id=data name=st010.data.rom size=0x1000\n" " rom id=program name=st010.program.rom size=0xc000\n"
" ram id=data name=save.ram size=0x1000\n" " rom id=data name=st010.data.rom size=0x1000\n"
" map id=io address=60-67,e0-e7:0000-3fff select=0x0001\n" " ram id=data name=save.ram size=0x1000\n"
" map id=ram address=68-6f,e8-ef:0000-7fff\n" " map id=io address=60-67,e0-e7:0000-3fff select=0x0001\n"
); " map id=ram address=68-6f,e8-ef:0000-7fff\n"
);
if((size & 0xffff) == 0xd000) {
firmware_appended = true;
rom_size -= 0xd000;
}
}
if(has_st011) markup.append( if(has_st011) {
" necdsp model=uPD96050 frequency=15000000\n" markup.append(
" rom id=program name=st011.program.rom size=0xc000\n" " necdsp model=uPD96050 frequency=15000000\n"
" rom id=data name=st011.data.rom size=0x1000\n" " rom id=program name=st011.program.rom size=0xc000\n"
" ram id=data name=save.ram size=0x1000\n" " rom id=data name=st011.data.rom size=0x1000\n"
" map id=io address=60-67,e0-e7:0000-3fff select=0x0001\n" " ram id=data name=save.ram size=0x1000\n"
" map id=ram address=68-6f,e8-ef:0000-7fff\n" " map id=io address=60-67,e0-e7:0000-3fff select=0x0001\n"
); " map id=ram address=68-6f,e8-ef:0000-7fff\n"
);
if((size & 0xffff) == 0xd000) {
firmware_appended = true;
rom_size -= 0xd000;
}
}
if(has_st018) markup.append( if(has_st018) {
" armdsp frequency=21477272\n" markup.append(
" rom id=program name=st018.program.rom size=0x20000\n" " armdsp frequency=21477272\n"
" rom id=data name=st018.data.rom size=0x8000\n" " rom id=program name=st018.program.rom size=0x20000\n"
" ram name=save.ram size=0x4000\n" " rom id=data name=st018.data.rom size=0x8000\n"
" map id=io address=00-3f,80-bf:3800-38ff\n" " ram name=save.ram size=0x4000\n"
); " map id=io address=00-3f,80-bf:3800-38ff\n"
);
if((size & 0x3ffff) == 0x28000) {
firmware_appended = true;
rom_size -= 0x28000;
}
}
} }
void SuperFamicomCartridge::read_header(const uint8_t *data, unsigned size) { void SuperFamicomCartridge::read_header(const uint8_t *data, unsigned size) {
@ -464,6 +535,7 @@ void SuperFamicomCartridge::read_header(const uint8_t *data, unsigned size) {
ram_size = 1024 << (data[index + RamSize] & 7); ram_size = 1024 << (data[index + RamSize] & 7);
if(ram_size == 1024) ram_size = 0; //no RAM present if(ram_size == 1024) ram_size = 0; //no RAM present
if(rom_size == 0 && ram_size) ram_size = 0; //fix for Bazooka Blitzkrieg's malformed header (swapped ROM and RAM sizes)
//0, 1, 13 = NTSC; 2 - 12 = PAL //0, 1, 13 = NTSC; 2 - 12 = PAL
region = (regionid <= 1 || regionid >= 13) ? NTSC : PAL; region = (regionid <= 1 || regionid >= 13) ? NTSC : PAL;

View File

@ -119,6 +119,7 @@ namespace nall {
inline optional<unsigned> find(const char*) const; inline optional<unsigned> find(const char*) const;
inline string concatenate(const char*) const; inline string concatenate(const char*) const;
inline void append() {} inline void append() {}
inline void isort();
template<typename... Args> inline void append(const string&, Args&&...); template<typename... Args> inline void append(const string&, Args&&...);
template<unsigned Limit = 0> inline lstring& split(const char*, const char*); template<unsigned Limit = 0> inline lstring& split(const char*, const char*);

View File

@ -151,6 +151,12 @@ template<typename... Args> void lstring::append(const string &data, Args&&... ar
append(std::forward<Args>(args)...); append(std::forward<Args>(args)...);
} }
void lstring::isort() {
nall::sort(pool, objectsize, [](const string &x, const string &y) {
return istrcmp(x, y) < 0;
});
}
bool lstring::operator==(const lstring &source) const { bool lstring::operator==(const lstring &source) const {
if(this == &source) return true; if(this == &source) return true;
if(size() != source.size()) return false; if(size() != source.size()) return false;

BIN
ananke/resource/file.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 844 B

BIN
ananke/resource/folder.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
ananke/resource/home.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 B

View File

@ -0,0 +1,5 @@
resource name=resource
binary id=home name=home.png
binary id=up name=up.png
binary id=folder name=folder.png
binary id=file name=file.png

View File

@ -0,0 +1,119 @@
namespace resource {
const uint8_t home[606] = {
137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255,
97,0,0,0,6,98,75,71,68,0,0,0,0,0,0,249,67,187,127,0,0,0,9,112,72,89,115,0,0,13,215,0,
0,13,215,1,66,40,155,120,0,0,0,7,116,73,77,69,7,213,10,14,20,37,19,83,42,210,59,0,0,1,235,73,
68,65,84,56,203,149,147,191,107,83,81,20,128,191,123,251,222,75,211,64,242,36,160,85,135,100,81,123,19,104,85,172,
17,92,28,140,66,19,167,135,212,74,39,145,162,163,24,92,58,180,110,193,169,254,24,234,212,37,139,245,199,96,19,240,
15,240,63,16,121,91,92,196,90,219,240,98,81,137,33,121,215,33,246,217,151,80,33,103,186,92,206,247,221,115,14,231,
194,1,225,41,85,172,128,174,128,246,148,122,200,48,177,7,123,74,105,79,169,61,73,113,104,120,177,56,163,203,55,111,
252,87,34,250,225,154,235,110,20,148,98,253,220,89,182,39,78,113,228,240,56,39,188,38,83,107,107,212,92,151,130,82,
215,14,185,110,117,64,176,31,126,83,156,97,247,248,49,148,202,50,22,141,210,106,181,24,219,252,74,182,92,30,144,136,
126,184,122,251,22,157,100,146,116,42,77,42,149,2,64,107,104,183,219,236,214,235,156,44,149,66,18,177,31,126,247,160,
68,199,48,201,229,46,96,219,118,208,154,214,26,0,223,247,249,185,181,69,114,110,46,144,136,10,232,130,82,188,127,84,
198,107,54,57,63,157,35,30,143,35,132,8,9,124,223,15,206,134,16,140,230,243,212,92,23,3,184,3,172,78,157,62,
195,253,210,61,54,170,111,3,240,201,202,51,86,30,63,69,139,17,116,167,133,48,70,209,221,223,44,47,45,209,238,165,
204,202,121,120,190,48,153,33,17,79,0,160,212,4,153,140,34,155,205,244,94,20,146,145,244,149,222,196,83,121,144,22,
90,107,22,38,51,204,195,186,236,239,211,178,44,76,211,196,48,140,224,254,75,227,7,0,31,234,59,116,187,126,144,11,
48,32,144,82,34,165,196,146,159,1,232,96,241,241,83,3,128,111,222,47,58,34,18,90,36,99,96,179,254,14,207,231,
40,0,151,46,78,115,53,26,67,234,113,46,75,147,237,77,66,21,24,253,21,252,155,126,239,165,239,222,14,162,217,56,
112,245,3,65,36,18,193,182,109,18,137,4,2,137,16,16,139,197,112,28,103,0,178,44,43,252,23,174,207,58,175,0,
135,225,98,245,229,139,215,119,255,0,86,248,213,163,133,187,128,26,0,0,0,0,73,69,78,68,174,66,96,130,
};
const uint8_t up[652] = {
137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255,
97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,
101,0,119,119,119,46,105,110,107,115,99,97,112,101,46,111,114,103,155,238,60,26,0,0,2,30,73,68,65,84,56,141,
149,147,79,104,19,65,20,198,191,55,187,51,217,141,133,122,104,76,255,209,130,4,237,193,64,42,168,208,213,138,104,68,
98,69,45,20,114,107,74,201,73,144,98,22,193,171,199,82,145,160,23,15,69,79,30,165,66,241,226,77,42,94,68,80,
208,67,41,180,42,149,148,52,137,166,154,38,217,217,25,15,81,172,33,169,246,29,223,251,230,199,124,223,155,33,173,53,
218,213,201,155,124,30,0,150,102,189,233,118,26,214,110,224,184,60,221,223,21,73,246,117,29,76,58,46,79,239,9,224,
184,60,26,16,251,178,87,206,76,6,199,70,147,193,128,8,102,29,151,71,255,11,224,184,188,3,132,197,137,115,211,214,
150,151,199,150,183,137,248,200,37,11,132,69,199,229,29,255,4,16,225,209,232,112,162,167,55,52,72,159,75,31,240,177,
244,30,157,157,157,20,27,58,209,13,194,195,93,1,142,203,211,253,7,34,137,179,71,199,249,74,254,13,12,198,97,50,
142,87,107,11,136,13,29,23,161,253,61,137,230,60,216,142,195,81,193,237,108,42,225,218,235,229,101,104,242,32,132,137,
58,125,199,54,21,241,46,255,28,23,78,95,13,154,166,248,43,15,182,211,247,212,88,198,82,228,161,34,75,16,1,1,
30,224,40,203,117,8,219,64,65,174,162,168,86,113,254,212,69,139,216,159,60,216,111,223,241,99,227,221,135,250,98,148,
175,172,193,228,6,56,55,80,81,5,84,141,175,16,54,131,176,25,150,191,189,64,184,55,68,71,14,15,135,137,53,242,
160,145,140,153,30,232,142,100,111,76,220,177,5,15,64,65,194,135,135,215,185,5,188,45,60,131,100,21,16,35,36,6,
50,208,90,67,41,160,94,175,225,241,211,249,74,177,180,57,99,18,67,234,83,110,197,158,185,119,185,225,137,163,122,247,
250,19,171,44,115,240,141,109,112,193,192,76,130,193,9,115,15,110,87,101,77,91,191,236,7,137,33,101,46,205,122,78,
211,38,180,214,10,165,250,23,48,131,96,112,6,30,104,64,100,77,91,47,231,60,218,245,29,0,128,210,62,126,212,139,
141,43,251,26,178,174,160,85,235,63,99,182,106,250,74,162,90,219,134,50,53,160,21,124,73,240,189,61,0,164,47,17,
31,188,6,98,0,49,2,17,246,0,32,108,220,186,63,25,110,37,38,194,70,115,239,39,48,247,197,219,182,208,154,34,
0,0,0,0,73,69,78,68,174,66,96,130,
};
const uint8_t folder[1176] = {
137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,32,0,0,0,32,8,6,0,0,0,115,122,122,
244,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,9,112,72,89,115,0,0,13,215,0,0,13,
215,1,66,40,155,120,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,119,119,119,46,105,110,107,115,99,
97,112,101,46,111,114,103,155,238,60,26,0,0,4,21,73,68,65,84,88,133,237,151,61,111,28,69,24,199,127,51,187,
119,123,175,246,57,145,48,9,5,86,148,194,31,0,9,5,33,83,110,149,130,26,137,2,90,58,62,64,36,62,64,74,
132,68,133,104,161,67,72,167,64,23,201,138,2,138,210,69,194,198,196,40,22,198,247,186,119,222,151,153,157,25,138,123,
201,58,119,142,19,114,82,40,248,75,143,118,118,118,247,121,126,243,60,51,179,187,34,12,67,94,167,228,107,141,254,95,
0,240,1,110,220,184,225,43,165,126,54,198,188,119,209,3,66,136,220,90,251,249,195,135,15,191,92,25,64,154,166,91,
149,74,229,157,155,55,111,250,73,146,224,156,3,192,90,11,48,63,159,182,253,59,119,238,220,222,222,222,254,254,209,163,
71,199,43,1,80,74,101,213,106,213,29,29,29,209,233,116,112,206,45,53,0,33,4,155,155,155,249,193,193,193,71,192,
237,149,0,104,173,211,44,203,196,165,75,27,24,99,176,214,158,9,92,204,132,16,130,106,181,90,63,60,60,252,98,123,
123,251,214,172,127,153,156,115,218,90,251,241,222,222,222,143,207,5,0,178,44,203,188,78,167,75,167,211,153,3,204,142,
179,32,197,64,91,91,91,245,70,163,65,179,217,68,8,129,16,2,0,41,229,188,29,69,17,247,238,221,187,5,60,31,
224,242,229,203,105,191,223,247,54,54,90,104,173,23,0,150,149,98,166,56,142,1,230,16,69,139,227,24,99,76,237,188,
224,115,128,221,221,93,117,237,218,53,217,235,245,230,25,0,150,130,204,178,81,212,108,196,197,224,82,202,25,64,229,66,
0,0,99,140,109,54,215,100,154,102,220,63,180,220,221,63,27,228,188,58,63,171,25,204,228,153,22,206,93,185,206,219,
31,232,226,61,158,39,190,93,255,253,155,79,206,0,56,231,116,183,219,245,187,221,46,143,59,13,62,253,240,93,174,191,
181,81,112,54,61,62,47,250,18,200,105,207,60,206,147,206,152,175,190,187,255,254,236,188,152,1,221,104,212,171,90,107,
212,31,146,102,181,204,254,223,99,162,56,159,140,108,233,104,207,35,17,11,77,1,52,42,62,42,211,8,65,103,118,121,
190,21,27,99,116,191,63,160,219,237,18,103,150,122,181,132,53,147,27,228,212,193,179,134,59,207,220,83,179,19,179,214,
145,100,134,52,203,193,137,249,6,86,44,65,86,169,4,180,90,45,50,35,168,5,37,172,83,120,114,53,175,139,113,154,
83,111,250,140,134,57,214,186,39,11,0,121,158,171,40,26,209,239,15,208,230,13,170,129,143,115,14,79,158,155,231,23,
147,131,81,170,209,185,37,240,37,113,170,173,49,249,209,2,128,49,38,43,151,75,84,155,27,172,213,202,56,64,10,177,
188,248,47,40,227,28,163,84,147,91,135,231,9,130,178,199,105,146,41,33,196,201,2,128,181,54,27,141,198,28,15,20,
235,245,75,232,220,190,210,232,51,109,137,51,3,78,224,79,253,148,61,201,232,84,229,130,167,147,176,152,129,212,247,125,
188,32,160,73,153,76,217,11,131,76,230,152,195,186,201,62,97,236,196,84,110,151,173,72,156,131,193,40,181,185,115,139,
0,214,218,100,60,30,211,25,248,84,90,101,162,68,147,233,233,75,8,200,141,69,27,135,206,45,185,153,110,203,47,153,
149,68,25,134,227,196,19,210,91,90,130,84,8,129,12,26,148,74,62,163,68,19,37,154,84,25,148,182,47,29,108,153,
226,44,231,52,209,62,231,148,32,142,227,83,122,81,133,74,13,30,159,196,12,99,189,212,209,191,145,0,134,177,66,25,
83,250,245,234,94,47,124,252,12,128,181,54,6,129,245,107,100,185,37,138,53,74,95,60,15,94,84,82,10,78,134,9,
82,200,56,220,221,157,59,62,51,7,146,36,33,74,12,87,175,4,84,3,143,160,188,186,111,86,41,4,105,170,144,82,
12,139,253,197,18,36,0,154,18,235,85,143,122,105,21,85,127,42,231,28,253,36,65,88,59,88,0,104,183,219,98,103,
103,199,68,177,98,112,234,248,243,100,136,236,190,226,14,184,68,199,199,67,155,36,195,7,187,237,118,45,12,195,120,14,
0,120,81,20,253,244,203,161,248,76,173,227,255,182,255,202,31,187,103,228,192,2,88,157,30,28,63,248,225,235,226,53,
49,251,53,107,183,219,205,96,109,237,205,90,208,218,116,56,41,133,92,201,18,200,141,49,42,75,107,185,16,121,62,58,
233,1,127,133,97,216,91,0,152,66,72,32,96,146,153,124,21,0,83,5,64,10,168,48,12,207,44,45,241,255,207,233,
235,6,248,7,188,50,165,151,203,8,55,43,0,0,0,0,73,69,78,68,174,66,96,130,
};
const uint8_t file[844] = {
137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,32,0,0,0,32,8,6,0,0,0,115,122,122,
244,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,3,3,73,68,65,84,88,133,229,151,79,110,212,
48,24,197,127,182,227,56,81,39,116,36,132,0,169,167,226,2,101,209,93,239,192,150,37,171,46,43,245,4,92,164,183,
40,82,89,21,36,134,84,76,18,59,44,90,91,142,243,103,50,21,59,62,201,138,227,120,236,247,189,247,252,37,3,255,
123,136,116,224,234,234,234,67,150,101,55,64,165,148,66,74,137,115,14,107,109,104,93,215,133,107,220,95,26,3,118,93,
215,125,188,185,185,249,26,239,151,141,16,9,113,125,113,113,81,61,247,195,120,223,247,131,121,241,253,202,126,117,121,121,
121,13,44,3,176,214,110,1,110,111,111,17,66,32,165,12,87,41,37,74,41,148,82,8,33,80,74,177,221,110,209,90,
15,158,167,125,33,4,251,253,158,166,105,182,233,126,50,29,232,251,30,33,68,104,64,88,208,55,207,78,215,117,24,99,
70,191,247,109,77,140,24,112,206,133,13,98,6,210,38,165,164,40,138,48,127,42,60,16,159,200,20,168,17,3,206,185,
17,11,177,4,49,40,231,28,77,211,28,204,114,137,141,17,0,107,109,232,207,177,224,159,41,165,208,90,31,100,97,9,
200,36,3,233,230,233,189,181,150,60,207,41,203,146,186,174,233,186,46,204,91,202,124,21,0,207,192,156,9,1,140,49,
20,69,65,93,215,100,89,70,158,231,3,173,231,50,127,17,128,88,123,127,239,105,55,198,96,140,161,109,219,85,174,95,
13,96,202,132,41,35,62,218,182,5,240,213,110,113,211,163,25,72,179,23,66,208,52,13,90,235,80,92,252,243,199,199,
199,229,244,97,210,172,7,37,136,93,47,165,164,170,42,178,44,67,8,193,201,201,73,232,151,101,57,152,63,197,194,139,
37,136,77,168,181,198,90,27,42,97,215,117,97,222,210,113,92,205,128,215,50,205,222,103,16,75,226,156,11,12,120,64,
62,203,41,38,142,146,32,213,190,239,123,172,181,225,69,228,105,143,193,214,117,141,115,110,86,134,163,0,196,11,11,33,
200,178,140,170,170,6,115,235,186,14,114,120,79,40,165,70,155,28,205,64,74,181,7,32,165,28,248,195,24,67,158,231,
1,172,82,106,117,89,158,5,144,158,231,212,7,113,40,165,6,12,120,169,210,170,184,20,171,142,161,47,54,177,254,254,
236,123,205,227,58,177,219,237,86,3,152,250,34,26,80,37,132,96,179,217,80,150,229,200,96,155,205,6,173,245,96,190,
49,38,48,177,6,196,162,9,189,15,178,44,27,140,123,96,109,219,142,36,136,95,90,107,98,214,3,177,9,211,240,99,
190,8,77,197,161,162,52,11,32,149,96,238,37,3,79,18,164,0,60,232,135,135,135,17,107,171,1,132,135,82,6,157,
227,240,0,119,187,221,8,160,63,5,167,167,167,65,138,163,62,201,226,5,189,235,167,88,232,251,30,173,245,36,56,95,
71,252,247,229,82,164,167,160,146,82,254,234,251,254,213,217,217,89,24,156,211,185,40,138,197,197,211,242,155,231,249,14,
120,7,252,4,246,41,128,10,120,115,127,127,255,249,252,252,252,19,80,46,174,190,50,242,60,167,105,26,132,16,127,238,
238,238,190,0,239,1,5,124,7,92,156,90,14,188,5,94,3,91,192,60,79,252,23,241,135,167,100,107,224,7,240,13,
248,13,19,127,78,159,55,46,158,1,173,43,103,135,195,1,45,79,180,239,129,96,140,191,182,58,238,12,241,249,173,246,
0,0,0,0,73,69,78,68,174,66,96,130,
};
};

View File

@ -0,0 +1,6 @@
namespace resource {
extern const uint8_t home[606];
extern const uint8_t up[652];
extern const uint8_t folder[1176];
extern const uint8_t file[844];
};

BIN
ananke/resource/up.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 652 B

View File

@ -1,3 +1,17 @@
void Ananke::copySuperFamicomSaves(const string &pathname) {
if(!file::exists({pathname, "save.ram"})) {
if(file::exists({information.path, nall::basename(information.name), ".srm"})) {
file::copy({information.path, nall::basename(information.name), ".srm"}, {pathname, "save.ram"});
}
}
if(!file::exists({pathname, "rtc.ram"})) {
if(file::exists({information.path, nall::basename(information.name), ".rtc"})) {
file::copy({information.path, nall::basename(information.name), ".rtc"}, {pathname, "rtc.ram"});
}
}
}
string Ananke::createSuperFamicomDatabase(vector<uint8_t> &buffer, Markup::Node &document, const string &manifest) { string Ananke::createSuperFamicomDatabase(vector<uint8_t> &buffer, Markup::Node &document, const string &manifest) {
string pathname = { string pathname = {
userpath(), "Emulation/Super Famicom/", userpath(), "Emulation/Super Famicom/",
@ -8,7 +22,7 @@ string Ananke::createSuperFamicomDatabase(vector<uint8_t> &buffer, Markup::Node
}; };
directory::create(pathname); directory::create(pathname);
//strip "release" root node from database entry //strip "release" root node from database entry (since a single game manifest isn't part of a database)
string markup = manifest; string markup = manifest;
markup.replace("\n ", "\n"); markup.replace("\n ", "\n");
markup.replace("information", "\ninformation"); markup.replace("information", "\ninformation");
@ -25,6 +39,7 @@ string Ananke::createSuperFamicomDatabase(vector<uint8_t> &buffer, Markup::Node
offset += size; offset += size;
} }
copySuperFamicomSaves(pathname);
return pathname; return pathname;
} }
@ -32,7 +47,7 @@ string Ananke::createSuperFamicomHeuristic(vector<uint8_t> &buffer) {
string pathname = { string pathname = {
userpath(), "Emulation/Super Famicom/", userpath(), "Emulation/Super Famicom/",
nall::basename(information.name), nall::basename(information.name),
" (unverified).sfc/" " (!).sfc/"
}; };
directory::create(pathname); directory::create(pathname);
@ -41,17 +56,36 @@ string Ananke::createSuperFamicomHeuristic(vector<uint8_t> &buffer) {
SuperFamicomCartridge info(buffer.data(), buffer.size()); SuperFamicomCartridge info(buffer.data(), buffer.size());
string markup = info.markup; string markup = info.markup;
if(!information.manifest.empty()) markup = information.manifest; //override with embedded beat manifest, if one exists if(!information.manifest.empty()) markup = information.manifest; //override with embedded beat manifest, if one exists
information.manifest = markup; //save for use with firmware routine below
file::write({pathname, "manifest.bml"}, markup); file::write({pathname, "manifest.bml"}, markup);
if(!markup.position("spc7110")) { if(!markup.position("spc7110")) {
file::write({pathname, "program.rom"}, buffer); file::write({pathname, "program.rom"}, buffer.data(), info.rom_size);
} else { } else {
file::write({pathname, "program.rom"}, buffer.data(), 0x100000); file::write({pathname, "program.rom"}, buffer.data(), 0x100000);
file::write({pathname, "data.rom"}, buffer.data() + 0x100000, buffer.size() - 0x100000); file::write({pathname, "data.rom"}, buffer.data() + 0x100000, info.rom_size - 0x100000);
} }
auto copyFirmware = [&](const string &name, unsigned programSize, unsigned dataSize) { createSuperFamicomHeuristicFirmware(buffer, pathname, info.firmware_appended);
copySuperFamicomSaves(pathname);
return pathname;
}
void Ananke::createSuperFamicomHeuristicFirmware(vector<uint8_t> &buffer, const string &pathname, bool firmware_appended) {
auto copyFirmwareInternal = [&](const string &name, unsigned programSize, unsigned dataSize) {
//firmware appended directly onto .sfc file
unsigned programOffset = buffer.size() - programSize - dataSize;
unsigned dataOffset = buffer.size() - dataSize;
string basename = nall::basename(name);
if(programSize) file::write({pathname, basename, ".program.rom"}, buffer.data() + programOffset, programSize);
if(dataSize) file::write({pathname, basename, ".data.rom"}, buffer.data() + dataOffset, dataSize);
};
auto copyFirmwareExternal = [&](const string &name, unsigned programSize, unsigned dataSize) {
//firmware stored in external file
auto buffer = file::read({information.path, name}); //try and read from the containing directory auto buffer = file::read({information.path, name}); //try and read from the containing directory
if(buffer.size() == 0) buffer = extractFile(name); //try and read from the containing archive, if one exists if(buffer.size() == 0) buffer = extractFile(name); //try and read from the containing archive, if one exists
if(buffer.size() == 0) { if(buffer.size() == 0) {
@ -67,6 +101,12 @@ string Ananke::createSuperFamicomHeuristic(vector<uint8_t> &buffer) {
if(dataSize) file::write({pathname, basename, ".data.rom"}, buffer.data() + programSize, dataSize); if(dataSize) file::write({pathname, basename, ".data.rom"}, buffer.data() + programSize, dataSize);
}; };
auto copyFirmware = [&](const string &name, unsigned programSize, unsigned dataSize) {
if(firmware_appended == 1) copyFirmwareInternal(name, programSize, dataSize);
if(firmware_appended == 0) copyFirmwareExternal(name, programSize, dataSize);
};
string markup = information.manifest;
if(markup.position("dsp1.program.rom" )) copyFirmware("dsp1.rom", 0x001800, 0x000800); if(markup.position("dsp1.program.rom" )) copyFirmware("dsp1.rom", 0x001800, 0x000800);
if(markup.position("dsp1b.program.rom")) copyFirmware("dsp1b.rom", 0x001800, 0x000800); if(markup.position("dsp1b.program.rom")) copyFirmware("dsp1b.rom", 0x001800, 0x000800);
if(markup.position("dsp2.program.rom" )) copyFirmware("dsp2.rom", 0x001800, 0x000800); if(markup.position("dsp2.program.rom" )) copyFirmware("dsp2.rom", 0x001800, 0x000800);
@ -76,14 +116,13 @@ string Ananke::createSuperFamicomHeuristic(vector<uint8_t> &buffer) {
if(markup.position("st011.program.rom")) copyFirmware("st011.rom", 0x00c000, 0x001000); if(markup.position("st011.program.rom")) copyFirmware("st011.rom", 0x00c000, 0x001000);
if(markup.position("st018.program.rom")) copyFirmware("st018.rom", 0x020000, 0x008000); if(markup.position("st018.program.rom")) copyFirmware("st018.rom", 0x020000, 0x008000);
if(markup.position("cx4.data.rom" )) copyFirmware("cx4.rom", 0x000000, 0x000c00); if(markup.position("cx4.data.rom" )) copyFirmware("cx4.rom", 0x000000, 0x000c00);
return pathname;
} }
string Ananke::openSuperFamicom(vector<uint8_t> &buffer) { string Ananke::openSuperFamicom(vector<uint8_t> &buffer) {
string sha256 = nall::sha256(buffer.data(), buffer.size()); string sha256 = nall::sha256(buffer.data(), buffer.size());
string databaseText = string::read({configpath(), "ananke/database/Super Famicom.bml"}).rtrim("\n"); string databaseText = string::read({configpath(), "ananke/database/Super Famicom.bml"}).rtrim("\n");
if(databaseText.empty()) databaseText = string{Database::SuperFamicom}.strip();
lstring databaseItem = databaseText.split("\n\n"); lstring databaseItem = databaseText.split("\n\n");
for(auto &item : databaseItem) { for(auto &item : databaseItem) {