diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 456823e7..f4038825 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -28,7 +28,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "106.65"; + static const string Version = "106.66"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "https://byuu.org/"; diff --git a/higan/md/cartridge/serialization.cpp b/higan/md/cartridge/serialization.cpp index 2b13fd8e..4866fe76 100644 --- a/higan/md/cartridge/serialization.cpp +++ b/higan/md/cartridge/serialization.cpp @@ -3,5 +3,11 @@ auto Cartridge::serialize(serializer& s) -> void { s.integer(ramEnable); s.integer(ramWritable); s.array(romBank); + s.boolean(gameGenie.enable); + for(auto& code : gameGenie.codes) { + s.boolean(code.enable); + s.integer(code.address); + s.integer(code.data); + } if(slot) slot->serialize(s); } diff --git a/higan/processor/huc6280/instructions.cpp b/higan/processor/huc6280/instructions.cpp index 63c18110..3713dd51 100644 --- a/higan/processor/huc6280/instructions.cpp +++ b/higan/processor/huc6280/instructions.cpp @@ -139,7 +139,8 @@ L io(); } auto HuC6280::instructionImmediate(fp alu, uint8& data) -> void { -L data = ALU(operand()); +L io(); + data = ALU(operand()); } auto HuC6280::instructionImplied(fp alu, uint8& data) -> void { diff --git a/higan/sfc/cartridge/load.cpp b/higan/sfc/cartridge/load.cpp index ca8932d1..2034d66d 100644 --- a/higan/sfc/cartridge/load.cpp +++ b/higan/sfc/cartridge/load.cpp @@ -125,7 +125,7 @@ auto Cartridge::loadMemory(Memory& ram, Markup::Node node, bool required) -> voi if(memory->type == "RAM" && !memory->nonVolatile) return; if(memory->type == "RTC" && !memory->nonVolatile) return; if(auto fp = platform->open(pathID(), memory->name(), File::Read, required)) { - fp->read(ram.data(), ram.size()); + fp->read(ram.data(), min(fp->size(), ram.size())); } } } diff --git a/higan/sfc/coprocessor/spc7110/serialization.cpp b/higan/sfc/coprocessor/spc7110/serialization.cpp index 8c490712..5860be4b 100644 --- a/higan/sfc/coprocessor/spc7110/serialization.cpp +++ b/higan/sfc/coprocessor/spc7110/serialization.cpp @@ -1,4 +1,5 @@ auto SPC7110::serialize(serializer& s) -> void { + Thread::serialize(s); s.array(ram.data(), ram.size()); s.integer(r4801); diff --git a/higan/target-bsnes/presentation/presentation.cpp b/higan/target-bsnes/presentation/presentation.cpp index 502a45ba..2d932d58 100644 --- a/higan/target-bsnes/presentation/presentation.cpp +++ b/higan/target-bsnes/presentation/presentation.cpp @@ -224,6 +224,9 @@ auto Presentation::clearViewport() -> void { if(!emulator->loaded()) viewportLayout.setPadding(); if(!visible() || !video) return; + uint32_t opaqueBlack = 0xff000000; + if(settings.video.format == "RGB30") opaqueBlack = 0xc0000000; + uint32_t* output; uint length; uint width = 16; @@ -231,7 +234,7 @@ auto Presentation::clearViewport() -> void { if(video.acquire(output, length, width, height)) { for(uint y : range(height)) { auto line = output + y * (length >> 2); - for(uint x : range(width)) *line++ = 0xff000000; + for(uint x : range(width)) *line++ = opaqueBlack; } video.release(); video.output(); diff --git a/higan/target-bsnes/program/video.cpp b/higan/target-bsnes/program/video.cpp index 989fd901..cb92be7f 100644 --- a/higan/target-bsnes/program/video.cpp +++ b/higan/target-bsnes/program/video.cpp @@ -50,6 +50,8 @@ auto Program::updateVideoFormat() -> void { settings.video.format = video.format(); } video.setFormat(settings.video.format); + Emulator::video.setDepth(settings.video.format == "RGB30" ? 30 : 24); + Emulator::video.setPalette(); } auto Program::updateVideoShader() -> void { diff --git a/higan/target-bsnes/settings/drivers.cpp b/higan/target-bsnes/settings/drivers.cpp index 5f090aea..740291c1 100644 --- a/higan/target-bsnes/settings/drivers.cpp +++ b/higan/target-bsnes/settings/drivers.cpp @@ -153,12 +153,13 @@ auto DriverSettings::videoFormatChanged() -> void { } //videoFormatOption.setEnabled(video.hasFormat()); layout.setGeometry(layout.geometry()); + videoFormatChange(); } auto DriverSettings::videoFormatChange() -> void { auto item = videoFormatOption.selected(); settings.video.format = item.text(); - video.setFormat(item.text()); + program.updateVideoFormat(); } // diff --git a/higan/video/video.cpp b/higan/video/video.cpp index 323afac8..41dba9cc 100644 --- a/higan/video/video.cpp +++ b/higan/video/video.cpp @@ -60,11 +60,17 @@ auto Video::setPalette() -> void { b = uclamp<16>(b * luminance); } - //convert color from 16-bits/channel to 8-bits/channel; force alpha to 1.0 - palette[index] = a.byte(1) << 24 | r.byte(1) << 16 | g.byte(1) << 8 | b.byte(1) << 0; + switch(depth) { + case 24: palette[index] = r >> 8 << 16 | g >> 8 << 8 | b >> 8 << 0; break; + case 30: palette[index] = r >> 6 << 20 | g >> 6 << 10 | b >> 6 << 0; break; + } } } +auto Video::setDepth(uint depth) -> void { + this->depth = depth; +} + auto Video::setSaturation(double saturation) -> void { this->saturation = saturation; } @@ -130,21 +136,23 @@ auto Video::refresh(uint32* input, uint pitch, uint width, uint height) -> void *target++ = color; } } else { + uint32 mask = depth == 30 ? 0x40100401 : 0x01010101; for(uint x : range(width)) { auto a = *target; auto b = palette[*source++]; - *target++ = (a + b - ((a ^ b) & 0x01010101)) >> 1; + *target++ = (a + b - ((a ^ b) & mask)) >> 1; } } } if(effects.colorBleed) { + uint32 mask = depth == 30 ? 0x40100401 : 0x01010101; for(uint y : range(height)) { auto target = output + y * width; for(uint x : range(width)) { auto a = target[x]; auto b = target[x + (x != width - 1)]; - target[x] = (a + b - ((a ^ b) & 0x01010101)) >> 1; + target[x] = (a + b - ((a ^ b) & mask)) >> 1; } } } @@ -164,6 +172,7 @@ auto Video::refresh(uint32* input, uint pitch, uint width, uint height) -> void for(auto& sprite : sprites) { if(!sprite->visible) continue; + uint32 opaqueAlpha = depth == 30 ? 0xc0000000 : 0xff000000; for(int y : range(sprite->height)) { for(int x : range(sprite->width)) { int pixelY = sprite->y + y; @@ -173,7 +182,7 @@ auto Video::refresh(uint32* input, uint pitch, uint width, uint height) -> void if(pixelX < 0 || pixelX >= width) continue; auto pixel = sprite->pixels[y * sprite->width + x]; - if(pixel) output[pixelY * width + pixelX] = 0xff000000 | pixel; + if(pixel) output[pixelY * width + pixelX] = opaqueAlpha | pixel; } } } diff --git a/higan/video/video.hpp b/higan/video/video.hpp index 7c71155d..7b57d829 100644 --- a/higan/video/video.hpp +++ b/higan/video/video.hpp @@ -17,6 +17,7 @@ struct Video { auto reset(Interface* interface) -> void; auto setPalette() -> void; + auto setDepth(uint depth) -> void; auto setSaturation(double saturation) -> void; auto setGamma(double gamma) -> void; auto setLuminance(double luminance) -> void; @@ -40,6 +41,7 @@ private: uint height = 0; uint colors = 0; + uint depth = 24; double saturation = 1.0; double gamma = 1.0; double luminance = 1.0; diff --git a/nall/GNUmakefile b/nall/GNUmakefile index 11308530..86446002 100644 --- a/nall/GNUmakefile +++ b/nall/GNUmakefile @@ -40,28 +40,28 @@ ifeq ($(platform),) endif compiler.c = $(compiler) -x c -std=c11 -compiler.cpp = $(compiler) -x c++ -std=c++14 +compiler.cpp = $(compiler) -x c++ -std=c++17 compiler.objc = $(compiler) -x objective-c -std=c11 -compiler.objcpp = $(compiler) -x objective-c++ -std=c++14 +compiler.objcpp = $(compiler) -x objective-c++ -std=c++17 flags.c = -x c -std=c11 -flags.cpp = -x c++ -std=c++14 +flags.cpp = -x c++ -std=c++17 flags.objc = -x objective-c -std=c11 -flags.objcpp = -x objective-c++ -std=c++14 +flags.objcpp = -x objective-c++ -std=c++17 flags.deps = -MMD -MP -MF $(@:.o=.d) # compiler detection ifeq ($(compiler),) ifeq ($(platform),windows) compiler := g++ - compiler.cpp = $(compiler) -x c++ -std=gnu++14 - flags.cpp = -x c++ -std=gnu++14 + compiler.cpp = $(compiler) -x c++ -std=gnu++17 + flags.cpp = -x c++ -std=gnu++17 else ifeq ($(platform),macos) compiler := clang++ else ifeq ($(platform),linux) compiler := g++ else ifeq ($(platform),bsd) - compiler := g++49 + compiler := g++8 else compiler := g++ endif @@ -126,7 +126,8 @@ endif ifeq ($(platform),bsd) flags += -I/usr/local/include options += -Wl,-rpath=/usr/local/lib - options += -Wl,-rpath=/usr/local/lib/gcc49 + options += -Wl,-rpath=/usr/local/lib/gcc8 + options += -lstdc++ -lm endif # threading support diff --git a/nall/file-map.hpp b/nall/file-map.hpp index 329e781e..647a823b 100644 --- a/nall/file-map.hpp +++ b/nall/file-map.hpp @@ -15,6 +15,11 @@ #include #endif +#if !defined(MAP_NORESERVE) + //not supported on FreeBSD; flag removed in 11.0 + #define MAP_NORESERVE 0 +#endif + namespace nall { struct file_map { @@ -39,7 +44,7 @@ struct file_map { //auto close() -> void; private: - bool _open = false; + bool _open = false; //zero-byte files return _data = nullptr, _size = 0 uint8_t* _data = nullptr; uint64_t _size = 0; @@ -66,6 +71,9 @@ public: } auto open(const string& filename, uint mode_) -> bool { + close(); + if(file::exists(filename) && file::size(filename) == 0) return _open = true; + int desiredAccess, creationDisposition, protection, mapAccess; switch(mode_) { @@ -111,7 +119,7 @@ public: } _data = (uint8_t*)MapViewOfFile(_map, mapAccess, 0, 0, _size); - return _open = _data; + return _open = true; } auto close() -> void { @@ -154,6 +162,8 @@ public: auto open(const string& filename, uint mode_) -> bool { close(); + if(file::exists(filename) && file::size(filename) == 0) return _open = true; + int openFlags = 0; int mmapFlags = 0; @@ -192,7 +202,7 @@ public: return false; } - return _open = _data; + return _open = true; } auto close() -> void { diff --git a/nall/intrinsics.hpp b/nall/intrinsics.hpp index 00ac58c6..a522ea03 100644 --- a/nall/intrinsics.hpp +++ b/nall/intrinsics.hpp @@ -7,7 +7,7 @@ namespace nall { enum class Platform : uint { Windows, MacOS, Linux, BSD, Unknown }; enum class API : uint { Windows, Posix, Unknown }; enum class DisplayServer : uint { Windows, Quartz, Xorg, Unknown }; - enum class Architecture : uint { x86, amd64, ARM, PPC32, PPC64, Unknown }; + enum class Architecture : uint { x86, amd64, ARM32, ARM64, PPC32, PPC64, Unknown }; enum class Endian : uint { LSB, MSB, Unknown }; enum class Build : uint { Debug, Stable, Size, Release, Performance }; @@ -123,9 +123,12 @@ namespace nall { #elif defined(__amd64__) || defined(_M_AMD64) #define ARCHITECTURE_AMD64 constexpr auto architecture() -> Architecture { return Architecture::amd64; } +#elif defined(__aarch64__) + #define ARCHITECTURE_ARM64 + constexpr auto architecture() -> Architecture { return Architecture::ARM64; } #elif defined(__arm__) - #define ARCHITECTURE_ARM - constexpr auto architecture() -> Architecture { return Architecture::ARM; } + #define ARCHITECTURE_ARM32 + constexpr auto architecture() -> Architecture { return Architecture::ARM32; } #elif defined(__ppc64__) || defined(_ARCH_PPC64) #define ARCHITECTURE_PPC64 constexpr auto architecture() -> Architecture { return Architecture::PPC64; } diff --git a/ruby/video/glx.cpp b/ruby/video/glx.cpp index da5a536d..569fa186 100644 --- a/ruby/video/glx.cpp +++ b/ruby/video/glx.cpp @@ -26,7 +26,7 @@ struct VideoGLX : VideoDriver, OpenGL { auto hasShader() -> bool override { return true; } auto hasFormats() -> vector override { - return {"RGB24"}; //"RGB30" + return {"RGB24"}; //"RGB30" is currently broken; use OpenGL 2.0 driver instead } auto setContext(uintptr context) -> bool override { diff --git a/ruby/video/glx2.cpp b/ruby/video/glx2.cpp index 667113e7..ff5a14b6 100644 --- a/ruby/video/glx2.cpp +++ b/ruby/video/glx2.cpp @@ -37,7 +37,7 @@ struct VideoGLX2 : VideoDriver { auto hasContext() -> bool override { return true; } auto hasBlocking() -> bool override { return true; } auto hasFlush() -> bool override { return true; } - auto hasFormats() -> vector override { return {"RGB24"}; } + auto hasFormats() -> vector override { return {"RGB24", "RGB30"}; } auto hasShader() -> bool override { return true; } auto setContext(uintptr context) -> bool override {