mirror of https://github.com/bsnes-emu/bsnes.git
v109.3
Fixed crash when idling with the snow effect enabled. Added Android target to libretro port [rtretiakov] Various nall library improvements.
This commit is contained in:
parent
c6d90d3ff1
commit
1e626e75ef
|
@ -29,7 +29,7 @@ using namespace nall;
|
|||
|
||||
namespace Emulator {
|
||||
static const string Name = "bsnes";
|
||||
static const string Version = "109.2";
|
||||
static const string Version = "109.3";
|
||||
static const string Author = "byuu";
|
||||
static const string License = "GPLv3";
|
||||
static const string Website = "https://byuu.org";
|
||||
|
|
|
@ -91,7 +91,7 @@ auto Program::viewportRefresh() -> void {
|
|||
|
||||
for(; SnowMover != 0; --SnowMover) {
|
||||
if(--SnowTimer == 0) {
|
||||
++NumSnow;
|
||||
if(NumSnow < 400) ++NumSnow;
|
||||
SnowTimer = 18;
|
||||
}
|
||||
uint32_t i = 0;
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
SRCDIR := $(LOCAL_PATH)/../../..
|
||||
|
||||
INCFLAGS := -I$(SRCDIR) -I$(SRCDIR)/bsnes
|
||||
COREFLAGS := -fomit-frame-pointer -ffast-math -D__LIBRETRO__ $(INCFLAGS)
|
||||
COREFLAGS += -DGB_INTERNAL -DDISABLE_DEBUGGER -DPLATFORM_ANDROID
|
||||
|
||||
GIT_VERSION := " $(shell git rev-parse --short HEAD || echo unknown)"
|
||||
ifneq ($(GIT_VERSION)," unknown")
|
||||
COREFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\"
|
||||
endif
|
||||
|
||||
SRCFILES := $(SRCDIR)/bsnes/target-libretro/libretro.cpp \
|
||||
$(SRCDIR)/bsnes/emulator/emulator.cpp \
|
||||
$(SRCDIR)/libco/libco.c \
|
||||
$(SRCDIR)/bsnes/filter/filter.cpp \
|
||||
$(SRCDIR)/bsnes/lzma/lzma.cpp \
|
||||
$(SRCDIR)/bsnes/sfc/interface/interface.cpp \
|
||||
$(SRCDIR)/bsnes/sfc/system/system.cpp \
|
||||
$(SRCDIR)/bsnes/sfc/controller/controller.cpp \
|
||||
$(SRCDIR)/bsnes/sfc/cartridge/cartridge.cpp \
|
||||
$(SRCDIR)/bsnes/sfc/memory/memory.cpp \
|
||||
$(SRCDIR)/bsnes/sfc/cpu/cpu.cpp \
|
||||
$(SRCDIR)/bsnes/sfc/smp/smp.cpp \
|
||||
$(SRCDIR)/bsnes/sfc/dsp/dsp.cpp \
|
||||
$(SRCDIR)/bsnes/sfc/ppu/ppu.cpp \
|
||||
$(SRCDIR)/bsnes/sfc/ppu-fast/ppu.cpp \
|
||||
$(SRCDIR)/bsnes/sfc/expansion/expansion.cpp \
|
||||
$(SRCDIR)/bsnes/sfc/coprocessor/coprocessor.cpp \
|
||||
$(SRCDIR)/bsnes/sfc/slot/slot.cpp \
|
||||
$(SRCDIR)/bsnes/gb/Core/apu.c \
|
||||
$(SRCDIR)/bsnes/gb/Core/camera.c \
|
||||
$(SRCDIR)/bsnes/gb/Core/display.c \
|
||||
$(SRCDIR)/bsnes/gb/Core/gb.c \
|
||||
$(SRCDIR)/bsnes/gb/Core/joypad.c \
|
||||
$(SRCDIR)/bsnes/gb/Core/mbc.c \
|
||||
$(SRCDIR)/bsnes/gb/Core/memory.c \
|
||||
$(SRCDIR)/bsnes/gb/Core/printer.c \
|
||||
$(SRCDIR)/bsnes/gb/Core/random.c \
|
||||
$(SRCDIR)/bsnes/gb/Core/rewind.c \
|
||||
$(SRCDIR)/bsnes/gb/Core/save_state.c \
|
||||
$(SRCDIR)/bsnes/gb/Core/sgb.c \
|
||||
$(SRCDIR)/bsnes/gb/Core/sm83_cpu.c \
|
||||
$(SRCDIR)/bsnes/gb/Core/symbol_hash.c \
|
||||
$(SRCDIR)/bsnes/gb/Core/timing.c \
|
||||
$(SRCDIR)/bsnes/processor/arm7tdmi/arm7tdmi.cpp \
|
||||
$(SRCDIR)/bsnes/processor/spc700/spc700.cpp \
|
||||
$(SRCDIR)/bsnes/processor/wdc65816/wdc65816.cpp
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := retro
|
||||
LOCAL_SRC_FILES := $(SRCFILES)
|
||||
LOCAL_CPPFLAGS := -std=c++17 $(COREFLAGS)
|
||||
LOCAL_CFLAGS := $(COREFLAGS)
|
||||
LOCAL_LDFLAGS := -Wl,-version-script=$(SRCDIR)/bsnes/target-libretro/link.T
|
||||
LOCAL_CPP_FEATURES := exceptions rtti
|
||||
include $(BUILD_SHARED_LIBRARY)
|
|
@ -0,0 +1,2 @@
|
|||
APP_ABI := all
|
||||
APP_STL := c++_static
|
File diff suppressed because it is too large
Load Diff
|
@ -25,7 +25,10 @@ inline auto create(array_view<uint8_t> source, array_view<uint8_t> target, strin
|
|||
encode(source.size()), encode(target.size()), encode(manifest.size());
|
||||
for(auto& byte : manifest) write(byte);
|
||||
|
||||
auto sourceArray = SuffixArray(source).lrcp();
|
||||
//generating lrcp() arrays for source requires O(4n) computations, and O(16m) memory,
|
||||
//but it reduces find() complexity from O(n log m) to O(n + log m). and yet in practice,
|
||||
//no matter how large n scales to, the O(n + log m) find() is paradoxically slower.
|
||||
auto sourceArray = SuffixArray(source);
|
||||
auto targetArray = SuffixArray(target).lpf();
|
||||
|
||||
enum : uint { SourceRead, TargetRead, SourceCopy, TargetCopy };
|
||||
|
@ -39,12 +42,12 @@ inline auto create(array_view<uint8_t> source, array_view<uint8_t> target, strin
|
|||
while(targetReadLength) write(target[offset++]), targetReadLength--;
|
||||
};
|
||||
|
||||
uint longestSize = max(source.size(), target.size());
|
||||
uint overlap = min(source.size(), target.size());
|
||||
while(outputOffset < target.size()) {
|
||||
uint mode = TargetRead, longestLength = 3, longestOffset = 0;
|
||||
int length = 0, offset = outputOffset;
|
||||
|
||||
while(offset < longestSize) {
|
||||
while(offset < overlap) {
|
||||
if(source[offset] != target[offset]) break;
|
||||
length++, offset++;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,8 @@ namespace nall {
|
|||
//where the first character is the empty suffix, equal to size
|
||||
|
||||
template<typename T>
|
||||
inline auto induced_sort(const T* data, const uint size, const uint characters = 256) -> vector<int> {
|
||||
inline auto induced_sort(array_view<T> data, const uint characters = 256) -> vector<int> {
|
||||
const uint size = data.size();
|
||||
if(size == 0) return vector<int>{0}; //required to avoid out-of-bounds accesses
|
||||
if(size == 1) return vector<int>{1, 0}; //not strictly necessary; but more performant
|
||||
|
||||
|
@ -153,14 +154,14 @@ inline auto induced_sort(const T* data, const uint size, const uint characters =
|
|||
}
|
||||
} else {
|
||||
//recurse until every character in summaryData is unique ...
|
||||
summaries = induced_sort(summaryData.data(), summaryData.size() - 1, summaryCharacters);
|
||||
summaries = induced_sort<int>({summaryData.data(), summaryData.size()}, summaryCharacters);
|
||||
}
|
||||
|
||||
suffixes.fill(-1); //reuse existing buffer for accurate sort
|
||||
|
||||
//accurate LMS sort
|
||||
getTails();
|
||||
for(uint n : reverse(range(1, summaries.size()))) {
|
||||
for(uint n : reverse(range(2, summaries.size()))) {
|
||||
auto index = summaryOffsets[summaries[n]];
|
||||
suffixes[tails[data[index]]--] = index; //advance from the tail of the bucket
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ namespace nall {
|
|||
using uint = unsigned;
|
||||
|
||||
enum class Compiler : uint { Clang, GCC, Microsoft, Unknown };
|
||||
enum class Platform : uint { Windows, MacOS, Linux, BSD, Unknown };
|
||||
enum class Platform : uint { Windows, MacOS, Linux, BSD, Android, Unknown };
|
||||
enum class API : uint { Windows, Posix, Unknown };
|
||||
enum class DisplayServer : uint { Windows, Quartz, Xorg, Unknown };
|
||||
enum class Architecture : uint { x86, amd64, ARM32, ARM64, PPC32, PPC64, Unknown };
|
||||
|
@ -82,6 +82,13 @@ namespace nall {
|
|||
constexpr auto platform() -> Platform { return Platform::MacOS; }
|
||||
constexpr auto api() -> API { return API::Posix; }
|
||||
constexpr auto display() -> DisplayServer { return DisplayServer::Quartz; }
|
||||
#elif defined(__ANDROID__)
|
||||
#define PLATFORM_ANDROID
|
||||
#define API_POSIX
|
||||
#define DISPLAY_UNKNOWN
|
||||
constexpr auto platform() -> Platform { return Platform::Android; }
|
||||
constexpr auto api() -> API { return API::Posix; }
|
||||
constexpr auto display() -> DisplayServer { return DisplayServer::Unknown; }
|
||||
#elif defined(linux) || defined(__linux__)
|
||||
#define PLATFORM_LINUX
|
||||
#define API_POSIX
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
#if !defined(property)
|
||||
#define property1(declaration) public: declaration
|
||||
#define property2(declaration, getter) public: __declspec(property(get=getter)) declaration; protected: declaration##_
|
||||
#define property3(declaration, getter, setter) public: __declspec(property(get=getter, put=setter)) declaration; protected: declaration##_
|
||||
#define property_(_1, _2, _3, name, ...) name
|
||||
#define property(...) property_(__VA_ARGS__, property3, property2, property1)(__VA_ARGS__)
|
||||
#else
|
||||
#undef property1
|
||||
#undef property2
|
||||
#undef property3
|
||||
#undef property_
|
||||
#undef property
|
||||
#endif
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
#if defined(PLATFORM_LINUX) && __has_include(<sys/random.h>)
|
||||
#include <sys/random.h>
|
||||
#elif defined(PLATFORM_ANDROID) && __has_include(<sys/syscall.h>)
|
||||
#include <sys/syscall.h>
|
||||
#elif defined(PLATFORM_WINDOWS) && __has_include(<wincrypt.h>)
|
||||
#include <wincrypt.h>
|
||||
#else
|
||||
|
@ -41,6 +43,8 @@ protected:
|
|||
for(uint n : range(8)) seed = seed << 32 | (uint32_t)arc4random();
|
||||
#elif defined(PLATFORM_LINUX) && __has_include(<sys/random.h>)
|
||||
getrandom(&seed, 32, GRND_NONBLOCK);
|
||||
#elif defined(PLATFORM_ANDROID) && __has_include(<sys/syscall.h>)
|
||||
syscall(__NR_getrandom, &seed, 32, 0x0001); //GRND_NONBLOCK
|
||||
#elif defined(PLATFORM_WINDOWS) && __has_include(<wincrypt.h>)
|
||||
HCRYPTPROV provider;
|
||||
if(CryptAcquireContext(&provider, nullptr, MS_STRONG_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
|
||||
|
@ -63,6 +67,8 @@ namespace PRNG {
|
|||
|
||||
//Galois linear feedback shift register using CRC64 polynomials
|
||||
struct LFSR : RNG<LFSR> {
|
||||
LFSR() { seed(); }
|
||||
|
||||
auto seed(maybe<uint64_t> seed = {}) -> void {
|
||||
lfsr = seed ? seed() : (uint64_t)randomSeed();
|
||||
for(uint n : range(8)) read(); //hide the CRC64 polynomial from initial output
|
||||
|
@ -84,6 +90,8 @@ private:
|
|||
};
|
||||
|
||||
struct PCG : RNG<PCG> {
|
||||
PCG() { seed(); }
|
||||
|
||||
auto seed(maybe<uint32_t> seed = {}, maybe<uint32_t> sequence = {}) -> void {
|
||||
if(!seed) seed = (uint32_t)randomSeed();
|
||||
if(!sequence) sequence = 0;
|
||||
|
|
|
@ -45,6 +45,7 @@ struct string_view {
|
|||
inline auto operator=(const string_view& source) -> type&;
|
||||
inline auto operator=(string_view&& source) -> type&;
|
||||
|
||||
inline explicit operator bool() const;
|
||||
inline operator const char*() const;
|
||||
inline auto data() const -> const char*;
|
||||
inline auto size() const -> uint;
|
||||
|
|
|
@ -81,6 +81,17 @@ 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));
|
||||
for(auto& line : lines) {
|
||||
if(!line.beginsWith("! ")) continue;
|
||||
state.output.append("<span>", markup(line.trimLeft("! ", 1L)), "</span>");
|
||||
}
|
||||
state.output.append("</h1>\n");
|
||||
}
|
||||
|
||||
//section
|
||||
else if(block.beginsWith("# ")) {
|
||||
if(settings.sectioned) {
|
||||
|
@ -90,12 +101,12 @@ 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.output.append("<h1 id=\"", name, "\">", data);
|
||||
state.output.append("<h2 id=\"", name, "\">", data);
|
||||
for(auto& line : lines) {
|
||||
if(!line.beginsWith("# ")) continue;
|
||||
state.output.append("<span>", line.trimLeft("# ", 1L), "</span>");
|
||||
}
|
||||
state.output.append("</h1>\n");
|
||||
state.output.append("</h2>\n");
|
||||
}
|
||||
|
||||
//header
|
||||
|
@ -103,13 +114,13 @@ inline auto DML::parseBlock(string& block, const string& pathname, uint depth) -
|
|||
auto content = slice(lines.takeLeft(), depth + 1).split("::", 1L).strip();
|
||||
auto data = markup(content[0]);
|
||||
auto name = escape(content(1, data.hash()));
|
||||
if(depth <= 5) {
|
||||
state.output.append("<h", depth + 1, " id=\"", name, "\">", data);
|
||||
if(depth <= 4) {
|
||||
state.output.append("<h", depth + 2, " id=\"", name, "\">", data);
|
||||
for(auto& line : lines) {
|
||||
if(count(line, '=') != depth) continue;
|
||||
state.output.append("<span>", slice(line, depth + 1), "</span>");
|
||||
}
|
||||
state.output.append("</h", depth + 1, ">\n");
|
||||
state.output.append("</h", depth + 2, ">\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -69,6 +69,10 @@ auto string_view::operator=(string_view&& source) -> type& {
|
|||
return *this;
|
||||
};
|
||||
|
||||
string_view::operator bool() const {
|
||||
return _size > 0;
|
||||
}
|
||||
|
||||
string_view::operator const char*() const {
|
||||
return _data;
|
||||
}
|
||||
|
|
|
@ -71,8 +71,8 @@ suffix_array_plcp:
|
|||
plcp = [1,0,0,3,2,2,1,1,0,0]
|
||||
|
||||
suffix_array_lrcp:
|
||||
llcp = [0,0,0,3,1,0,0,0,0,1] => llcp[m] == lcp(l, m)
|
||||
rlcp = [0,1,1,1,2,0,2,0,0,0] => rlcp[m] == lcp(m, r)
|
||||
llcp = [0,0,0,3,0,2,0,2,0,0] => llcp[m] == lcp(l, m)
|
||||
rlcp = [0,1,1,1,0,0,0,0,0,0] => rlcp[m] == lcp(m, r)
|
||||
|
||||
suffix_array_lpf:
|
||||
lengths = [0,0,1,3,2,1,0,2,1,0]
|
||||
|
@ -93,7 +93,7 @@ suffix_array_lpf:
|
|||
// suffix array via induced sorting
|
||||
// O(n)
|
||||
inline auto suffix_array(array_view<uint8_t> input) -> vector<int> {
|
||||
return induced_sort(input.data(), input.size());
|
||||
return induced_sort(input);
|
||||
}
|
||||
|
||||
// inverse
|
||||
|
@ -192,17 +192,17 @@ inline auto suffix_array_lrcp(vector<int>& llcp, vector<int>& rlcp, array_view<i
|
|||
rlcp.reset(), rlcp.reallocate(size + 1);
|
||||
|
||||
function<int (int, int)> recurse = [&](int l, int r) -> int {
|
||||
if(l == r - 1) {
|
||||
if(r > size) return 0;
|
||||
if(lcp) return lcp[r];
|
||||
return plcp[sa[r]];
|
||||
if(l >= r - 1) {
|
||||
if(l >= size) return 0;
|
||||
if(lcp) return lcp[l];
|
||||
return plcp[sa[l]];
|
||||
}
|
||||
int m = l + r >> 1;
|
||||
llcp[m] = recurse(l, m);
|
||||
rlcp[m] = recurse(m, r);
|
||||
return min(llcp[m], rlcp[m]);
|
||||
llcp[m - 1] = recurse(l, m);
|
||||
rlcp[m - 1] = recurse(m, r);
|
||||
return min(llcp[m - 1], rlcp[m - 1]);
|
||||
};
|
||||
recurse(0, size + 1);
|
||||
recurse(1, size + 1);
|
||||
|
||||
llcp[0] = 0;
|
||||
rlcp[0] = 0;
|
||||
|
@ -274,6 +274,8 @@ inline auto suffix_array_find(int& length, int& offset, array_view<int> sa, arra
|
|||
if(k == match.size()) return true;
|
||||
}
|
||||
|
||||
if(k == match.size() || s + k == input.size()) k--;
|
||||
|
||||
if(match[k] < input[s + k]) {
|
||||
r = m;
|
||||
} else {
|
||||
|
@ -304,6 +306,8 @@ inline auto suffix_array_find(int& length, int& offset, array_view<int> llcp, ar
|
|||
if(k == match.size()) return true;
|
||||
}
|
||||
|
||||
if(k == match.size() || s + k == input.size()) k--;
|
||||
|
||||
if(match[k] < input[s + k]) {
|
||||
r = m;
|
||||
k = min(k, llcp[m]);
|
||||
|
|
Loading…
Reference in New Issue