mirror of https://github.com/bsnes-emu/bsnes.git
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:
parent
019fc1a2c6
commit
85f2e9a6d4
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
@ -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);
|
||||||
|
}
|
|
@ -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;
|
||||||
|
};
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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("'", "\"");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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("'", "\"");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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("'", "\"");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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*);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 844 B |
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 606 B |
|
@ -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
|
|
@ -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,
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
|
@ -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];
|
||||||
|
};
|
Binary file not shown.
After Width: | Height: | Size: 652 B |
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue