SFC: Disable color blending for first hires pixel with accuracy PPU
(fixes a green scanline on the left-edge of Jurassic Park)
libco: Don't include <sys/mman.h> when not using mprotect
nall: Detect Windows without invoking uname [Alcaro]
This commit is contained in:
byuu 2019-12-02 19:54:03 +09:00
parent 0d1d6f329d
commit a64c1adaa8
12 changed files with 126 additions and 64 deletions

View File

@ -29,7 +29,7 @@ using namespace nall;
namespace Emulator { namespace Emulator {
static const string Name = "bsnes"; static const string Name = "bsnes";
static const string Version = "112.10"; static const string Version = "112.11";
static const string Author = "byuu"; static const string Author = "byuu";
static const string License = "GPLv3"; static const string License = "GPLv3";
static const string Website = "https://byuu.org"; static const string Website = "https://byuu.org";

View File

@ -10,8 +10,8 @@ auto PPU::Screen::scanline() -> void {
math.above.color = paletteColor(0); math.above.color = paletteColor(0);
math.below.color = math.above.color; math.below.color = math.above.color;
math.above.colorEnable = !(ppu.window.io.col.aboveMask & 1); math.above.colorEnable = false;
math.below.colorEnable = !(ppu.window.io.col.belowMask & 1) && io.back.colorEnable; math.below.colorEnable = false;
math.transparent = true; math.transparent = true;
math.blendMode = false; math.blendMode = false;

View File

@ -39,9 +39,9 @@ endif
verbose: hiro.verbose ruby.verbose nall.verbose all; verbose: hiro.verbose ruby.verbose nall.verbose all;
install: all install: all
ifeq ($(shell id -un),root) ifeq ($(platform),windows)
else ifeq ($(shell id -un),root)
$(error "make install should not be run as root") $(error "make install should not be run as root")
else ifeq ($(platform),windows)
else ifeq ($(platform),macos) else ifeq ($(platform),macos)
mkdir -p ~/Library/Application\ Support/$(name)/ mkdir -p ~/Library/Application\ Support/$(name)/
mkdir -p ~/Library/Application\ Support/$(name)/Database/ mkdir -p ~/Library/Application\ Support/$(name)/Database/
@ -64,9 +64,9 @@ else ifneq ($(filter $(platform),linux bsd),)
endif endif
uninstall: uninstall:
ifeq ($(shell id -un),root) ifeq ($(platform),windows)
else ifeq ($(shell id -un),root)
$(error "make uninstall should not be run as root") $(error "make uninstall should not be run as root")
else ifeq ($(platform),windows)
else ifeq ($(platform),macos) else ifeq ($(platform),macos)
rm -rf /Applications/$(name).app rm -rf /Applications/$(name).app
else ifneq ($(filter $(platform),linux bsd),) else ifneq ($(filter $(platform),linux bsd),)

View File

@ -5,8 +5,10 @@
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <unistd.h> #ifdef LIBCO_MPROTECT
#include <sys/mman.h> #include <unistd.h>
#include <sys/mman.h>
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@ -98,8 +98,10 @@ static void (*co_swap)(cothread_t, cothread_t) = 0;
0xff, 0xe0, /* jmp rax */ 0xff, 0xe0, /* jmp rax */
}; };
#include <unistd.h> #ifdef LIBCO_MPROTECT
#include <sys/mman.h> #include <unistd.h>
#include <sys/mman.h>
#endif
static void co_init() { static void co_init() {
#ifdef LIBCO_MPROTECT #ifdef LIBCO_MPROTECT

View File

@ -4,8 +4,10 @@
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #ifdef LIBCO_MPROTECT
#include <sys/mman.h> #include <unistd.h>
#include <sys/mman.h>
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@ -8,7 +8,7 @@
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#if LIBCO_MPROTECT #ifdef LIBCO_MPROTECT
#include <unistd.h> #include <unistd.h>
#include <sys/mman.h> #include <sys/mman.h>
#endif #endif

View File

@ -52,8 +52,10 @@ static const unsigned char co_swap_function[4096] = {
#endif #endif
} }
#else #else
#include <unistd.h> #ifdef LIBCO_MPROTECT
#include <sys/mman.h> #include <unistd.h>
#include <sys/mman.h>
#endif
static void co_init() { static void co_init() {
#ifdef LIBCO_MPROTECT #ifdef LIBCO_MPROTECT

View File

@ -11,6 +11,12 @@ MAKEFLAGS := Rr
[space] += [space] +=
# platform detection # platform detection
ifeq ($(platform),)
ifeq ($(OS),Windows_NT)
platform := windows
endif
endif
ifeq ($(platform),) ifeq ($(platform),)
uname := $(shell uname) uname := $(shell uname)
ifeq ($(uname),) ifeq ($(uname),)

View File

@ -11,17 +11,22 @@ struct Variable {
}; };
struct SharedVariable { struct SharedVariable {
SharedVariable(const string& name = "", const string& value = "") : shared(new Variable{name, value}) {} SharedVariable(const nall::string& name = "", const nall::string& value = "") : shared(new Variable{name, value}) {}
explicit operator bool() const { return (bool)shared->name; } explicit operator bool() const { return (bool)shared->name; }
auto operator()() const { return shared->value; } auto operator()() const { return shared->value; }
auto& operator=(const string& value) { shared->value = value; return *this; } auto& operator=(const nall::string& value) { shared->value = value; return *this; }
auto name() const { return shared->name; } auto name() const { return shared->name; }
auto value() const { return shared->value; } auto value() const { return shared->value; }
auto string() const { return nall::string{shared->value}.strip().replace("\r", ""); }
auto boolean() const { return string() == "true"; }
auto integer() const { return string().integer(); }
auto natural() const { return string().natural(); }
auto real() const { return string().real(); }
auto& setName(const string& name) { shared->name = name; return *this; } auto& setName(const nall::string& name) { shared->name = name; return *this; }
auto& setValue(const string& value = "") { shared->value = value; return *this; } auto& setValue(const nall::string& value = "") { shared->value = value; return *this; }
shared_pointer<Variable> shared; shared_pointer<Variable> shared;
}; };

View File

@ -35,6 +35,11 @@ struct serializer {
return _size; return _size;
} }
auto setMode(Mode mode) -> void {
_mode = mode;
_size = 0;
}
auto mode() const -> Mode { auto mode() const -> Mode {
return _mode; return _mode;
} }
@ -51,11 +56,6 @@ struct serializer {
return _capacity; return _capacity;
} }
auto setMode(Mode mode) -> void {
_mode = mode;
_size = 0;
}
template<typename T> auto real(T& value) -> serializer& { template<typename T> auto real(T& value) -> serializer& {
enum : uint { size = sizeof(T) }; enum : uint { size = sizeof(T) };
//this is rather dangerous, and not cross-platform safe; //this is rather dangerous, and not cross-platform safe;

View File

@ -23,6 +23,8 @@ struct DML {
auto parse(const string& filedata, const string& pathname) -> string; auto parse(const string& filedata, const string& pathname) -> string;
auto parse(const string& filename) -> string; auto parse(const string& filename) -> string;
auto attribute(const string& name) const -> string;
private: private:
struct Settings { struct Settings {
bool allowHTML = true; bool allowHTML = true;
@ -40,6 +42,12 @@ private:
uint sections = 0; uint sections = 0;
} state; } state;
struct Attribute {
string name;
string value;
};
vector<Attribute> attributes;
auto parseDocument(const string& filedata, const string& pathname, uint depth) -> bool; auto parseDocument(const string& filedata, const string& pathname, uint depth) -> bool;
auto parseBlock(string& block, const string& pathname, uint depth) -> bool; auto parseBlock(string& block, const string& pathname, uint depth) -> bool;
auto count(const string& text, char value) -> uint; auto count(const string& text, char value) -> uint;
@ -48,6 +56,13 @@ private:
auto markup(const string& text) -> string; auto markup(const string& text) -> string;
}; };
inline auto DML::attribute(const string& name) const -> string {
for(auto& attribute : attributes) {
if(attribute.name == name) return attribute.value;
}
return {};
}
inline auto DML::parse(const string& filedata, const string& pathname) -> string { inline auto DML::parse(const string& filedata, const string& pathname) -> string {
state = {}; state = {};
settings.path = pathname; settings.path = pathname;
@ -91,15 +106,12 @@ inline auto DML::parseBlock(string& block, const string& pathname, uint depth) -
} }
} }
//title //attribute
else if(block.beginsWith("! ")) { else if(block.beginsWith("! ")) {
state.title = lines.takeLeft().trimLeft("! ", 1L);
state.output.append("<h1>", markup(state.title));
for(auto& line : lines) { for(auto& line : lines) {
if(!line.beginsWith("! ")) continue; auto parts = line.trimLeft("! ", 1L).split(":", 1L);
state.output.append("<span>", markup(line.trimLeft("! ", 1L)), "</span>"); if(parts.size() == 2) attributes.append({parts[0].strip(), parts[1].strip()});
} }
state.output.append("</h1>\n");
} }
//description //description
@ -206,7 +218,12 @@ inline auto DML::parseBlock(string& block, const string& pathname, uint depth) -
//paragraph //paragraph
else { else {
state.output.append("<p>", markup(block), "</p>\n"); auto content = markup(block);
if(content.beginsWith("<figure") && content.endsWith("</figure>")) {
state.output.append(content, "\n");
} else {
state.output.append("<p>", content, "</p>\n");
}
} }
return true; return true;
@ -243,58 +260,87 @@ inline auto DML::markup(const string& s) -> string {
boolean deletion; boolean deletion;
boolean code; boolean code;
natural link, linkBase; maybe<uint> link;
natural embed, embedBase; maybe<uint> image;
natural photo, photoBase;
natural iframe, iframeBase;
for(uint n = 0; n < s.size();) { for(uint n = 0; n < s.size();) {
char a = s[n]; char a = s[n];
char b = s[n + 1]; char b = s[n + 1];
if(!link && !embed && !photo && !iframe) { if(!link && !image) {
if(a == '*' && b == '*') { t.append(strong.flip() ? "<strong>" : "</strong>"); n += 2; continue; } if(a == '*' && b == '*') { t.append(strong.flip() ? "<strong>" : "</strong>"); n += 2; continue; }
if(a == '/' && b == '/') { t.append(emphasis.flip() ? "<em>" : "</em>"); n += 2; continue; } if(a == '/' && b == '/') { t.append(emphasis.flip() ? "<em>" : "</em>"); n += 2; continue; }
if(a == '_' && b == '_') { t.append(insertion.flip() ? "<ins>" : "</ins>"); n += 2; continue; } if(a == '_' && b == '_') { t.append(insertion.flip() ? "<ins>" : "</ins>"); n += 2; continue; }
if(a == '~' && b == '~') { t.append(deletion.flip() ? "<del>" : "</del>"); n += 2; continue; } if(a == '~' && b == '~') { t.append(deletion.flip() ? "<del>" : "</del>"); n += 2; continue; }
if(a == '|' && b == '|') { t.append(code.flip() ? "<code>" : "</code>"); n += 2; continue; } if(a == '|' && b == '|') { t.append(code.flip() ? "<code>" : "</code>"); n += 2; continue; }
if(a =='\\' && b =='\\') { t.append("<br>"); n += 2; continue; } if(a =='\\' && b =='\\') { t.append("<br>"); n += 2; continue; }
if(a == '[' && b == '[') { n += 2; link = n; continue; }
if(a == '{' && b == '{') { n += 2; image = n; continue; }
} }
if(iframe == 0 && a == '<' && b == '<') { t.append("<iframe width='772' height='434' src=\""); iframe = 1; iframeBase = n += 2; continue; } if(link && !image && a == ']' && b == ']') {
if(iframe != 0 && a == '>' && b == '>') { t.append("\" frameborder='0' allowfullscreen></iframe>"); iframe = 0; n += 2; continue; } auto list = slice(s, link(), n - link()).split("::", 1L);
string uri = list.last();
string name = list.size() == 2 ? list.first() : list.last().split("//", 1L).last();
if(!embed && !link) { t.append("<a href=\"", escape(uri), "\">", escape(name), "</a>");
if(photo == 0 && a == '[' && b == '{') { t.append("<a href=\""); photo = 1; photoBase = n += 2; continue; }
if(photo == 1 && a == '}' && b == ']') { t.append(slice(s, photoBase, n - photoBase).replace("@/", settings.host), "\"><img src=\"", slice(s, photoBase, n - photoBase).replace("@/", settings.host), "\" alt=\"\"></a>"); n += 2; photo = 0; continue; } n += 2;
if(photo == 1 && a == ':' && b == ':') { t.append(slice(s, photoBase, n - photoBase).replace("@/", settings.host), "\"><img src=\"", slice(s, photoBase, n - photoBase).replace("@/", settings.host), "\" alt=\""); photo = 2; photoBase = n += 2; continue; } link = nothing;
if(photo == 2 && a == '}' && b == ']') { t.append(slice(s, photoBase, n - photoBase).replace("@/", settings.host), "\"></a>"); n += 2; photo = 0; continue; } continue;
if(photo != 0) { n++; continue; }
} }
if(!photo && !embed) { if(image && !link && a == '}' && b == '}') {
if(link == 0 && a == '[' && b == '[') { t.append("<a href=\""); link = 1; linkBase = n += 2; continue; } auto side = slice(s, image(), n - image()).split("}{", 1L);
if(link == 1 && a == ':' && b == ':') { t.append("\">"); link = 2; n += 2; continue; } auto list = side(0).split("::", 1L);
if(link == 1 && a == ']' && b == ']') { t.append("\">", slice(s, linkBase, n - linkBase), "</a>"); n += 2; link = 0; continue; } string uri = list.last();
if(link == 2 && a == ']' && b == ']') { t.append("</a>"); n += 2; link = 0; continue; } string name = list.size() == 2 ? list.first() : list.last().split("//", 1L).last();
if(link == 1 && a == '@' && b == '/') { t.append(settings.host); n += 2; continue; } list = side(1).split("; ");
} boolean link, title, caption;
string width, height;
if(!photo && !link) { for(auto p : list) {
if(embed == 0 && a == '{' && b == '{') { t.append("<img src=\""); embed = 1; embedBase = n += 2; continue; } if(p == "link") { link = true; continue; }
if(embed == 1 && a == ':' && b == ':') { t.append("\" alt=\""); embed = 2; n += 2; continue; } if(p == "title") { title = true; continue; }
if(embed != 0 && a == '}' && b == '}') { t.append("\">"); embed = 0; n += 2; continue; } if(p == "caption") { caption = true; continue; }
if(embed == 1 && a == '@' && b == '/') { t.append(settings.host); n += 2; continue; } if(p.beginsWith("width:")) { p.trimLeft("width:", 1L); width = p.strip(); continue; }
if(p.beginsWith("height:")) { p.trimLeft("height:", 1L); height = p.strip(); continue; }
}
if(caption) {
t.append("<figure class='image'>\n");
if(link) t.append("<a href=\"", escape(uri), "\">");
t.append("<img loading=\"lazy\" src=\"", escape(uri), "\" alt=\"", escape(name ? name : uri.hash()), "\"");
if(title) t.append(" title=\"", escape(name), "\"");
if(width) t.append(" width=\"", escape(width), "\"");
if(height) t.append(" height=\"", escape(height), "\"");
t.append(">\n");
if(link) t.append("</a>\n");
t.append("<figcaption>", escape(name), "</figcaption>\n");
t.append("</figure>");
} else {
if(link) t.append("<a href=\"", escape(uri), "\">");
t.append("<img loading=\"lazy\" src=\"", escape(uri), "\" alt=\"", escape(name ? name : uri.hash()), "\"");
if(title) t.append(" title=\"", escape(name), "\"");
if(width && height) t.append(" style=\"width: ", escape(width), "px; max-height: ", escape(height), "px;\"");
if(width) t.append(" width=\"", escape(width), "\"");
if(height) t.append(" height=\"", escape(height), "\"");
t.append(">");
if(link) t.append("</a>");
}
n += 2;
image = nothing;
continue;
} }
if(link || image) { n++; continue; }
if(a =='\\') { t.append(b); n += 2; continue; } if(a =='\\') { t.append(b); n += 2; continue; }
if(a == '&') { t.append("&amp;"); n++; continue; } if(a == '&') { t.append("&amp;"); n++; continue; }
if(a == '<') { t.append("&lt;"); n++; continue; } if(a == '<') { t.append("&lt;"); n++; continue; }
if(a == '>') { t.append("&gt;"); n++; continue; } if(a == '>') { t.append("&gt;"); n++; continue; }
if(a == '"') { t.append("&quot;"); n++; continue; } if(a == '"') { t.append("&quot;"); n++; continue; }
t.append(a); n++; continue;
t.append(a);
n++;
} }
if(strong) t.append("</strong>"); if(strong) t.append("</strong>");
@ -302,9 +348,6 @@ inline auto DML::markup(const string& s) -> string {
if(insertion) t.append("</ins>"); if(insertion) t.append("</ins>");
if(deletion) t.append("</del>"); if(deletion) t.append("</del>");
if(code) t.append("</code>"); if(code) t.append("</code>");
if(link == 1) t.append("\">", slice(s, linkBase, s.size() - linkBase), "</a>");
if(link == 2) t.append("</a>");
if(embed != 0) t.append("\">");
return t; return t;
} }