Update to higan v092r01, ananke v02r01 and purify v03r01 releases.

byuu says:

higan changelog:
- compiler is set to g++-4.7, subst(cc,++) rule is gone, C files compile
  with $(compiler) -x c
- make throws an error when you specify an invalid profile or compile on
  an unsupported platform (instead of hanging forever)
- added unverified.png to resources (causes too big of a speed hit to
  actually check for folder/unverified file ... so disabled for now)
- fixed default browser paths for Game Boy, Sufami Turbo and BS-X
  Satellaview (have to delete paths.cfg to see this)
- browser home button seeks to configpath()/higan/library.cfg
- settings->driver is now settings->advanced, and it adds game library
  path setting and profile information
- emulation cores now load manifest files internally, manifest.bml is
  not required for a game folder to be recognized by higan as such
- BS-X Satellaview and Sufami Turbo slot cartridge handling moved out of
  sfc/chip and into sfc/slot
- Video::StartFullScreen only sets fullscreen when a game is specified
  on the command-line

purify and ananke changelog:
- library output path shown in purify window
- added button to change library path
- squelch firmware warning windows to prevent multi-threading crash, but
  only via purify (they show up in higan still)
This commit is contained in:
Tim Allen 2013-01-21 23:27:15 +11:00
parent 65c4011bec
commit bbc33fe05f
90 changed files with 962 additions and 367 deletions

View File

@ -17,6 +17,9 @@ namespace Database {
struct Ananke { struct Ananke {
#include "configuration.cpp" #include "configuration.cpp"
string libraryPath;
Ananke();
struct Information { struct Information {
string path; //path to selected file string path; //path to selected file
@ -89,6 +92,12 @@ struct Ananke {
FileDialog *fileDialog = nullptr; FileDialog *fileDialog = nullptr;
Ananke::Ananke() {
libraryPath = string::read({configpath(), "higan/library.cfg"}).strip();
if(libraryPath.empty()) libraryPath = {userpath(), "Emulation/"};
if(libraryPath.endswith("/") == false) libraryPath.append("/");
}
bool Ananke::supported(const string &filename) { bool Ananke::supported(const string &filename) {
string extension = nall::extension(filename); string extension = nall::extension(filename);

View File

@ -1,6 +1,6 @@
string Ananke::createBsxSatellaviewDatabase(vector<uint8_t> &buffer, Markup::Node &document, const string &manifest) { string Ananke::createBsxSatellaviewDatabase(vector<uint8_t> &buffer, Markup::Node &document, const string &manifest) {
string pathname = { string pathname = {
userpath(), "Emulation/BS-X Satellaview/", libraryPath, "BS-X Satellaview/",
document["release/information/name"].text(), document["release/information/name"].text(),
" (", document["release/information/region"].text(), ")", " (", document["release/information/region"].text(), ")",
" (", document["release/information/revision"].text(), ")", " (", document["release/information/revision"].text(), ")",
@ -22,11 +22,12 @@ string Ananke::createBsxSatellaviewDatabase(vector<uint8_t> &buffer, Markup::Nod
string Ananke::createBsxSatellaviewHeuristic(vector<uint8_t> &buffer) { string Ananke::createBsxSatellaviewHeuristic(vector<uint8_t> &buffer) {
string pathname = { string pathname = {
userpath(), "Emulation/BS-X Satellaview/", libraryPath, "BS-X Satellaview/",
nall::basename(information.name), nall::basename(information.name),
" (!).bs/" ".bs/"
}; };
directory::create(pathname); directory::create(pathname);
file::create({pathname, "unverified"});
file::write({pathname, "manifest.bml"}, { file::write({pathname, "manifest.bml"}, {
"cartridge\n" "cartridge\n"

View File

@ -8,11 +8,12 @@ void Ananke::copyFamicomSaves(const string &pathname) {
string Ananke::createFamicomHeuristic(vector<uint8_t> &buffer) { string Ananke::createFamicomHeuristic(vector<uint8_t> &buffer) {
string pathname = { string pathname = {
userpath(), "Emulation/Famicom/", libraryPath, "Famicom/",
nall::basename(information.name), nall::basename(information.name),
" (!).fc/" ".fc/"
}; };
directory::create(pathname); directory::create(pathname);
file::create({pathname, "unverified"});
FamicomCartridge info(buffer.data(), buffer.size()); FamicomCartridge info(buffer.data(), buffer.size());
string markup = info.markup(); string markup = info.markup();

View File

@ -14,11 +14,12 @@ void Ananke::copyGameBoyAdvanceSaves(const string &pathname) {
string Ananke::createGameBoyAdvanceHeuristic(vector<uint8_t> &buffer) { string Ananke::createGameBoyAdvanceHeuristic(vector<uint8_t> &buffer) {
string pathname = { string pathname = {
userpath(), "Emulation/Game Boy Advance/", libraryPath, "Game Boy Advance/",
nall::basename(information.name), nall::basename(information.name),
" (!).gba/" ".gba/"
}; };
directory::create(pathname); directory::create(pathname);
file::create({pathname, "unverified"});
GameBoyAdvanceCartridge info(buffer.data(), buffer.size()); GameBoyAdvanceCartridge info(buffer.data(), buffer.size());
string markup = info.markup; string markup = info.markup;

View File

@ -16,12 +16,12 @@ string Ananke::createGameBoyHeuristic(vector<uint8_t> &buffer) {
GameBoyCartridge info(buffer.data(), buffer.size()); GameBoyCartridge info(buffer.data(), buffer.size());
string pathname = { string pathname = {
userpath(), libraryPath, "Game Boy", (info.info.cgb ? " Color" : ""), "/",
"Emulation/Game Boy", (info.info.cgb ? " Color" : ""), "/",
nall::basename(information.name), nall::basename(information.name),
" (!).", (info.info.cgb ? "gbc" : "gb"), "/" ".", (info.info.cgb ? "gbc" : "gb"), "/"
}; };
directory::create(pathname); directory::create(pathname);
file::create({pathname, "unverified"});
string markup = info.markup; string markup = info.markup;
markup.append("\ninformation\n title: ", nall::basename(information.name), "\n"); markup.append("\ninformation\n title: ", nall::basename(information.name), "\n");

View File

@ -36,16 +36,16 @@ endif
ifeq ($(compiler),) ifeq ($(compiler),)
ifeq ($(platform),win) ifeq ($(platform),win)
compiler := gcc compiler := g++
else ifeq ($(platform),osx) else ifeq ($(platform),osx)
compiler := gcc-mp-4.7 compiler := g++-mp-4.7
else else
compiler := gcc-4.7 compiler := g++-4.7
endif endif
endif endif
c := $(compiler) -std=gnu99 c := $(compiler) -x c -std=gnu99
cpp := $(subst cc,++,$(compiler)) -std=gnu++11 cpp := $(compiler) -std=gnu++11
ifeq ($(arch),x86) ifeq ($(arch),x86)
c := $(c) -m32 c := $(c) -m32

View File

@ -98,6 +98,14 @@ namespace nall {
return true; return true;
} }
static bool create(const string &filename) {
//create an empty file (will replace existing files)
file fp;
if(fp.open(filename, mode::write) == false) return false;
fp.close();
return true;
}
static string sha256(const string &filename) { static string sha256(const string &filename) {
auto buffer = read(filename); auto buffer = read(filename);
return nall::sha256(buffer.data(), buffer.size()); return nall::sha256(buffer.data(), buffer.size());

View File

@ -48,6 +48,15 @@ struct stream {
while(length--) *data++ = read(); while(length--) *data++ = read();
} }
string text() const {
string buffer;
buffer.resize(size() + 1);
buffer[size()] = 0;
seek(0);
read((uint8_t*)buffer(), size());
return buffer;
}
void writel(uintmax_t data, unsigned length = 1) const { void writel(uintmax_t data, unsigned length = 1) const {
while(length--) { while(length--) {
write(data); write(data);

View File

@ -23,6 +23,7 @@ namespace nall {
struct string { struct string {
inline static string read(const string &filename); inline static string read(const string &filename);
inline static string date(); inline static string date();
inline static string time(); inline static string time();
inline static string datetime(); inline static string datetime();

View File

@ -33,11 +33,13 @@ string realpath(const string &name) {
return result; return result;
} }
// /home/username/
// c:/users/username/
string userpath() { string userpath() {
string result; string result;
#ifdef _WIN32 #ifdef _WIN32
wchar_t path[PATH_MAX] = L""; wchar_t path[PATH_MAX] = L"";
SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, path); SHGetFolderPathW(0, CSIDL_PROFILE | CSIDL_FLAG_CREATE, 0, 0, path);
result = (const char*)utf8_t(path); result = (const char*)utf8_t(path);
result.transform("\\", "/"); result.transform("\\", "/");
#else #else
@ -51,20 +53,30 @@ string userpath() {
return result; return result;
} }
// /home/username/.config/
// c:/users/username/appdata/roaming/
string configpath() { string configpath() {
string result;
#ifdef _WIN32 #ifdef _WIN32
return userpath(); wchar_t path[PATH_MAX] = L"";
SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, path);
result = (const char*)utf8_t(path);
result.transform("\\", "/");
#else #else
return {userpath(), ".config/"}; result = {userpath(), ".config/"};
#endif #endif
if(result.empty()) result = ".";
if(result.endswith("/") == false) result.append("/");
return result;
} }
string temppath() { string temppath() {
#ifdef _WIN32 #ifdef _WIN32
wchar_t path[PATH_MAX] = L""; wchar_t path[PATH_MAX] = L"";
GetTempPathW(PATH_MAX, path); GetTempPathW(PATH_MAX, path);
//path.transform("\\", "/"); string result = (const char*)utf8_t(path);
return (const char*)utf8_t(path); result.transform("\\", "/");
return result;
#else #else
return "/tmp/"; return "/tmp/";
#endif #endif

View File

@ -13,6 +13,7 @@ namespace nall {
struct thread { struct thread {
thread(function<void ()> entryPoint) : entryPoint(entryPoint), completed(false), dead(false) { thread(function<void ()> entryPoint) : entryPoint(entryPoint), completed(false), dead(false) {
initialize();
pthread_create(&pthread, NULL, thread_entry_point, (void*)this); pthread_create(&pthread, NULL, thread_entry_point, (void*)this);
} }
@ -30,11 +31,28 @@ namespace nall {
pthread_join(pthread, NULL); pthread_join(pthread, NULL);
} }
static bool primary() {
initialize();
return pthread_equal(primaryThread(), pthread_self());
}
private: private:
pthread_t pthread; pthread_t pthread;
function<void ()> entryPoint; function<void ()> entryPoint;
volatile bool completed, dead; volatile bool completed, dead;
friend void* thread_entry_point(void*); friend void* thread_entry_point(void*);
static void initialize() {
static bool initialized = false;
if(initialized) return;
initialized = true;
primaryThread() = pthread_self();
}
static pthread_t& primaryThread() {
static pthread_t thread;
return thread;
}
}; };
void* thread_entry_point(void *parameter) { void* thread_entry_point(void *parameter) {
@ -50,6 +68,7 @@ namespace nall {
struct thread { struct thread {
thread(function<void ()> entryPoint) : entryPoint(entryPoint), completed(false), dead(false) { thread(function<void ()> entryPoint) : entryPoint(entryPoint), completed(false), dead(false) {
initialize();
hthread = CreateThread(NULL, 0, thread_entry_point, (void*)this, 0, NULL); hthread = CreateThread(NULL, 0, thread_entry_point, (void*)this, 0, NULL);
} }
@ -68,11 +87,28 @@ namespace nall {
CloseHandle(hthread); CloseHandle(hthread);
} }
static bool primary() {
initialize();
return primaryThread() == GetCurrentThreadId();
}
private: private:
HANDLE hthread; HANDLE hthread;
function<void ()> entryPoint; function<void ()> entryPoint;
volatile bool completed, dead; volatile bool completed, dead;
friend DWORD WINAPI thread_entry_point(LPVOID); friend DWORD WINAPI thread_entry_point(LPVOID);
static void initialize() {
static bool initialized = false;
if(initialized) return;
initialized = true;
primaryThread() = GetCurrentThreadId();
}
static DWORD& primaryThread() {
static DWORD thread;
return thread;
}
}; };
inline DWORD WINAPI thread_entry_point(LPVOID parameter) { inline DWORD WINAPI thread_entry_point(LPVOID parameter) {

View File

@ -8,7 +8,7 @@ void Ananke::copySufamiTurboSaves(const string &pathname) {
string Ananke::createSufamiTurboDatabase(vector<uint8_t> &buffer, Markup::Node &document, const string &manifest) { string Ananke::createSufamiTurboDatabase(vector<uint8_t> &buffer, Markup::Node &document, const string &manifest) {
string pathname = { string pathname = {
userpath(), "Emulation/Sufami Turbo/", libraryPath, "Sufami Turbo/",
document["release/information/name"].text(), document["release/information/name"].text(),
" (", document["release/information/region"].text(), ")", " (", document["release/information/region"].text(), ")",
" (", document["release/information/revision"].text(), ")", " (", document["release/information/revision"].text(), ")",
@ -31,11 +31,12 @@ string Ananke::createSufamiTurboDatabase(vector<uint8_t> &buffer, Markup::Node &
string Ananke::createSufamiTurboHeuristic(vector<uint8_t> &buffer) { string Ananke::createSufamiTurboHeuristic(vector<uint8_t> &buffer) {
string pathname = { string pathname = {
userpath(), "Emulation/Sufami Turbo/", libraryPath, "Sufami Turbo/",
nall::basename(information.name), nall::basename(information.name),
" (!).st/" ".st/"
}; };
directory::create(pathname); directory::create(pathname);
file::create({pathname, "unverified"});
file::write({pathname, "manifest.bml"}, { file::write({pathname, "manifest.bml"}, {
"cartridge\n", "cartridge\n",

View File

@ -14,7 +14,7 @@ void Ananke::copySuperFamicomSaves(const string &pathname) {
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/", libraryPath, "Super Famicom/",
document["release/information/name"].text(), document["release/information/name"].text(),
" (", document["release/information/region"].text(), ")", " (", document["release/information/region"].text(), ")",
" (", document["release/information/revision"].text(), ")", " (", document["release/information/revision"].text(), ")",
@ -45,11 +45,12 @@ string Ananke::createSuperFamicomDatabase(vector<uint8_t> &buffer, Markup::Node
string Ananke::createSuperFamicomHeuristic(vector<uint8_t> &buffer) { string Ananke::createSuperFamicomHeuristic(vector<uint8_t> &buffer) {
string pathname = { string pathname = {
userpath(), "Emulation/Super Famicom/", libraryPath, "Super Famicom/",
nall::basename(information.name), nall::basename(information.name),
" (!).sfc/" ".sfc/"
}; };
directory::create(pathname); directory::create(pathname);
file::create({pathname, "unverified"});
if((buffer.size() & 0x7fff) == 512) buffer.remove(0, 512); //strip copier header, if present if((buffer.size() & 0x7fff) == 512) buffer.remove(0, 512); //strip copier header, if present
@ -88,8 +89,9 @@ void Ananke::createSuperFamicomHeuristicFirmware(vector<uint8_t> &buffer, const
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) {
MessageWindow::critical(Window::none(), { if(thread::primary()) MessageWindow::critical(Window::none(), {
"Error: required firmware ", name, " not found. Game will not be playable!\n\n", "Error: ", information.name, "\n\n",
"Required firmware ", name, " not found. Game will not be playable!\n\n",
"You must obtain this file, and place it in the same folder as this game." "You must obtain this file, and place it in the same folder as this game."
}); });
return; return;

View File

@ -10,12 +10,10 @@ profile := accuracy
target := ethos target := ethos
# options += debugger # options += debugger
# arch := win32 # arch := x86
# console := true # console := true
# compiler # compiler
c := $(compiler) -std=gnu99
cpp := $(subst cc,++,$(compiler)) -std=gnu++0x
flags := -I. -O3 -fomit-frame-pointer flags := -I. -O3 -fomit-frame-pointer
link := -s link := -s
objects := libco objects := libco
@ -48,7 +46,7 @@ else ifeq ($(platform),win)
link += -mthreads -luuid -lkernel32 -luser32 -lgdi32 -lcomctl32 -lcomdlg32 -lshell32 -lole32 -lws2_32 link += -mthreads -luuid -lkernel32 -luser32 -lgdi32 -lcomctl32 -lcomdlg32 -lshell32 -lole32 -lws2_32
link += -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc link += -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc
else else
unknown_platform: help; $(error unsupported platform.)
endif endif
ui := target-$(target) ui := target-$(target)

View File

@ -3,7 +3,7 @@
namespace Emulator { namespace Emulator {
static const char Name[] = "higan"; static const char Name[] = "higan";
static const char Version[] = "092"; static const char Version[] = "092.01";
static const char Author[] = "byuu"; static const char Author[] = "byuu";
static const char License[] = "GPLv3"; static const char License[] = "GPLv3";
} }

View File

@ -83,9 +83,9 @@ struct Interface {
virtual bool loaded() { return false; } virtual bool loaded() { return false; }
virtual string sha256() { return ""; } virtual string sha256() { return ""; }
virtual unsigned group(unsigned id) = 0; virtual unsigned group(unsigned id) = 0;
virtual void load(unsigned id, const string &manifest) {} virtual void load(unsigned id) {}
virtual void save() {} virtual void save() {}
virtual void load(unsigned id, const stream &memory, const string &markup = "") {} virtual void load(unsigned id, const stream &memory) {}
virtual void save(unsigned id, const stream &memory) {} virtual void save(unsigned id, const stream &memory) {}
virtual void unload() {} virtual void unload() {}

View File

@ -18,10 +18,10 @@ void Cartridge::main() {
board->main(); board->main();
} }
void Cartridge::load(const string &manifest) { void Cartridge::load() {
information.markup = manifest; interface->loadRequest(ID::Manifest, "manifest.bml");
Board::load(manifest); //this call will set Cartridge::board if successful Board::load(information.markup); //this call will set Cartridge::board if successful
if(board == nullptr) return; if(board == nullptr) return;
sha256_ctx sha; sha256_ctx sha;

View File

@ -5,7 +5,7 @@ struct Cartridge : Thread, property<Cartridge> {
static void Main(); static void Main();
void main(); void main();
void load(const string &manifest); void load();
void unload(); void unload();
void power(); void power();

View File

@ -26,6 +26,7 @@ string Interface::sha256() {
unsigned Interface::group(unsigned id) { unsigned Interface::group(unsigned id) {
switch(id) { switch(id) {
case ID::Manifest:
case ID::ProgramROM: case ID::ProgramROM:
case ID::ProgramRAM: case ID::ProgramRAM:
case ID::CharacterROM: case ID::CharacterROM:
@ -36,8 +37,8 @@ unsigned Interface::group(unsigned id) {
throw; throw;
} }
void Interface::load(unsigned id, const string &manifest) { void Interface::load(unsigned id) {
cartridge.load(manifest); cartridge.load();
} }
void Interface::save() { void Interface::save() {
@ -46,7 +47,9 @@ void Interface::save() {
} }
} }
void Interface::load(unsigned id, const stream &stream, const string &manifest) { void Interface::load(unsigned id, const stream &stream) {
if(id == ID::Manifest) cartridge.information.markup = stream.text();
if(id == ID::ProgramROM) { if(id == ID::ProgramROM) {
stream.read(cartridge.board->prgrom.data, min(cartridge.board->prgrom.size, stream.size())); stream.read(cartridge.board->prgrom.data, min(cartridge.board->prgrom.size, stream.size()));
} }

View File

@ -9,6 +9,7 @@ struct ID {
}; };
enum : unsigned { enum : unsigned {
Manifest,
ProgramROM, ProgramROM,
ProgramRAM, ProgramRAM,
CharacterROM, CharacterROM,
@ -29,9 +30,9 @@ struct Interface : Emulator::Interface {
bool loaded(); bool loaded();
string sha256(); string sha256();
unsigned group(unsigned id); unsigned group(unsigned id);
void load(unsigned id, const string &manifest); void load(unsigned id);
void save(); void save();
void load(unsigned id, const stream &stream, const string &manifest = ""); void load(unsigned id, const stream &stream);
void save(unsigned id, const stream &stream); void save(unsigned id, const stream &stream);
void unload(); void unload();

View File

@ -18,8 +18,12 @@ string Cartridge::title() {
return information.title; return information.title;
} }
void Cartridge::load(System::Revision revision, const string &manifest) { void Cartridge::load(System::Revision revision) {
information.markup = manifest; system.load(revision);
if(revision != System::Revision::SuperGameBoy) {
interface->loadRequest(ID::Manifest, "manifest.bml");
}
information.mapper = Mapper::Unknown; information.mapper = Mapper::Unknown;
information.ram = false; information.ram = false;
information.battery = false; information.battery = false;
@ -29,7 +33,7 @@ void Cartridge::load(System::Revision revision, const string &manifest) {
information.romsize = 0; information.romsize = 0;
information.ramsize = 0; information.ramsize = 0;
auto document = Markup::Document(manifest); auto document = Markup::Document(information.markup);
information.title = document["information/title"].text(); information.title = document["information/title"].text();
auto mapperid = document["cartridge/board/type"].text(); auto mapperid = document["cartridge/board/type"].text();
@ -54,8 +58,6 @@ void Cartridge::load(System::Revision revision, const string &manifest) {
ramsize = numeral(ram["size"].data); ramsize = numeral(ram["size"].data);
ramdata = allocate<uint8>(ramsize, 0xff); ramdata = allocate<uint8>(ramsize, 0xff);
system.load(revision);
//Super Game Boy core loads memory from Super Famicom core //Super Game Boy core loads memory from Super Famicom core
if(revision != System::Revision::SuperGameBoy) { if(revision != System::Revision::SuperGameBoy) {
if(rom["name"].exists()) interface->loadRequest(ID::ROM, rom["name"].data); if(rom["name"].exists()) interface->loadRequest(ID::ROM, rom["name"].data);

View File

@ -54,7 +54,7 @@ struct Cartridge : MMIO, property<Cartridge> {
MMIO *mapper; MMIO *mapper;
bool bootrom_enable; bool bootrom_enable;
void load(System::Revision revision, const string &manifest); void load(System::Revision revision);
void unload(); void unload();
uint8 rom_read(unsigned addr); uint8 rom_read(unsigned addr);

View File

@ -38,6 +38,7 @@ unsigned Interface::group(unsigned id) {
case ID::SuperGameBoyBootROM: case ID::SuperGameBoyBootROM:
case ID::GameBoyColorBootROM: case ID::GameBoyColorBootROM:
return 0; return 0;
case ID::Manifest:
case ID::ROM: case ID::ROM:
case ID::RAM: case ID::RAM:
if(system.revision() == System::Revision::GameBoy) return ID::GameBoy; if(system.revision() == System::Revision::GameBoy) return ID::GameBoy;
@ -49,10 +50,10 @@ unsigned Interface::group(unsigned id) {
throw; throw;
} }
void Interface::load(unsigned id, const string &manifest) { void Interface::load(unsigned id) {
if(id == ID::GameBoy) cartridge.load(System::Revision::GameBoy, manifest); if(id == ID::GameBoy) cartridge.load(System::Revision::GameBoy);
if(id == ID::SuperGameBoy) cartridge.load(System::Revision::SuperGameBoy, manifest); if(id == ID::SuperGameBoy) cartridge.load(System::Revision::SuperGameBoy);
if(id == ID::GameBoyColor) cartridge.load(System::Revision::GameBoyColor, manifest); if(id == ID::GameBoyColor) cartridge.load(System::Revision::GameBoyColor);
} }
void Interface::save() { void Interface::save() {
@ -61,7 +62,7 @@ void Interface::save() {
} }
} }
void Interface::load(unsigned id, const stream &stream, const string &manifest) { void Interface::load(unsigned id, const stream &stream) {
if(id == ID::GameBoyBootROM) { if(id == ID::GameBoyBootROM) {
stream.read(system.bootROM.dmg, min( 256u, stream.size())); stream.read(system.bootROM.dmg, min( 256u, stream.size()));
} }
@ -74,6 +75,8 @@ void Interface::load(unsigned id, const stream &stream, const string &manifest)
stream.read(system.bootROM.cgb, min(2048u, stream.size())); stream.read(system.bootROM.cgb, min(2048u, stream.size()));
} }
if(id == ID::Manifest) cartridge.information.markup = stream.text();
if(id == ID::ROM) { if(id == ID::ROM) {
stream.read(cartridge.romdata, min(cartridge.romsize, stream.size())); stream.read(cartridge.romdata, min(cartridge.romsize, stream.size()));
} }

View File

@ -14,8 +14,8 @@ struct ID {
GameBoyBootROM, GameBoyBootROM,
SuperGameBoyBootROM, SuperGameBoyBootROM,
GameBoyColorBootROM, GameBoyColorBootROM,
GameBoyROM,
GameBoyColorROM, Manifest,
ROM, ROM,
RAM, RAM,
}; };
@ -42,9 +42,9 @@ struct Interface : Emulator::Interface {
bool loaded(); bool loaded();
string sha256(); string sha256();
unsigned group(unsigned id); unsigned group(unsigned id);
void load(unsigned id, const string &manifest); void load(unsigned id);
void save(); void save();
void load(unsigned id, const stream &stream, const string &manifest = ""); void load(unsigned id, const stream &stream);
void save(unsigned id, const stream &stream); void save(unsigned id, const stream &stream);
void unload(); void unload();

View File

@ -11,9 +11,10 @@ string Cartridge::title() {
return information.title; return information.title;
} }
void Cartridge::load(const string &manifest) { void Cartridge::load() {
information.markup = manifest; interface->loadRequest(ID::Manifest, "manifest.bml");
auto document = Markup::Document(manifest);
auto document = Markup::Document(information.markup);
information.title = document["information/title"].text(); information.title = document["information/title"].text();
unsigned rom_size = 0; unsigned rom_size = 0;

View File

@ -21,7 +21,7 @@ struct Cartridge : property<Cartridge> {
}; };
vector<Media> memory; vector<Media> memory;
void load(const string &manifest); void load();
void unload(); void unload();
void power(); void power();

View File

@ -24,6 +24,7 @@ unsigned Interface::group(unsigned id) {
switch(id) { switch(id) {
case ID::BIOS: case ID::BIOS:
return ID::System; return ID::System;
case ID::Manifest:
case ID::ROM: case ID::ROM:
case ID::RAM: case ID::RAM:
case ID::EEPROM: case ID::EEPROM:
@ -34,8 +35,8 @@ unsigned Interface::group(unsigned id) {
throw; throw;
} }
void Interface::load(unsigned id, const string &manifest) { void Interface::load(unsigned id) {
cartridge.load(manifest); cartridge.load();
} }
void Interface::save() { void Interface::save() {
@ -44,11 +45,13 @@ void Interface::save() {
} }
} }
void Interface::load(unsigned id, const stream &stream, const string &manifest) { void Interface::load(unsigned id, const stream &stream) {
if(id == ID::BIOS) { if(id == ID::BIOS) {
stream.read(bios.data, min(bios.size, stream.size())); stream.read(bios.data, min(bios.size, stream.size()));
} }
if(id == ID::Manifest) cartridge.information.markup = stream.text();
if(id == ID::ROM) { if(id == ID::ROM) {
stream.read(cartridge.rom.data, min(cartridge.rom.size, stream.size())); stream.read(cartridge.rom.data, min(cartridge.rom.size, stream.size()));
} }

View File

@ -10,6 +10,8 @@ struct ID {
enum : unsigned { enum : unsigned {
BIOS, BIOS,
Manifest,
ROM, ROM,
RAM, RAM,
EEPROM, EEPROM,
@ -28,9 +30,9 @@ struct Interface : Emulator::Interface {
bool loaded(); bool loaded();
unsigned group(unsigned id); unsigned group(unsigned id);
void load(unsigned id, const string &manifest); void load(unsigned id);
void save(); void save();
void load(unsigned id, const stream &stream, const string &manifest = ""); void load(unsigned id, const stream &stream);
void save(unsigned id, const stream &stream); void save(unsigned id, const stream &stream);
void unload(); void unload();

View File

@ -36,16 +36,21 @@ endif
ifeq ($(compiler),) ifeq ($(compiler),)
ifeq ($(platform),win) ifeq ($(platform),win)
compiler := gcc compiler := g++
else ifeq ($(platform),osx) else ifeq ($(platform),osx)
compiler := gcc-mp-4.7 compiler := g++-mp-4.7
else else
compiler := gcc-4.7 compiler := g++-4.7
endif endif
endif endif
c := $(compiler) -std=gnu99 c := $(compiler) -x c -std=gnu99
cpp := $(subst cc,++,$(compiler)) -std=gnu++0x cpp := $(compiler) -std=gnu++11
ifeq ($(arch),x86)
c := $(c) -m32
cpp := $(cpp) -m32
endif
ifeq ($(prefix),) ifeq ($(prefix),)
prefix := /usr/local prefix := /usr/local

View File

@ -98,6 +98,14 @@ namespace nall {
return true; return true;
} }
static bool create(const string &filename) {
//create an empty file (will replace existing files)
file fp;
if(fp.open(filename, mode::write) == false) return false;
fp.close();
return true;
}
static string sha256(const string &filename) { static string sha256(const string &filename) {
auto buffer = read(filename); auto buffer = read(filename);
return nall::sha256(buffer.data(), buffer.size()); return nall::sha256(buffer.data(), buffer.size());

View File

@ -39,6 +39,7 @@
#include <nall/stdint.hpp> #include <nall/stdint.hpp>
#include <nall/stream.hpp> #include <nall/stream.hpp>
#include <nall/string.hpp> #include <nall/string.hpp>
#include <nall/thread.hpp>
#include <nall/traits.hpp> #include <nall/traits.hpp>
#include <nall/unzip.hpp> #include <nall/unzip.hpp>
#include <nall/utility.hpp> #include <nall/utility.hpp>

View File

@ -5,12 +5,6 @@
//example: property<owner>::readonly<type> implies that only owner has full //example: property<owner>::readonly<type> implies that only owner has full
//access to type; and all other code has readonly access. //access to type; and all other code has readonly access.
// //
//this code relies on extended friend semantics from C++0x to work, as it
//declares a friend class via a template paramter. it also exploits a bug in
//G++ 4.x to work even in C++98 mode.
//
//if compiling elsewhere, simply remove the friend class and private semantics
//property can be used either of two ways: //property can be used either of two ways:
//struct foo { //struct foo {
// property<foo>::readonly<bool> x; // property<foo>::readonly<bool> x;
@ -50,8 +44,6 @@
namespace nall { namespace nall {
template<typename C> struct property { template<typename C> struct property {
template<typename T> struct traits { typedef T type; };
template<typename T> struct readonly { template<typename T> struct readonly {
const T* operator->() const { return &value; } const T* operator->() const { return &value; }
const T& operator()() const { return value; } const T& operator()() const { return value; }
@ -61,7 +53,7 @@ namespace nall {
operator T&() { return value; } operator T&() { return value; }
const T& operator=(const T& value_) { return value = value_; } const T& operator=(const T& value_) { return value = value_; }
T value; T value;
friend class traits<C>::type; friend C;
}; };
template<typename T> struct writeonly { template<typename T> struct writeonly {
@ -73,7 +65,7 @@ namespace nall {
T* operator->() { return &value; } T* operator->() { return &value; }
operator T&() { return value; } operator T&() { return value; }
T value; T value;
friend class traits<C>::type; friend C;
}; };
template<typename T> struct readwrite { template<typename T> struct readwrite {

View File

@ -48,6 +48,15 @@ struct stream {
while(length--) *data++ = read(); while(length--) *data++ = read();
} }
string text() const {
string buffer;
buffer.resize(size() + 1);
buffer[size()] = 0;
seek(0);
read((uint8_t*)buffer(), size());
return buffer;
}
void writel(uintmax_t data, unsigned length = 1) const { void writel(uintmax_t data, unsigned length = 1) const {
while(length--) { while(length--) {
write(data); write(data);

View File

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

View File

@ -23,11 +23,14 @@ namespace nall {
struct string { struct string {
inline static string read(const string &filename); inline static string read(const string &filename);
inline static string date(); inline static string date();
inline static string time(); inline static string time();
inline static string datetime(); inline static string datetime();
inline void reserve(unsigned); inline void reserve(unsigned);
inline void resize(unsigned);
inline void clear(char);
inline bool empty() const; inline bool empty() const;
template<typename... Args> inline string& assign(Args&&... args); template<typename... Args> inline string& assign(Args&&... args);
@ -64,6 +67,7 @@ namespace nall {
inline string& qlower(); inline string& qlower();
inline string& qupper(); inline string& qupper();
inline string& transform(const char *before, const char *after); inline string& transform(const char *before, const char *after);
inline string& reverse();
template<unsigned limit = 0> inline string& ltrim(const char *key = " "); template<unsigned limit = 0> inline string& ltrim(const char *key = " ");
template<unsigned limit = 0> inline string& rtrim(const char *key = " "); template<unsigned limit = 0> inline string& rtrim(const char *key = " ");
@ -159,6 +163,12 @@ namespace nall {
inline char* qstrupper(char *str); inline char* qstrupper(char *str);
inline char* strtr(char *dest, const char *before, const char *after); inline char* strtr(char *dest, const char *before, const char *after);
//format.hpp
template<signed precision = 0, char padchar = ' '> inline string format(const string &value);
template<signed precision = 0, char padchar = '0'> inline string hex(uintmax_t value);
template<signed precision = 0, char padchar = '0'> inline string octal(uintmax_t value);
template<signed precision = 0, char padchar = '0'> inline string binary(uintmax_t value);
//math.hpp //math.hpp
inline bool strint(const char *str, int &result); inline bool strint(const char *str, int &result);
inline bool strmath(const char *str, int &result); inline bool strmath(const char *str, int &result);
@ -200,12 +210,11 @@ namespace nall {
inline char* integer(char *result, intmax_t value); inline char* integer(char *result, intmax_t value);
inline char* decimal(char *result, uintmax_t value); inline char* decimal(char *result, uintmax_t value);
//these functions are deprecated, use format() instead:
template<unsigned length = 0, char padding = ' '> inline string integer(intmax_t value); template<unsigned length = 0, char padding = ' '> inline string integer(intmax_t value);
template<unsigned length = 0, char padding = ' '> inline string linteger(intmax_t value); template<unsigned length = 0, char padding = ' '> inline string linteger(intmax_t value);
template<unsigned length = 0, char padding = ' '> inline string decimal(uintmax_t value); template<unsigned length = 0, char padding = ' '> inline string decimal(uintmax_t value);
template<unsigned length = 0, char padding = ' '> inline string ldecimal(uintmax_t value); template<unsigned length = 0, char padding = ' '> inline string ldecimal(uintmax_t value);
template<unsigned length = 0, char padding = '0'> inline string hex(uintmax_t value);
template<unsigned length = 0, char padding = '0'> inline string binary(uintmax_t value);
inline unsigned fp(char *str, long double value); inline unsigned fp(char *str, long double value);
inline string fp(long double value); inline string fp(long double value);

View File

@ -12,11 +12,18 @@ static void istring(string &output, const T &value, Args&&... args) {
} }
void string::reserve(unsigned size_) { void string::reserve(unsigned size_) {
if(size_ > size) { if(size_ > size) resize(size_);
}
void string::resize(unsigned size_) {
size = size_; size = size_;
data = (char*)realloc(data, size + 1); data = (char*)realloc(data, size + 1);
data[size] = 0; data[size] = 0;
} }
void string::clear(char c) {
for(unsigned n = 0; n < size; n++) data[n] = c;
data[size] = 0;
} }
bool string::empty() const { bool string::empty() const {

View File

@ -0,0 +1,73 @@
#ifdef NALL_STRING_INTERNAL_HPP
namespace nall {
template<signed precision, char padchar> string format(const string &value) {
if(precision == 0) return value;
bool padright = precision >= 0;
unsigned padding = abs(precision);
unsigned length = value.length();
if(padding <= length) {
if(padright) return substr(value, length - padding);
else return substr(value, 0, padding);
}
string buffer;
buffer.resize(padding);
buffer.clear(padchar);
memcpy(buffer() + (padright ? padding - length : 0), value, length);
return buffer;
}
template<signed precision, char padchar> string hex(uintmax_t value) {
string buffer;
buffer.resize(sizeof(uintmax_t) * 2);
unsigned size = 0;
do {
unsigned n = value & 15;
buffer[size++] = n < 10 ? '0' + n : 'a' + n - 10;
value >>= 4;
} while(value);
buffer[size] = 0;
buffer.reverse();
return format<precision, padchar>(buffer);
}
template<signed precision, char padchar> string octal(uintmax_t value) {
string buffer;
buffer.resize(sizeof(uintmax_t) * 3);
unsigned size = 0;
do {
buffer[size++] = '0' + (value & 7);
value >>= 3;
} while(value);
buffer[size] = 0;
buffer.reverse();
return format<precision, padchar>(buffer);
}
template<signed precision, char padchar> string binary(uintmax_t value) {
string buffer;
buffer.resize(sizeof(uintmax_t) * 8);
unsigned size = 0;
do {
buffer[size++] = '0' + (value & 1);
value >>= 1;
} while(value);
buffer[size] = 0;
buffer.reverse();
return format<precision, padchar>(buffer);
}
}
#endif

View File

@ -33,11 +33,13 @@ string realpath(const string &name) {
return result; return result;
} }
// /home/username/
// c:/users/username/
string userpath() { string userpath() {
string result; string result;
#ifdef _WIN32 #ifdef _WIN32
wchar_t path[PATH_MAX] = L""; wchar_t path[PATH_MAX] = L"";
SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, path); SHGetFolderPathW(0, CSIDL_PROFILE | CSIDL_FLAG_CREATE, 0, 0, path);
result = (const char*)utf8_t(path); result = (const char*)utf8_t(path);
result.transform("\\", "/"); result.transform("\\", "/");
#else #else
@ -51,20 +53,30 @@ string userpath() {
return result; return result;
} }
// /home/username/.config/
// c:/users/username/appdata/roaming/
string configpath() { string configpath() {
string result;
#ifdef _WIN32 #ifdef _WIN32
return userpath(); wchar_t path[PATH_MAX] = L"";
SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, path);
result = (const char*)utf8_t(path);
result.transform("\\", "/");
#else #else
return {userpath(), ".config/"}; result = {userpath(), ".config/"};
#endif #endif
if(result.empty()) result = ".";
if(result.endswith("/") == false) result.append("/");
return result;
} }
string temppath() { string temppath() {
#ifdef _WIN32 #ifdef _WIN32
wchar_t path[PATH_MAX] = L""; wchar_t path[PATH_MAX] = L"";
GetTempPathW(PATH_MAX, path); GetTempPathW(PATH_MAX, path);
//path.transform("\\", "/"); string result = (const char*)utf8_t(path);
return (const char*)utf8_t(path); result.transform("\\", "/");
return result;
#else #else
return "/tmp/"; return "/tmp/";
#endif #endif

View File

@ -201,50 +201,6 @@ template<unsigned length_, char padding> string ldecimal(uintmax_t value) {
return (const char*)result; return (const char*)result;
} }
template<unsigned length_, char padding> string hex(uintmax_t value) {
char buffer[64];
unsigned size = 0;
do {
unsigned n = value & 15;
buffer[size++] = n < 10 ? '0' + n : 'a' + n - 10;
value >>= 4;
} while(value);
unsigned length = (length_ == 0 ? size : length_);
char result[length + 1];
memset(result, padding, length);
result[length] = 0;
for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) {
result[x] = buffer[y];
}
return (const char*)result;
}
template<unsigned length_, char padding> string binary(uintmax_t value) {
char buffer[256];
unsigned size = 0;
do {
unsigned n = value & 1;
buffer[size++] = '0' + n;
value >>= 1;
} while(value);
unsigned length = (length_ == 0 ? size : length_);
char result[length + 1];
memset(result, padding, length);
result[length] = 0;
for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) {
result[x] = buffer[y];
}
return (const char*)result;
}
//using sprintf is certainly not the most ideal method to convert //using sprintf is certainly not the most ideal method to convert
//a double to a string ... but attempting to parse a double by //a double to a string ... but attempting to parse a double by
//hand, digit-by-digit, results in subtle rounding errors. //hand, digit-by-digit, results in subtle rounding errors.

View File

@ -27,6 +27,11 @@ string& string::upper() { nall::strupper(data); return *this; }
string& string::qlower() { nall::qstrlower(data); return *this; } string& string::qlower() { nall::qstrlower(data); return *this; }
string& string::qupper() { nall::qstrupper(data); return *this; } string& string::qupper() { nall::qstrupper(data); return *this; }
string& string::transform(const char *before, const char *after) { nall::strtr(data, before, after); return *this; } string& string::transform(const char *before, const char *after) { nall::strtr(data, before, after); return *this; }
string& string::reverse() {
unsigned length = strlen(data), pivot = length >> 1;
for(signed x = 0, y = length - 1; x < pivot && y >= 0; x++, y--) std::swap(data[x], data[y]);
return *this;
}
template<unsigned limit> string& string::ltrim(const char *key) { nall::ltrim<limit>(data, key); return *this; } template<unsigned limit> string& string::ltrim(const char *key) { nall::ltrim<limit>(data, key); return *this; }
template<unsigned limit> string& string::rtrim(const char *key) { nall::rtrim<limit>(data, key); return *this; } template<unsigned limit> string& string::rtrim(const char *key) { nall::rtrim<limit>(data, key); return *this; }

123
higan/nall/thread.hpp Normal file
View File

@ -0,0 +1,123 @@
#ifndef NALL_THREAD_HPP
#define NALL_THREAD_HPP
#include <nall/platform.hpp>
#include <nall/function.hpp>
#include <nall/intrinsics.hpp>
#if defined(PLATFORM_X) || defined(PLATFORM_OSX)
#include <pthread.h>
namespace nall {
void* thread_entry_point(void*);
struct thread {
thread(function<void ()> entryPoint) : entryPoint(entryPoint), completed(false), dead(false) {
initialize();
pthread_create(&pthread, NULL, thread_entry_point, (void*)this);
}
~thread() {
join();
}
bool active() const {
return completed == false;
}
void join() {
if(dead) return;
dead = true;
pthread_join(pthread, NULL);
}
static bool primary() {
initialize();
return pthread_equal(primaryThread(), pthread_self());
}
private:
pthread_t pthread;
function<void ()> entryPoint;
volatile bool completed, dead;
friend void* thread_entry_point(void*);
static void initialize() {
static bool initialized = false;
if(initialized) return;
initialized = true;
primaryThread() = pthread_self();
}
static pthread_t& primaryThread() {
static pthread_t thread;
return thread;
}
};
void* thread_entry_point(void *parameter) {
thread *context = (thread*)parameter;
context->entryPoint();
context->completed = true;
pthread_exit(0);
}
}
#elif defined(PLATFORM_WIN)
namespace nall {
inline DWORD WINAPI thread_entry_point(LPVOID);
struct thread {
thread(function<void ()> entryPoint) : entryPoint(entryPoint), completed(false), dead(false) {
initialize();
hthread = CreateThread(NULL, 0, thread_entry_point, (void*)this, 0, NULL);
}
~thread() {
join();
}
bool active() const {
return completed == false;
}
void join() {
if(dead) return;
dead = true;
WaitForSingleObject(hthread, INFINITE);
CloseHandle(hthread);
}
static bool primary() {
initialize();
return primaryThread() == GetCurrentThreadId();
}
private:
HANDLE hthread;
function<void ()> entryPoint;
volatile bool completed, dead;
friend DWORD WINAPI thread_entry_point(LPVOID);
static void initialize() {
static bool initialized = false;
if(initialized) return;
initialized = true;
primaryThread() = GetCurrentThreadId();
}
static DWORD& primaryThread() {
static DWORD thread;
return thread;
}
};
inline DWORD WINAPI thread_entry_point(LPVOID parameter) {
thread *context = (thread*)parameter;
context->entryPoint();
context->completed = true;
return 0;
}
}
#endif
#endif

View File

@ -15,11 +15,6 @@ ifeq ($(platform),x)
else ifeq ($(platform),win) else ifeq ($(platform),win)
phoenixflags := -DPHOENIX_WINDOWS phoenixflags := -DPHOENIX_WINDOWS
phoenixlink := -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32 -lshlwapi phoenixlink := -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32 -lshlwapi
ifeq ($(arch),win32)
phoenixflags := -m32 $(phoenixflags)
phoenixlink := -m32 $(phoenixlink)
endif
else else
phoenixflags := -DPHOENIX_REFERENCE phoenixflags := -DPHOENIX_REFERENCE
phoenixlink := phoenixlink :=

View File

@ -23,9 +23,4 @@ else ifeq ($(platform),osx)
rubylink += $(if $(findstring audio.openal,$(ruby)),-framework OpenAL) rubylink += $(if $(findstring audio.openal,$(ruby)),-framework OpenAL)
else ifeq ($(platform),win) else ifeq ($(platform),win)
rubylink += $(if $(findstring audio.openal,$(ruby)),-lopenal32) rubylink += $(if $(findstring audio.openal,$(ruby)),-lopenal32)
ifeq ($(arch),win32)
rubyflags := -m32 $(rubyflags)
rubylink := -m32 $(rubylink)
endif
endif endif

View File

@ -1,12 +1,13 @@
sfc_objects := sfc-interface sfc-system sfc-controller sfc_objects := sfc-interface sfc-system sfc-controller
sfc_objects += sfc-cartridge sfc-cheat sfc_objects += sfc-cartridge sfc-cheat
sfc_objects += sfc-memory sfc-cpu sfc-smp sfc-dsp sfc-ppu sfc_objects += sfc-memory sfc-cpu sfc-smp sfc-dsp sfc-ppu
sfc_objects += sfc-icd2 sfc-bsx sfc-sufamiturbo sfc-nss sfc-event sfc_objects += sfc-icd2 sfc-bsx sfc-nss sfc-event
sfc_objects += sfc-sa1 sfc-superfx sfc_objects += sfc-sa1 sfc-superfx
sfc_objects += sfc-armdsp sfc-hitachidsp sfc-necdsp sfc_objects += sfc-armdsp sfc-hitachidsp sfc-necdsp
sfc_objects += sfc-epsonrtc sfc-sharprtc sfc_objects += sfc-epsonrtc sfc-sharprtc
sfc_objects += sfc-spc7110 sfc-sdd1 sfc-obc1 sfc_objects += sfc-spc7110 sfc-sdd1 sfc-obc1
sfc_objects += sfc-hsu1 sfc-msu1 sfc_objects += sfc-hsu1 sfc-msu1
sfc_objects += sfc-satellaview sfc-sufamiturbo
objects += $(sfc_objects) objects += $(sfc_objects)
ifeq ($(profile),accuracy) ifeq ($(profile),accuracy)
@ -27,6 +28,8 @@ else ifeq ($(profile),performance)
sfcsmp := $(sfc)/alt/smp sfcsmp := $(sfc)/alt/smp
sfcdsp := $(sfc)/alt/dsp sfcdsp := $(sfc)/alt/dsp
sfcppu := $(sfc)/alt/ppu-performance sfcppu := $(sfc)/alt/ppu-performance
else
$(error unknown profile.)
endif endif
obj/sfc-interface.o: $(sfc)/interface/interface.cpp $(call rwildcard,$(sfc)/interface) obj/sfc-interface.o: $(sfc)/interface/interface.cpp $(call rwildcard,$(sfc)/interface)
@ -42,7 +45,6 @@ obj/sfc-ppu.o: $(sfcppu)/ppu.cpp $(call rwildcard,$(sfcppu)/)
obj/sfc-icd2.o: $(sfc)/chip/icd2/icd2.cpp $(call rwildcard,$(sfc)/chip/icd2/) obj/sfc-icd2.o: $(sfc)/chip/icd2/icd2.cpp $(call rwildcard,$(sfc)/chip/icd2/)
obj/sfc-bsx.o: $(sfc)/chip/bsx/bsx.cpp $(call rwildcard,$(sfc)/chip/bsx/) obj/sfc-bsx.o: $(sfc)/chip/bsx/bsx.cpp $(call rwildcard,$(sfc)/chip/bsx/)
obj/sfc-sufamiturbo.o: $(sfc)/chip/sufamiturbo/sufamiturbo.cpp $(sfc)/chip/sufamiturbo/*
obj/sfc-nss.o: $(sfc)/chip/nss/nss.cpp $(call rwildcard,$(sfc)/chip/nss/) obj/sfc-nss.o: $(sfc)/chip/nss/nss.cpp $(call rwildcard,$(sfc)/chip/nss/)
obj/sfc-event.o: $(sfc)/chip/event/event.cpp $(call rwildcard,$(sfc)/chip/event/) obj/sfc-event.o: $(sfc)/chip/event/event.cpp $(call rwildcard,$(sfc)/chip/event/)
@ -62,3 +64,6 @@ obj/sfc-obc1.o: $(sfc)/chip/obc1/obc1.cpp $(sfc)/chip/obc1/*
obj/sfc-hsu1.o: $(sfc)/chip/hsu1/hsu1.cpp $(sfc)/chip/hsu1/* obj/sfc-hsu1.o: $(sfc)/chip/hsu1/hsu1.cpp $(sfc)/chip/hsu1/*
obj/sfc-msu1.o: $(sfc)/chip/msu1/msu1.cpp $(sfc)/chip/msu1/* obj/sfc-msu1.o: $(sfc)/chip/msu1/msu1.cpp $(sfc)/chip/msu1/*
obj/sfc-satellaview.o: $(sfc)/slot/satellaview/satellaview.cpp $(call rwildcard,$(sfc)/slot/satellaview/)
obj/sfc-sufamiturbo.o: $(sfc)/slot/sufamiturbo/sufamiturbo.cpp $(call rwildcard,$(sfc)/slot/sufamiturbo/)

View File

@ -27,7 +27,7 @@ string Cartridge::title() {
return information.title.cartridge; return information.title.cartridge;
} }
void Cartridge::load(const string &manifest) { void Cartridge::load() {
region = Region::NTSC; region = Region::NTSC;
has_gb_slot = false; has_gb_slot = false;
@ -49,13 +49,20 @@ void Cartridge::load(const string &manifest) {
has_hsu1 = false; has_hsu1 = false;
has_msu1 = false; has_msu1 = false;
information.markup.cartridge = "";
information.markup.gameBoy = "";
information.markup.satellaview = "";
information.markup.sufamiTurboA = "";
information.markup.sufamiTurboB = "";
information.title.cartridge = ""; information.title.cartridge = "";
information.title.gameBoy = ""; information.title.gameBoy = "";
information.title.satellaview = ""; information.title.satellaview = "";
information.title.sufamiTurboA = ""; information.title.sufamiTurboA = "";
information.title.sufamiTurboB = ""; information.title.sufamiTurboB = "";
parse_markup(information.markup = manifest); interface->loadRequest(ID::Manifest, "manifest.bml");
parse_markup(information.markup.cartridge);
//Super Game Boy //Super Game Boy
if(cartridge.has_gb_slot()) { if(cartridge.has_gb_slot()) {
@ -64,7 +71,7 @@ void Cartridge::load(const string &manifest) {
//Broadcast Satellaview //Broadcast Satellaview
else if(cartridge.has_bs_cart() && cartridge.has_bs_slot()) { else if(cartridge.has_bs_cart() && cartridge.has_bs_slot()) {
sha256 = nall::sha256(bsxflash.memory.data(), bsxflash.memory.size()); sha256 = nall::sha256(satellaviewcartridge.memory.data(), satellaviewcartridge.memory.size());
} }
//Sufami Turbo //Sufami Turbo
@ -72,8 +79,8 @@ void Cartridge::load(const string &manifest) {
sha256_ctx sha; sha256_ctx sha;
uint8_t hash[32]; uint8_t hash[32];
sha256_init(&sha); sha256_init(&sha);
sha256_chunk(&sha, sufamiturbo.slotA.rom.data(), sufamiturbo.slotA.rom.size()); sha256_chunk(&sha, sufamiturboA.rom.data(), sufamiturboA.rom.size());
sha256_chunk(&sha, sufamiturbo.slotB.rom.data(), sufamiturbo.slotB.rom.size()); sha256_chunk(&sha, sufamiturboB.rom.data(), sufamiturboB.rom.size());
sha256_final(&sha); sha256_final(&sha);
sha256_hash(&sha, hash); sha256_hash(&sha, hash);
string result; string result;
@ -118,37 +125,41 @@ void Cartridge::load(const string &manifest) {
loaded = true; loaded = true;
} }
void Cartridge::load_super_game_boy(const string &manifest) { void Cartridge::load_super_game_boy() {
auto document = Markup::Document(manifest); interface->loadRequest(ID::SuperGameBoyManifest, "manifest.bml");
auto document = Markup::Document(information.markup.gameBoy);
information.title.gameBoy = document["information/title"].text(); information.title.gameBoy = document["information/title"].text();
auto rom = document["cartridge/rom"]; auto rom = document["cartridge/rom"];
auto ram = document["cartridge/ram"]; auto ram = document["cartridge/ram"];
GameBoy::cartridge.load(GameBoy::System::Revision::SuperGameBoy, manifest); GameBoy::cartridge.information.markup = information.markup.gameBoy;
GameBoy::cartridge.load(GameBoy::System::Revision::SuperGameBoy);
if(rom["name"].exists()) interface->loadRequest(ID::SuperGameBoyROM, rom["name"].data); if(rom["name"].exists()) interface->loadRequest(ID::SuperGameBoyROM, rom["name"].data);
if(ram["name"].exists()) interface->loadRequest(ID::SuperGameBoyRAM, ram["name"].data); if(ram["name"].exists()) interface->loadRequest(ID::SuperGameBoyRAM, ram["name"].data);
if(ram["name"].exists()) memory.append({ID::SuperGameBoyRAM, ram["name"].data}); if(ram["name"].exists()) memory.append({ID::SuperGameBoyRAM, ram["name"].data});
} }
void Cartridge::load_satellaview(const string &manifest) { void Cartridge::load_satellaview() {
auto document = Markup::Document(manifest); interface->loadRequest(ID::SatellaviewManifest, "manifest.bml");
auto document = Markup::Document(information.markup.satellaview);
information.title.satellaview = document["information/title"].text(); information.title.satellaview = document["information/title"].text();
auto rom = document["cartridge/rom"]; auto rom = document["cartridge/rom"];
if(rom["name"].exists()) { if(rom["name"].exists()) {
unsigned size = numeral(rom["size"].data); unsigned size = numeral(rom["size"].data);
bsxflash.memory.map(allocate<uint8>(size, 0xff), size); satellaviewcartridge.memory.map(allocate<uint8>(size, 0xff), size);
interface->loadRequest(ID::BsxFlashROM, rom["name"].data); interface->loadRequest(ID::SatellaviewROM, rom["name"].data);
bsxflash.readonly = (rom["type"].text() == "MaskROM"); satellaviewcartridge.readonly = (rom["type"].text() == "MaskROM");
} }
} }
void Cartridge::load_sufami_turbo_a(const string &manifest) { void Cartridge::load_sufami_turbo_a() {
auto document = Markup::Document(manifest); interface->loadRequest(ID::SufamiTurboSlotAManifest, "manifest.bml");
auto document = Markup::Document(information.markup.sufamiTurboA);
information.title.sufamiTurboA = document["information/title"].text(); information.title.sufamiTurboA = document["information/title"].text();
auto rom = document["cartridge/rom"]; auto rom = document["cartridge/rom"];
@ -156,13 +167,13 @@ void Cartridge::load_sufami_turbo_a(const string &manifest) {
if(rom["name"].exists()) { if(rom["name"].exists()) {
unsigned size = numeral(rom["size"].data); unsigned size = numeral(rom["size"].data);
sufamiturbo.slotA.rom.map(allocate<uint8>(size, 0xff), size); sufamiturboA.rom.map(allocate<uint8>(size, 0xff), size);
interface->loadRequest(ID::SufamiTurboSlotAROM, rom["name"].data); interface->loadRequest(ID::SufamiTurboSlotAROM, rom["name"].data);
} }
if(ram["name"].exists()) { if(ram["name"].exists()) {
unsigned size = numeral(ram["size"].data); unsigned size = numeral(ram["size"].data);
sufamiturbo.slotA.ram.map(allocate<uint8>(size, 0xff), size); sufamiturboA.ram.map(allocate<uint8>(size, 0xff), size);
interface->loadRequest(ID::SufamiTurboSlotARAM, ram["name"].data); interface->loadRequest(ID::SufamiTurboSlotARAM, ram["name"].data);
memory.append({ID::SufamiTurboSlotARAM, ram["name"].data}); memory.append({ID::SufamiTurboSlotARAM, ram["name"].data});
} }
@ -172,8 +183,9 @@ void Cartridge::load_sufami_turbo_a(const string &manifest) {
} }
} }
void Cartridge::load_sufami_turbo_b(const string &manifest) { void Cartridge::load_sufami_turbo_b() {
auto document = Markup::Document(manifest); interface->loadRequest(ID::SufamiTurboSlotBManifest, "manifest.bml");
auto document = Markup::Document(information.markup.sufamiTurboB);
information.title.sufamiTurboB = document["information/title"].text(); information.title.sufamiTurboB = document["information/title"].text();
auto rom = document["cartridge/rom"]; auto rom = document["cartridge/rom"];
@ -181,13 +193,13 @@ void Cartridge::load_sufami_turbo_b(const string &manifest) {
if(rom["name"].exists()) { if(rom["name"].exists()) {
unsigned size = numeral(rom["size"].data); unsigned size = numeral(rom["size"].data);
sufamiturbo.slotB.rom.map(allocate<uint8>(size, 0xff), size); sufamiturboB.rom.map(allocate<uint8>(size, 0xff), size);
interface->loadRequest(ID::SufamiTurboSlotBROM, rom["name"].data); interface->loadRequest(ID::SufamiTurboSlotBROM, rom["name"].data);
} }
if(ram["name"].exists()) { if(ram["name"].exists()) {
unsigned size = numeral(ram["size"].data); unsigned size = numeral(ram["size"].data);
sufamiturbo.slotB.ram.map(allocate<uint8>(size, 0xff), size); sufamiturboB.ram.map(allocate<uint8>(size, 0xff), size);
interface->loadRequest(ID::SufamiTurboSlotBRAM, ram["name"].data); interface->loadRequest(ID::SufamiTurboSlotBRAM, ram["name"].data);
memory.append({ID::SufamiTurboSlotBRAM, ram["name"].data}); memory.append({ID::SufamiTurboSlotBRAM, ram["name"].data});
} }

View File

@ -61,7 +61,14 @@ struct Cartridge : property<Cartridge> {
vector<Memory> memory; vector<Memory> memory;
struct Information { struct Information {
string markup; struct Markup {
string cartridge;
string gameBoy;
string satellaview;
string sufamiTurboA;
string sufamiTurboB;
} markup;
struct Title { struct Title {
string cartridge; string cartridge;
string gameBoy; string gameBoy;
@ -73,11 +80,7 @@ struct Cartridge : property<Cartridge> {
string title(); string title();
void load(const string &manifest); void load();
void load_super_game_boy(const string &manifest);
void load_satellaview(const string &manifest);
void load_sufami_turbo_a(const string &manifest);
void load_sufami_turbo_b(const string &manifest);
void unload(); void unload();
void serialize(serializer&); void serialize(serializer&);
@ -85,6 +88,11 @@ struct Cartridge : property<Cartridge> {
~Cartridge(); ~Cartridge();
private: private:
void load_super_game_boy();
void load_satellaview();
void load_sufami_turbo_a();
void load_sufami_turbo_b();
void parse_markup(const char*); void parse_markup(const char*);
void parse_markup_map(Mapping&, Markup::Node); void parse_markup_map(Mapping&, Markup::Node);
void parse_markup_memory(MappedRAM&, Markup::Node, unsigned id, bool writable); void parse_markup_memory(MappedRAM&, Markup::Node, unsigned id, bool writable);
@ -108,6 +116,8 @@ private:
void parse_markup_obc1(Markup::Node); void parse_markup_obc1(Markup::Node);
void parse_markup_hsu1(Markup::Node); void parse_markup_hsu1(Markup::Node);
void parse_markup_msu1(Markup::Node); void parse_markup_msu1(Markup::Node);
friend class Interface;
}; };
extern Cartridge cartridge; extern Cartridge cartridge;

View File

@ -135,9 +135,9 @@ void Cartridge::parse_markup_bsxslot(Markup::Node root) {
if(node.name != "map") continue; if(node.name != "map") continue;
if(node["id"].data == "rom") { if(node["id"].data == "rom") {
if(bsxflash.memory.size() == 0) continue; if(satellaviewcartridge.memory.size() == 0) continue;
Mapping m(bsxflash); Mapping m(satellaviewcartridge);
parse_markup_map(m, node); parse_markup_map(m, node);
mapping.append(m); mapping.append(m);
} }
@ -159,7 +159,7 @@ void Cartridge::parse_markup_sufamiturbo(Markup::Node root) {
if(node.name != "map") continue; if(node.name != "map") continue;
if(node["id"].data == "rom") { if(node["id"].data == "rom") {
SuperFamicom::Memory &memory = slotid == 0 ? sufamiturbo.slotA.rom : sufamiturbo.slotB.rom; SuperFamicom::Memory &memory = slotid == 0 ? sufamiturboA.rom : sufamiturboB.rom;
if(memory.size() == 0) continue; if(memory.size() == 0) continue;
Mapping m(memory); Mapping m(memory);
@ -169,7 +169,7 @@ void Cartridge::parse_markup_sufamiturbo(Markup::Node root) {
} }
if(node["id"].data == "ram") { if(node["id"].data == "ram") {
SuperFamicom::Memory &memory = slotid == 0 ? sufamiturbo.slotA.ram : sufamiturbo.slotB.ram; SuperFamicom::Memory &memory = slotid == 0 ? sufamiturboA.ram : sufamiturboB.ram;
if(memory.size() == 0) continue; if(memory.size() == 0) continue;
Mapping m(memory); Mapping m(memory);

View File

@ -4,5 +4,4 @@
namespace SuperFamicom { namespace SuperFamicom {
#include "satellaview/satellaview.cpp" #include "satellaview/satellaview.cpp"
#include "cartridge/cartridge.cpp" #include "cartridge/cartridge.cpp"
#include "flash/flash.cpp"
} }

View File

@ -1,3 +1,2 @@
#include "satellaview/satellaview.hpp" #include "satellaview/satellaview.hpp"
#include "cartridge/cartridge.hpp" #include "cartridge/cartridge.hpp"
#include "flash/flash.hpp"

View File

@ -80,7 +80,7 @@ uint8 BSXCartridge::mcu_access(bool write, unsigned addr, uint8 data) {
|| ((addr & 0x400000) == 0x400000) //$40-7f|c0-ff:0000-ffff || ((addr & 0x400000) == 0x400000) //$40-7f|c0-ff:0000-ffff
) { ) {
if(r02 == 0) addr = ((addr & 0x7f0000) >> 1) | (addr & 0x7fff); if(r02 == 0) addr = ((addr & 0x7f0000) >> 1) | (addr & 0x7fff);
Memory &memory = (r01 == 0 ? (Memory&)bsxflash : (Memory&)psram); Memory &memory = (r01 == 0 ? (Memory&)satellaviewcartridge : (Memory&)psram);
return memory_access(write, memory, addr & 0x7fffff, data); return memory_access(write, memory, addr & 0x7fffff, data);
} }

View File

@ -5,7 +5,6 @@ struct Coprocessor : Thread {
#include <sfc/chip/icd2/icd2.hpp> #include <sfc/chip/icd2/icd2.hpp>
#include <sfc/chip/bsx/bsx.hpp> #include <sfc/chip/bsx/bsx.hpp>
#include <sfc/chip/sufamiturbo/sufamiturbo.hpp>
#include <sfc/chip/nss/nss.hpp> #include <sfc/chip/nss/nss.hpp>
#include <sfc/chip/event/event.hpp> #include <sfc/chip/event/event.hpp>

View File

@ -87,7 +87,7 @@ void MSU1::reset() {
void MSU1::data_open() { void MSU1::data_open() {
if(datafile.open()) datafile.close(); if(datafile.open()) datafile.close();
auto document = Markup::Document(cartridge.information.markup); auto document = Markup::Document(cartridge.information.markup.cartridge);
string name = document["cartridge/msu1/rom/name"].data; string name = document["cartridge/msu1/rom/name"].data;
if(name.empty()) name = "msu1.rom"; if(name.empty()) name = "msu1.rom";
if(datafile.open({interface->path(ID::SuperFamicom), name}, file::mode::read)) { if(datafile.open({interface->path(ID::SuperFamicom), name}, file::mode::read)) {
@ -97,7 +97,7 @@ void MSU1::data_open() {
void MSU1::audio_open() { void MSU1::audio_open() {
if(audiofile.open()) audiofile.close(); if(audiofile.open()) audiofile.close();
auto document = Markup::Document(cartridge.information.markup); auto document = Markup::Document(cartridge.information.markup.cartridge);
string name = {"track-", mmio.audio_track, ".pcm"}; string name = {"track-", mmio.audio_track, ".pcm"};
for(auto &track : document.find("cartridge/msu1/track")) { for(auto &track : document.find("cartridge/msu1/track")) {
if(numeral(track["number"].data) != mmio.audio_track) continue; if(numeral(track["number"].data) != mmio.audio_track) continue;

View File

@ -1,8 +0,0 @@
#ifdef SUFAMITURBO_CPP
void SufamiTurbo::serialize(serializer &s) {
s.array(slotA.ram.data(), slotA.ram.size());
s.array(slotB.ram.data(), slotB.ram.size());
}
#endif

View File

@ -1,19 +0,0 @@
#include <sfc/sfc.hpp>
#define SUFAMITURBO_CPP
namespace SuperFamicom {
#include "serialization.cpp"
SufamiTurbo sufamiturbo;
void SufamiTurbo::load() {
}
void SufamiTurbo::unload() {
slotA.rom.reset();
slotA.ram.reset();
slotB.rom.reset();
slotB.ram.reset();
}
}

View File

@ -1,12 +0,0 @@
struct SufamiTurbo {
struct Slot {
MappedRAM rom;
MappedRAM ram;
} slotA, slotB;
void load();
void unload();
void serialize(serializer&);
};
extern SufamiTurbo sufamiturbo;

View File

@ -31,6 +31,7 @@ unsigned Interface::group(unsigned id) {
switch(id) { switch(id) {
case ID::IPLROM: case ID::IPLROM:
return 0; return 0;
case ID::Manifest:
case ID::ROM: case ID::ROM:
case ID::RAM: case ID::RAM:
case ID::EventROM0: case ID::EventROM0:
@ -70,17 +71,21 @@ unsigned Interface::group(unsigned id) {
case ID::BsxPSRAM: case ID::BsxPSRAM:
return 1; return 1;
case ID::SuperGameBoy: case ID::SuperGameBoy:
case ID::SuperGameBoyManifest:
case ID::SuperGameBoyROM: case ID::SuperGameBoyROM:
case ID::SuperGameBoyRAM: case ID::SuperGameBoyRAM:
return 2; return 2;
case ID::Satellaview: case ID::Satellaview:
case ID::BsxFlashROM: case ID::SatellaviewManifest:
case ID::SatellaviewROM:
return 3; return 3;
case ID::SufamiTurboSlotA: case ID::SufamiTurboSlotA:
case ID::SufamiTurboSlotAManifest:
case ID::SufamiTurboSlotAROM: case ID::SufamiTurboSlotAROM:
case ID::SufamiTurboSlotARAM: case ID::SufamiTurboSlotARAM:
return 4; return 4;
case ID::SufamiTurboSlotB: case ID::SufamiTurboSlotB:
case ID::SufamiTurboSlotBManifest:
case ID::SufamiTurboSlotBROM: case ID::SufamiTurboSlotBROM:
case ID::SufamiTurboSlotBRAM: case ID::SufamiTurboSlotBRAM:
return 5; return 5;
@ -89,12 +94,12 @@ unsigned Interface::group(unsigned id) {
throw; throw;
} }
void Interface::load(unsigned id, const string &manifest) { void Interface::load(unsigned id) {
if(id == ID::SuperFamicom) cartridge.load(manifest); if(id == ID::SuperFamicom) cartridge.load();
if(id == ID::SuperGameBoy) cartridge.load_super_game_boy(manifest); if(id == ID::SuperGameBoy) cartridge.load_super_game_boy();
if(id == ID::Satellaview) cartridge.load_satellaview(manifest); if(id == ID::Satellaview) cartridge.load_satellaview();
if(id == ID::SufamiTurboSlotA) cartridge.load_sufami_turbo_a(manifest); if(id == ID::SufamiTurboSlotA) cartridge.load_sufami_turbo_a();
if(id == ID::SufamiTurboSlotB) cartridge.load_sufami_turbo_b(manifest); if(id == ID::SufamiTurboSlotB) cartridge.load_sufami_turbo_b();
} }
void Interface::save() { void Interface::save() {
@ -103,11 +108,12 @@ void Interface::save() {
} }
} }
void Interface::load(unsigned id, const stream &stream, const string &manifest) { void Interface::load(unsigned id, const stream &stream) {
if(id == ID::IPLROM) { if(id == ID::IPLROM) {
stream.read(smp.iplrom, min(64u, stream.size())); stream.read(smp.iplrom, min(64u, stream.size()));
} }
if(id == ID::Manifest) cartridge.information.markup.cartridge = stream.text();
if(id == ID::ROM) cartridge.rom.read(stream); if(id == ID::ROM) cartridge.rom.read(stream);
if(id == ID::RAM) cartridge.ram.read(stream); if(id == ID::RAM) cartridge.ram.read(stream);
@ -187,6 +193,12 @@ void Interface::load(unsigned id, const stream &stream, const string &manifest)
stream.read(GameBoy::system.bootROM.sgb, min(stream.size(), 256u)); stream.read(GameBoy::system.bootROM.sgb, min(stream.size(), 256u));
} }
if(id == ID::BsxROM) bsxcartridge.rom.read(stream);
if(id == ID::BsxRAM) bsxcartridge.ram.read(stream);
if(id == ID::BsxPSRAM) bsxcartridge.psram.read(stream);
if(id == ID::SuperGameBoyManifest) cartridge.information.markup.gameBoy = stream.text();
if(id == ID::SuperGameBoyROM) { if(id == ID::SuperGameBoyROM) {
stream.read(GameBoy::cartridge.romdata, min(GameBoy::cartridge.romsize, stream.size())); stream.read(GameBoy::cartridge.romdata, min(GameBoy::cartridge.romsize, stream.size()));
} }
@ -195,16 +207,16 @@ void Interface::load(unsigned id, const stream &stream, const string &manifest)
stream.read(GameBoy::cartridge.ramdata, min(GameBoy::cartridge.ramsize, stream.size())); stream.read(GameBoy::cartridge.ramdata, min(GameBoy::cartridge.ramsize, stream.size()));
} }
if(id == ID::BsxFlashROM) bsxflash.memory.read(stream); if(id == ID::SatellaviewManifest) cartridge.information.markup.satellaview = stream.text();
if(id == ID::BsxROM) bsxcartridge.rom.read(stream); if(id == ID::SatellaviewROM) satellaviewcartridge.memory.read(stream);
if(id == ID::BsxRAM) bsxcartridge.ram.read(stream);
if(id == ID::BsxPSRAM) bsxcartridge.psram.read(stream);
if(id == ID::SufamiTurboSlotAROM) sufamiturbo.slotA.rom.read(stream); if(id == ID::SufamiTurboSlotAManifest) cartridge.information.markup.sufamiTurboA = stream.text();
if(id == ID::SufamiTurboSlotBROM) sufamiturbo.slotB.rom.read(stream); if(id == ID::SufamiTurboSlotAROM) sufamiturboA.rom.read(stream);
if(id == ID::SufamiTurboSlotBROM) sufamiturboB.rom.read(stream);
if(id == ID::SufamiTurboSlotARAM) sufamiturbo.slotA.ram.read(stream); if(id == ID::SufamiTurboSlotBManifest) cartridge.information.markup.sufamiTurboB = stream.text();
if(id == ID::SufamiTurboSlotBRAM) sufamiturbo.slotB.ram.read(stream); if(id == ID::SufamiTurboSlotARAM) sufamiturboA.ram.read(stream);
if(id == ID::SufamiTurboSlotBRAM) sufamiturboB.ram.read(stream);
} }
void Interface::save(unsigned id, const stream &stream) { void Interface::save(unsigned id, const stream &stream) {
@ -251,8 +263,8 @@ void Interface::save(unsigned id, const stream &stream) {
if(id == ID::BsxRAM) stream.write(bsxcartridge.ram.data(), bsxcartridge.ram.size()); if(id == ID::BsxRAM) stream.write(bsxcartridge.ram.data(), bsxcartridge.ram.size());
if(id == ID::BsxPSRAM) stream.write(bsxcartridge.psram.data(), bsxcartridge.psram.size()); if(id == ID::BsxPSRAM) stream.write(bsxcartridge.psram.data(), bsxcartridge.psram.size());
if(id == ID::SufamiTurboSlotARAM) stream.write(sufamiturbo.slotA.ram.data(), sufamiturbo.slotA.ram.size()); if(id == ID::SufamiTurboSlotARAM) stream.write(sufamiturboA.ram.data(), sufamiturboA.ram.size());
if(id == ID::SufamiTurboSlotBRAM) stream.write(sufamiturbo.slotB.ram.data(), sufamiturbo.slotB.ram.size()); if(id == ID::SufamiTurboSlotBRAM) stream.write(sufamiturboB.ram.data(), sufamiturboB.ram.size());
} }
void Interface::unload() { void Interface::unload() {
@ -376,9 +388,9 @@ Interface::Interface() {
information.capability.cheats = true; information.capability.cheats = true;
media.append({ID::SuperFamicom, "Super Famicom", "sfc", true }); media.append({ID::SuperFamicom, "Super Famicom", "sfc", true });
media.append({ID::SuperFamicom, "Super Famicom", "gb", false}); media.append({ID::SuperFamicom, "Game Boy", "gb", false});
media.append({ID::SuperFamicom, "Super Famicom", "bs", false}); media.append({ID::SuperFamicom, "BS-X Satellaview", "bs", false});
media.append({ID::SuperFamicom, "Super Famicom", "st", false}); media.append({ID::SuperFamicom, "Sufami Turbo", "st", false});
{ {
Device device{0, ID::Port1 | ID::Port2, "Controller"}; Device device{0, ID::Port1 | ID::Port2, "Controller"};

View File

@ -15,6 +15,7 @@ struct ID {
//memory (files) //memory (files)
IPLROM, IPLROM,
Manifest,
ROM, ROM,
RAM, RAM,
@ -61,17 +62,24 @@ struct ID {
OBC1RAM, OBC1RAM,
SuperGameBoyBootROM, SuperGameBoyBootROM,
SuperGameBoyROM,
SuperGameBoyRAM,
BsxFlashROM,
BsxROM, BsxROM,
BsxRAM, BsxRAM,
BsxPSRAM, BsxPSRAM,
SuperGameBoyManifest,
SuperGameBoyROM,
SuperGameBoyRAM,
SatellaviewManifest,
SatellaviewROM,
SufamiTurboSlotAManifest,
SufamiTurboSlotAROM, SufamiTurboSlotAROM,
SufamiTurboSlotBROM,
SufamiTurboSlotARAM, SufamiTurboSlotARAM,
SufamiTurboSlotBManifest,
SufamiTurboSlotBROM,
SufamiTurboSlotBRAM, SufamiTurboSlotBRAM,
//controller ports //controller ports
@ -88,9 +96,9 @@ struct Interface : Emulator::Interface {
bool loaded(); bool loaded();
string sha256(); string sha256();
unsigned group(unsigned id); unsigned group(unsigned id);
void load(unsigned id, const string &manifest); void load(unsigned id);
void save(); void save();
void load(unsigned id, const stream &stream, const string &markup = ""); void load(unsigned id, const stream &stream);
void save(unsigned id, const stream &stream); void save(unsigned id, const stream &stream);
void unload(); void unload();

View File

@ -66,6 +66,7 @@ namespace SuperFamicom {
#include <sfc/controller/controller.hpp> #include <sfc/controller/controller.hpp>
#include <sfc/system/system.hpp> #include <sfc/system/system.hpp>
#include <sfc/chip/chip.hpp> #include <sfc/chip/chip.hpp>
#include <sfc/slot/slot.hpp>
#include <sfc/cartridge/cartridge.hpp> #include <sfc/cartridge/cartridge.hpp>
#include <sfc/cheat/cheat.hpp> #include <sfc/cheat/cheat.hpp>
#include <sfc/interface/interface.hpp> #include <sfc/interface/interface.hpp>

View File

@ -1,24 +1,27 @@
#ifdef BSX_CPP #include <sfc/sfc.hpp>
BSXFlash bsxflash; #define SATELLAVIEW_CARTRIDGE_CPP
namespace SuperFamicom {
void BSXFlash::init() { SatellaviewCartridge satellaviewcartridge;
void SatellaviewCartridge::init() {
} }
void BSXFlash::load() { void SatellaviewCartridge::load() {
if(memory.size() == 0) { if(memory.size() == 0) {
memory.map(allocate<uint8>(1024 * 1024, 0xff), 1024 * 1024); memory.map(allocate<uint8>(1024 * 1024, 0xff), 1024 * 1024);
} }
} }
void BSXFlash::unload() { void SatellaviewCartridge::unload() {
memory.reset(); memory.reset();
} }
void BSXFlash::power() { void SatellaviewCartridge::power() {
} }
void BSXFlash::reset() { void SatellaviewCartridge::reset() {
regs.command = 0; regs.command = 0;
regs.write_old = 0x00; regs.write_old = 0x00;
regs.write_new = 0x00; regs.write_new = 0x00;
@ -29,11 +32,11 @@ void BSXFlash::reset() {
memory.write_protect(!regs.write_enable); memory.write_protect(!regs.write_enable);
} }
unsigned BSXFlash::size() const { unsigned SatellaviewCartridge::size() const {
return memory.size(); return memory.size();
} }
uint8 BSXFlash::read(unsigned addr) { uint8 SatellaviewCartridge::read(unsigned addr) {
if(readonly) return memory.read(bus.mirror(addr, memory.size())); if(readonly) return memory.read(bus.mirror(addr, memory.size()));
if(addr == 0x0002) { if(addr == 0x0002) {
@ -62,7 +65,7 @@ uint8 BSXFlash::read(unsigned addr) {
return memory.read(addr); return memory.read(addr);
} }
void BSXFlash::write(unsigned addr, uint8 data) { void SatellaviewCartridge::write(unsigned addr, uint8 data) {
if(readonly) return; if(readonly) return;
if((addr & 0xff0000) == 0) { if((addr & 0xff0000) == 0) {
@ -118,4 +121,4 @@ void BSXFlash::write(unsigned addr, uint8 data) {
} }
} }
#endif }

View File

@ -1,4 +1,4 @@
struct BSXFlash : Memory { struct SatellaviewCartridge : Memory {
MappedRAM memory; MappedRAM memory;
bool readonly; bool readonly;
@ -24,4 +24,4 @@ private:
} regs; } regs;
}; };
extern BSXFlash bsxflash; extern SatellaviewCartridge satellaviewcartridge;

2
higan/sfc/slot/slot.hpp Normal file
View File

@ -0,0 +1,2 @@
#include <sfc/slot/satellaview/satellaview.hpp>
#include <sfc/slot/sufamiturbo/sufamiturbo.hpp>

View File

@ -0,0 +1,7 @@
#ifdef SUFAMITURBO_CPP
void SufamiTurboCartridge::serialize(serializer &s) {
s.array(ram.data(), ram.size());
}
#endif

View File

@ -0,0 +1,18 @@
#include <sfc/sfc.hpp>
#define SUFAMITURBO_CPP
namespace SuperFamicom {
#include "serialization.cpp"
SufamiTurboCartridge sufamiturboA;
SufamiTurboCartridge sufamiturboB;
void SufamiTurboCartridge::load() {
}
void SufamiTurboCartridge::unload() {
rom.reset();
ram.reset();
}
}

View File

@ -0,0 +1,11 @@
struct SufamiTurboCartridge {
MappedRAM rom;
MappedRAM ram;
void load();
void unload();
void serialize(serializer&);
};
extern SufamiTurboCartridge sufamiturboA;
extern SufamiTurboCartridge sufamiturboB;

View File

@ -59,7 +59,6 @@ void System::serialize_all(serializer &s) {
if(cartridge.has_gb_slot()) icd2.serialize(s); if(cartridge.has_gb_slot()) icd2.serialize(s);
if(cartridge.has_bs_cart()) bsxcartridge.serialize(s); if(cartridge.has_bs_cart()) bsxcartridge.serialize(s);
if(cartridge.has_st_slots()) sufamiturbo.serialize(s);
if(cartridge.has_event()) event.serialize(s); if(cartridge.has_event()) event.serialize(s);
if(cartridge.has_sa1()) sa1.serialize(s); if(cartridge.has_sa1()) sa1.serialize(s);
if(cartridge.has_superfx()) superfx.serialize(s); if(cartridge.has_superfx()) superfx.serialize(s);
@ -73,6 +72,7 @@ void System::serialize_all(serializer &s) {
if(cartridge.has_obc1()) obc1.serialize(s); if(cartridge.has_obc1()) obc1.serialize(s);
if(cartridge.has_hsu1()) hsu1.serialize(s); if(cartridge.has_hsu1()) hsu1.serialize(s);
if(cartridge.has_msu1()) msu1.serialize(s); if(cartridge.has_msu1()) msu1.serialize(s);
if(cartridge.has_st_slots()) sufamiturboA.serialize(s), sufamiturboB.serialize(s);
} }
//perform dry-run state save: //perform dry-run state save:

View File

@ -67,7 +67,6 @@ void System::init() {
bsxsatellaview.init(); bsxsatellaview.init();
icd2.init(); icd2.init();
bsxcartridge.init(); bsxcartridge.init();
bsxflash.init();
nss.init(); nss.init();
event.init(); event.init();
sa1.init(); sa1.init();
@ -82,6 +81,7 @@ void System::init() {
obc1.init(); obc1.init();
hsu1.init(); hsu1.init();
msu1.init(); msu1.init();
satellaviewcartridge.init();
video.init(); video.init();
audio.init(); audio.init();
@ -122,8 +122,6 @@ void System::load() {
if(expansion() == ExpansionPortDevice::BSX) bsxsatellaview.load(); if(expansion() == ExpansionPortDevice::BSX) bsxsatellaview.load();
if(cartridge.has_gb_slot()) icd2.load(); if(cartridge.has_gb_slot()) icd2.load();
if(cartridge.has_bs_cart()) bsxcartridge.load(); if(cartridge.has_bs_cart()) bsxcartridge.load();
if(cartridge.has_bs_slot()) bsxflash.load();
if(cartridge.has_st_slots()) sufamiturbo.load();
if(cartridge.has_nss_dip()) nss.load(); if(cartridge.has_nss_dip()) nss.load();
if(cartridge.has_event()) event.load(); if(cartridge.has_event()) event.load();
if(cartridge.has_sa1()) sa1.load(); if(cartridge.has_sa1()) sa1.load();
@ -138,6 +136,8 @@ void System::load() {
if(cartridge.has_obc1()) obc1.load(); if(cartridge.has_obc1()) obc1.load();
if(cartridge.has_hsu1()) hsu1.load(); if(cartridge.has_hsu1()) hsu1.load();
if(cartridge.has_msu1()) msu1.load(); if(cartridge.has_msu1()) msu1.load();
if(cartridge.has_bs_slot()) satellaviewcartridge.load();
if(cartridge.has_st_slots()) sufamiturboA.load(), sufamiturboB.load();
serialize_init(); serialize_init();
cheat.init(); cheat.init();
@ -147,8 +147,6 @@ void System::unload() {
if(expansion() == ExpansionPortDevice::BSX) bsxsatellaview.unload(); if(expansion() == ExpansionPortDevice::BSX) bsxsatellaview.unload();
if(cartridge.has_gb_slot()) icd2.unload(); if(cartridge.has_gb_slot()) icd2.unload();
if(cartridge.has_bs_cart()) bsxcartridge.unload(); if(cartridge.has_bs_cart()) bsxcartridge.unload();
if(cartridge.has_bs_slot()) bsxflash.unload();
if(cartridge.has_st_slots()) sufamiturbo.unload();
if(cartridge.has_nss_dip()) nss.unload(); if(cartridge.has_nss_dip()) nss.unload();
if(cartridge.has_event()) event.unload(); if(cartridge.has_event()) event.unload();
if(cartridge.has_sa1()) sa1.unload(); if(cartridge.has_sa1()) sa1.unload();
@ -163,6 +161,8 @@ void System::unload() {
if(cartridge.has_obc1()) obc1.unload(); if(cartridge.has_obc1()) obc1.unload();
if(cartridge.has_hsu1()) hsu1.unload(); if(cartridge.has_hsu1()) hsu1.unload();
if(cartridge.has_msu1()) msu1.unload(); if(cartridge.has_msu1()) msu1.unload();
if(cartridge.has_bs_slot()) satellaviewcartridge.unload();
if(cartridge.has_st_slots()) sufamiturboA.unload(), sufamiturboB.unload();
} }
void System::power() { void System::power() {
@ -176,7 +176,6 @@ void System::power() {
if(expansion() == ExpansionPortDevice::BSX) bsxsatellaview.power(); if(expansion() == ExpansionPortDevice::BSX) bsxsatellaview.power();
if(cartridge.has_gb_slot()) icd2.power(); if(cartridge.has_gb_slot()) icd2.power();
if(cartridge.has_bs_cart()) bsxcartridge.power(); if(cartridge.has_bs_cart()) bsxcartridge.power();
if(cartridge.has_bs_slot()) bsxflash.power();
if(cartridge.has_nss_dip()) nss.power(); if(cartridge.has_nss_dip()) nss.power();
if(cartridge.has_event()) event.power(); if(cartridge.has_event()) event.power();
if(cartridge.has_sa1()) sa1.power(); if(cartridge.has_sa1()) sa1.power();
@ -191,6 +190,7 @@ void System::power() {
if(cartridge.has_obc1()) obc1.power(); if(cartridge.has_obc1()) obc1.power();
if(cartridge.has_hsu1()) hsu1.power(); if(cartridge.has_hsu1()) hsu1.power();
if(cartridge.has_msu1()) msu1.power(); if(cartridge.has_msu1()) msu1.power();
if(cartridge.has_bs_slot()) satellaviewcartridge.power();
reset(); reset();
} }
@ -204,7 +204,6 @@ void System::reset() {
if(expansion() == ExpansionPortDevice::BSX) bsxsatellaview.reset(); if(expansion() == ExpansionPortDevice::BSX) bsxsatellaview.reset();
if(cartridge.has_gb_slot()) icd2.reset(); if(cartridge.has_gb_slot()) icd2.reset();
if(cartridge.has_bs_cart()) bsxcartridge.reset(); if(cartridge.has_bs_cart()) bsxcartridge.reset();
if(cartridge.has_bs_slot()) bsxflash.reset();
if(cartridge.has_nss_dip()) nss.reset(); if(cartridge.has_nss_dip()) nss.reset();
if(cartridge.has_event()) event.reset(); if(cartridge.has_event()) event.reset();
if(cartridge.has_sa1()) sa1.reset(); if(cartridge.has_sa1()) sa1.reset();
@ -219,6 +218,7 @@ void System::reset() {
if(cartridge.has_obc1()) obc1.reset(); if(cartridge.has_obc1()) obc1.reset();
if(cartridge.has_hsu1()) hsu1.reset(); if(cartridge.has_hsu1()) hsu1.reset();
if(cartridge.has_msu1()) msu1.reset(); if(cartridge.has_msu1()) msu1.reset();
if(cartridge.has_bs_slot()) satellaviewcartridge.reset();
if(cartridge.has_gb_slot()) cpu.coprocessors.append(&icd2); if(cartridge.has_gb_slot()) cpu.coprocessors.append(&icd2);
if(cartridge.has_event()) cpu.coprocessors.append(&event); if(cartridge.has_event()) cpu.coprocessors.append(&event);

View File

@ -79,7 +79,7 @@ Application::Application(int argc, char **argv) {
hotkeySettings = new HotkeySettings; hotkeySettings = new HotkeySettings;
timingSettings = new TimingSettings; timingSettings = new TimingSettings;
serverSettings = new ServerSettings; serverSettings = new ServerSettings;
driverSettings = new DriverSettings; advancedSettings = new AdvancedSettings;
settings = new Settings; settings = new Settings;
cheatDatabase = new CheatDatabase; cheatDatabase = new CheatDatabase;
cheatEditor = new CheatEditor; cheatEditor = new CheatEditor;
@ -106,7 +106,7 @@ Application::Application(int argc, char **argv) {
utility->synchronizeRuby(); utility->synchronizeRuby();
utility->updateShader(); utility->updateShader();
if(config->video.startFullScreen) utility->toggleFullScreen(); if(config->video.startFullScreen && argc >= 2) utility->toggleFullScreen();
OS::processEvents(); OS::processEvents();
if(argc >= 2) utility->loadMedia(argv[1]); if(argc >= 2) utility->loadMedia(argv[1]);

View File

@ -28,7 +28,10 @@ Browser::Browser() {
}; };
homeButton.onActivate = [&] { homeButton.onActivate = [&] {
setPath({userpath(), "Emulation/"}); string libraryPath = string::read({configpath(), "higan/library.cfg"}).strip();
if(libraryPath.empty()) libraryPath = {userpath(), "Emulation/"};
if(libraryPath.endswith("/") == false) libraryPath.append("/");
setPath(libraryPath);
}; };
upButton.onActivate = [&] { upButton.onActivate = [&] {
@ -164,7 +167,12 @@ void Browser::setPath(const string &path, unsigned selection) {
string name = filename; string name = filename;
name.rtrim<1>(suffix); name.rtrim<1>(suffix);
fileList.append(name); fileList.append(name);
if(1 || file::exists({path, filename, "unverified"}) == false) {
fileList.setImage(filenameList.size(), 0, {resource::game, sizeof resource::game}); fileList.setImage(filenameList.size(), 0, {resource::game, sizeof resource::game});
} else {
//disabled for now due to performance penalty
fileList.setImage(filenameList.size(), 0, {resource::unverified, sizeof resource::unverified});
}
filenameList.append(filename); filenameList.append(filename);
} }
} }

View File

@ -3,3 +3,4 @@ resource name=resource
binary id=up name=up.png binary id=up name=up.png
binary id=folder name=folder.png binary id=folder name=folder.png
binary id=game name=game.png binary id=game name=game.png
binary id=unverified name=unverified.png

View File

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

View File

@ -3,4 +3,5 @@ namespace resource {
extern const uint8_t up[652]; extern const uint8_t up[652];
extern const uint8_t folder[1176]; extern const uint8_t folder[1176];
extern const uint8_t game[1490]; extern const uint8_t game[1490];
extern const uint8_t unverified[1675];
}; };

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,81 @@
AdvancedSettings *advancedSettings = nullptr;
AdvancedSettings::AdvancedSettings() {
driverTitle.setFont(application->titleFont);
driverTitle.setText("Driver Selection");
videoLabel.setText("Video:");
audioLabel.setText("Audio:");
inputLabel.setText("Input:");
libraryTitle.setFont(application->titleFont);
libraryTitle.setText("Game Library Path");
libraryLabel.setText("Path:");
libraryPath.setEditable(false);
string path = string::read({configpath(), "higan/library.cfg"}).strip().transform("\\", "/");
if(path.empty()) path = {userpath(), "Emulation/"};
if(path.endswith("/") == false) path.append("/");
libraryPath.setText(path);
libraryBrowse.setText("Browse ...");
infoLabel.setFont(application->boldFont);
string profile;
#if defined(PROFILE_ACCURACY)
profile = "Accuracy";
#elif defined(PROFILE_BALANCED)
profile = "Balanced";
#elif defined(PROFILE_PERFORMANCE)
profile = "Performance";
#endif
infoLabel.setText({
Emulator::Name, " v", Emulator::Version, "\n",
" ", profile, " Profile\n",
" Author: byuu\n",
" Website: http://byuu.org/\n",
" License: GPLv3"
});
lstring list;
list.split(";", video.driver_list());
for(unsigned n = 0; n < list.size(); n++) {
videoDriver.append(list[n]);
if(list[n] == config->video.driver) videoDriver.setSelection(n);
}
list.split(";", audio.driver_list());
for(unsigned n = 0; n < list.size(); n++) {
audioDriver.append(list[n]);
if(list[n] == config->audio.driver) audioDriver.setSelection(n);
}
list.split(";", input.driver_list());
for(unsigned n = 0; n < list.size(); n++) {
inputDriver.append(list[n]);
if(list[n] == config->input.driver) inputDriver.setSelection(n);
}
append(driverTitle, {~0, 0}, 5);
append(driverLayout, {~0, 0}, 15);
driverLayout.append(videoLabel, {0, 0}, 5);
driverLayout.append(videoDriver, {~0, 0}, 5);
driverLayout.append(audioLabel, {0, 0}, 5);
driverLayout.append(audioDriver, {~0, 0}, 5);
driverLayout.append(inputLabel, {0, 0}, 5);
driverLayout.append(inputDriver, {~0, 0});
append(libraryTitle, {~0, 0}, 5);
append(libraryLayout, {~0, 0}, 15);
libraryLayout.append(libraryLabel, {0, 0}, 5);
libraryLayout.append(libraryPath, {~0, 0}, 5);
libraryLayout.append(libraryBrowse, {80, 0});
append(spacer, {~0, ~0});
append(infoLabel, {~0, 0});
videoDriver.onChange = [&] { config->video.driver = videoDriver.text(); };
audioDriver.onChange = [&] { config->audio.driver = audioDriver.text(); };
inputDriver.onChange = [&] { config->input.driver = inputDriver.text(); };
libraryBrowse.onActivate = [&] {
string path = DialogWindow::folderSelect(Window::none(), userpath());
if(path.empty()) return;
file::write({configpath(), "higan/library.cfg"}, path);
libraryPath.setText(path);
};
}

View File

@ -0,0 +1,23 @@
struct AdvancedSettings : SettingsLayout {
Label driverTitle;
HorizontalLayout driverLayout;
Label videoLabel;
ComboBox videoDriver;
Label audioLabel;
ComboBox audioDriver;
Label inputLabel;
ComboBox inputDriver;
Label libraryTitle;
HorizontalLayout libraryLayout;
Label libraryLabel;
LineEdit libraryPath;
Button libraryBrowse;
Widget spacer;
Label infoLabel;
AdvancedSettings();
};
extern AdvancedSettings *advancedSettings;

View File

@ -1,42 +0,0 @@
DriverSettings *driverSettings = nullptr;
DriverSettings::DriverSettings() {
title.setFont(application->titleFont);
title.setText("Driver Configuration");
videoLabel.setText("Video:");
audioLabel.setText("Audio:");
inputLabel.setText("Input:");
lstring list;
list.split(";", video.driver_list());
for(unsigned n = 0; n < list.size(); n++) {
videoDriver.append(list[n]);
if(list[n] == config->video.driver) videoDriver.setSelection(n);
}
list.split(";", audio.driver_list());
for(unsigned n = 0; n < list.size(); n++) {
audioDriver.append(list[n]);
if(list[n] == config->audio.driver) audioDriver.setSelection(n);
}
list.split(";", input.driver_list());
for(unsigned n = 0; n < list.size(); n++) {
inputDriver.append(list[n]);
if(list[n] == config->input.driver) inputDriver.setSelection(n);
}
append(title, {~0, 0}, 5);
append(driverLayout, {~0, 0});
driverLayout.append(videoLabel, {0, 0}, 5);
driverLayout.append(videoDriver, {~0, 0}, 5);
driverLayout.append(audioLabel, {0, 0}, 5);
driverLayout.append(audioDriver, {~0, 0}, 5);
driverLayout.append(inputLabel, {0, 0}, 5);
driverLayout.append(inputDriver, {~0, 0});
videoDriver.onChange = [&] { config->video.driver = videoDriver.text(); };
audioDriver.onChange = [&] { config->audio.driver = audioDriver.text(); };
inputDriver.onChange = [&] { config->input.driver = inputDriver.text(); };
}

View File

@ -1,14 +0,0 @@
struct DriverSettings : SettingsLayout {
Label title;
HorizontalLayout driverLayout;
Label videoLabel;
ComboBox videoDriver;
Label audioLabel;
ComboBox audioDriver;
Label inputLabel;
ComboBox inputDriver;
DriverSettings();
};
extern DriverSettings *driverSettings;

View File

@ -5,7 +5,7 @@
#include "hotkey.cpp" #include "hotkey.cpp"
#include "timing.cpp" #include "timing.cpp"
#include "server.cpp" #include "server.cpp"
#include "driver.cpp" #include "advanced.cpp"
Settings *settings = nullptr; Settings *settings = nullptr;
void SettingsLayout::append(Sizable &sizable, const Size &size, unsigned spacing) { void SettingsLayout::append(Sizable &sizable, const Size &size, unsigned spacing) {
@ -33,7 +33,7 @@ Settings::Settings() {
panelList.append("Hotkeys"); panelList.append("Hotkeys");
panelList.append("Timing"); panelList.append("Timing");
panelList.append("Server"); panelList.append("Server");
panelList.append("Driver"); panelList.append("Advanced");
append(layout); append(layout);
layout.append(panelList, {120, ~0}, 5); layout.append(panelList, {120, ~0}, 5);
@ -43,7 +43,7 @@ Settings::Settings() {
append(*hotkeySettings); append(*hotkeySettings);
append(*timingSettings); append(*timingSettings);
append(*serverSettings); append(*serverSettings);
append(*driverSettings); append(*advancedSettings);
onClose = [&] { onClose = [&] {
timingSettings->analysis.stop = true; timingSettings->analysis.stop = true;
@ -63,7 +63,7 @@ void Settings::panelChanged() {
hotkeySettings->setVisible(false); hotkeySettings->setVisible(false);
timingSettings->setVisible(false); timingSettings->setVisible(false);
serverSettings->setVisible(false); serverSettings->setVisible(false);
driverSettings->setVisible(false); advancedSettings->setVisible(false);
if(panelList.selected() == false) return; if(panelList.selected() == false) return;
switch(panelList.selection()) { switch(panelList.selection()) {
@ -73,6 +73,6 @@ void Settings::panelChanged() {
case 3: return hotkeySettings->setVisible(); case 3: return hotkeySettings->setVisible();
case 4: return timingSettings->setVisible(); case 4: return timingSettings->setVisible();
case 5: return serverSettings->setVisible(); case 5: return serverSettings->setVisible();
case 6: return driverSettings->setVisible(); case 6: return advancedSettings->setVisible();
} }
} }

View File

@ -12,7 +12,7 @@ struct SettingsLayout : HorizontalLayout {
#include "hotkey.hpp" #include "hotkey.hpp"
#include "timing.hpp" #include "timing.hpp"
#include "server.hpp" #include "server.hpp"
#include "driver.hpp" #include "advanced.hpp"
struct Settings : Window { struct Settings : Window {
HorizontalLayout layout; HorizontalLayout layout;

View File

@ -41,7 +41,6 @@ void Utility::loadMedia(string pathname) {
void Utility::loadMedia(Emulator::Interface *emulator, Emulator::Interface::Media &media) { void Utility::loadMedia(Emulator::Interface *emulator, Emulator::Interface::Media &media) {
string pathname = browser->select({"Load ", media.name}, media.type); string pathname = browser->select({"Load ", media.name}, media.type);
if(!directory::exists(pathname)) return; if(!directory::exists(pathname)) return;
if(!file::exists({pathname, "manifest.bml"})) return;
return loadMedia(emulator, media, pathname); return loadMedia(emulator, media, pathname);
} }
@ -53,7 +52,7 @@ void Utility::loadMedia(Emulator::Interface *emulator, Emulator::Interface::Medi
path(media.id) = pathname; path(media.id) = pathname;
this->pathname.append(pathname); this->pathname.append(pathname);
system().load(media.id, string::read({pathname, "manifest.bml"})); system().load(media.id);
system().power(); system().power();
presentation->setSystemName(media.name); presentation->setSystemName(media.name);
@ -67,7 +66,7 @@ void Utility::loadRequest(unsigned id, const string &name, const string &type) {
path(id) = pathname; path(id) = pathname;
this->pathname.append(pathname); this->pathname.append(pathname);
system().load(id, string::read({pathname, "manifest.bml"})); system().load(id);
} }
//request from emulation core to load non-volatile media file //request from emulation core to load non-volatile media file

View File

@ -36,16 +36,16 @@ endif
ifeq ($(compiler),) ifeq ($(compiler),)
ifeq ($(platform),win) ifeq ($(platform),win)
compiler := gcc compiler := g++
else ifeq ($(platform),osx) else ifeq ($(platform),osx)
compiler := gcc-mp-4.7 compiler := g++-mp-4.7
else else
compiler := gcc-4.7 compiler := g++-4.7
endif endif
endif endif
c := $(compiler) -std=gnu99 c := $(compiler) -x c -std=gnu99
cpp := $(subst cc,++,$(compiler)) -std=gnu++11 cpp := $(compiler) -std=gnu++11
ifeq ($(arch),x86) ifeq ($(arch),x86)
c := $(c) -m32 c := $(c) -m32

View File

@ -98,6 +98,14 @@ namespace nall {
return true; return true;
} }
static bool create(const string &filename) {
//create an empty file (will replace existing files)
file fp;
if(fp.open(filename, mode::write) == false) return false;
fp.close();
return true;
}
static string sha256(const string &filename) { static string sha256(const string &filename) {
auto buffer = read(filename); auto buffer = read(filename);
return nall::sha256(buffer.data(), buffer.size()); return nall::sha256(buffer.data(), buffer.size());

View File

@ -48,6 +48,15 @@ struct stream {
while(length--) *data++ = read(); while(length--) *data++ = read();
} }
string text() const {
string buffer;
buffer.resize(size() + 1);
buffer[size()] = 0;
seek(0);
read((uint8_t*)buffer(), size());
return buffer;
}
void writel(uintmax_t data, unsigned length = 1) const { void writel(uintmax_t data, unsigned length = 1) const {
while(length--) { while(length--) {
write(data); write(data);

View File

@ -23,6 +23,7 @@ namespace nall {
struct string { struct string {
inline static string read(const string &filename); inline static string read(const string &filename);
inline static string date(); inline static string date();
inline static string time(); inline static string time();
inline static string datetime(); inline static string datetime();

View File

@ -33,11 +33,13 @@ string realpath(const string &name) {
return result; return result;
} }
// /home/username/
// c:/users/username/
string userpath() { string userpath() {
string result; string result;
#ifdef _WIN32 #ifdef _WIN32
wchar_t path[PATH_MAX] = L""; wchar_t path[PATH_MAX] = L"";
SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, path); SHGetFolderPathW(0, CSIDL_PROFILE | CSIDL_FLAG_CREATE, 0, 0, path);
result = (const char*)utf8_t(path); result = (const char*)utf8_t(path);
result.transform("\\", "/"); result.transform("\\", "/");
#else #else
@ -51,20 +53,30 @@ string userpath() {
return result; return result;
} }
// /home/username/.config/
// c:/users/username/appdata/roaming/
string configpath() { string configpath() {
string result;
#ifdef _WIN32 #ifdef _WIN32
return userpath(); wchar_t path[PATH_MAX] = L"";
SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, path);
result = (const char*)utf8_t(path);
result.transform("\\", "/");
#else #else
return {userpath(), ".config/"}; result = {userpath(), ".config/"};
#endif #endif
if(result.empty()) result = ".";
if(result.endswith("/") == false) result.append("/");
return result;
} }
string temppath() { string temppath() {
#ifdef _WIN32 #ifdef _WIN32
wchar_t path[PATH_MAX] = L""; wchar_t path[PATH_MAX] = L"";
GetTempPathW(PATH_MAX, path); GetTempPathW(PATH_MAX, path);
//path.transform("\\", "/"); string result = (const char*)utf8_t(path);
return (const char*)utf8_t(path); result.transform("\\", "/");
return result;
#else #else
return "/tmp/"; return "/tmp/";
#endif #endif

View File

@ -13,6 +13,7 @@ namespace nall {
struct thread { struct thread {
thread(function<void ()> entryPoint) : entryPoint(entryPoint), completed(false), dead(false) { thread(function<void ()> entryPoint) : entryPoint(entryPoint), completed(false), dead(false) {
initialize();
pthread_create(&pthread, NULL, thread_entry_point, (void*)this); pthread_create(&pthread, NULL, thread_entry_point, (void*)this);
} }
@ -30,11 +31,28 @@ namespace nall {
pthread_join(pthread, NULL); pthread_join(pthread, NULL);
} }
static bool primary() {
initialize();
return pthread_equal(primaryThread(), pthread_self());
}
private: private:
pthread_t pthread; pthread_t pthread;
function<void ()> entryPoint; function<void ()> entryPoint;
volatile bool completed, dead; volatile bool completed, dead;
friend void* thread_entry_point(void*); friend void* thread_entry_point(void*);
static void initialize() {
static bool initialized = false;
if(initialized) return;
initialized = true;
primaryThread() = pthread_self();
}
static pthread_t& primaryThread() {
static pthread_t thread;
return thread;
}
}; };
void* thread_entry_point(void *parameter) { void* thread_entry_point(void *parameter) {
@ -50,6 +68,7 @@ namespace nall {
struct thread { struct thread {
thread(function<void ()> entryPoint) : entryPoint(entryPoint), completed(false), dead(false) { thread(function<void ()> entryPoint) : entryPoint(entryPoint), completed(false), dead(false) {
initialize();
hthread = CreateThread(NULL, 0, thread_entry_point, (void*)this, 0, NULL); hthread = CreateThread(NULL, 0, thread_entry_point, (void*)this, 0, NULL);
} }
@ -68,11 +87,28 @@ namespace nall {
CloseHandle(hthread); CloseHandle(hthread);
} }
static bool primary() {
initialize();
return primaryThread() == GetCurrentThreadId();
}
private: private:
HANDLE hthread; HANDLE hthread;
function<void ()> entryPoint; function<void ()> entryPoint;
volatile bool completed, dead; volatile bool completed, dead;
friend DWORD WINAPI thread_entry_point(LPVOID); friend DWORD WINAPI thread_entry_point(LPVOID);
static void initialize() {
static bool initialized = false;
if(initialized) return;
initialized = true;
primaryThread() = GetCurrentThreadId();
}
static DWORD& primaryThread() {
static DWORD thread;
return thread;
}
}; };
inline DWORD WINAPI thread_entry_point(LPVOID parameter) { inline DWORD WINAPI thread_entry_point(LPVOID parameter) {

View File

@ -16,10 +16,12 @@ struct Application : Window {
Button browseButton; Button browseButton;
ListView fileList; ListView fileList;
ProgressBar progressBar; ProgressBar progressBar;
Label libraryPath;
HorizontalLayout controlLayout; HorizontalLayout controlLayout;
Button selectAllButton; Button selectAllButton;
Button unselectAllButton; Button unselectAllButton;
Widget spacer; Widget spacer;
Button setPathButton;
Button purifyButton; Button purifyButton;
lstring filenameList; lstring filenameList;
@ -41,15 +43,20 @@ Application::Application() {
exit(0); exit(0);
} }
string path = string::read({configpath(), "higan/library.cfg"}).strip();
if(path.empty()) path = {userpath(), "Emulation/"};
setFrameGeometry({64, 64, 720, 480}); setFrameGeometry({64, 64, 720, 480});
setTitle("purify v03"); setTitle("purify v03.01");
layout.setMargin(5); layout.setMargin(5);
pathLabel.setText("Path:"); pathLabel.setText("Path:");
browseButton.setText("Browse ..."); browseButton.setText("Browse ...");
fileList.setCheckable(true); fileList.setCheckable(true);
libraryPath.setText({"Library Path: ", path});
selectAllButton.setText("Select All"); selectAllButton.setText("Select All");
unselectAllButton.setText("Unselect All"); unselectAllButton.setText("Unselect All");
setPathButton.setText("Set Path ...");
purifyButton.setText("Purify"); purifyButton.setText("Purify");
append(layout); append(layout);
@ -59,11 +66,13 @@ Application::Application() {
pathLayout.append(browseButton, {80, 0}); pathLayout.append(browseButton, {80, 0});
layout.append(fileList, {~0, ~0}, 5); layout.append(fileList, {~0, ~0}, 5);
layout.append(progressBar, {~0, 0}, 5); layout.append(progressBar, {~0, 0}, 5);
layout.append(libraryPath, {~0, 0}, 5);
layout.append(controlLayout, {~0, 0}); layout.append(controlLayout, {~0, 0});
controlLayout.append(selectAllButton, {100, 0}, 5); controlLayout.append(selectAllButton, {100, 0}, 5);
controlLayout.append(unselectAllButton, {100, 0}, 5); controlLayout.append(unselectAllButton, {100, 0}, 5);
controlLayout.append(spacer, {~0, 0}); controlLayout.append(spacer, {~0, 0});
controlLayout.append(purifyButton, {80, 0}); controlLayout.append(setPathButton, {100, 0}, 5);
controlLayout.append(purifyButton, {100, 0});
setVisible(); setVisible();
@ -87,11 +96,24 @@ Application::Application() {
for(unsigned n = 0; n < filenameList.size(); n++) fileList.setChecked(n, false); for(unsigned n = 0; n < filenameList.size(); n++) fileList.setChecked(n, false);
}; };
setPathButton.onActivate = [&] {
string path = DialogWindow::folderSelect(*this, userpath());
if(path.empty()) return;
directory::create({configpath(), "higan/"});
file::write({configpath(), "higan/library.cfg"}, path);
libraryPath.setText({"Library Path: ", path});
};
purifyButton.onActivate = {&Application::purify, this}; purifyButton.onActivate = {&Application::purify, this};
} }
void Application::scanPath() { void Application::scanPath() {
string path = pathEdit.text(); string path = pathEdit.text();
path.transform("\\", "/");
if(path.endswith("/") == false) path.append("/");
pathEdit.setText(path);
fileList.reset(); fileList.reset();
filenameList.reset(); filenameList.reset();
scanPath(path, path); scanPath(path, path);
@ -117,7 +139,11 @@ void Application::scanPath(const string &path, const string &basepath) {
) { ) {
fileList.append(string{path, file}.ltrim<1>(basepath).rtrim<1>("/")); fileList.append(string{path, file}.ltrim<1>(basepath).rtrim<1>("/"));
filenameList.append({path, file}); filenameList.append({path, file});
if(file::exists({path, file, "unverified"}) == false) {
fileList.setImage(filenameList.size() - 1, 0, {resource::game, sizeof resource::game}); fileList.setImage(filenameList.size() - 1, 0, {resource::game, sizeof resource::game});
} else {
fileList.setImage(filenameList.size() - 1, 0, {resource::unverified, sizeof resource::unverified});
}
} else if( } else if(
file.endswith(".fc") || file.endswith(".nes") file.endswith(".fc") || file.endswith(".nes")
|| file.endswith(".sfc") || file.endswith(".smc") || file.endswith(".sfc") || file.endswith(".smc")
@ -125,14 +151,14 @@ void Application::scanPath(const string &path, const string &basepath) {
|| file.endswith(".gb") || file.endswith(".gb")
|| file.endswith(".gbc") || file.endswith(".gbc")
|| file.endswith(".gba") || file.endswith(".gba")
|| file.endswith(".bpa") || file.endswith(".zip") || file.endswith(".zip")
) { ) {
fileList.append(string{path, file}.ltrim<1>(basepath)); fileList.append(string{path, file}.ltrim<1>(basepath));
filenameList.append({path, file}); filenameList.append({path, file});
if(file.endswith(".bpa") || file.endswith(".zip")) { if(file.endswith(".zip") == false) {
fileList.setImage(filenameList.size() - 1, 0, {resource::archive, sizeof resource::archive});
} else {
fileList.setImage(filenameList.size() - 1, 0, {resource::file, sizeof resource::file}); fileList.setImage(filenameList.size() - 1, 0, {resource::file, sizeof resource::file});
} else {
fileList.setImage(filenameList.size() - 1, 0, {resource::archive, sizeof resource::archive});
} }
} }
} }

View File

@ -1,4 +1,5 @@
resource name=resource resource name=resource
binary id=game name=game.png binary id=game name=game.png
binary id=unverified name=unverified.png
binary id=file name=file.png binary id=file name=file.png
binary id=archive name=archive.png binary id=archive name=archive.png

View File

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

View File

@ -1,5 +1,6 @@
namespace resource { namespace resource {
extern const uint8_t game[1490]; extern const uint8_t game[1490];
extern const uint8_t unverified[1675];
extern const uint8_t file[844]; extern const uint8_t file[844];
extern const uint8_t archive[1067]; extern const uint8_t archive[1067];
}; };

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB