mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-08-31 02:00:27 +02:00
v111.8
Serialize SDD1 decompressor Major speedup to nall/serializer [Alcaro] Removed fast PPU tile cache (major speedup for run-ahead mode)
This commit is contained in:
@@ -9,7 +9,7 @@ namespace nall::DSP::Resampler {
|
||||
struct Cubic {
|
||||
inline auto reset(double inputFrequency, double outputFrequency = 0, uint queueSize = 0) -> void;
|
||||
inline auto setInputFrequency(double inputFrequency) -> void;
|
||||
inline auto pending() const -> uint;
|
||||
inline auto pending() const -> bool;
|
||||
inline auto read() -> double;
|
||||
inline auto write(double sample) -> void;
|
||||
inline auto serialize(serializer&) -> void;
|
||||
@@ -39,7 +39,7 @@ auto Cubic::setInputFrequency(double inputFrequency) -> void {
|
||||
ratio = inputFrequency / outputFrequency;
|
||||
}
|
||||
|
||||
auto Cubic::pending() const -> uint {
|
||||
auto Cubic::pending() const -> bool {
|
||||
return samples.pending();
|
||||
}
|
||||
|
||||
|
@@ -241,11 +241,26 @@ auto Response::setFile(const string& value) -> type& {
|
||||
}
|
||||
if(!valid) return *this;
|
||||
|
||||
//cache images for seven days
|
||||
auto suffix = Location::suffix(value);
|
||||
uint maxAge = 0;
|
||||
if(suffix == ".svg"
|
||||
|| suffix == ".ico"
|
||||
|| suffix == ".png"
|
||||
|| suffix == ".gif"
|
||||
|| suffix == ".jpg"
|
||||
|| suffix == ".jpeg") {
|
||||
maxAge = 7 * 24 * 60 * 60;
|
||||
}
|
||||
|
||||
_file = value;
|
||||
string eTag = {"\"", chrono::utc::datetime(file::timestamp(value, file::time::modify)), "\""};
|
||||
header.assign("Content-Length", file::size(value));
|
||||
header.assign("Cache-Control", "public");
|
||||
header.assign("ETag", eTag);
|
||||
header.assign("ETag", {"\"", chrono::utc::datetime(file::timestamp(value, file::time::modify)), "\""});
|
||||
if(maxAge == 0) {
|
||||
header.assign("Cache-Control", {"public"});
|
||||
} else {
|
||||
header.assign("Cache-Control", {"public, max-age=", maxAge});
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@@ -41,7 +41,7 @@ struct queue {
|
||||
template<typename U = T> auto capacity() const -> uint { return _capacity * sizeof(T) / sizeof(U); }
|
||||
template<typename U = T> auto size() const -> uint { return _size * sizeof(T) / sizeof(U); }
|
||||
auto empty() const -> bool { return _size == 0; }
|
||||
auto pending() const -> uint { return _size; }
|
||||
auto pending() const -> bool { return _size > 0; }
|
||||
auto full() const -> bool { return _size >= (int)_capacity; }
|
||||
auto underflow() const -> bool { return _size < 0; }
|
||||
auto overflow() const -> bool { return _size > (int)_capacity; }
|
||||
|
@@ -51,13 +51,9 @@ struct serializer {
|
||||
return _capacity;
|
||||
}
|
||||
|
||||
auto setMode(Mode mode) -> bool {
|
||||
if(_mode == Mode::Save && mode == Mode::Load) {
|
||||
_mode = mode;
|
||||
_size = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
auto setMode(Mode mode) -> void {
|
||||
_mode = mode;
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
template<typename T> auto real(T& value) -> serializer& {
|
||||
@@ -110,35 +106,38 @@ struct serializer {
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<int N> auto array(uint8_t (&array_)[N]) -> serializer& {
|
||||
array(array_, N);
|
||||
return *this;
|
||||
}
|
||||
auto array(uint8_t* array, uint size) -> serializer& {
|
||||
if(_mode == Save) {
|
||||
memcpy(_data+_size, array, size);
|
||||
} else if(_mode == Load) {
|
||||
memcpy(array, _data+_size, size);
|
||||
}
|
||||
_size += size;
|
||||
return *this;
|
||||
}
|
||||
#ifdef ENDIAN_LSB
|
||||
template<int N> auto array(uint16_t (&array_)[N]) -> serializer& {
|
||||
array(array_, N);
|
||||
return *this;
|
||||
}
|
||||
auto array(uint16_t* array_, uint size) -> serializer& {
|
||||
array((uint8_t*)array_, size*2);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T, uint Size> auto array(nall::array<T[Size]>& array) -> serializer& {
|
||||
for(auto& value : array) operator()(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//optimized specializations
|
||||
|
||||
auto array(uint8_t* data, uint size) -> serializer& {
|
||||
if(_mode == Save) {
|
||||
memory::copy(_data + _size, data, size);
|
||||
} else if(_mode == Load) {
|
||||
memory::copy(data, _data + _size, size);
|
||||
} else {
|
||||
}
|
||||
_size += size;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<int N> auto array(uint8_t (&data)[N]) -> serializer& {
|
||||
return array(data, N);
|
||||
}
|
||||
|
||||
//nall/serializer saves data in little-endian ordering
|
||||
#if defined(ENDIAN_LSB)
|
||||
auto array(uint16_t* data, uint size) -> serializer& { return array((uint8_t*)data, size * sizeof(uint16_t)); }
|
||||
auto array(uint32_t* data, uint size) -> serializer& { return array((uint8_t*)data, size * sizeof(uint32_t)); }
|
||||
auto array(uint64_t* data, uint size) -> serializer& { return array((uint8_t*)data, size * sizeof(uint64_t)); }
|
||||
template<int N> auto array(uint16_t (&data)[N]) -> serializer& { return array(data, N); }
|
||||
template<int N> auto array(uint32_t (&data)[N]) -> serializer& { return array(data, N); }
|
||||
template<int N> auto array(uint64_t (&data)[N]) -> serializer& { return array(data, N); }
|
||||
#endif
|
||||
|
||||
template<typename T> auto operator()(T& value, typename std::enable_if<has_serialize<T>::value>::type* = 0) -> serializer& { value.serialize(*this); return *this; }
|
||||
template<typename T> auto operator()(T& value, typename std::enable_if<std::is_integral<T>::value>::type* = 0) -> serializer& { return integer(value); }
|
||||
template<typename T> auto operator()(T& value, typename std::enable_if<std::is_floating_point<T>::value>::type* = 0) -> serializer& { return real(value); }
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
/* Document Markup Language (DML) v1.0 parser
|
||||
* revision 0.04
|
||||
* revision 0.05
|
||||
*/
|
||||
|
||||
#include <nall/location.hpp>
|
||||
@@ -9,6 +9,11 @@
|
||||
namespace nall {
|
||||
|
||||
struct DML {
|
||||
inline auto title() const -> string { return state.title; }
|
||||
inline auto subtitle() const -> string { return state.subtitle; }
|
||||
inline auto description() const -> string { return state.description; }
|
||||
inline auto content() const -> string { return state.output; }
|
||||
|
||||
auto& setAllowHTML(bool allowHTML) { settings.allowHTML = allowHTML; return *this; }
|
||||
auto& setHost(const string& hostname) { settings.host = {hostname, "/"}; return *this; }
|
||||
auto& setPath(const string& pathname) { settings.path = pathname; return *this; }
|
||||
@@ -28,6 +33,9 @@ private:
|
||||
} settings;
|
||||
|
||||
struct State {
|
||||
string title;
|
||||
string subtitle;
|
||||
string description;
|
||||
string output;
|
||||
uint sections = 0;
|
||||
} state;
|
||||
@@ -41,12 +49,14 @@ private:
|
||||
};
|
||||
|
||||
inline auto DML::parse(const string& filedata, const string& pathname) -> string {
|
||||
state = {};
|
||||
settings.path = pathname;
|
||||
parseDocument(filedata, settings.path, 0);
|
||||
return state.output;
|
||||
}
|
||||
|
||||
inline auto DML::parse(const string& filename) -> string {
|
||||
state = {};
|
||||
if(!settings.path) settings.path = Location::path(filename);
|
||||
string document = settings.reader ? settings.reader(filename) : string::read(filename);
|
||||
parseDocument(document, settings.path, 0);
|
||||
@@ -83,8 +93,8 @@ inline auto DML::parseBlock(string& block, const string& pathname, uint depth) -
|
||||
|
||||
//title
|
||||
else if(block.beginsWith("! ")) {
|
||||
auto name = lines.takeLeft().trimLeft("! ", 1L);
|
||||
state.output.append("<h1>", markup(name));
|
||||
state.title = lines.takeLeft().trimLeft("! ", 1L);
|
||||
state.output.append("<h1>", markup(state.title));
|
||||
for(auto& line : lines) {
|
||||
if(!line.beginsWith("! ")) continue;
|
||||
state.output.append("<span>", markup(line.trimLeft("! ", 1L)), "</span>");
|
||||
@@ -92,6 +102,14 @@ inline auto DML::parseBlock(string& block, const string& pathname, uint depth) -
|
||||
state.output.append("</h1>\n");
|
||||
}
|
||||
|
||||
//description
|
||||
else if(block.beginsWith("? ")) {
|
||||
while(lines) {
|
||||
state.description.append(lines.takeLeft().trimLeft("? ", 1L), " ");
|
||||
}
|
||||
state.description.strip();
|
||||
}
|
||||
|
||||
//section
|
||||
else if(block.beginsWith("# ")) {
|
||||
if(settings.sectioned) {
|
||||
@@ -101,6 +119,7 @@ inline auto DML::parseBlock(string& block, const string& pathname, uint depth) -
|
||||
auto content = lines.takeLeft().trimLeft("# ", 1L).split("::", 1L).strip();
|
||||
auto data = markup(content[0]);
|
||||
auto name = escape(content(1, data.hash()));
|
||||
state.subtitle = content[0];
|
||||
state.output.append("<h2 id=\"", name, "\">", data);
|
||||
for(auto& line : lines) {
|
||||
if(!line.beginsWith("# ")) continue;
|
||||
@@ -226,13 +245,14 @@ inline auto DML::markup(const string& s) -> string {
|
||||
|
||||
natural link, linkBase;
|
||||
natural embed, embedBase;
|
||||
natural photo, photoBase;
|
||||
natural iframe, iframeBase;
|
||||
|
||||
for(uint n = 0; n < s.size();) {
|
||||
char a = s[n];
|
||||
char b = s[n + 1];
|
||||
|
||||
if(!link && !embed && !iframe) {
|
||||
if(!link && !embed && !photo && !iframe) {
|
||||
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(insertion.flip() ? "<ins>" : "</ins>"); n += 2; continue; }
|
||||
@@ -244,7 +264,15 @@ inline auto DML::markup(const string& s) -> string {
|
||||
if(iframe == 0 && a == '<' && b == '<') { t.append("<iframe width='772' height='434' src=\""); iframe = 1; iframeBase = n += 2; continue; }
|
||||
if(iframe != 0 && a == '>' && b == '>') { t.append("\" frameborder='0' allowfullscreen></iframe>"); iframe = 0; n += 2; continue; }
|
||||
|
||||
if(!embed) {
|
||||
if(!embed && !link) {
|
||||
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; }
|
||||
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; }
|
||||
if(photo == 2 && a == '}' && b == ']') { t.append(slice(s, photoBase, n - photoBase).replace("@/", settings.host), "\"></a>"); n += 2; photo = 0; continue; }
|
||||
if(photo != 0) { n++; continue; }
|
||||
}
|
||||
|
||||
if(!photo && !embed) {
|
||||
if(link == 0 && a == '[' && b == '[') { t.append("<a href=\""); link = 1; linkBase = n += 2; continue; }
|
||||
if(link == 1 && a == ':' && b == ':') { t.append("\">"); link = 2; n += 2; continue; }
|
||||
if(link == 1 && a == ']' && b == ']') { t.append("\">", slice(s, linkBase, n - linkBase), "</a>"); n += 2; link = 0; continue; }
|
||||
@@ -252,7 +280,7 @@ inline auto DML::markup(const string& s) -> string {
|
||||
if(link == 1 && a == '@' && b == '/') { t.append(settings.host); n += 2; continue; }
|
||||
}
|
||||
|
||||
if(!link) {
|
||||
if(!photo && !link) {
|
||||
if(embed == 0 && a == '{' && b == '{') { t.append("<img src=\""); embed = 1; embedBase = n += 2; continue; }
|
||||
if(embed == 1 && a == ':' && b == ':') { t.append("\" alt=\""); embed = 2; n += 2; continue; }
|
||||
if(embed != 0 && a == '}' && b == '}') { t.append("\">"); embed = 0; n += 2; continue; }
|
||||
|
Reference in New Issue
Block a user