mirror of
https://github.com/libretro/bsnes-libretro.git
synced 2024-11-28 03:20:30 +00:00
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:
parent
c495c132a7
commit
ab345ff20c
@ -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";
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
31
higan/nall/string/datetime.hpp
Normal file
31
higan/nall/string/datetime.hpp
Normal file
@ -0,0 +1,31 @@
|
||||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
string string::date() {
|
||||
time_t timestamp = ::time(0);
|
||||
tm *info = localtime(×tamp);
|
||||
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(×tamp);
|
||||
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
|
@ -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;
|
||||
}
|
||||
static Node node;
|
||||
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;
|
||||
}
|
||||
|
||||
const Node& operator[](const string &name) const {
|
||||
return operator[](name);
|
||||
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;
|
||||
}
|
||||
|
||||
vector<Node> operator()(const string &pattern) const {
|
||||
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;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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(); }
|
||||
|
@ -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
|
||||
|
@ -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); }
|
||||
|
9
higan/profile/BS-X Satellaview.sfc/manifest.bml
Normal file
9
higan/profile/BS-X Satellaview.sfc/manifest.bml
Normal 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
|
@ -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>
|
10
higan/profile/Sufami Turbo.sfc/manifest.bml
Normal file
10
higan/profile/Sufami Turbo.sfc/manifest.bml
Normal 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
|
@ -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>
|
3
higan/profile/Super Famicom.sys/manifest.bml
Normal file
3
higan/profile/Super Famicom.sys/manifest.bml
Normal file
@ -0,0 +1,3 @@
|
||||
system name:Super Famicom
|
||||
smp
|
||||
rom name=spc700.rom size=64
|
@ -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>
|
6
higan/profile/Super Game Boy.sfc/manifest.bml
Normal file
6
higan/profile/Super Game Boy.sfc/manifest.bml
Normal 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
|
@ -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>
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
//ARMv3 (ARM6)
|
||||
|
||||
struct ArmDSP : Processor::ARM, Coprocessor {
|
||||
uint8 *firmware;
|
||||
uint8 *programROM;
|
||||
uint8 *dataROM;
|
||||
uint8 *programRAM;
|
||||
|
@ -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)
|
||||
|
@ -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,27 +120,42 @@ 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) {
|
||||
if(id == ID::Nec96050DSPRAM) {
|
||||
for(unsigned n = 0; n < 2048; n++) necdsp.dataRAM[n] = stream.readl(2);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -11,6 +11,7 @@ struct Configuration : configuration {
|
||||
unsigned saturation;
|
||||
unsigned gamma;
|
||||
unsigned luminance;
|
||||
bool startFullScreen;
|
||||
} video;
|
||||
|
||||
struct Audio {
|
||||
|
@ -23,18 +23,22 @@ 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;
|
||||
|
||||
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) {
|
||||
|
@ -160,39 +160,37 @@ 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));
|
||||
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;
|
||||
name.rtrim<1>(suffix);
|
||||
fileList.append(name);
|
||||
fileList.setImage(filenameList.size(), 0, image(resource::gameFile, sizeof resource::gameFile));
|
||||
fileList.setImage(filenameList.size(), 0, image(resource::file, sizeof resource::file));
|
||||
filenameList.append(filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileList.setSelection(selection);
|
||||
fileList.setFocused();
|
||||
|
Before Width: | Height: | Size: 667 B After Width: | Height: | Size: 667 B |
Before Width: | Height: | Size: 844 B After Width: | Height: | Size: 844 B |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@ -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,
|
||||
|
@ -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];
|
||||
};
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
};
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
struct PathSettings : SettingsLayout {
|
||||
Label title;
|
||||
HorizontalLayout gameLayout;
|
||||
Label gameLabel;
|
||||
LineEdit gamePath;
|
||||
Button gameBrowse;
|
||||
|
||||
PathSettings();
|
||||
};
|
||||
|
||||
extern PathSettings *pathSettings;
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
return loadMedia(emulator, media, {outputPath, name});
|
||||
|
||||
offset += size;
|
||||
}
|
||||
|
||||
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."
|
||||
);
|
||||
}
|
||||
|
@ -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;
|
||||
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>(" + ");
|
||||
}
|
||||
presentation->setTitle(title);
|
||||
|
||||
cheatEditor->load({pathname[0], "cheats.xml"});
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user