Update to v091r09 release.

[r07 and r08 were not posted to the WIP thread. -Ed.]

byuu says:

I'd appreciate it if you guys wouldn't mind testing out the database
functionality.

Save this file as database.bml (remove the date) inside
~/.config/higan/Super Famicom.sfc/ or %APPDATA%/higan/Super Famicom.sfc/

    http://byuu.org/snes/database/database_2012-10-21.bml

Now load any of the 20 games in the database from the file dialog. They
need to be named *.sfc, have no copier header, and have firmware
appended (for Mario Kart only so far.)

If anyone actually does test it, please let me know how it goes for you
and what you think. Note that future versions of higan will have the
database.bml file included with the release.
This commit is contained in:
Tim Allen 2012-10-23 09:45:18 +11:00
parent c495c132a7
commit ab345ff20c
44 changed files with 449 additions and 291 deletions

View File

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

View File

@ -84,15 +84,15 @@ void Board::serialize(serializer &s) {
Board::Board(Markup::Node &document) {
cartridge.board = this;
auto &cartridge = document["cartridge"];
auto cartridge = document["cartridge"];
information.type = cartridge["board"]["type"].data;
information.battery = cartridge["prg"]["ram"]["nonvolatile"].data == "true";
auto &prom = cartridge["prg"]["rom"];
auto &pram = cartridge["prg"]["ram"];
auto &crom = cartridge["chr"]["rom"];
auto &cram = cartridge["chr"]["ram"];
auto prom = cartridge["prg"]["rom"];
auto pram = cartridge["prg"]["ram"];
auto crom = cartridge["chr"]["rom"];
auto cram = cartridge["chr"]["ram"];
prgrom.size = numeral(prom["size"].data);
prgram.size = numeral(pram["size"].data);

View File

@ -27,7 +27,7 @@ void Cartridge::load(System::Revision revision, const string &manifest) {
auto document = Markup::Document(manifest);
auto &mapperid = document["cartridge"]["board"]["type"].data;
auto mapperid = document["cartridge"]["board"]["type"].data;
if(mapperid == "none" ) information.mapper = Mapper::MBC0;
if(mapperid == "MBC1" ) information.mapper = Mapper::MBC1;
if(mapperid == "MBC2" ) information.mapper = Mapper::MBC2;
@ -40,8 +40,8 @@ void Cartridge::load(System::Revision revision, const string &manifest) {
information.rtc = false;
information.rumble = false;
auto &rom = document["cartridge"]["rom"];
auto &ram = document["cartridge"]["ram"];
auto rom = document["cartridge"]["rom"];
auto ram = document["cartridge"]["ram"];
romsize = numeral(rom["size"].data);
romdata = allocate<uint8>(romsize, 0xff);

View File

@ -13,7 +13,7 @@ void Cartridge::load(const string &manifest) {
unsigned rom_size = 0;
if(document["cartridge"]["rom"].exists()) {
auto &info = document["cartridge"]["rom"];
auto info = document["cartridge"]["rom"];
interface->loadRequest(ID::ROM, info["name"].data);
rom_size = numeral(info["size"].data);
for(unsigned addr = rom_size; addr < rom.size; addr++) {
@ -26,7 +26,7 @@ void Cartridge::load(const string &manifest) {
has_flashrom = false;
if(document["cartridge"]["ram"].exists()) {
auto &info = document["cartridge"]["ram"];
auto info = document["cartridge"]["ram"];
if(info["type"].data == "SRAM" || info["type"].data == "FRAM") {
has_sram = true;

View File

@ -28,6 +28,7 @@
#include <nall/string/convert.hpp>
#include <nall/string/core.hpp>
#include <nall/string/cstring.hpp>
#include <nall/string/datetime.hpp>
#include <nall/string/filename.hpp>
#include <nall/string/math-fixed-point.hpp>
#include <nall/string/math-floating-point.hpp>

View File

@ -23,6 +23,9 @@ 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 bool empty() const;
@ -65,6 +68,7 @@ namespace nall {
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& trim(const char *key = " ", const char *rkey = 0);
inline string& strip();
inline optional<unsigned> position(const char *key) const;
inline optional<unsigned> iposition(const char *key) const;
@ -183,6 +187,7 @@ namespace nall {
template<unsigned limit = 0> inline char* ltrim(char *str, const char *key = " ");
template<unsigned limit = 0> inline char* rtrim(char *str, const char *key = " ");
template<unsigned limit = 0> inline char* trim(char *str, const char *key = " ", const char *rkey = 0);
inline char* strip(char *s);
//utility.hpp
template<bool Insensitive> alwaysinline bool chrequal(char x, char y);

View File

@ -0,0 +1,31 @@
#ifdef NALL_STRING_INTERNAL_HPP
namespace nall {
string string::date() {
time_t timestamp = ::time(0);
tm *info = localtime(&timestamp);
return {
decimal<4, '0'>(1900 + info->tm_year), "-",
decimal<2, '0'>(1 + info->tm_mon), "-",
decimal<2, '0'>(info->tm_mday)
};
}
string string::time() {
time_t timestamp = ::time(0);
tm *info = localtime(&timestamp);
return {
decimal<2, '0'>(info->tm_hour), ":",
decimal<2, '0'>(info->tm_min), ":",
decimal<2, '0'>(info->tm_sec)
};
}
string string::datetime() {
return {string::date(), " ", string::time()};
}
}
#endif

View File

@ -16,34 +16,118 @@ struct Node {
return !name.empty();
}
string content() const {
return string{data}.trim(" ");
string text() const {
return string{data}.strip();
}
intmax_t integer() const {
return numeral(text());
}
uintmax_t decimal() const {
return numeral(text());
}
void reset() {
children.reset();
}
Node& operator[](const string &name) {
for(auto &node : *this) {
if(node.name == name) return node;
bool evaluate(const string &query) const {
if(query.empty()) return true;
lstring rules = string{query}.replace(" ", "").split(",");
for(auto &rule : rules) {
enum class Comparator : unsigned { ID, EQ, NE, LT, LE, GT, GE };
auto comparator = Comparator::ID;
if(rule.wildcard("*!=*")) comparator = Comparator::NE;
else if(rule.wildcard("*<=*")) comparator = Comparator::LE;
else if(rule.wildcard("*>=*")) comparator = Comparator::GE;
else if(rule.wildcard ("*=*")) comparator = Comparator::EQ;
else if(rule.wildcard ("*<*")) comparator = Comparator::LT;
else if(rule.wildcard ("*>*")) comparator = Comparator::GT;
if(comparator == Comparator::ID) {
if(find(rule).size()) continue;
return false;
}
lstring side;
switch(comparator) {
case Comparator::EQ: side = rule.split<1> ("="); break;
case Comparator::NE: side = rule.split<1>("!="); break;
case Comparator::LT: side = rule.split<1> ("<"); break;
case Comparator::LE: side = rule.split<1>("<="); break;
case Comparator::GT: side = rule.split<1> (">"); break;
case Comparator::GE: side = rule.split<1>(">="); break;
}
string data = text();
if(side(0).empty() == false) {
auto result = find(side(0));
if(result.size() == 0) return false;
data = result(0).data;
}
switch(comparator) {
case Comparator::EQ: if(data.wildcard(side(1)) == true) continue; break;
case Comparator::NE: if(data.wildcard(side(1)) == false) continue; break;
case Comparator::LT: if(numeral(data) < numeral(side(1))) continue; break;
case Comparator::LE: if(numeral(data) <= numeral(side(1))) continue; break;
case Comparator::GT: if(numeral(data) > numeral(side(1))) continue; break;
case Comparator::GE: if(numeral(data) >= numeral(side(1))) continue; break;
}
return false;
}
static Node node;
return node;
return true;
}
const Node& operator[](const string &name) const {
return operator[](name);
}
vector<Node> operator()(const string &pattern) const {
vector<Node> find(const string &query) const {
vector<Node> result;
for(auto &node : *this) {
if(node.name.wildcard(pattern)) result.append(node);
lstring path = query.split("/");
string name = path.take(0), rule;
unsigned lo = 0u, hi = ~0u;
if(name.wildcard("*[*]")) {
lstring side = name.split<1>("[");
name = side(0);
side = side(1).rtrim<1>("]").split<1>("-");
lo = side(0).empty() ? 0u : numeral(side(0));
hi = side(1).empty() ? ~0u : numeral(side(1));
}
if(name.wildcard("*(*)")) {
lstring side = name.split<1>("(");
name = side(0);
rule = side(1).rtrim<1>(")");
}
unsigned position = 0;
for(auto &node : children) {
if(node.name.wildcard(name) == false) continue;
if(node.evaluate(rule) == false) continue;
bool inrange = position >= lo && position <= hi;
position++;
if(inrange == false) continue;
if(path.size() == 0) result.append(node);
else {
auto list = node.find(path.concatenate("/"));
for(auto &item : list) result.append(item);
}
}
return result;
}
Node operator[](const string &query) const {
auto result = find(query);
return result(0);
}
Node* begin() { return children.begin(); }
Node* end() { return children.end(); }
const Node* begin() const { return children.begin(); }

View File

@ -33,6 +33,23 @@ template<unsigned limit> char* trim(char *str, const char *key, const char *rkey
return ltrim<limit>(rtrim<limit>(str, key), key);
}
//remove whitespace characters from both left and right sides of string
char* strip(char *s) {
signed n = 0, p = 0;
while(s[n]) {
if(s[n] != ' ' && s[n] != '\t' && s[n] != '\r' && s[n] != '\n') break;
n++;
}
while(s[n]) s[p++] = s[n++];
s[p--] = 0;
while(p >= 0) {
if(s[p] != ' ' && s[p] != '\t' && s[p] != '\r' && s[p] != '\n') break;
p--;
}
s[++p] = 0;
return s;
}
}
#endif

View File

@ -31,6 +31,7 @@ string& string::transform(const char *before, const char *after) { nall::strtr(d
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::trim(const char *key, const char *rkey) { nall::trim <limit>(data, key, rkey); return *this; }
string& string::strip() { nall::strip(data); return *this; }
optional<unsigned> string::position(const char *key) const { return strpos(data, key); }
optional<unsigned> string::iposition(const char *key) const { return istrpos(data, key); }

View File

@ -0,0 +1,9 @@
cartridge region=NTSC
bsx
rom name=program.rom size=0x100000
ram name=save.rwm size=0x8000
psram name=bsx.rwm size=0x40000
map id=io address=00-3f,80-bf:5000-5fff
map id=rom address=00-3f,80-bf:8000-ffff
map id=rom address=40-7f,c0-ff:0000-7fff
map id=ram address=20-3f:6000-7fff

View File

@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<cartridge region="NTSC">
<bsx>
<rom name="program.rom" size="0x100000"/>
<ram name="save.rwm" size="0x8000"/>
<psram name="bsx.rwm" size="0x40000"/>
<map address="00-3f:8000-ffff" id="rom"/>
<map address="80-bf:8000-ffff" id="rom"/>
<map address="40-7f:0000-ffff" id="rom"/>
<map address="c0-ff:0000-ffff" id="rom"/>
<map address="20-3f:6000-7fff" id="ram"/>
<map address="00-3f:5000-5fff" id="io"/>
<map address="80-bf:5000-5fff" id="io"/>
</bsx>
</cartridge>

View File

@ -0,0 +1,10 @@
cartridge region=NTSC
rom name=program.rom size=0x40000
map id=rom address=00-1f,80-9f:8000-ffff mask=0x8000
sufamiturbo
slot id=A
map id=rom address=20-3f,a0-bf:8000-ffff mask=0x8000
map id=ram address=60-63,e0-e3:8000-ffff
slot id=B
map id=rom address=40-5f,c0-df:8000-ffff mask=0x8000
map id=ram address=70-73,f0-f3:8000-ffff

View File

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<cartridge region="NTSC">
<rom name="program.rom" size="0x40000"/>
<map address="00-1f:8000-ffff" id="rom" mode="linear"/>
<map address="80-9f:8000-ffff" id="rom" mode="linear"/>
<sufamiturbo>
<slot id="A">
<map address="20-3f:8000-ffff" id="rom" mode="linear"/>
<map address="a0-bf:8000-ffff" id="rom" mode="linear"/>
<map address="60-63:8000-ffff" id="ram" mode="linear"/>
<map address="e0-e3:8000-ffff" id="ram" mode="linear"/>
</slot>
<slot id="B">
<map address="40-5f:8000-ffff" id="rom" mode="linear"/>
<map address="c0-df:8000-ffff" id="rom" mode="linear"/>
<map address="70-73:8000-ffff" id="ram" mode="linear"/>
<map address="f0-f3:8000-ffff" id="ram" mode="linear"/>
</slot>
</sufamiturbo>
</cartridge>

View File

@ -0,0 +1,3 @@
system name:Super Famicom
smp
rom name=spc700.rom size=64

View File

@ -1,6 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<system name="Super Famicom">
<smp>
<firmware name="spc700.rom" size="64" sha256="c95f88b299030d5afa55b1031e2b5ef2dff650c4b4e6bb6f8b1359436521278f"/>
</smp>
</system>

View File

@ -0,0 +1,6 @@
cartridge region=NTSC
rom name=program.rom size=0x80000
map id=rom address=00-7f,80-ff:8000-ffff mask=0x8000
icd2 revision=1
rom name=boot.rom size=0x100
map id=io address=00-3f,80-bf:6000-7fff

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<cartridge region="NTSC">
<rom name="program.rom" size="0x80000"/>
<map address="00-7f:8000-ffff" id="rom" mode="linear"/>
<map address="80-ff:8000-ffff" id="rom" mode="linear"/>
<icd2 revision="1">
<firmware name="boot.rom" size="256" sha256="0e4ddff32fc9d1eeaae812a157dd246459b00c9e14f2f61751f661f32361e360"/>
<map address="00-3f:6000-7fff" id="io"/>
<map address="80-bf:6000-7fff" id="io"/>
</icd2>
</cartridge>

View File

@ -77,8 +77,8 @@ void Cartridge::load(const string &manifest) {
void Cartridge::load_super_game_boy(const string &manifest) {
XML::Document document(manifest);
auto &rom = document["cartridge"]["rom"];
auto &ram = document["cartridge"]["ram"];
auto rom = document["cartridge"]["rom"];
auto ram = document["cartridge"]["ram"];
GameBoy::cartridge.load(GameBoy::System::Revision::SuperGameBoy, manifest);
@ -89,7 +89,7 @@ void Cartridge::load_super_game_boy(const string &manifest) {
void Cartridge::load_satellaview(const string &manifest) {
XML::Document document(manifest);
auto &rom = document["cartridge"]["rom"];
auto rom = document["cartridge"]["rom"];
if(rom["name"].exists()) {
unsigned size = numeral(rom["size"].data);
@ -100,8 +100,8 @@ void Cartridge::load_satellaview(const string &manifest) {
void Cartridge::load_sufami_turbo_a(const string &manifest) {
XML::Document document(manifest);
auto &rom = document["cartridge"]["rom"];
auto &ram = document["cartridge"]["ram"];
auto rom = document["cartridge"]["rom"];
auto ram = document["cartridge"]["ram"];
if(rom["name"].exists()) {
unsigned size = numeral(rom["size"].data);
@ -123,8 +123,8 @@ void Cartridge::load_sufami_turbo_a(const string &manifest) {
void Cartridge::load_sufami_turbo_b(const string &manifest) {
XML::Document document(manifest);
auto &rom = document["cartridge"]["rom"];
auto &ram = document["cartridge"]["ram"];
auto rom = document["cartridge"]["rom"];
auto ram = document["cartridge"]["ram"];
if(rom["name"].exists()) {
unsigned size = numeral(rom["size"].data);

View File

@ -73,27 +73,27 @@ struct Cartridge : property<Cartridge> {
private:
void parse_markup(const char*);
void parse_markup_map(Mapping&, Markup::Node&);
void parse_markup_memory(MappedRAM&, Markup::Node&, unsigned id, bool writable);
void parse_markup_map(Mapping&, Markup::Node);
void parse_markup_memory(MappedRAM&, Markup::Node, unsigned id, bool writable);
void parse_markup_board(Markup::Node&);
void parse_markup_icd2(Markup::Node&);
void parse_markup_bsx(Markup::Node&);
void parse_markup_bsxslot(Markup::Node&);
void parse_markup_sufamiturbo(Markup::Node&);
void parse_markup_nss(Markup::Node&);
void parse_markup_event(Markup::Node&);
void parse_markup_sa1(Markup::Node&);
void parse_markup_superfx(Markup::Node&);
void parse_markup_armdsp(Markup::Node&);
void parse_markup_hitachidsp(Markup::Node&);
void parse_markup_necdsp(Markup::Node&);
void parse_markup_epsonrtc(Markup::Node&);
void parse_markup_sharprtc(Markup::Node&);
void parse_markup_spc7110(Markup::Node&);
void parse_markup_sdd1(Markup::Node&);
void parse_markup_obc1(Markup::Node&);
void parse_markup_msu1(Markup::Node&);
void parse_markup_board(Markup::Node);
void parse_markup_icd2(Markup::Node);
void parse_markup_bsx(Markup::Node);
void parse_markup_bsxslot(Markup::Node);
void parse_markup_sufamiturbo(Markup::Node);
void parse_markup_nss(Markup::Node);
void parse_markup_event(Markup::Node);
void parse_markup_sa1(Markup::Node);
void parse_markup_superfx(Markup::Node);
void parse_markup_armdsp(Markup::Node);
void parse_markup_hitachidsp(Markup::Node);
void parse_markup_necdsp(Markup::Node);
void parse_markup_epsonrtc(Markup::Node);
void parse_markup_sharprtc(Markup::Node);
void parse_markup_spc7110(Markup::Node);
void parse_markup_sdd1(Markup::Node);
void parse_markup_obc1(Markup::Node);
void parse_markup_msu1(Markup::Node);
};
extern Cartridge cartridge;

View File

@ -4,8 +4,8 @@ void Cartridge::parse_markup(const char *markup) {
mapping.reset();
auto document = Markup::Document(markup);
auto &cartridge = document["cartridge"];
auto &board = cartridge["board"];
auto cartridge = document["cartridge"];
auto board = cartridge["board"];
region = cartridge["region"].data != "PAL" ? Region::NTSC : Region::PAL;
parse_markup_board(board);
@ -30,14 +30,14 @@ void Cartridge::parse_markup(const char *markup) {
//
void Cartridge::parse_markup_map(Mapping &m, Markup::Node &map) {
void Cartridge::parse_markup_map(Mapping &m, Markup::Node map) {
m.addr = map["address"].data;
m.size = numeral(map["size"].data);
m.base = numeral(map["base"].data);
m.mask = numeral(map["mask"].data);
}
void Cartridge::parse_markup_memory(MappedRAM &ram, Markup::Node &node, unsigned id, bool writable) {
void Cartridge::parse_markup_memory(MappedRAM &ram, Markup::Node node, unsigned id, bool writable) {
string name = node["name"].data;
unsigned size = numeral(node["size"].data);
ram.map(allocate<uint8>(size, 0xff), size);
@ -49,7 +49,7 @@ void Cartridge::parse_markup_memory(MappedRAM &ram, Markup::Node &node, unsigned
//
void Cartridge::parse_markup_board(Markup::Node &root) {
void Cartridge::parse_markup_board(Markup::Node root) {
if(root.exists() == false) return;
parse_markup_memory(rom, root["rom"], ID::ROM, false);
@ -74,18 +74,15 @@ void Cartridge::parse_markup_board(Markup::Node &root) {
}
}
void Cartridge::parse_markup_icd2(Markup::Node &root) {
void Cartridge::parse_markup_icd2(Markup::Node root) {
if(root.exists() == false) return;
has_gb_slot = true;
icd2.revision = max(1, numeral(root["revision"].data));
interface->loadRequest(ID::SuperGameBoy, "Game Boy", "gb");
string firmware = root["firmware"]["name"].data;
interface->loadRequest(ID::SuperGameBoyBootROM, firmware);
if(!file::exists({interface->path(ID::SuperFamicom), firmware})) {
interface->notify("Error: required firmware ", firmware, " not found.\n");
}
string bootROMName = root["rom"]["name"].data;
interface->loadRequest(ID::SuperGameBoyBootROM, bootROMName);
for(auto &node : root) {
if(node.name != "map") continue;
@ -98,7 +95,7 @@ void Cartridge::parse_markup_icd2(Markup::Node &root) {
}
}
void Cartridge::parse_markup_bsx(Markup::Node &root) {
void Cartridge::parse_markup_bsx(Markup::Node root) {
if(root.exists() == false) return;
has_bs_cart = true;
has_bs_slot = true;
@ -127,7 +124,7 @@ void Cartridge::parse_markup_bsx(Markup::Node &root) {
}
}
void Cartridge::parse_markup_bsxslot(Markup::Node &root) {
void Cartridge::parse_markup_bsxslot(Markup::Node root) {
if(root.exists() == false) return;
has_bs_slot = true;
@ -146,7 +143,7 @@ void Cartridge::parse_markup_bsxslot(Markup::Node &root) {
}
}
void Cartridge::parse_markup_sufamiturbo(Markup::Node &root) {
void Cartridge::parse_markup_sufamiturbo(Markup::Node root) {
if(root.exists() == false) return;
has_st_slots = true;
@ -183,7 +180,7 @@ void Cartridge::parse_markup_sufamiturbo(Markup::Node &root) {
}
}
void Cartridge::parse_markup_nss(Markup::Node &root) {
void Cartridge::parse_markup_nss(Markup::Node root) {
if(root.exists() == false) return;
has_nss_dip = true;
nss.dip = interface->dipSettings(root);
@ -199,7 +196,7 @@ void Cartridge::parse_markup_nss(Markup::Node &root) {
}
}
void Cartridge::parse_markup_event(Markup::Node &root) {
void Cartridge::parse_markup_event(Markup::Node root) {
if(root.exists() == false) return;
has_event = true;
@ -257,13 +254,13 @@ void Cartridge::parse_markup_event(Markup::Node &root) {
}
}
void Cartridge::parse_markup_sa1(Markup::Node &root) {
void Cartridge::parse_markup_sa1(Markup::Node root) {
if(root.exists() == false) return;
has_sa1 = true;
parse_markup_memory(sa1.rom, root["rom"], ID::SA1ROM, false);
parse_markup_memory(sa1.iram, root["iram"], ID::SA1IRAM, true);
parse_markup_memory(sa1.bwram, root["bwram"], ID::SA1BWRAM, true);
parse_markup_memory(sa1.bwram, root["ram(id=bitmap)"], ID::SA1BWRAM, true);
parse_markup_memory(sa1.iram, root["ram(id=internal)"], ID::SA1IRAM, true);
for(auto &node : root) {
if(node.name != "map") continue;
@ -280,22 +277,22 @@ void Cartridge::parse_markup_sa1(Markup::Node &root) {
mapping.append(m);
}
if(node["id"].data == "bwram") {
Mapping m({&SA1::mmcbwram_read, &sa1}, {&SA1::mmcbwram_write, &sa1});
parse_markup_map(m, node);
mapping.append(m);
}
if(node["id"].data == "iram") {
Mapping m(sa1.cpuiram);
parse_markup_map(m, node);
if(m.size == 0) m.size = sa1.cpuiram.size();
mapping.append(m);
}
if(node["id"].data == "bwram") {
Mapping m({&SA1::mmcbwram_read, &sa1}, {&SA1::mmcbwram_write, &sa1});
parse_markup_map(m, node);
mapping.append(m);
}
}
}
void Cartridge::parse_markup_superfx(Markup::Node &root) {
void Cartridge::parse_markup_superfx(Markup::Node root) {
if(root.exists() == false) return;
has_superfx = true;
@ -327,14 +324,20 @@ void Cartridge::parse_markup_superfx(Markup::Node &root) {
}
}
void Cartridge::parse_markup_armdsp(Markup::Node &root) {
void Cartridge::parse_markup_armdsp(Markup::Node root) {
if(root.exists() == false) return;
has_armdsp = true;
string firmware = root["firmware"]["name"].data;
string sha256 = root["firmware"]["sha256"].data;
string programROMName = root["rom(id=program)/name"].data;
string dataROMName = root["rom(id=data)/name"].data;
string dataRAMName = root["ram/name"].data;
interface->loadRequest(ID::ArmDSP, firmware);
interface->loadRequest(ID::ArmDSPPROM, programROMName);
interface->loadRequest(ID::ArmDSPDROM, dataROMName);
if(dataRAMName.empty() == false) {
interface->loadRequest(ID::ArmDSPRAM, dataRAMName);
memory.append({ID::ArmDSPRAM, dataRAMName});
}
for(auto &node : root) {
if(node.name != "map") continue;
@ -347,20 +350,25 @@ void Cartridge::parse_markup_armdsp(Markup::Node &root) {
}
}
void Cartridge::parse_markup_hitachidsp(Markup::Node &root) {
void Cartridge::parse_markup_hitachidsp(Markup::Node root) {
if(root.exists() == false) return;
has_hitachidsp = true;
for(unsigned n = 0; n < 1024; n++) hitachidsp.dataROM[n] = 0x000000;
for(auto &n : hitachidsp.dataROM) hitachidsp.dataROM[n] = 0x000000;
for(auto &n : hitachidsp.dataRAM) hitachidsp.dataRAM[n] = 0x00;
hitachidsp.frequency = numeral(root["frequency"].data);
if(hitachidsp.frequency == 0) hitachidsp.frequency = 20000000;
string firmware = root["firmware"]["name"].data;
string sha256 = root["firmware"]["sha256"].data;
interface->loadRequest(ID::HitachiDSP, firmware);
string dataROMName = root["rom(id=data)/name"].data;
string dataRAMName = root["ram/name"].data;
parse_markup_memory(hitachidsp.rom, root["rom"], ID::HitachiDSPROM, false);
interface->loadRequest(ID::HitachiDSPDROM, dataROMName);
if(dataRAMName.empty() == false) {
interface->loadRequest(ID::HitachiDSPRAM, dataRAMName);
}
parse_markup_memory(hitachidsp.rom, root["rom(id!=data)"], ID::HitachiDSPROM, false);
for(auto &node : root) {
if(node.name != "map") continue;
@ -380,12 +388,13 @@ void Cartridge::parse_markup_hitachidsp(Markup::Node &root) {
}
}
void Cartridge::parse_markup_necdsp(Markup::Node &root) {
void Cartridge::parse_markup_necdsp(Markup::Node root) {
if(root.exists() == false) return;
has_necdsp = true;
for(unsigned n = 0; n < 16384; n++) necdsp.programROM[n] = 0x000000;
for(unsigned n = 0; n < 2048; n++) necdsp.dataROM[n] = 0x0000;
for(auto &n : necdsp.programROM) n = 0x000000;
for(auto &n : necdsp.dataROM) n = 0x0000;
for(auto &n : necdsp.dataRAM) n = 0x0000;
necdsp.frequency = numeral(root["frequency"].data);
if(necdsp.frequency == 0) necdsp.frequency = 8000000;
@ -393,18 +402,27 @@ void Cartridge::parse_markup_necdsp(Markup::Node &root) {
= root["model"].data == "uPD7725" ? NECDSP::Revision::uPD7725
: root["model"].data == "uPD96050" ? NECDSP::Revision::uPD96050
: NECDSP::Revision::uPD7725;
string firmware = root["firmware"]["name"].data;
string sha256 = root["firmware"]["sha256"].data;
string programROMName = root["rom(id=program)/name"].data;
string dataROMName = root["rom(id=data)/name"].data;
string dataRAMName = root["ram/name"].data;
if(necdsp.revision == NECDSP::Revision::uPD7725) {
interface->loadRequest(ID::Nec7725DSP, firmware);
interface->loadRequest(ID::Nec7725DSPPROM, programROMName);
interface->loadRequest(ID::Nec7725DSPDROM, dataROMName);
if(dataRAMName.empty() == false) {
interface->loadRequest(ID::Nec7725DSPRAM, dataRAMName);
memory.append({ID::Nec7725DSPRAM, dataRAMName});
}
}
if(necdsp.revision == NECDSP::Revision::uPD96050) {
interface->loadRequest(ID::Nec96050DSP, firmware);
string name = root["ram"]["name"].data;
interface->loadRequest(ID::NecDSPRAM, name);
memory.append({ID::NecDSPRAM, name});
interface->loadRequest(ID::Nec96050DSPPROM, programROMName);
interface->loadRequest(ID::Nec96050DSPDROM, dataROMName);
if(dataRAMName.empty() == false) {
interface->loadRequest(ID::Nec96050DSPRAM, dataRAMName);
memory.append({ID::Nec96050DSPRAM, dataRAMName});
}
}
for(auto &node : root) {
@ -430,7 +448,7 @@ void Cartridge::parse_markup_necdsp(Markup::Node &root) {
}
}
void Cartridge::parse_markup_epsonrtc(Markup::Node &root) {
void Cartridge::parse_markup_epsonrtc(Markup::Node root) {
if(root.exists() == false) return;
has_epsonrtc = true;
@ -449,7 +467,7 @@ void Cartridge::parse_markup_epsonrtc(Markup::Node &root) {
}
}
void Cartridge::parse_markup_sharprtc(Markup::Node &root) {
void Cartridge::parse_markup_sharprtc(Markup::Node root) {
if(root.exists() == false) return;
has_sharprtc = true;
@ -468,12 +486,12 @@ void Cartridge::parse_markup_sharprtc(Markup::Node &root) {
}
}
void Cartridge::parse_markup_spc7110(Markup::Node &root) {
void Cartridge::parse_markup_spc7110(Markup::Node root) {
if(root.exists() == false) return;
has_spc7110 = true;
parse_markup_memory(spc7110.prom, root["prom"], ID::SPC7110PROM, false);
parse_markup_memory(spc7110.drom, root["drom"], ID::SPC7110DROM, false);
parse_markup_memory(spc7110.prom, root["rom(id=program)"], ID::SPC7110PROM, false);
parse_markup_memory(spc7110.drom, root["rom(id=data)"], ID::SPC7110DROM, false);
parse_markup_memory(spc7110.ram, root["ram"], ID::SPC7110RAM, true);
for(auto &node : root) {
@ -499,7 +517,7 @@ void Cartridge::parse_markup_spc7110(Markup::Node &root) {
}
}
void Cartridge::parse_markup_sdd1(Markup::Node &root) {
void Cartridge::parse_markup_sdd1(Markup::Node root) {
if(root.exists() == false) return;
has_sdd1 = true;
@ -529,7 +547,7 @@ void Cartridge::parse_markup_sdd1(Markup::Node &root) {
}
}
void Cartridge::parse_markup_obc1(Markup::Node &root) {
void Cartridge::parse_markup_obc1(Markup::Node root) {
if(root.exists() == false) return;
has_obc1 = true;
@ -546,7 +564,7 @@ void Cartridge::parse_markup_obc1(Markup::Node &root) {
}
}
void Cartridge::parse_markup_msu1(Markup::Node &root) {
void Cartridge::parse_markup_msu1(Markup::Node root) {
if(root.exists() == false) return;
has_msu1 = true;

View File

@ -120,15 +120,14 @@ void ArmDSP::arm_reset() {
}
ArmDSP::ArmDSP() {
firmware = new uint8[160 * 1024]();
programRAM = new uint8[16 * 1024]();
programROM = &firmware[0];
dataROM = &firmware[128 * 1024];
programROM = new uint8[128 * 1024];
dataROM = new uint8[32 * 1024];
programRAM = new uint8[16 * 1024];
}
ArmDSP::~ArmDSP() {
delete[] firmware;
delete[] programROM;
delete[] dataROM;
delete[] programRAM;
}

View File

@ -1,7 +1,6 @@
//ARMv3 (ARM6)
struct ArmDSP : Processor::ARM, Coprocessor {
uint8 *firmware;
uint8 *programROM;
uint8 *dataROM;
uint8 *programRAM;

View File

@ -109,9 +109,10 @@ uint8 SDD1::mmc_read(unsigned addr) {
//the actual S-DD1 transfer can occur on any channel, but it is most likely limited to
//one transfer per $420b write (for spooling purposes). however, this is not known for certain.
uint8 SDD1::mcurom_read(unsigned addr) {
if((addr & 0x408000) == 0x008000) { //$00-3f|80-bf:8000-ffff
addr = ((addr & 0x7f0000) >> 1) | (addr & 0x7fff);
if(addr < 0x400000) { //(addr & 0x408000) == 0x008000) { //$00-3f|80-bf:8000-ffff
return rom.read(addr);
//addr = ((addr & 0x7f0000) >> 1) | (addr & 0x7fff);
//return rom.read(addr);
}
//$40-7f|c0-ff:0000-ffff (MMC)

View File

@ -39,12 +39,18 @@ unsigned Interface::group(unsigned id) {
case ID::SA1BWRAM:
case ID::SuperFXROM:
case ID::SuperFXRAM:
case ID::ArmDSP:
case ID::HitachiDSP:
case ID::ArmDSPPROM:
case ID::ArmDSPDROM:
case ID::ArmDSPRAM:
case ID::HitachiDSPROM:
case ID::Nec7725DSP:
case ID::Nec96050DSP:
case ID::NecDSPRAM:
case ID::HitachiDSPDROM:
case ID::HitachiDSPRAM:
case ID::Nec7725DSPPROM:
case ID::Nec7725DSPDROM:
case ID::Nec7725DSPRAM:
case ID::Nec96050DSPPROM:
case ID::Nec96050DSPDROM:
case ID::Nec96050DSPRAM:
case ID::EpsonRTC:
case ID::SharpRTC:
case ID::SPC7110PROM:
@ -76,7 +82,6 @@ unsigned Interface::group(unsigned id) {
}
print(id, "\n");
return 1;
throw;
}
@ -115,28 +120,43 @@ void Interface::load(unsigned id, const stream &stream, const string &manifest)
if(id == ID::SuperFXROM) superfx.rom.read(stream);
if(id == ID::SuperFXRAM) superfx.ram.read(stream);
if(id == ID::ArmDSP) {
stream.read(armdsp.firmware, stream.size());
if(id == ID::ArmDSPPROM) {
for(unsigned n = 0; n < 128 * 1024; n++) armdsp.programROM[n] = stream.read();
}
if(id == ID::ArmDSPDROM) {
for(unsigned n = 0; n < 32 * 1024; n++) armdsp.dataROM[n] = stream.read();
}
if(id == ID::ArmDSPRAM) {
for(unsigned n = 0; n < 16 * 1024; n++) armdsp.programRAM[n] = stream.read();
}
if(id == ID::HitachiDSP) {
if(id == ID::HitachiDSPROM) {
hitachidsp.rom.read(stream);
}
if(id == ID::HitachiDSPDROM) {
for(unsigned n = 0; n < 1024; n++) hitachidsp.dataROM[n] = stream.readl(3);
}
if(id == ID::HitachiDSPRAM) {
for(unsigned n = 0; n < 3072; n++) hitachidsp.dataRAM[n] = stream.readl(1);
}
if(id == ID::HitachiDSPROM) hitachidsp.rom.read(stream);
if(id == ID::Nec7725DSP) {
if(id == ID::Nec7725DSPPROM) {
for(unsigned n = 0; n < 2048; n++) necdsp.programROM[n] = stream.readl(3);
}
if(id == ID::Nec7725DSPDROM) {
for(unsigned n = 0; n < 1024; n++) necdsp.dataROM[n] = stream.readl(2);
}
if(id == ID::Nec96050DSP) {
if(id == ID::Nec7725DSPRAM) {
for(unsigned n = 0; n < 256; n++) necdsp.dataRAM[n] = stream.readl(2);
}
if(id == ID::Nec96050DSPPROM) {
for(unsigned n = 0; n < 16384; n++) necdsp.programROM[n] = stream.readl(3);
}
if(id == ID::Nec96050DSPDROM) {
for(unsigned n = 0; n < 2048; n++) necdsp.dataROM[n] = stream.readl(2);
}
if(id == ID::NecDSPRAM) {
for(unsigned n = 0; n < 2048; n++) necdsp.dataRAM[n] = stream.readl(2);
if(id == ID::Nec96050DSPRAM) {
for(unsigned n = 0; n < 2048; n++) necdsp.dataRAM[n] = stream.readl(2);
}
if(id == ID::EpsonRTC) {
@ -191,7 +211,18 @@ void Interface::save(unsigned id, const stream &stream) {
if(id == ID::SA1BWRAM) stream.write(sa1.bwram.data(), sa1.bwram.size());
if(id == ID::SuperFXRAM) stream.write(superfx.ram.data(), superfx.ram.size());
if(id == ID::NecDSPRAM) {
if(id == ID::ArmDSPRAM) {
for(unsigned n = 0; n < 16 * 1024; n++) stream.write(armdsp.programRAM[n]);
}
if(id == ID::HitachiDSPRAM) {
for(unsigned n = 0; n < 3072; n++) stream.writel(hitachidsp.dataRAM[n], 1);
}
if(id == ID::Nec96050DSPRAM) {
for(unsigned n = 0; n < 256; n++) stream.writel(necdsp.dataRAM[n], 2);
}
if(id == ID::Nec96050DSPRAM) {
for(unsigned n = 0; n < 2048; n++) stream.writel(necdsp.dataRAM[n], 2);
}

View File

@ -31,12 +31,21 @@ struct ID {
SuperFXROM,
SuperFXRAM,
ArmDSP,
HitachiDSP,
ArmDSPPROM,
ArmDSPDROM,
ArmDSPRAM,
HitachiDSPROM,
Nec7725DSP,
Nec96050DSP,
NecDSPRAM,
HitachiDSPDROM,
HitachiDSPRAM,
Nec7725DSPPROM,
Nec7725DSPDROM,
Nec7725DSPRAM,
Nec96050DSPPROM,
Nec96050DSPDROM,
Nec96050DSPRAM,
EpsonRTC,
SharpRTC,

View File

@ -94,12 +94,12 @@ void System::term() {
void System::load() {
string path = interface->path(ID::System), manifest;
manifest.readfile({path, "manifest.xml"});
XML::Document document(manifest);
string firmware = document["system"]["smp"]["firmware"]["name"].data;
interface->loadRequest(ID::IPLROM, document["system"]["smp"]["firmware"]["name"].data);
if(!file::exists({interface->path(ID::System), firmware})) {
interface->notify("Error: required firmware ", firmware, " not found.\n");
manifest.readfile({path, "manifest.bml"});
auto document = Markup::Document(manifest);
string iplrom = document["system"]["smp"]["rom"]["name"].data;
interface->loadRequest(ID::IPLROM, iplrom);
if(!file::exists({interface->path(ID::System), iplrom})) {
interface->notify("Error: required firmware ", iplrom, " not found.\n");
}
region = config.region;

View File

@ -13,6 +13,7 @@ Configuration::Configuration() {
append(video.saturation = 100, "Video::Saturation");
append(video.gamma = 150, "Video::Gamma");
append(video.luminance = 100, "Video::Luminance");
append(video.startFullScreen = false, "Video::StartFullScreen");
append(audio.driver = ruby::audio.default_driver(), "Audio::Driver");
append(audio.synchronize = true, "Audio::Synchronize");
append(audio.frequency = 48000, "Audio::Frequency");

View File

@ -11,6 +11,7 @@ struct Configuration : configuration {
unsigned saturation;
unsigned gamma;
unsigned luminance;
bool startFullScreen;
} video;
struct Audio {

View File

@ -23,17 +23,21 @@ string Application::path(const string &filename) {
void Application::commandLineLoad(string pathname) {
pathname.transform("\\", "/");
pathname.rtrim<1>("/");
if(directory::exists(pathname) == false) return;
string type = extension(pathname);
pathname.append("/");
string type = extension(string{pathname}.rtrim<1>("/"));
if(!directory::exists(pathname) && !file::exists(pathname)) return;
for(auto &emulator : this->emulator) {
for(auto &media : emulator->media) {
if(!media.load.empty()) continue;
if(type != media.type) continue;
return utility->loadMedia(emulator, media, pathname);
if(directory::exists(pathname)) {
return utility->loadMedia(emulator, media, pathname);
}
if(file::exists(pathname)) {
return utility->loadMediaFromDatabase(emulator, media, pathname);
}
}
}
}
@ -93,7 +97,6 @@ Application::Application(int argc, char **argv) {
inputSettings = new InputSettings;
hotkeySettings = new HotkeySettings;
timingSettings = new TimingSettings;
pathSettings = new PathSettings;
driverSettings = new DriverSettings;
settings = new Settings;
cheatDatabase = new CheatDatabase;
@ -121,6 +124,9 @@ Application::Application(int argc, char **argv) {
utility->synchronizeRuby();
utility->updateShader();
if(config->video.startFullScreen) utility->toggleFullScreen();
OS::processEvents();
if(argc >= 2) commandLineLoad(argv[1]);
while(quit == false) {

View File

@ -160,37 +160,35 @@ void Browser::setPath(const string &path, unsigned selection) {
lstring contents = directory::contents(path);
for(auto &filename : contents) {
if(!filename.wildcard(R"(*.??/)") && !filename.wildcard(R"(*.???/)") && filename.endswith("/")) {
string suffix = {".", this->extension, "/"};
if(filename.endswith("/") && !filename.endswith(suffix)) {
string name = filename;
name.rtrim<1>("/");
fileList.append(name);
fileList.setImage(filenameList.size(), 0, image(resource::systemFolder, sizeof resource::systemFolder));
fileList.setImage(filenameList.size(), 0, image(resource::cabinet, sizeof resource::cabinet));
filenameList.append(filename);
}
}
for(auto &filename : contents) {
string suffix = {".", this->extension, "/"};
if(filename.wildcard(R"(*.??/)") || filename.wildcard(R"(*.???/)")) {
if(filename.endswith(suffix)) {
string name = filename;
name.rtrim<1>(suffix);
fileList.append(name);
fileList.setImage(filenameList.size(), 0, image(resource::gameFolder, sizeof resource::gameFolder));
filenameList.append(filename);
}
if(filename.endswith(suffix)) {
string name = filename;
name.rtrim<1>(suffix);
fileList.append(name);
fileList.setImage(filenameList.size(), 0, image(resource::folder, sizeof resource::folder));
filenameList.append(filename);
}
}
for(auto &filename : contents) {
string suffix = {".", this->extension};
if(filename.wildcard(R"(*.??)") || filename.wildcard(R"(*.???)")) {
if(filename.endswith(suffix)) {
string name = filename;
fileList.append(name);
fileList.setImage(filenameList.size(), 0, image(resource::gameFile, sizeof resource::gameFile));
filenameList.append(filename);
}
if(filename.endswith(suffix)) {
string name = filename;
name.rtrim<1>(suffix);
fileList.append(name);
fileList.setImage(filenameList.size(), 0, image(resource::file, sizeof resource::file));
filenameList.append(filename);
}
}

View File

Before

Width:  |  Height:  |  Size: 667 B

After

Width:  |  Height:  |  Size: 667 B

View File

Before

Width:  |  Height:  |  Size: 844 B

After

Width:  |  Height:  |  Size: 844 B

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1,6 +1,6 @@
namespace resource {
const uint8_t systemFolder[667] = {
const uint8_t cabinet[667] = {
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,2,82,73,68,65,84,88,133,237,148,205,107,19,
81,20,197,127,153,36,218,84,48,65,138,164,74,186,16,108,236,34,75,65,148,110,252,8,214,165,127,128,165,160,224,206,
@ -24,7 +24,7 @@ const uint8_t systemFolder[667] = {
42,180,76,114,239,241,27,4,79,89,165,234,42,236,66,0,0,0,0,73,69,78,68,174,66,96,130,
};
const uint8_t gameFolder[1176] = {
const uint8_t folder[1176] = {
137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,32,0,0,0,32,8,6,0,0,0,115,122,122,
244,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,9,112,72,89,115,0,0,13,215,0,0,13,
215,1,66,40,155,120,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,119,119,119,46,105,110,107,115,99,
@ -64,7 +64,7 @@ const uint8_t gameFolder[1176] = {
235,6,248,7,188,50,165,151,203,8,55,43,0,0,0,0,73,69,78,68,174,66,96,130,
};
const uint8_t gameFile[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,
244,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,3,3,73,68,65,84,88,133,229,151,79,110,212,
48,24,197,127,182,227,56,81,39,116,36,132,0,169,167,226,2,101,209,93,239,192,150,37,171,46,43,245,4,92,164,183,

View File

@ -1,7 +1,7 @@
namespace resource {
extern const uint8_t systemFolder[667];
extern const uint8_t gameFolder[1176];
extern const uint8_t gameFile[844];
extern const uint8_t cabinet[667];
extern const uint8_t folder[1176];
extern const uint8_t file[844];
extern const uint8_t home[1774];
extern const uint8_t up[1193];
};

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<resource name="resource">
<binary id="systemFolder" name="system-folder.png"/>
<binary id="gameFolder" name="game-folder.png"/>
<binary id="gameFile" name="game-file.png"/>
<binary id="cabinet" name="cabinet.png"/>
<binary id="folder" name="folder.png"/>
<binary id="file" name="file.png"/>
<binary id="home" name="home.png"/>
<binary id="up" name="up.png"/>
</resource>

View File

@ -1,21 +0,0 @@
PathSettings *pathSettings = nullptr;
PathSettings::PathSettings() {
title.setFont(application->titleFont);
title.setText("Path Settings");
gameLabel.setText("Games:");
gamePath.setEditable(false);
gamePath.setText(config->path.game);
gameBrowse.setText("Browse ...");
append(title, {~0, 0}, 5);
append(gameLayout, {~0, 0});
gameLayout.append(gameLabel, {0, 0}, 5);
gameLayout.append(gamePath, {~0, 0}, 5);
gameLayout.append(gameBrowse, {80, 0});
gameBrowse.onActivate = [&] {
string path = DialogWindow::folderSelect(*settings, userpath());
if(path.empty() == false) gamePath.setText(config->path.game = path);
};
}

View File

@ -1,11 +0,0 @@
struct PathSettings : SettingsLayout {
Label title;
HorizontalLayout gameLayout;
Label gameLabel;
LineEdit gamePath;
Button gameBrowse;
PathSettings();
};
extern PathSettings *pathSettings;

View File

@ -4,7 +4,6 @@
#include "input.cpp"
#include "hotkey.cpp"
#include "timing.cpp"
#include "path.cpp"
#include "driver.cpp"
Settings *settings = nullptr;
@ -32,7 +31,6 @@ Settings::Settings() {
panelList.append("Input");
panelList.append("Hotkeys");
panelList.append("Timing");
panelList.append("Paths");
panelList.append("Driver");
append(layout);
@ -42,7 +40,6 @@ Settings::Settings() {
append(*inputSettings);
append(*hotkeySettings);
append(*timingSettings);
append(*pathSettings);
append(*driverSettings);
onClose = [&] {
@ -62,7 +59,6 @@ void Settings::panelChanged() {
inputSettings->setVisible(false);
hotkeySettings->setVisible(false);
timingSettings->setVisible(false);
pathSettings->setVisible(false);
driverSettings->setVisible(false);
if(panelList.selected() == false) return;
@ -72,7 +68,6 @@ void Settings::panelChanged() {
case 2: return inputSettings->setVisible();
case 3: return hotkeySettings->setVisible();
case 4: return timingSettings->setVisible();
case 5: return pathSettings->setVisible();
case 6: return driverSettings->setVisible();
case 5: return driverSettings->setVisible();
}
}

View File

@ -11,7 +11,6 @@ struct SettingsLayout : HorizontalLayout {
#include "input.hpp"
#include "hotkey.hpp"
#include "timing.hpp"
#include "path.hpp"
#include "driver.hpp"
struct Settings : Window {

View File

@ -3,31 +3,46 @@ void Utility::loadMediaFromDatabase(Emulator::Interface *emulator, Emulator::Int
string systemPath = {configpath(), "higan/", emulator->information.name, ".sys/"};
string outputPath = {config->path.game, emulator->information.name, "/"};
string databaseText = string::read({systemPath, "database.bml"}).rtrim("\n");
string databaseText = string::read({systemPath(), "database.bml"}).rtrim("\n");
lstring databaseItem = databaseText.split("\n\n");
for(auto &item : databaseItem) {
item.append("\n");
auto document = Markup::Document(item);
if(document["cartridge"]["information"]["sha256"].content() == sha256) {
string name = {document["cartridge"]["information"]["name"].content(), ".", extension(filename), "/"};
directory::create({outputPath, name});
file::write({outputPath, name, "manifest.bml"}, (const uint8_t*)(const char*)item, item.length());
if(document["cartridge"]["information"]["sha256"].text() == sha256) {
string folderPath = {
outputPath,
document["cartridge"]["information"]["name"].text(),
" (", document["cartridge"]["information"]["region"].text(), ")",
" (", document["cartridge"]["information"]["revision"].text(), ")",
".", extension(filename), "/"
};
directory::create(folderPath);
file::write({folderPath, "sha256"}, (const uint8_t*)(const char*)sha256, sha256.length());
file::write({folderPath, "manifest.bml"}, (const uint8_t*)(const char*)item, item.length());
auto buffer = file::read(filename);
unsigned offset = 0;
for(auto &node : document["cartridge"]["layout"]) {
if(node.name != "file") continue;
string filename = node["name"].content();
unsigned filesize = numeral(node["size"].content());
file::write({outputPath, name, filename}, buffer.data() + offset, filesize);
offset += filesize;
for(auto &node : document["cartridge"]["information"]["configuration"]) {
if(node.name != "rom") continue;
string name = node["name"].text();
unsigned size = node["size"].decimal();
if(file::exists({folderPath, name}) == false) {
file::write({folderPath, name}, buffer.data() + offset, size);
}
offset += size;
}
return loadMedia(emulator, media, {outputPath, name});
return loadMedia(emulator, media, folderPath);
}
}
MessageWindow::warning(*presentation,
"Game not found in database. Mapping information unavailable.\n\n"
"As such, emulation cannot proceed."
"Game not found in database; mapping information not available.\n\n"
"Unable to proceed with emulation."
);
}

View File

@ -13,9 +13,11 @@ void Utility::loadMedia(Emulator::Interface *emulator, Emulator::Interface::Medi
string pathname;
if(!media.load.empty()) pathname = application->path({media.load, "/"});
if(!directory::exists(pathname)) pathname = browser->select("Load Media", media.type);
if(directory::exists(pathname) && file::exists({pathname, "manifest.bml"})) {
return loadMedia(emulator, media, pathname);
}
if(file::exists(pathname)) {
return loadMediaFromDatabase(emulator, media, pathname);
}
@ -36,7 +38,7 @@ void Utility::loadMedia(Emulator::Interface *emulator, Emulator::Interface::Medi
if(this->pathname.size() == 0) this->pathname.append(pathname);
presentation->setSystemName(media.name);
load();
load(Markup::Document(manifest)["cartridge"]["information"]["title"].text());
}
//request from emulation core to load non-volatile media folder
@ -81,14 +83,15 @@ void Utility::reset() {
system().reset();
}
void Utility::load() {
string title;
for(auto &path : pathname) {
string name = path;
name.rtrim<1>("/");
title.append(notdir(nall::basename(name)), " + ");
void Utility::load(string title) {
if(title.empty()) {
for(auto &path : pathname) {
string name = path;
name.rtrim<1>("/");
title.append(notdir(nall::basename(name)), " + ");
}
title.rtrim<1>(" + ");
}
title.rtrim<1>(" + ");
presentation->setTitle(title);
cheatEditor->load({pathname[0], "cheats.xml"});

View File

@ -12,7 +12,7 @@ struct Utility {
void connect(unsigned port, unsigned device);
void power();
void reset();
void load();
void load(string title = "");
void unload();
void saveState(unsigned slot);