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 {
#include "configuration.cpp"
string libraryPath;
Ananke();
struct Information {
string path; //path to selected file
@ -89,6 +92,12 @@ struct Ananke {
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) {
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 pathname = {
userpath(), "Emulation/BS-X Satellaview/",
libraryPath, "BS-X Satellaview/",
document["release/information/name"].text(),
" (", document["release/information/region"].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 pathname = {
userpath(), "Emulation/BS-X Satellaview/",
libraryPath, "BS-X Satellaview/",
nall::basename(information.name),
" (!).bs/"
".bs/"
};
directory::create(pathname);
file::create({pathname, "unverified"});
file::write({pathname, "manifest.bml"}, {
"cartridge\n"

View File

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

View File

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

View File

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

View File

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

View File

@ -98,6 +98,14 @@ namespace nall {
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) {
auto buffer = read(filename);
return nall::sha256(buffer.data(), buffer.size());

View File

@ -48,6 +48,15 @@ struct stream {
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 {
while(length--) {
write(data);

View File

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

View File

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

View File

@ -13,6 +13,7 @@ namespace nall {
struct thread {
thread(function<void ()> entryPoint) : entryPoint(entryPoint), completed(false), dead(false) {
initialize();
pthread_create(&pthread, NULL, thread_entry_point, (void*)this);
}
@ -30,11 +31,28 @@ namespace nall {
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) {
@ -50,6 +68,7 @@ namespace nall {
struct thread {
thread(function<void ()> entryPoint) : entryPoint(entryPoint), completed(false), dead(false) {
initialize();
hthread = CreateThread(NULL, 0, thread_entry_point, (void*)this, 0, NULL);
}
@ -68,11 +87,28 @@ namespace nall {
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) {

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 pathname = {
userpath(), "Emulation/Sufami Turbo/",
libraryPath, "Sufami Turbo/",
document["release/information/name"].text(),
" (", document["release/information/region"].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 pathname = {
userpath(), "Emulation/Sufami Turbo/",
libraryPath, "Sufami Turbo/",
nall::basename(information.name),
" (!).st/"
".st/"
};
directory::create(pathname);
file::create({pathname, "unverified"});
file::write({pathname, "manifest.bml"}, {
"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 pathname = {
userpath(), "Emulation/Super Famicom/",
libraryPath, "Super Famicom/",
document["release/information/name"].text(),
" (", document["release/information/region"].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 pathname = {
userpath(), "Emulation/Super Famicom/",
libraryPath, "Super Famicom/",
nall::basename(information.name),
" (!).sfc/"
".sfc/"
};
directory::create(pathname);
file::create({pathname, "unverified"});
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
if(buffer.size() == 0) buffer = extractFile(name); //try and read from the containing archive, if one exists
if(buffer.size() == 0) {
MessageWindow::critical(Window::none(), {
"Error: required firmware ", name, " not found. Game will not be playable!\n\n",
if(thread::primary()) MessageWindow::critical(Window::none(), {
"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."
});
return;

View File

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

View File

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

View File

@ -83,9 +83,9 @@ struct Interface {
virtual bool loaded() { return false; }
virtual string sha256() { return ""; }
virtual unsigned group(unsigned id) = 0;
virtual void load(unsigned id, const string &manifest) {}
virtual void load(unsigned id) {}
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 unload() {}

View File

@ -18,10 +18,10 @@ void Cartridge::main() {
board->main();
}
void Cartridge::load(const string &manifest) {
information.markup = manifest;
void Cartridge::load() {
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;
sha256_ctx sha;

View File

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

View File

@ -26,6 +26,7 @@ string Interface::sha256() {
unsigned Interface::group(unsigned id) {
switch(id) {
case ID::Manifest:
case ID::ProgramROM:
case ID::ProgramRAM:
case ID::CharacterROM:
@ -36,8 +37,8 @@ unsigned Interface::group(unsigned id) {
throw;
}
void Interface::load(unsigned id, const string &manifest) {
cartridge.load(manifest);
void Interface::load(unsigned id) {
cartridge.load();
}
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) {
stream.read(cartridge.board->prgrom.data, min(cartridge.board->prgrom.size, stream.size()));
}

View File

@ -9,6 +9,7 @@ struct ID {
};
enum : unsigned {
Manifest,
ProgramROM,
ProgramRAM,
CharacterROM,
@ -29,9 +30,9 @@ struct Interface : Emulator::Interface {
bool loaded();
string sha256();
unsigned group(unsigned id);
void load(unsigned id, const string &manifest);
void load(unsigned id);
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 unload();

View File

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

View File

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

View File

@ -38,6 +38,7 @@ unsigned Interface::group(unsigned id) {
case ID::SuperGameBoyBootROM:
case ID::GameBoyColorBootROM:
return 0;
case ID::Manifest:
case ID::ROM:
case ID::RAM:
if(system.revision() == System::Revision::GameBoy) return ID::GameBoy;
@ -49,10 +50,10 @@ unsigned Interface::group(unsigned id) {
throw;
}
void Interface::load(unsigned id, const string &manifest) {
if(id == ID::GameBoy) cartridge.load(System::Revision::GameBoy, manifest);
if(id == ID::SuperGameBoy) cartridge.load(System::Revision::SuperGameBoy, manifest);
if(id == ID::GameBoyColor) cartridge.load(System::Revision::GameBoyColor, manifest);
void Interface::load(unsigned id) {
if(id == ID::GameBoy) cartridge.load(System::Revision::GameBoy);
if(id == ID::SuperGameBoy) cartridge.load(System::Revision::SuperGameBoy);
if(id == ID::GameBoyColor) cartridge.load(System::Revision::GameBoyColor);
}
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) {
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()));
}
if(id == ID::Manifest) cartridge.information.markup = stream.text();
if(id == ID::ROM) {
stream.read(cartridge.romdata, min(cartridge.romsize, stream.size()));
}

View File

@ -14,8 +14,8 @@ struct ID {
GameBoyBootROM,
SuperGameBoyBootROM,
GameBoyColorBootROM,
GameBoyROM,
GameBoyColorROM,
Manifest,
ROM,
RAM,
};
@ -42,9 +42,9 @@ struct Interface : Emulator::Interface {
bool loaded();
string sha256();
unsigned group(unsigned id);
void load(unsigned id, const string &manifest);
void load(unsigned id);
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 unload();

View File

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

View File

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

View File

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

View File

@ -10,6 +10,8 @@ struct ID {
enum : unsigned {
BIOS,
Manifest,
ROM,
RAM,
EEPROM,
@ -28,9 +30,9 @@ struct Interface : Emulator::Interface {
bool loaded();
unsigned group(unsigned id);
void load(unsigned id, const string &manifest);
void load(unsigned id);
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 unload();

View File

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

View File

@ -98,6 +98,14 @@ namespace nall {
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) {
auto buffer = read(filename);
return nall::sha256(buffer.data(), buffer.size());

View File

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

View File

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

View File

@ -48,6 +48,15 @@ struct stream {
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 {
while(length--) {
write(data);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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)
phoenixflags := -DPHOENIX_WINDOWS
phoenixlink := -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32 -lshlwapi
ifeq ($(arch),win32)
phoenixflags := -m32 $(phoenixflags)
phoenixlink := -m32 $(phoenixlink)
endif
else
phoenixflags := -DPHOENIX_REFERENCE
phoenixlink :=

View File

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

View File

@ -1,12 +1,13 @@
sfc_objects := sfc-interface sfc-system sfc-controller
sfc_objects += sfc-cartridge sfc-cheat
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-armdsp sfc-hitachidsp sfc-necdsp
sfc_objects += sfc-epsonrtc sfc-sharprtc
sfc_objects += sfc-spc7110 sfc-sdd1 sfc-obc1
sfc_objects += sfc-hsu1 sfc-msu1
sfc_objects += sfc-satellaview sfc-sufamiturbo
objects += $(sfc_objects)
ifeq ($(profile),accuracy)
@ -27,6 +28,8 @@ else ifeq ($(profile),performance)
sfcsmp := $(sfc)/alt/smp
sfcdsp := $(sfc)/alt/dsp
sfcppu := $(sfc)/alt/ppu-performance
else
$(error unknown profile.)
endif
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-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-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-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;
}
void Cartridge::load(const string &manifest) {
void Cartridge::load() {
region = Region::NTSC;
has_gb_slot = false;
@ -49,13 +49,20 @@ void Cartridge::load(const string &manifest) {
has_hsu1 = false;
has_msu1 = false;
information.markup.cartridge = "";
information.markup.gameBoy = "";
information.markup.satellaview = "";
information.markup.sufamiTurboA = "";
information.markup.sufamiTurboB = "";
information.title.cartridge = "";
information.title.gameBoy = "";
information.title.satellaview = "";
information.title.sufamiTurboA = "";
information.title.sufamiTurboB = "";
parse_markup(information.markup = manifest);
interface->loadRequest(ID::Manifest, "manifest.bml");
parse_markup(information.markup.cartridge);
//Super Game Boy
if(cartridge.has_gb_slot()) {
@ -64,7 +71,7 @@ void Cartridge::load(const string &manifest) {
//Broadcast Satellaview
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
@ -72,8 +79,8 @@ void Cartridge::load(const string &manifest) {
sha256_ctx sha;
uint8_t hash[32];
sha256_init(&sha);
sha256_chunk(&sha, sufamiturbo.slotA.rom.data(), sufamiturbo.slotA.rom.size());
sha256_chunk(&sha, sufamiturbo.slotB.rom.data(), sufamiturbo.slotB.rom.size());
sha256_chunk(&sha, sufamiturboA.rom.data(), sufamiturboA.rom.size());
sha256_chunk(&sha, sufamiturboB.rom.data(), sufamiturboB.rom.size());
sha256_final(&sha);
sha256_hash(&sha, hash);
string result;
@ -118,37 +125,41 @@ void Cartridge::load(const string &manifest) {
loaded = true;
}
void Cartridge::load_super_game_boy(const string &manifest) {
auto document = Markup::Document(manifest);
void Cartridge::load_super_game_boy() {
interface->loadRequest(ID::SuperGameBoyManifest, "manifest.bml");
auto document = Markup::Document(information.markup.gameBoy);
information.title.gameBoy = document["information/title"].text();
auto rom = document["cartridge/rom"];
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(ram["name"].exists()) interface->loadRequest(ID::SuperGameBoyRAM, ram["name"].data);
if(ram["name"].exists()) memory.append({ID::SuperGameBoyRAM, ram["name"].data});
}
void Cartridge::load_satellaview(const string &manifest) {
auto document = Markup::Document(manifest);
void Cartridge::load_satellaview() {
interface->loadRequest(ID::SatellaviewManifest, "manifest.bml");
auto document = Markup::Document(information.markup.satellaview);
information.title.satellaview = document["information/title"].text();
auto rom = document["cartridge/rom"];
if(rom["name"].exists()) {
unsigned size = numeral(rom["size"].data);
bsxflash.memory.map(allocate<uint8>(size, 0xff), size);
interface->loadRequest(ID::BsxFlashROM, rom["name"].data);
satellaviewcartridge.memory.map(allocate<uint8>(size, 0xff), size);
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) {
auto document = Markup::Document(manifest);
void Cartridge::load_sufami_turbo_a() {
interface->loadRequest(ID::SufamiTurboSlotAManifest, "manifest.bml");
auto document = Markup::Document(information.markup.sufamiTurboA);
information.title.sufamiTurboA = document["information/title"].text();
auto rom = document["cartridge/rom"];
@ -156,13 +167,13 @@ void Cartridge::load_sufami_turbo_a(const string &manifest) {
if(rom["name"].exists()) {
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);
}
if(ram["name"].exists()) {
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);
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) {
auto document = Markup::Document(manifest);
void Cartridge::load_sufami_turbo_b() {
interface->loadRequest(ID::SufamiTurboSlotBManifest, "manifest.bml");
auto document = Markup::Document(information.markup.sufamiTurboB);
information.title.sufamiTurboB = document["information/title"].text();
auto rom = document["cartridge/rom"];
@ -181,13 +193,13 @@ void Cartridge::load_sufami_turbo_b(const string &manifest) {
if(rom["name"].exists()) {
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);
}
if(ram["name"].exists()) {
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);
memory.append({ID::SufamiTurboSlotBRAM, ram["name"].data});
}

View File

@ -61,7 +61,14 @@ struct Cartridge : property<Cartridge> {
vector<Memory> memory;
struct Information {
string markup;
struct Markup {
string cartridge;
string gameBoy;
string satellaview;
string sufamiTurboA;
string sufamiTurboB;
} markup;
struct Title {
string cartridge;
string gameBoy;
@ -73,11 +80,7 @@ struct Cartridge : property<Cartridge> {
string title();
void load(const string &manifest);
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 load();
void unload();
void serialize(serializer&);
@ -85,6 +88,11 @@ struct Cartridge : property<Cartridge> {
~Cartridge();
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_map(Mapping&, Markup::Node);
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_hsu1(Markup::Node);
void parse_markup_msu1(Markup::Node);
friend class Interface;
};
extern Cartridge cartridge;

View File

@ -135,9 +135,9 @@ void Cartridge::parse_markup_bsxslot(Markup::Node root) {
if(node.name != "map") continue;
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);
mapping.append(m);
}
@ -159,7 +159,7 @@ void Cartridge::parse_markup_sufamiturbo(Markup::Node root) {
if(node.name != "map") continue;
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;
Mapping m(memory);
@ -169,7 +169,7 @@ void Cartridge::parse_markup_sufamiturbo(Markup::Node root) {
}
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;
Mapping m(memory);

View File

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

View File

@ -1,3 +1,2 @@
#include "satellaview/satellaview.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
) {
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);
}

View File

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

View File

@ -87,7 +87,7 @@ void MSU1::reset() {
void MSU1::data_open() {
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;
if(name.empty()) name = "msu1.rom";
if(datafile.open({interface->path(ID::SuperFamicom), name}, file::mode::read)) {
@ -97,7 +97,7 @@ void MSU1::data_open() {
void MSU1::audio_open() {
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"};
for(auto &track : document.find("cartridge/msu1/track")) {
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) {
case ID::IPLROM:
return 0;
case ID::Manifest:
case ID::ROM:
case ID::RAM:
case ID::EventROM0:
@ -70,17 +71,21 @@ unsigned Interface::group(unsigned id) {
case ID::BsxPSRAM:
return 1;
case ID::SuperGameBoy:
case ID::SuperGameBoyManifest:
case ID::SuperGameBoyROM:
case ID::SuperGameBoyRAM:
return 2;
case ID::Satellaview:
case ID::BsxFlashROM:
case ID::SatellaviewManifest:
case ID::SatellaviewROM:
return 3;
case ID::SufamiTurboSlotA:
case ID::SufamiTurboSlotAManifest:
case ID::SufamiTurboSlotAROM:
case ID::SufamiTurboSlotARAM:
return 4;
case ID::SufamiTurboSlotB:
case ID::SufamiTurboSlotBManifest:
case ID::SufamiTurboSlotBROM:
case ID::SufamiTurboSlotBRAM:
return 5;
@ -89,12 +94,12 @@ unsigned Interface::group(unsigned id) {
throw;
}
void Interface::load(unsigned id, const string &manifest) {
if(id == ID::SuperFamicom) cartridge.load(manifest);
if(id == ID::SuperGameBoy) cartridge.load_super_game_boy(manifest);
if(id == ID::Satellaview) cartridge.load_satellaview(manifest);
if(id == ID::SufamiTurboSlotA) cartridge.load_sufami_turbo_a(manifest);
if(id == ID::SufamiTurboSlotB) cartridge.load_sufami_turbo_b(manifest);
void Interface::load(unsigned id) {
if(id == ID::SuperFamicom) cartridge.load();
if(id == ID::SuperGameBoy) cartridge.load_super_game_boy();
if(id == ID::Satellaview) cartridge.load_satellaview();
if(id == ID::SufamiTurboSlotA) cartridge.load_sufami_turbo_a();
if(id == ID::SufamiTurboSlotB) cartridge.load_sufami_turbo_b();
}
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) {
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::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));
}
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) {
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()));
}
if(id == ID::BsxFlashROM) bsxflash.memory.read(stream);
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::SatellaviewManifest) cartridge.information.markup.satellaview = stream.text();
if(id == ID::SatellaviewROM) satellaviewcartridge.memory.read(stream);
if(id == ID::SufamiTurboSlotAROM) sufamiturbo.slotA.rom.read(stream);
if(id == ID::SufamiTurboSlotBROM) sufamiturbo.slotB.rom.read(stream);
if(id == ID::SufamiTurboSlotAManifest) cartridge.information.markup.sufamiTurboA = stream.text();
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::SufamiTurboSlotBRAM) sufamiturbo.slotB.ram.read(stream);
if(id == ID::SufamiTurboSlotBManifest) cartridge.information.markup.sufamiTurboB = stream.text();
if(id == ID::SufamiTurboSlotARAM) sufamiturboA.ram.read(stream);
if(id == ID::SufamiTurboSlotBRAM) sufamiturboB.ram.read(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::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::SufamiTurboSlotBRAM) stream.write(sufamiturbo.slotB.ram.data(), sufamiturbo.slotB.ram.size());
if(id == ID::SufamiTurboSlotARAM) stream.write(sufamiturboA.ram.data(), sufamiturboA.ram.size());
if(id == ID::SufamiTurboSlotBRAM) stream.write(sufamiturboB.ram.data(), sufamiturboB.ram.size());
}
void Interface::unload() {
@ -376,9 +388,9 @@ Interface::Interface() {
information.capability.cheats = true;
media.append({ID::SuperFamicom, "Super Famicom", "sfc", true });
media.append({ID::SuperFamicom, "Super Famicom", "gb", false});
media.append({ID::SuperFamicom, "Super Famicom", "bs", false});
media.append({ID::SuperFamicom, "Super Famicom", "st", false});
media.append({ID::SuperFamicom, "Game Boy", "gb", false});
media.append({ID::SuperFamicom, "BS-X Satellaview", "bs", false});
media.append({ID::SuperFamicom, "Sufami Turbo", "st", false});
{
Device device{0, ID::Port1 | ID::Port2, "Controller"};

View File

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

View File

@ -66,6 +66,7 @@ namespace SuperFamicom {
#include <sfc/controller/controller.hpp>
#include <sfc/system/system.hpp>
#include <sfc/chip/chip.hpp>
#include <sfc/slot/slot.hpp>
#include <sfc/cartridge/cartridge.hpp>
#include <sfc/cheat/cheat.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) {
memory.map(allocate<uint8>(1024 * 1024, 0xff), 1024 * 1024);
}
}
void BSXFlash::unload() {
void SatellaviewCartridge::unload() {
memory.reset();
}
void BSXFlash::power() {
void SatellaviewCartridge::power() {
}
void BSXFlash::reset() {
void SatellaviewCartridge::reset() {
regs.command = 0;
regs.write_old = 0x00;
regs.write_new = 0x00;
@ -29,11 +32,11 @@ void BSXFlash::reset() {
memory.write_protect(!regs.write_enable);
}
unsigned BSXFlash::size() const {
unsigned SatellaviewCartridge::size() const {
return memory.size();
}
uint8 BSXFlash::read(unsigned addr) {
uint8 SatellaviewCartridge::read(unsigned addr) {
if(readonly) return memory.read(bus.mirror(addr, memory.size()));
if(addr == 0x0002) {
@ -62,7 +65,7 @@ uint8 BSXFlash::read(unsigned addr) {
return memory.read(addr);
}
void BSXFlash::write(unsigned addr, uint8 data) {
void SatellaviewCartridge::write(unsigned addr, uint8 data) {
if(readonly) return;
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;
bool readonly;
@ -24,4 +24,4 @@ private:
} 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_bs_cart()) bsxcartridge.serialize(s);
if(cartridge.has_st_slots()) sufamiturbo.serialize(s);
if(cartridge.has_event()) event.serialize(s);
if(cartridge.has_sa1()) sa1.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_hsu1()) hsu1.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:

View File

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

View File

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

View File

@ -28,7 +28,10 @@ Browser::Browser() {
};
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 = [&] {
@ -164,7 +167,12 @@ void Browser::setPath(const string &path, unsigned selection) {
string name = filename;
name.rtrim<1>(suffix);
fileList.append(name);
if(1 || file::exists({path, filename, "unverified"}) == false) {
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);
}
}

View File

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

View File

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

View File

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

View File

@ -98,6 +98,14 @@ namespace nall {
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) {
auto buffer = read(filename);
return nall::sha256(buffer.data(), buffer.size());

View File

@ -48,6 +48,15 @@ struct stream {
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 {
while(length--) {
write(data);

View File

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

View File

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

View File

@ -13,6 +13,7 @@ namespace nall {
struct thread {
thread(function<void ()> entryPoint) : entryPoint(entryPoint), completed(false), dead(false) {
initialize();
pthread_create(&pthread, NULL, thread_entry_point, (void*)this);
}
@ -30,11 +31,28 @@ namespace nall {
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) {
@ -50,6 +68,7 @@ namespace nall {
struct thread {
thread(function<void ()> entryPoint) : entryPoint(entryPoint), completed(false), dead(false) {
initialize();
hthread = CreateThread(NULL, 0, thread_entry_point, (void*)this, 0, NULL);
}
@ -68,11 +87,28 @@ namespace nall {
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) {

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB