mirror of https://github.com/bsnes-emu/bsnes.git
Update to v082r28 release.
byuu says: Was mostly working on BML. Still working on the spec. Added NES-BNROM, NES-GNROM/NES-MHROM boards. I don't even know why. The latter games do not work very well without Zapper support.
This commit is contained in:
parent
ba2e6b5789
commit
b629a46779
|
@ -29,7 +29,7 @@ endif
|
|||
|
||||
# platform
|
||||
ifeq ($(platform),x)
|
||||
# tree vectorization causes code generation errors with GCC 4.6.1
|
||||
# tree vectorization causes code generation errors with Linux/GCC 4.6.1
|
||||
flags += -fno-tree-vectorize
|
||||
link += -s -ldl -lX11 -lXext
|
||||
else ifeq ($(platform),osx)
|
||||
|
|
|
@ -53,21 +53,14 @@ namespace nall {
|
|||
operator[](buffersize) = data;
|
||||
}
|
||||
|
||||
void append(const T data[], unsigned length) {
|
||||
for(unsigned n = 0; n < length; n++) operator[](buffersize) = data[n];
|
||||
}
|
||||
|
||||
void remove() {
|
||||
if(size > 0) resize(size - 1); //remove last element only
|
||||
}
|
||||
|
||||
template<typename U> void insert(unsigned index, const U list) {
|
||||
unsigned listsize = container_size(list);
|
||||
resize(buffersize + listsize);
|
||||
memmove(pool + index + listsize, pool + index, (buffersize - index) * sizeof(T));
|
||||
for(auto &item : list) pool[index++] = item;
|
||||
}
|
||||
|
||||
void insert(unsigned index, const T item) {
|
||||
insert(index, array<T>{ item });
|
||||
}
|
||||
|
||||
void remove(unsigned index, unsigned count = 1) {
|
||||
for(unsigned i = index; count + i < buffersize; i++) {
|
||||
pool[i] = pool[count + i];
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <nall/string/cast.hpp>
|
||||
#include <nall/string/compare.hpp>
|
||||
#include <nall/string/convert.hpp>
|
||||
#include <nall/string/cstring.hpp>
|
||||
#include <nall/string/filename.hpp>
|
||||
#include <nall/string/math.hpp>
|
||||
#include <nall/string/platform.hpp>
|
||||
|
|
|
@ -1,11 +1,26 @@
|
|||
#ifndef NALL_STRING_BASE_HPP
|
||||
#define NALL_STRING_BASE_HPP
|
||||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
struct cstring;
|
||||
struct string;
|
||||
struct lstring;
|
||||
template<typename T> inline const char* to_string(T);
|
||||
|
||||
struct cstring {
|
||||
inline operator const char*() const;
|
||||
inline unsigned length() const;
|
||||
inline bool operator==(const char*) const;
|
||||
inline bool operator!=(const char*) const;
|
||||
inline optional<unsigned> position(const char *key) const;
|
||||
inline optional<unsigned> iposition(const char *key) const;
|
||||
inline cstring& operator=(const char *data);
|
||||
inline cstring(const char *data);
|
||||
inline cstring();
|
||||
|
||||
protected:
|
||||
const char *data;
|
||||
};
|
||||
|
||||
struct string {
|
||||
inline void reserve(unsigned);
|
||||
|
||||
|
|
|
@ -1,124 +1,175 @@
|
|||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
//BML parser
|
||||
//version 0.02
|
||||
//BML v1.0 parser
|
||||
//revision 0.03
|
||||
|
||||
namespace nall {
|
||||
namespace BML {
|
||||
|
||||
struct Node : linear_vector<Node> {
|
||||
Node *parent;
|
||||
const char *cname;
|
||||
const char *cvalue;
|
||||
inline static string encode(const char *s) {
|
||||
array<char> output;
|
||||
while(*s) {
|
||||
char c = *s++;
|
||||
(c == '\n') ? output.append("{lf}", 4) :
|
||||
(c == '{') ? output.append("{lb}", 4) :
|
||||
(c == '}') ? output.append("{rb}", 4) :
|
||||
output.append(c);
|
||||
}
|
||||
output.append(0);
|
||||
return output.get();
|
||||
}
|
||||
|
||||
inline string name() { return cname; }
|
||||
inline string value() { return cvalue; }
|
||||
struct Node {
|
||||
cstring name;
|
||||
cstring value;
|
||||
signed depth;
|
||||
|
||||
private:
|
||||
linear_vector<Node> children;
|
||||
|
||||
inline bool valid(char p) const {
|
||||
if(p >= 'A' && p <= 'Z') return true;
|
||||
if(p >= 'a' && p <= 'z') return true;
|
||||
if(p >= '0' && p <= '9') return true;
|
||||
if(p == '+' || p == '-') return true;
|
||||
if(p == '.' || p == '_') return true;
|
||||
if(p == ':') return true;
|
||||
if(p == '-' || p == '.') return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool space(char p) const {
|
||||
return p == ' ' || p == '\t';
|
||||
}
|
||||
|
||||
inline unsigned parseDepth(char *p) {
|
||||
unsigned depth = 0;
|
||||
while(space(*p)) depth++, p++;
|
||||
while(*p == '\t') depth++, p++;
|
||||
return depth;
|
||||
}
|
||||
|
||||
inline void parseNode(char *&p) {
|
||||
inline void parseName(char *&p) {
|
||||
if(valid(*p)) {
|
||||
cname = p;
|
||||
name = p;
|
||||
while(valid(*p)) p++;
|
||||
if(*p != '=') return;
|
||||
*p++ = 0;
|
||||
}
|
||||
if(*p == '\n') throw "Missing node value";
|
||||
}
|
||||
|
||||
if(valid(*p)) {
|
||||
cvalue = p;
|
||||
while(valid(*p)) p++;
|
||||
} else {
|
||||
char terminal = *p++;
|
||||
cvalue = p;
|
||||
while(*p && *p != terminal) p++;
|
||||
if(*p == 0) throw "Unclosed terminal";
|
||||
*p++ = 0;
|
||||
inline void parseValue(char *&p) {
|
||||
*p++ = 0; //'{'
|
||||
value = p;
|
||||
char *w = p;
|
||||
while(*p) {
|
||||
if(*p == '\n') throw "Unclosed node value";
|
||||
if(*p == '}') break;
|
||||
if(*p == '{') {
|
||||
if(*(p + 1) == 'l' && *(p + 2) == 'b' && *(p + 3) == '}') *w++ = '{', p += 4;
|
||||
else if(*(p + 1) == 'r' && *(p + 2) == 'b' && *(p + 3) == '}') *w++ = '}', p += 4;
|
||||
else if(*(p + 1) == 'l' && *(p + 2) == 'f' && *(p + 3) == '}') *w++ = '\n', p += 4;
|
||||
else throw "Unrecognized escape sequence";
|
||||
continue;
|
||||
}
|
||||
*w++ = *p++;
|
||||
}
|
||||
|
||||
if(*p != '}') throw "Unclosed node value";
|
||||
*w = *p++ = 0; //'}'
|
||||
}
|
||||
|
||||
inline void parseLine(char *&p) {
|
||||
unsigned depth = parseDepth(p);
|
||||
while(space(*p)) p++;
|
||||
parseNode(p);
|
||||
depth = parseDepth(p);
|
||||
while(*p == '\t') p++;
|
||||
|
||||
while(space(*p)) {
|
||||
parseName(p);
|
||||
bool multiLine = false;
|
||||
if(*p == ':') {
|
||||
multiLine = true;
|
||||
*p++ = 0;
|
||||
Node node(this);
|
||||
node.parseNode(p);
|
||||
append(node);
|
||||
} else if(*p == '{') {
|
||||
parseValue(p);
|
||||
if(*p != ' ' && *p != '\n') throw "Invalid character after first node value";
|
||||
}
|
||||
|
||||
if(*p == '\n') *p++ = 0;
|
||||
while(*p == ' ') {
|
||||
*p++ = 0;
|
||||
Node node;
|
||||
node.parseName(p);
|
||||
if(*p == '{') node.parseValue(p);
|
||||
if(*p != ' ' && *p != '\n') throw "Invalid character after node";
|
||||
children.append(node);
|
||||
}
|
||||
|
||||
while(parseDepth(p) > depth) {
|
||||
Node node(this);
|
||||
node.parseLine(p);
|
||||
append(node);
|
||||
if(*p == 0) throw "Missing line feed";
|
||||
while(*p == '\n') *p++ = 0;
|
||||
|
||||
if(multiLine == false) {
|
||||
while(parseDepth(p) > depth) {
|
||||
Node node;
|
||||
node.parseLine(p);
|
||||
children.append(node);
|
||||
}
|
||||
} else {
|
||||
value = p;
|
||||
char *w = p;
|
||||
while(parseDepth(p) > depth) {
|
||||
p += depth + 1;
|
||||
while(*p && *p != '\n') *w++ = *p++;
|
||||
if(*p != '\n') throw "Multi-line value missing line feed";
|
||||
*w++ = *p++;
|
||||
}
|
||||
*(w - 1) = 0;
|
||||
if(value == p) value = p - 1; //no text data copied, point it back at null data
|
||||
*(p - 1) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline void parse(char *&p, unsigned parentDepth = 0) {
|
||||
inline void parse(char *&p) {
|
||||
while(*p) {
|
||||
while(*p == '\n') *p++ = 0;
|
||||
Node node(this);
|
||||
Node node;
|
||||
node.parseLine(p);
|
||||
append(node);
|
||||
children.append(node);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
inline Node& operator[](const string &name) {
|
||||
for(auto &node : *this) {
|
||||
if(!strcmp(node.cname, name)) return node;
|
||||
inline Node& operator[](const char *name) {
|
||||
for(auto &node : children) {
|
||||
if(node.name == name) return node;
|
||||
}
|
||||
static Node node;
|
||||
node.name = nullptr;
|
||||
return node;
|
||||
}
|
||||
|
||||
inline bool exists() {
|
||||
return parent != nullptr;
|
||||
inline bool exists() const {
|
||||
return name;
|
||||
}
|
||||
|
||||
inline string content(const string &separator = "\n") const {
|
||||
string result;
|
||||
for(auto &node : *this) result.append(node.cvalue, separator);
|
||||
result.rtrim<1>(separator);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline Node(const string &document) : parent(nullptr), cname(nullptr), cvalue(nullptr) {
|
||||
inline bool load(const char *document) {
|
||||
if(document == nullptr) return false;
|
||||
char *p = strdup(document);
|
||||
cvalue = p;
|
||||
name = nullptr;
|
||||
value = p;
|
||||
try {
|
||||
parse(p);
|
||||
} catch(const char *error) {
|
||||
reset();
|
||||
free((void*)(const char*)value);
|
||||
children.reset();
|
||||
return false;
|
||||
}
|
||||
depth = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline Node(Node *parent) : parent(parent), cname(""), cvalue("") {}
|
||||
inline Node() : parent(nullptr), cname(""), cvalue("") {}
|
||||
inline ~Node() { if(cname == nullptr && cvalue) free((void*)cvalue); }
|
||||
inline void constructor() {
|
||||
depth = 0;
|
||||
name = "";
|
||||
value = "";
|
||||
}
|
||||
|
||||
unsigned size() const { return children.size(); }
|
||||
Node* begin() { return children.begin(); }
|
||||
Node* end() { return children.end(); }
|
||||
const Node* begin() const { return children.begin(); }
|
||||
const Node* end() const { return children.end(); }
|
||||
|
||||
inline Node() { constructor(); }
|
||||
inline Node(const char *document) { constructor(); load(document); }
|
||||
inline ~Node() { if(depth == -1) free((void*)(const char*)value); }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
//BSV parser
|
||||
//version 0.02
|
||||
//BSV v1.0 parser
|
||||
//revision 0.02
|
||||
|
||||
namespace nall {
|
||||
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
#ifndef NALL_STRING_CAST_HPP
|
||||
#define NALL_STRING_CAST_HPP
|
||||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
//this is needed, as C++0x does not support explicit template specialization inside classes
|
||||
template<> inline const char* to_string<bool> (bool v) { return v ? "true" : "false"; }
|
||||
template<> inline const char* to_string<signed int> (signed int v) { static char temp[256]; snprintf(temp, 255, "%+d", v); return temp; }
|
||||
template<> inline const char* to_string<unsigned int> (unsigned int v) { static char temp[256]; snprintf(temp, 255, "%u", v); return temp; }
|
||||
template<> inline const char* to_string<intmax_t> (intmax_t v) { static char temp[256]; snprintf(temp, 255, "%+lld", (long long)v); return temp; }
|
||||
template<> inline const char* to_string<uintmax_t> (uintmax_t v) { static char temp[256]; snprintf(temp, 255, "%llu", (unsigned long long)v); return temp; }
|
||||
template<> inline const char* to_string<double> (double v) { static char temp[256]; snprintf(temp, 255, "%f", v); return temp; }
|
||||
template<> inline const char* to_string<char*> (char *v) { return v; }
|
||||
template<> inline const char* to_string<const char*> (const char *v) { return v; }
|
||||
template<> inline const char* to_string<string> (string v) { return v; }
|
||||
template<> inline const char* to_string<const string&>(const string &v) { return v; }
|
||||
template<> inline const char* to_string<bool> (bool v) { return v ? "true" : "false"; }
|
||||
template<> inline const char* to_string<signed int> (signed int v) { static char temp[256]; snprintf(temp, 255, "%+d", v); return temp; }
|
||||
template<> inline const char* to_string<unsigned int> (unsigned int v) { static char temp[256]; snprintf(temp, 255, "%u", v); return temp; }
|
||||
template<> inline const char* to_string<intmax_t> (intmax_t v) { static char temp[256]; snprintf(temp, 255, "%+lld", (long long)v); return temp; }
|
||||
template<> inline const char* to_string<uintmax_t> (uintmax_t v) { static char temp[256]; snprintf(temp, 255, "%llu", (unsigned long long)v); return temp; }
|
||||
template<> inline const char* to_string<double> (double v) { static char temp[256]; snprintf(temp, 255, "%f", v); return temp; }
|
||||
template<> inline const char* to_string<char*> (char *v) { return v; }
|
||||
template<> inline const char* to_string<const char*> (const char *v) { return v; }
|
||||
template<> inline const char* to_string<string> (string v) { return v; }
|
||||
template<> inline const char* to_string<const string&> (const string &v) { return v; }
|
||||
template<> inline const char* to_string<cstring> (cstring v) { return v; }
|
||||
template<> inline const char* to_string<const cstring&>(const cstring &v) { return v; }
|
||||
|
||||
template<typename T> lstring& lstring::operator<<(T value) {
|
||||
operator[](size()).assign(to_string<T>(value));
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef NALL_STRING_COMPARE_HPP
|
||||
#define NALL_STRING_COMPARE_HPP
|
||||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef NALL_STRING_CONVERT_HPP
|
||||
#define NALL_STRING_CONVERT_HPP
|
||||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef NALL_STRING_CORE_HPP
|
||||
#define NALL_STRING_CORE_HPP
|
||||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
//const string:
|
||||
//bind a const char* pointer to an object that has various testing functionality;
|
||||
//yet lacks the memory allocation and modification functionality of the string class
|
||||
|
||||
namespace nall {
|
||||
|
||||
cstring::operator const char*() const { return data; }
|
||||
unsigned cstring::length() const { return strlen(data); }
|
||||
bool cstring::operator==(const char *s) const { return !strcmp(data, s); }
|
||||
bool cstring::operator!=(const char *s) const { return strcmp(data, s); }
|
||||
optional<unsigned> cstring::position (const char *key) const { return strpos(data, key); }
|
||||
optional<unsigned> cstring::iposition(const char *key) const { return istrpos(data, key); }
|
||||
cstring& cstring::operator=(const char *data) { this->data = data; return *this; }
|
||||
cstring::cstring(const char *data) : data(data) {}
|
||||
cstring::cstring() : data("") {}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef NALL_FILENAME_HPP
|
||||
#define NALL_FILENAME_HPP
|
||||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef NALL_STRING_MATH_HPP
|
||||
#define NALL_STRING_MATH_HPP
|
||||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef NALL_STRING_PLATFORM_HPP
|
||||
#define NALL_STRING_PLATFORM_HPP
|
||||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef NALL_STRING_REPLACE_HPP
|
||||
#define NALL_STRING_REPLACE_HPP
|
||||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef NALL_STRING_SPLIT_HPP
|
||||
#define NALL_STRING_SPLIT_HPP
|
||||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef NALL_STRING_STRL_HPP
|
||||
#define NALL_STRING_STRL_HPP
|
||||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef NALL_STRING_STRPOS_HPP
|
||||
#define NALL_STRING_STRPOS_HPP
|
||||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
//usage example:
|
||||
//if(auto position = strpos(str, key)) print(position(), "\n");
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef NALL_STRING_TRIM_HPP
|
||||
#define NALL_STRING_TRIM_HPP
|
||||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef NALL_STRING_UTILITY_HPP
|
||||
#define NALL_STRING_UTILITY_HPP
|
||||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef NALL_STRING_VARIADIC_HPP
|
||||
#define NALL_STRING_VARIADIC_HPP
|
||||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef NALL_STRING_WRAPPER_HPP
|
||||
#define NALL_STRING_WRAPPER_HPP
|
||||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
#ifndef NALL_STRING_XML_HPP
|
||||
#define NALL_STRING_XML_HPP
|
||||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
//XML subset parser
|
||||
//version 0.05
|
||||
//XML v1.0 subset parser
|
||||
//revision 0.05
|
||||
|
||||
namespace nall {
|
||||
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
#include "axrom.cpp"
|
||||
#include "cnrom.cpp"
|
||||
#include "nrom.cpp"
|
||||
#include "sxrom.cpp"
|
||||
#include "txrom.cpp"
|
||||
#include "uxrom.cpp"
|
||||
#include "bandai-fcg.cpp"
|
||||
#include "konami-vrc6.cpp"
|
||||
#include "nes-axrom.cpp"
|
||||
#include "nes-bnrom.cpp"
|
||||
#include "nes-cnrom.cpp"
|
||||
#include "nes-gxrom.cpp"
|
||||
#include "nes-nrom.cpp"
|
||||
#include "nes-sxrom.cpp"
|
||||
#include "nes-txrom.cpp"
|
||||
#include "nes-uxrom.cpp"
|
||||
|
||||
unsigned Board::mirror(unsigned addr, unsigned size) const {
|
||||
unsigned base = 0;
|
||||
|
@ -75,13 +77,13 @@ void Board::serialize(serializer &s) {
|
|||
}
|
||||
|
||||
Board::Board(BML::Node &board, const uint8_t *data, unsigned size) {
|
||||
information.type = board["type"].value();
|
||||
information.battery = board["prg"]["battery"].value();
|
||||
information.type = board["type"].value;
|
||||
information.battery = board["prg"]["battery"].value;
|
||||
|
||||
prgrom.size = decimal(board["prg"]["rom"].value());
|
||||
prgram.size = decimal(board["prg"]["ram"].value());
|
||||
chrrom.size = decimal(board["chr"]["rom"].value());
|
||||
chrram.size = decimal(board["chr"]["ram"].value());
|
||||
prgrom.size = decimal(board["prg"]["rom"].value);
|
||||
prgram.size = decimal(board["prg"]["ram"].value);
|
||||
chrrom.size = decimal(board["chr"]["rom"].value);
|
||||
chrram.size = decimal(board["chr"]["ram"].value);
|
||||
|
||||
if(prgrom.size) prgrom.data = new uint8[prgrom.size]();
|
||||
if(prgram.size) prgram.data = new uint8[prgram.size]();
|
||||
|
@ -102,23 +104,34 @@ Board::~Board() {
|
|||
Board* Board::load(const string &markup, const uint8_t *data, unsigned size) {
|
||||
BML::Node document(markup);
|
||||
auto &board = document["cartridge"]["board"];
|
||||
string type = board["type"].value();
|
||||
|
||||
if(type == "NES-AMROM" ) return new AxROM(board, data, size);
|
||||
if(type == "NES-ANROM" ) return new AxROM(board, data, size);
|
||||
if(type == "NES-AN1ROM" ) return new AxROM(board, data, size);
|
||||
if(type == "NES-AOROM" ) return new AxROM(board, data, size);
|
||||
if(type == "NES-CNROM" ) return new CNROM(board, data, size);
|
||||
if(type == "NES-NROM-256") return new NROM (board, data, size);
|
||||
if(type == "NES-UNROM" ) return new UxROM(board, data, size);
|
||||
if(type == "NES-SNROM" ) return new SxROM(board, data, size);
|
||||
if(type == "NES-SXROM" ) return new SxROM(board, data, size);
|
||||
if(type == "NES-TLROM" ) return new TxROM(board, data, size);
|
||||
if(type == "NES-UOROM" ) return new UxROM(board, data, size);
|
||||
string type = board["type"].value;
|
||||
|
||||
if(type == "BANDAI-FCG") return new BandaiFCG(board, data, size);
|
||||
|
||||
if(type == "KONAMI-VRC-6") return new KonamiVRC6(board, data, size);
|
||||
|
||||
if(type == "NES-AMROM" ) return new NES_AxROM(board, data, size);
|
||||
if(type == "NES-ANROM" ) return new NES_AxROM(board, data, size);
|
||||
if(type == "NES-AN1ROM" ) return new NES_AxROM(board, data, size);
|
||||
if(type == "NES-AOROM" ) return new NES_AxROM(board, data, size);
|
||||
|
||||
if(type == "NES-BNROM" ) return new NES_BNROM(board, data, size);
|
||||
|
||||
if(type == "NES-CNROM" ) return new NES_CNROM(board, data, size);
|
||||
|
||||
if(type == "NES-GNROM" ) return new NES_GxROM(board, data, size);
|
||||
if(type == "NES-MHROM" ) return new NES_GxROM(board, data, size);
|
||||
|
||||
if(type == "NES-NROM-128") return new NES_NROM(board, data, size);
|
||||
if(type == "NES-NROM-256") return new NES_NROM(board, data, size);
|
||||
|
||||
if(type == "NES-SNROM" ) return new NES_SxROM(board, data, size);
|
||||
if(type == "NES-SXROM" ) return new NES_SxROM(board, data, size);
|
||||
|
||||
if(type == "NES-TLROM" ) return new NES_TxROM(board, data, size);
|
||||
|
||||
if(type == "NES-UNROM" ) return new NES_UxROM(board, data, size);
|
||||
if(type == "NES-UOROM" ) return new NES_UxROM(board, data, size);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
//NES-AN1ROM
|
||||
//NES-AOROM
|
||||
|
||||
struct AxROM : Board {
|
||||
struct NES_AxROM : Board {
|
||||
|
||||
uint4 prg_bank;
|
||||
bool mirror_select;
|
||||
|
@ -46,7 +46,7 @@ void serialize(serializer &s) {
|
|||
s.integer(mirror_select);
|
||||
}
|
||||
|
||||
AxROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
NES_AxROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
}
|
||||
|
||||
};
|
|
@ -0,0 +1,53 @@
|
|||
//NES-BN-ROM-01
|
||||
|
||||
struct NES_BNROM : Board {
|
||||
|
||||
struct Settings {
|
||||
bool mirror; //0 = horizontal, 1 = vertical
|
||||
} settings;
|
||||
|
||||
uint2 prg_bank;
|
||||
|
||||
uint8 prg_read(unsigned addr) {
|
||||
if(addr & 0x8000) return Board::prg_read((prg_bank << 15) | (addr & 0x7fff));
|
||||
return cpu.mdr();
|
||||
}
|
||||
|
||||
void prg_write(unsigned addr, uint8 data) {
|
||||
if(addr & 0x8000) prg_bank = data & 0x03;
|
||||
}
|
||||
|
||||
uint8 chr_read(unsigned addr) {
|
||||
if(addr & 0x2000) {
|
||||
if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff);
|
||||
return ppu.ciram_read(addr);
|
||||
}
|
||||
return Board::chr_read(addr);
|
||||
}
|
||||
|
||||
void chr_write(unsigned addr, uint8 data) {
|
||||
if(addr & 0x2000) {
|
||||
if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff);
|
||||
return ppu.ciram_write(addr, data);
|
||||
}
|
||||
return Board::chr_write(addr, data);
|
||||
}
|
||||
|
||||
void power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void reset() {
|
||||
prg_bank = 0;
|
||||
}
|
||||
|
||||
void serialize(serializer &s) {
|
||||
Board::serialize(s);
|
||||
s.integer(prg_bank);
|
||||
}
|
||||
|
||||
NES_BNROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
settings.mirror = board["mirror"].value == "vertical" ? 1 : 0;
|
||||
}
|
||||
|
||||
};
|
|
@ -1,6 +1,6 @@
|
|||
//NES-CNROM
|
||||
|
||||
struct CNROM : Board {
|
||||
struct NES_CNROM : Board {
|
||||
|
||||
struct Settings {
|
||||
bool mirror; //0 = horizontal, 1 = vertical
|
||||
|
@ -49,8 +49,8 @@ void serialize(serializer &s) {
|
|||
s.integer(chr_bank);
|
||||
}
|
||||
|
||||
CNROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
settings.mirror = board["mirror"].value() == "vertical" ? 1 : 0;
|
||||
NES_CNROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
settings.mirror = board["mirror"].value == "vertical" ? 1 : 0;
|
||||
}
|
||||
|
||||
};
|
|
@ -0,0 +1,62 @@
|
|||
//NES-GNROM
|
||||
//NES-MHROM
|
||||
|
||||
struct NES_GxROM : Board {
|
||||
|
||||
struct Settings {
|
||||
bool mirror; //0 = horizontal, 1 = vertical
|
||||
} settings;
|
||||
|
||||
uint2 prg_bank;
|
||||
uint2 chr_bank;
|
||||
|
||||
uint8 prg_read(unsigned addr) {
|
||||
if(addr & 0x8000) return Board::prg_read((prg_bank << 15) | (addr & 0x7fff));
|
||||
return cpu.mdr();
|
||||
}
|
||||
|
||||
void prg_write(unsigned addr, uint8 data) {
|
||||
if(addr & 0x8000) {
|
||||
prg_bank = (data & 0x30) >> 4;
|
||||
chr_bank = (data & 0x03) >> 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 chr_read(unsigned addr) {
|
||||
if(addr & 0x2000) {
|
||||
if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff);
|
||||
return ppu.ciram_read(addr & 0x07ff);
|
||||
}
|
||||
addr = (chr_bank * 0x2000) + (addr & 0x1fff);
|
||||
return Board::chr_read(addr);
|
||||
}
|
||||
|
||||
void chr_write(unsigned addr, uint8 data) {
|
||||
if(addr & 0x2000) {
|
||||
if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff);
|
||||
return ppu.ciram_write(addr & 0x07ff, data);
|
||||
}
|
||||
addr = (chr_bank * 0x2000) + (addr & 0x1fff);
|
||||
Board::chr_write(addr, data);
|
||||
}
|
||||
|
||||
void power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void reset() {
|
||||
prg_bank = 0;
|
||||
chr_bank = 0;
|
||||
}
|
||||
|
||||
void serialize(serializer &s) {
|
||||
Board::serialize(s);
|
||||
s.integer(prg_bank);
|
||||
s.integer(chr_bank);
|
||||
}
|
||||
|
||||
NES_GxROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
settings.mirror = board["mirror"].value == "vertical" ? 1 : 0;
|
||||
}
|
||||
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
//NES-NROM-128
|
||||
//NES-NROM-256
|
||||
|
||||
struct NROM : Board {
|
||||
struct NES_NROM : Board {
|
||||
|
||||
struct Settings {
|
||||
bool mirror; //0 = horizontal, 1 = vertical
|
||||
|
@ -35,8 +35,8 @@ void serialize(serializer &s) {
|
|||
Board::serialize(s);
|
||||
}
|
||||
|
||||
NROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
settings.mirror = board["mirror"].value() == "vertical" ? 1 : 0;
|
||||
NES_NROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
settings.mirror = board["mirror"].value == "vertical" ? 1 : 0;
|
||||
}
|
||||
|
||||
};
|
|
@ -1,4 +1,4 @@
|
|||
struct SxROM : Board {
|
||||
struct NES_SxROM : Board {
|
||||
|
||||
enum class Revision : unsigned {
|
||||
SAROM,
|
||||
|
@ -138,7 +138,7 @@ void serialize(serializer &s) {
|
|||
s.integer(shiftdata);
|
||||
}
|
||||
|
||||
SxROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), mmc1(*this) {
|
||||
NES_SxROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), mmc1(*this) {
|
||||
revision = Revision::SXROM;
|
||||
|
||||
shiftaddr = 0;
|
|
@ -1,4 +1,4 @@
|
|||
struct TxROM : Board {
|
||||
struct NES_TxROM : Board {
|
||||
|
||||
enum class Revision : unsigned {
|
||||
TBROM,
|
||||
|
@ -110,7 +110,7 @@ void serialize(serializer &s) {
|
|||
mmc3.serialize(s);
|
||||
}
|
||||
|
||||
TxROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), mmc3(*this) {
|
||||
NES_TxROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), mmc3(*this) {
|
||||
revision = Revision::TLROM;
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
//NES-UNROM
|
||||
//NES-UOROM
|
||||
|
||||
struct UxROM : Board {
|
||||
struct NES_UxROM : Board {
|
||||
|
||||
struct Settings {
|
||||
bool mirror; //0 = horizontal, 1 = vertical
|
||||
|
@ -49,8 +49,8 @@ void serialize(serializer &s) {
|
|||
s.integer(prg_bank);
|
||||
}
|
||||
|
||||
UxROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
settings.mirror = board["mirror"].value() == "vertical" ? 1 : 0;
|
||||
NES_UxROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
settings.mirror = board["mirror"].value == "vertical" ? 1 : 0;
|
||||
}
|
||||
|
||||
};
|
|
@ -23,6 +23,7 @@ void Cartridge::load(const string &markup, const uint8_t *data, unsigned size) {
|
|||
sha256 = nall::sha256(data + 16, size - 16);
|
||||
board = Board::load(markup != "" ? markup : iNES(data, size), data + 16, size - 16);
|
||||
}
|
||||
if(board == nullptr) return;
|
||||
|
||||
system.load();
|
||||
loaded = true;
|
||||
|
|
|
@ -20,55 +20,65 @@ static string iNES(const uint8_t *data, unsigned size) {
|
|||
|
||||
switch(mapper) {
|
||||
default:
|
||||
output.append(" board type=NES-NROM-256\n");
|
||||
output.append(" mirror=", mirror == 0 ? "horizontal" : "vertical", "\n");
|
||||
output.append("\tboard type{NES-NROM-256}\n");
|
||||
output.append("\t\tmirror{", mirror == 0 ? "horizontal" : "vertical", "}\n");
|
||||
break;
|
||||
|
||||
case 1:
|
||||
output.append(" board type=NES-SXROM\n");
|
||||
output.append(" chip type=MMC1B2\n");
|
||||
output.append("\tboard type{NES-SXROM}\n");
|
||||
output.append("\t\tchip type{MMC1B2}\n");
|
||||
prgram = 8192;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
output.append(" board type=NES-UOROM\n");
|
||||
output.append(" mirror=", mirror == 0 ? "horizontal" : "vertical", "\n");
|
||||
output.append("\tboard type{NES-UOROM}\n");
|
||||
output.append("\t\tmirror{", mirror == 0 ? "horizontal" : "vertical", "}\n");
|
||||
break;
|
||||
|
||||
case 3:
|
||||
output.append(" board type=NES-CNROM\n");
|
||||
output.append(" mirror=", mirror == 0 ? "horizontal" : "vertical", "\n");
|
||||
output.append("\tboard type{NES-CNROM}\n");
|
||||
output.append("\t\tmirror{", mirror == 0 ? "horizontal" : "vertical", "}\n");
|
||||
break;
|
||||
|
||||
case 4:
|
||||
output.append(" board type=NES-TLROM\n");
|
||||
output.append(" chip type=MMC3B\n");
|
||||
output.append("\tboard type{NES-TLROM}\n");
|
||||
output.append("\t\tchip type{MMC3B}\n");
|
||||
prgram = 8192;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
output.append(" board type=NES-AOROM\n");
|
||||
output.append("\tboard type{NES-AOROM}\n");
|
||||
break;
|
||||
|
||||
case 16:
|
||||
output.append(" board type=BANDAI-FCG\n");
|
||||
output.append(" chip type=LZ93D50 manufacturer=Sharp\n");
|
||||
output.append("\tboard type{BANDAI-FCG}\n");
|
||||
output.append("\t\tchip type{LZ93D50}\n");
|
||||
break;
|
||||
|
||||
case 24:
|
||||
output.append(" board type=KONAMI-VRC-6\n");
|
||||
output.append(" chip type=VRC6\n");
|
||||
case 24:
|
||||
output.append("\tboard type{KONAMI-VRC-6}\n");
|
||||
output.append("\t\tchip type{VRC6}\n");
|
||||
break;
|
||||
|
||||
case 26:
|
||||
output.append(" board type=KONAMI-VRC-6\n");
|
||||
output.append(" chip type=VRC6\n");
|
||||
case 26:
|
||||
output.append("\tboard type{KONAMI-VRC-6}\n");
|
||||
output.append("\t\tchip type{VRC6}\n");
|
||||
prgram = 8192;
|
||||
break;
|
||||
|
||||
case 34:
|
||||
output.append("\tboard type{NES-BNROM}\n");
|
||||
output.append("\t\tmirror{", mirror == 0 ? "horizontal" : "vertical", "}\n");
|
||||
break;
|
||||
|
||||
case 66:
|
||||
output.append("\tboard type{NES-GNROM}\n");
|
||||
output.append("\t\tmirror{", mirror == 0 ? "horizontal" : "vertical", "}\n");
|
||||
break;
|
||||
}
|
||||
|
||||
output.append(" prg rom=", prgrom, " ram=", prgram, "\n");
|
||||
output.append(" chr rom=", chrrom, " ram=", chrram, "\n");
|
||||
output.append("\t\tprg rom{", prgrom, "} ram{", prgram, "}\n");
|
||||
output.append("\t\tchr rom{", chrrom, "} ram{", chrram, "}\n");
|
||||
|
||||
print(output, "\n");
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ Application::Application(int argc, char **argv) {
|
|||
inputManager = new InputManager;
|
||||
utility = new Utility;
|
||||
|
||||
title = "bsnes v082.27";
|
||||
title = "bsnes v082.28";
|
||||
|
||||
string fontFamily = Intrinsics::platform() == Intrinsics::Platform::Windows ? "Tahoma, " : "Sans, ";
|
||||
normalFont = { fontFamily, "8" };
|
||||
|
|
|
@ -131,10 +131,10 @@ bool CheatEditor::load(const string &filename) {
|
|||
unsigned n = 0;
|
||||
BML::Node document(data);
|
||||
for(auto &cheat : document["cartridge"]) {
|
||||
if(cheat.name() != "cheat") continue;
|
||||
if(cheat.name != "cheat") continue;
|
||||
cheatList.setChecked(n, cheat["enable"].exists());
|
||||
cheatText[n][Code] = cheat["code"].value();
|
||||
cheatText[n][Desc] = cheat["description"].value();
|
||||
cheatText[n][Code] = cheat["code"].value;
|
||||
cheatText[n][Desc] = cheat["description"].value;
|
||||
if(++n >= 128) break;
|
||||
}
|
||||
|
||||
|
@ -161,11 +161,11 @@ bool CheatEditor::save(const string &filename) {
|
|||
file fp;
|
||||
if(fp.open(filename, file::mode::write) == false) return false;
|
||||
|
||||
fp.print("cartridge sha256=`", interface->sha256(), "`\n");
|
||||
fp.print("cartridge sha256{", interface->sha256(), "}\n");
|
||||
for(unsigned n = 0; n <= lastSave; n++) {
|
||||
fp.print(" cheat", cheatList.checked(n) ? " enable" : "", "\n");
|
||||
fp.print(" description=`", string{cheatText[n][Desc]}.transform("`", "'"), "`\n");
|
||||
fp.print(" code=`", string{cheatText[n][Code]}.transform("`", "'"), "`\n");
|
||||
fp.print("\tcheat", cheatList.checked(n) ? " enable" : "", "\n");
|
||||
fp.print("\t\tdescription{", BML::encode(cheatText[n][Desc]), "}\n");
|
||||
fp.print("\t\tcode{", BML::encode(cheatText[n][Code]), "}\n");
|
||||
}
|
||||
|
||||
fp.close();
|
||||
|
|
Loading…
Reference in New Issue