diff --git a/higan/GNUmakefile b/higan/GNUmakefile index e3c62903..b74420df 100644 --- a/higan/GNUmakefile +++ b/higan/GNUmakefile @@ -1,4 +1,4 @@ -target := higan +target := bsnes binary := application build := performance openmp := true @@ -42,6 +42,49 @@ obj/audio.o: audio/audio.cpp obj/video.o: video/video.cpp obj/resource.o: resource/resource.cpp +ifeq ($(target),higan) + cores := fc sfc ms md pce gb gba ws +endif + +ifeq ($(target),bsnes) + cores := sfc gb +endif + +ifneq ($(filter $(cores),fc),) + include fc/GNUmakefile +endif + +ifneq ($(filter $(cores),sfc),) + include sfc/GNUmakefile +endif + +ifneq ($(filter $(cores),ms),) + include ms/GNUmakefile +endif + +ifneq ($(filter $(cores),md),) + include md/GNUmakefile +endif + +ifneq ($(filter $(cores),pce),) + include pce/GNUmakefile +endif + +ifneq ($(filter $(cores),gb),) + include gb/GNUmakefile +endif + +ifneq ($(filter $(cores),gba),) + include gba/GNUmakefile +endif + +ifneq ($(filter $(cores),ws),) + include ws/GNUmakefile +endif + +include processor/GNUmakefile + +flags += $(foreach c,$(call strupper,$(cores)),-DCORE_$c) ui := target-$(target) include $(ui)/GNUmakefile -include obj/*.d diff --git a/higan/emulator/cheat.hpp b/higan/emulator/cheat.hpp index 5e8c82fb..1ef898e4 100644 --- a/higan/emulator/cheat.hpp +++ b/higan/emulator/cheat.hpp @@ -17,11 +17,11 @@ struct Cheat { codes.reset(); } - auto append(uint addr, uint data, maybe comp = nothing) -> void { + auto append(uint addr, uint data, maybe comp = {}) -> void { codes.append({addr, data, comp}); } - auto assign(const string_vector& list) -> void { + auto assign(const vector& list) -> void { reset(); for(auto& entry : list) { for(auto code : entry.split("+")) { diff --git a/higan/emulator/game.hpp b/higan/emulator/game.hpp index 15d16d89..13f1b5cb 100644 --- a/higan/emulator/game.hpp +++ b/higan/emulator/game.hpp @@ -6,7 +6,7 @@ struct Game { struct Memory; struct Oscillator; - inline auto load(string_view) -> void; + inline auto load(view) -> void; inline auto memory(Markup::Node) -> maybe; inline auto oscillator(natural = 0) -> maybe; @@ -44,7 +44,7 @@ struct Game { vector oscillatorList; }; -auto Game::load(string_view text) -> void { +auto Game::load(view text) -> void { document = BML::unserialize(text); sha256 = document["game/sha256"].text(); diff --git a/higan/emulator/interface.hpp b/higan/emulator/interface.hpp index d8e1dc62..c2e48d91 100644 --- a/higan/emulator/interface.hpp +++ b/higan/emulator/interface.hpp @@ -3,22 +3,20 @@ namespace Emulator { struct Interface { - //information struct Information { string manufacturer; string name; string extension; bool resettable = false; }; - virtual auto information() -> Information = 0; - virtual auto manifest() -> string = 0; - virtual auto title() -> string = 0; struct Display { struct Type { enum : uint { CRT, LCD, };}; + uint id = 0; + string name; uint type = 0; uint colors = 0; uint width = 0; @@ -28,28 +26,16 @@ struct Interface { double aspectCorrection = 0; double refreshRate = 0; }; - virtual auto display() -> Display = 0; - virtual auto color(uint32 color) -> uint64 = 0; - //game interface - virtual auto loaded() -> bool = 0; - virtual auto sha256() -> string { return ""; } - virtual auto load() -> bool = 0; - virtual auto save() -> void = 0; - virtual auto unload() -> void = 0; - - //system interface struct Port { uint id; string name; }; - virtual auto ports() -> vector = 0; struct Device { uint id; string name; }; - virtual auto devices(uint port) -> vector = 0; struct Input { struct Type { enum : uint { @@ -60,35 +46,51 @@ struct Interface { Axis, Rumble, };}; + uint type; string name; }; - virtual auto inputs(uint device) -> vector = 0; + //information + virtual auto information() -> Information { return {}; } + + virtual auto displays() -> vector { return {}; } + virtual auto color(uint32 color) -> uint64 { return 0; } + + //game interface + virtual auto loaded() -> bool { return false; } + virtual auto hashes() -> vector { return {}; } + virtual auto manifests() -> vector { return {}; } + virtual auto titles() -> vector { return {}; } + virtual auto load() -> bool { return false; } + virtual auto save() -> void {} + virtual auto unload() -> void {} + + //system interface + virtual auto ports() -> vector { return {}; } + virtual auto devices(uint port) -> vector { return {}; } + virtual auto inputs(uint device) -> vector { return {}; } virtual auto connected(uint port) -> uint { return 0; } virtual auto connect(uint port, uint device) -> void {} - virtual auto power() -> void = 0; + virtual auto power() -> void {} virtual auto reset() -> void {} - virtual auto run() -> void = 0; + virtual auto run() -> void {} //time functions virtual auto rtc() -> bool { return false; } - virtual auto rtcSynchronize() -> void {} + virtual auto synchronize(uint64 timestamp = 0) -> void {} //state functions - virtual auto serialize() -> serializer = 0; - virtual auto unserialize(serializer&) -> bool = 0; + virtual auto serialize() -> serializer { return {}; } + virtual auto unserialize(serializer&) -> bool { return false; } //cheat functions - virtual auto cheatSet(const string_vector& = {}) -> void {} + virtual auto cheats(const vector& = {}) -> void {} //settings virtual auto cap(const string& name) -> bool { return false; } virtual auto get(const string& name) -> any { return {}; } virtual auto set(const string& name, const any& value) -> bool { return false; } - - //shared functions - auto videoColor(uint16 r, uint16 g, uint16 b) -> uint32; }; } diff --git a/higan/emulator/platform.hpp b/higan/emulator/platform.hpp index cd341fad..111cc07f 100644 --- a/higan/emulator/platform.hpp +++ b/higan/emulator/platform.hpp @@ -4,27 +4,24 @@ namespace Emulator { struct Platform { struct Load { - Load() : _pathID(nothing) {} - Load(uint pathID, string option = "") : _pathID(pathID), _option(option) {} + Load() = default; + Load(uint pathID, string option = "") : valid(true), pathID(pathID), option(option) {} + explicit operator bool() const { return valid; } - explicit operator bool() const { return (bool)_pathID; } - auto pathID() const -> uint { return _pathID(); } - auto option() const -> string { return _option; } - - private: - maybe _pathID; - string _option; + bool valid = false; + uint pathID = 0; + string option; }; virtual auto path(uint id) -> string { return ""; } virtual auto open(uint id, string name, vfs::file::mode mode, bool required = false) -> vfs::shared::file { return {}; } - virtual auto load(uint id, string name, string type, string_vector options = {}) -> Load { return {}; } - virtual auto videoRefresh(const uint32* data, uint pitch, uint width, uint height) -> void {} + virtual auto load(uint id, string name, string type, vector options = {}) -> Load { return {}; } + virtual auto videoRefresh(uint display, const uint32* data, uint pitch, uint width, uint height) -> void {} virtual auto audioSample(const double* samples, uint channels) -> void {} virtual auto inputPoll(uint port, uint device, uint input) -> int16 { return 0; } virtual auto inputRumble(uint port, uint device, uint input, bool enable) -> void {} virtual auto dipSettings(Markup::Node node) -> uint { return 0; } - virtual auto notify(string text) -> void { print(text, "\n"); } + virtual auto notify(string text) -> void {} }; extern Platform* platform; diff --git a/higan/fc/cartridge/board/bandai-fcg.cpp b/higan/fc/cartridge/board/bandai-fcg.cpp index 3d77bd0a..f1ceeab1 100644 --- a/higan/fc/cartridge/board/bandai-fcg.cpp +++ b/higan/fc/cartridge/board/bandai-fcg.cpp @@ -22,6 +22,7 @@ struct BandaiFCG : Board { case 2: return 0x0000 | (addr & 0x03ff); case 3: return 0x0400 | (addr & 0x03ff); } + unreachable; } auto readPRG(uint addr) -> uint8 { diff --git a/higan/fc/cartridge/board/sunsoft-5b.cpp b/higan/fc/cartridge/board/sunsoft-5b.cpp index 5f5d4fb3..402d2450 100644 --- a/higan/fc/cartridge/board/sunsoft-5b.cpp +++ b/higan/fc/cartridge/board/sunsoft-5b.cpp @@ -151,6 +151,7 @@ struct Sunsoft5B : Board { case 2: return 0x0000 | (addr & 0x03ff); //first case 3: return 0x0400 | (addr & 0x03ff); //second } + unreachable; } auto readCHR(uint addr) -> uint8 { diff --git a/higan/fc/cartridge/cartridge.cpp b/higan/fc/cartridge/cartridge.cpp index 663c3255..f36dd2fd 100644 --- a/higan/fc/cartridge/cartridge.cpp +++ b/higan/fc/cartridge/cartridge.cpp @@ -17,8 +17,8 @@ auto Cartridge::main() -> void { auto Cartridge::load() -> bool { if(auto loaded = platform->load(ID::Famicom, "Famicom", "fc", {"NTSC-J", "NTSC-U", "PAL"})) { - information.pathID = loaded.pathID(); - information.region = loaded.option(); + information.pathID = loaded.pathID; + information.region = loaded.option; } else return false; if(auto fp = platform->open(pathID(), "manifest.bml", File::Read, File::Required)) { diff --git a/higan/fc/cartridge/cartridge.hpp b/higan/fc/cartridge/cartridge.hpp index 50e6a8ca..d29e035a 100644 --- a/higan/fc/cartridge/cartridge.hpp +++ b/higan/fc/cartridge/cartridge.hpp @@ -10,7 +10,7 @@ struct Cartridge : Thread { auto pathID() const -> uint { return information.pathID; } auto region() const -> string { return information.region; } - auto sha256() const -> string { return information.sha256; } + auto hash() const -> string { return information.sha256; } auto manifest() const -> string { return information.manifest; } auto title() const -> string { return information.title; } diff --git a/higan/fc/cartridge/chip/mmc1.cpp b/higan/fc/cartridge/chip/mmc1.cpp index bd0a73b7..30b525fc 100644 --- a/higan/fc/cartridge/chip/mmc1.cpp +++ b/higan/fc/cartridge/chip/mmc1.cpp @@ -34,6 +34,7 @@ struct MMC1 : Chip { case 2: return ((addr & 0x0400) >> 0) | (addr & 0x03ff); case 3: return ((addr & 0x0800) >> 1) | (addr & 0x03ff); } + unreachable; } auto writeIO(uint addr, uint8 data) -> void { diff --git a/higan/fc/cartridge/chip/mmc3.cpp b/higan/fc/cartridge/chip/mmc3.cpp index e7049dd3..0920c131 100644 --- a/higan/fc/cartridge/chip/mmc3.cpp +++ b/higan/fc/cartridge/chip/mmc3.cpp @@ -35,6 +35,7 @@ struct MMC3 : Chip { case 3: return (0x3f << 13) | (addr & 0x1fff); } + unreachable; } auto addrCHR(uint addr) const -> uint { @@ -53,11 +54,13 @@ struct MMC3 : Chip { if(addr <= 0x17ff) return (chrBank[0] << 10) | (addr & 0x07ff); if(addr <= 0x1fff) return (chrBank[1] << 10) | (addr & 0x07ff); } + return 0; } auto addrCIRAM(uint addr) const -> uint { if(mirror == 0) return ((addr & 0x0400) >> 0) | (addr & 0x03ff); if(mirror == 1) return ((addr & 0x0800) >> 1) | (addr & 0x03ff); + unreachable; } auto readRAM(uint addr) -> uint8 { diff --git a/higan/fc/cartridge/chip/mmc5.cpp b/higan/fc/cartridge/chip/mmc5.cpp index c48f7bc2..278892b3 100644 --- a/higan/fc/cartridge/chip/mmc5.cpp +++ b/higan/fc/cartridge/chip/mmc5.cpp @@ -83,6 +83,8 @@ struct MMC5 : Chip { case 0x5205: return (multiplier * multiplicand) >> 0; case 0x5206: return (multiplier * multiplicand) >> 8; } + + return 0x00; } auto writePRG(uint addr, uint8 data) -> void { @@ -215,6 +217,8 @@ struct MMC5 : Chip { auto bank = chrSpriteBank[(addr / 0x0400)]; return (bank * 0x0400) + (addr & 0x03ff); } + + unreachable; } auto chrBGAddr(uint addr) -> uint { @@ -239,6 +243,8 @@ struct MMC5 : Chip { auto bank = chrBGBank[(addr / 0x0400)]; return (bank * 0x0400) + (addr & 0x03ff); } + + unreachable; } auto chrVSAddr(uint addr) -> uint { @@ -274,6 +280,7 @@ struct MMC5 : Chip { case 2: return exramMode < 2 ? exram[addr & 0x03ff] : (uint8)0x00; case 3: return (hcounter & 2) == 0 ? fillmodeTile : fillmodeColor; } + unreachable; } auto readCHR(uint addr) -> uint8 { diff --git a/higan/fc/cartridge/chip/mmc6.cpp b/higan/fc/cartridge/chip/mmc6.cpp index b2dff3d4..4aa76456 100644 --- a/higan/fc/cartridge/chip/mmc6.cpp +++ b/higan/fc/cartridge/chip/mmc6.cpp @@ -35,6 +35,7 @@ struct MMC6 : Chip { case 3: return (0x3f << 13) | (addr & 0x1fff); } + unreachable; } auto addrCHR(uint addr) const -> uint { @@ -53,11 +54,13 @@ struct MMC6 : Chip { if(addr <= 0x17ff) return (chrBank[0] << 10) | (addr & 0x07ff); if(addr <= 0x1fff) return (chrBank[1] << 10) | (addr & 0x07ff); } + return 0; } auto addrCIRAM(uint addr) const -> uint { if(mirror == 0) return ((addr & 0x0400) >> 0) | (addr & 0x03ff); if(mirror == 1) return ((addr & 0x0800) >> 1) | (addr & 0x03ff); + unreachable; } auto readRAM(uint addr) -> uint8 { diff --git a/higan/fc/cartridge/chip/vrc6.cpp b/higan/fc/cartridge/chip/vrc6.cpp index a0123ab4..4cdd8760 100644 --- a/higan/fc/cartridge/chip/vrc6.cpp +++ b/higan/fc/cartridge/chip/vrc6.cpp @@ -115,6 +115,7 @@ struct VRC6 : Chip { if((addr & 0xc000) == 0x8000) return (prgBank[0] << 14) | (addr & 0x3fff); if((addr & 0xe000) == 0xc000) return (prgBank[1] << 13) | (addr & 0x1fff); if((addr & 0xe000) == 0xe000) return ( 0xff << 13) | (addr & 0x1fff); + return 0x00; } auto addrCHR(uint addr) const -> uint { @@ -129,6 +130,7 @@ struct VRC6 : Chip { case 2: return 0x0000 | (addr & 0x03ff); //one-screen mirroring (first) case 3: return 0x0400 | (addr & 0x03ff); //one-screen mirroring (second) } + unreachable; } auto readRAM(uint addr) -> uint8 { diff --git a/higan/fc/cartridge/chip/vrc7.cpp b/higan/fc/cartridge/chip/vrc7.cpp index 4903d13f..461f052f 100644 --- a/higan/fc/cartridge/chip/vrc7.cpp +++ b/higan/fc/cartridge/chip/vrc7.cpp @@ -96,6 +96,7 @@ struct VRC7 : Chip { case 2: return 0x0000 | (addr & 0x03ff); //one-screen mirroring (first) case 3: return 0x0400 | (addr & 0x03ff); //one-screen mirroring (second) } + unreachable; } auto power() -> void { diff --git a/higan/fc/interface/interface.cpp b/higan/fc/interface/interface.cpp index 58a622ca..255a80f4 100644 --- a/higan/fc/interface/interface.cpp +++ b/higan/fc/interface/interface.cpp @@ -2,36 +2,30 @@ namespace Famicom { -#define returns(T) T { return ([&] { struct With : T { With() { -#define $ }}; return With(); })(); } - Settings settings; -auto Interface::information() -> returns(Information) { - manufacturer = "Nintendo"; - name = "Famicom"; - resettable = true; -}$ - -auto Interface::manifest() -> string { - return cartridge.manifest(); +auto Interface::information() -> Information { + Information information; + information.manufacturer = "Nintendo"; + information.name = "Famicom"; + information.extension = "fc"; + information.resettable = true; + return information; } -auto Interface::title() -> string { - return cartridge.title(); +auto Interface::displays() -> vector { + Display display; + display.type = Display::Type::CRT; + display.colors = 1 << 9; + display.width = 256; + display.height = 240; + display.internalWidth = 256; + display.internalHeight = 240; + display.aspectCorrection = 8.0 / 7.0; + display.refreshRate = system.frequency() / (ppu.vlines() * ppu.rate() * 341.0); + return {display}; } -auto Interface::display() -> returns(Display) { - type = Display::Type::CRT; - colors = 1 << 9; - width = 256; - height = 240; - internalWidth = 256; - internalHeight = 240; - aspectCorrection = 8.0 / 7.0; - refreshRate = system.frequency() / (ppu.vlines() * ppu.rate() * 341.0); -}$ - auto Interface::color(uint32 n) -> uint64 { double saturation = 2.0; double hue = 0.0; @@ -87,8 +81,16 @@ auto Interface::loaded() -> bool { return system.loaded(); } -auto Interface::sha256() -> string { - return cartridge.sha256(); +auto Interface::hashes() -> vector { + return {cartridge.hash()}; +} + +auto Interface::manifests() -> vector { + return {cartridge.manifest()}; +} + +auto Interface::titles() -> vector { + return {cartridge.title()}; } auto Interface::load() -> bool { @@ -181,7 +183,7 @@ auto Interface::unserialize(serializer& s) -> bool { return system.unserialize(s); } -auto Interface::cheatSet(const string_vector& list) -> void { +auto Interface::cheats(const vector& list) -> void { cheat.assign(list); } @@ -207,7 +209,4 @@ auto Interface::set(const string& name, const any& value) -> bool { return false; } -#undef returns -#undef $ - } diff --git a/higan/fc/interface/interface.hpp b/higan/fc/interface/interface.hpp index 26462ea1..88dca3d7 100644 --- a/higan/fc/interface/interface.hpp +++ b/higan/fc/interface/interface.hpp @@ -1,3 +1,5 @@ +#if defined(CORE_FC) + namespace Famicom { struct ID { @@ -19,18 +21,15 @@ struct ID { }; struct Interface : Emulator::Interface { - using Emulator::Interface::load; - auto information() -> Information override; - auto manifest() -> string override; - auto title() -> string override; - - auto display() -> Display override; + auto displays() -> vector override; auto color(uint32 color) -> uint64 override; auto loaded() -> bool override; - auto sha256() -> string override; + auto hashes() -> vector override; + auto manifests() -> vector override; + auto titles() -> vector override; auto load() -> bool override; auto save() -> void override; auto unload() -> void override; @@ -48,7 +47,7 @@ struct Interface : Emulator::Interface { auto serialize() -> serializer override; auto unserialize(serializer&) -> bool override; - auto cheatSet(const string_vector&) -> void override; + auto cheats(const vector&) -> void override; auto cap(const string& name) -> bool override; auto get(const string& name) -> any override; @@ -67,3 +66,5 @@ struct Settings { extern Settings settings; } + +#endif diff --git a/higan/fc/system/serialization.cpp b/higan/fc/system/serialization.cpp index d653465d..83002044 100644 --- a/higan/fc/system/serialization.cpp +++ b/higan/fc/system/serialization.cpp @@ -3,14 +3,11 @@ auto System::serialize() -> serializer { uint signature = 0x31545342; char version[16] = {0}; - char hash[64] = {0}; char description[512] = {0}; memory::copy(&version, (const char*)Emulator::SerializerVersion, Emulator::SerializerVersion.size()); - memory::copy(&hash, (const char*)cartridge.sha256(), 64); s.integer(signature); s.array(version); - s.array(hash); s.array(description); serializeAll(s); @@ -20,12 +17,10 @@ auto System::serialize() -> serializer { auto System::unserialize(serializer& s) -> bool { uint signature; char version[16]; - char hash[64]; char description[512]; s.integer(signature); s.array(version); - s.array(hash); s.array(description); if(signature != 0x31545342) return false; @@ -54,12 +49,10 @@ auto System::serializeInit() -> void { uint signature = 0; char version[16]; - char hash[64]; char description[512]; s.integer(signature); s.array(version); - s.array(hash); s.array(description); serializeAll(s); diff --git a/higan/gb/cartridge/cartridge.cpp b/higan/gb/cartridge/cartridge.cpp index f2d46ff0..012ff51f 100644 --- a/higan/gb/cartridge/cartridge.cpp +++ b/higan/gb/cartridge/cartridge.cpp @@ -28,19 +28,19 @@ auto Cartridge::load() -> bool { if(Model::GameBoy()) { if(auto loaded = platform->load(ID::GameBoy, "Game Boy", "gb")) { - information.pathID = loaded.pathID(); + information.pathID = loaded.pathID; } else return false; } if(Model::GameBoyColor()) { if(auto loaded = platform->load(ID::GameBoyColor, "Game Boy Color", "gbc")) { - information.pathID = loaded.pathID(); + information.pathID = loaded.pathID; } else return false; } if(Model::SuperGameBoy()) { if(auto loaded = platform->load(ID::SuperGameBoy, "Game Boy", "gb")) { - information.pathID = loaded.pathID(); + information.pathID = loaded.pathID; } else return false; } diff --git a/higan/gb/cartridge/cartridge.hpp b/higan/gb/cartridge/cartridge.hpp index c5cd7cc7..2e25a5ad 100644 --- a/higan/gb/cartridge/cartridge.hpp +++ b/higan/gb/cartridge/cartridge.hpp @@ -1,6 +1,6 @@ struct Cartridge : MMIO { auto pathID() const -> uint { return information.pathID; } - auto sha256() const -> string { return information.sha256; } + auto hash() const -> string { return information.sha256; } auto manifest() const -> string { return information.manifest; } auto title() const -> string { return information.title; } diff --git a/higan/gb/interface/game-boy-color.cpp b/higan/gb/interface/game-boy-color.cpp index 615263f4..645d6dac 100644 --- a/higan/gb/interface/game-boy-color.cpp +++ b/higan/gb/interface/game-boy-color.cpp @@ -1,8 +1,10 @@ -auto GameBoyColorInterface::information() -> returns(Information) { - manufacturer = "Nintendo"; - name = "Game Boy Color"; - extension = "gbc"; -}$ +auto GameBoyColorInterface::information() -> Information { + Information information; + information.manufacturer = "Nintendo"; + information.name = "Game Boy Color"; + information.extension = "gbc"; + return information; +} auto GameBoyColorInterface::color(uint32 color) -> uint64 { uint r = color.bits( 0, 4); diff --git a/higan/gb/interface/game-boy.cpp b/higan/gb/interface/game-boy.cpp index 1d9a2ea3..cd02025e 100644 --- a/higan/gb/interface/game-boy.cpp +++ b/higan/gb/interface/game-boy.cpp @@ -1,8 +1,10 @@ -auto GameBoyInterface::information() -> returns(Information) { - manufacturer = "Nintendo"; - name = "Game Boy"; - extension = "gb"; -}$ +auto GameBoyInterface::information() -> Information { + Information information; + information.manufacturer = "Nintendo"; + information.name = "Game Boy"; + information.extension = "gb"; + return information; +} auto GameBoyInterface::color(uint32 color) -> uint64 { if(!settings.colorEmulation) { diff --git a/higan/gb/interface/interface.cpp b/higan/gb/interface/interface.cpp index 8726ccd7..0f156df3 100644 --- a/higan/gb/interface/interface.cpp +++ b/higan/gb/interface/interface.cpp @@ -2,39 +2,38 @@ namespace GameBoy { -#define returns(T) T { return ([&] { struct With : T { With() { -#define $ }}; return With(); })(); } - SuperGameBoyInterface* superGameBoy = nullptr; Settings settings; #include "game-boy.cpp" #include "game-boy-color.cpp" -auto Interface::manifest() -> string { - return cartridge.manifest(); +auto Interface::displays() -> vector { + Display display; + display.type = Display::Type::LCD; + display.colors = Model::GameBoyColor() ? 1 << 15 : 1 << 2; + display.width = 160; + display.height = 144; + display.internalWidth = 160; + display.internalHeight = 144; + display.aspectCorrection = 1.0; + display.refreshRate = (4.0 * 1024.0 * 1024.0) / (154.0 * 456.0); + return {display}; } -auto Interface::title() -> string { - return cartridge.title(); -} - -auto Interface::display() -> returns(Display) { - type = Display::Type::LCD; - colors = Model::GameBoyColor() ? 1 << 15 : 1 << 2; - width = 160; - height = 144; - internalWidth = 160; - internalHeight = 144; - aspectCorrection = 1.0; - refreshRate = (4.0 * 1024.0 * 1024.0) / (154.0 * 456.0); -}$ - auto Interface::loaded() -> bool { return system.loaded(); } -auto Interface::sha256() -> string { - return cartridge.sha256(); +auto Interface::hashes() -> vector { + return {cartridge.hash()}; +} + +auto Interface::manifests() -> vector { + return {cartridge.manifest()}; +} + +auto Interface::titles() -> vector { + return {cartridge.title()}; } auto Interface::save() -> void { @@ -95,7 +94,7 @@ auto Interface::unserialize(serializer& s) -> bool { return system.unserialize(s); } -auto Interface::cheatSet(const string_vector& list) -> void { +auto Interface::cheats(const vector& list) -> void { cheat.assign(list); } @@ -129,7 +128,4 @@ auto Interface::set(const string& name, const any& value) -> bool { return false; } -#undef returns -#undef $ - } diff --git a/higan/gb/interface/interface.hpp b/higan/gb/interface/interface.hpp index d464c84b..cf07b310 100644 --- a/higan/gb/interface/interface.hpp +++ b/higan/gb/interface/interface.hpp @@ -1,3 +1,5 @@ +#if defined(CORE_GB) + namespace GameBoy { struct ID { @@ -18,13 +20,12 @@ struct ID { }; struct Interface : Emulator::Interface { - auto manifest() -> string override; - auto title() -> string override; - - auto display() -> Display override; + auto displays() -> vector override; auto loaded() -> bool override; - auto sha256() -> string override; + auto hashes() -> vector override; + auto manifests() -> vector override; + auto titles() -> vector override; auto save() -> void override; auto unload() -> void override; @@ -39,7 +40,7 @@ struct Interface : Emulator::Interface { auto serialize() -> serializer override; auto unserialize(serializer&) -> bool override; - auto cheatSet(const string_vector&) -> void override; + auto cheats(const vector&) -> void override; auto cap(const string& name) -> bool override; auto get(const string& name) -> any override; @@ -47,8 +48,6 @@ struct Interface : Emulator::Interface { }; struct GameBoyInterface : Interface { - using Emulator::Interface::load; - auto information() -> Information override; auto color(uint32 color) -> uint64 override; @@ -57,8 +56,6 @@ struct GameBoyInterface : Interface { }; struct GameBoyColorInterface : Interface { - using Emulator::Interface::load; - auto information() -> Information override; auto color(uint32 color) -> uint64 override; @@ -85,3 +82,5 @@ extern SuperGameBoyInterface* superGameBoy; extern Settings settings; } + +#endif diff --git a/higan/gb/system/serialization.cpp b/higan/gb/system/serialization.cpp index c4e50207..3af96d27 100644 --- a/higan/gb/system/serialization.cpp +++ b/higan/gb/system/serialization.cpp @@ -3,14 +3,11 @@ auto System::serialize() -> serializer { uint signature = 0x31545342; char version[16] = {0}; - char hash[64] = {0}; char description[512] = {0}; memory::copy(&version, (const char*)Emulator::SerializerVersion, Emulator::SerializerVersion.size()); - memory::copy(&hash, (const char*)cartridge.sha256(), 64); s.integer(signature); s.array(version); - s.array(hash); s.array(description); serializeAll(s); @@ -20,12 +17,10 @@ auto System::serialize() -> serializer { auto System::unserialize(serializer& s) -> bool { uint signature; char version[16] = {0}; - char hash[64] = {0}; char description[512]; s.integer(signature); s.array(version); - s.array(hash); s.array(description); if(signature != 0x31545342) return false; @@ -53,12 +48,10 @@ auto System::serializeInit() -> void { uint signature = 0; char version[16] = {0}; - char hash[64] = {0}; char description[512] = {0}; s.integer(signature); s.array(version); - s.array(hash); s.array(description); serializeAll(s); diff --git a/higan/gba/apu/noise.cpp b/higan/gba/apu/noise.cpp index 68f6d934..9795f714 100644 --- a/higan/gba/apu/noise.cpp +++ b/higan/gba/apu/noise.cpp @@ -37,6 +37,7 @@ auto APU::Noise::read(uint addr) const -> uint8 { case 3: return (divisor << 0) | (narrowlfsr << 3) | (frequency << 4); case 4: return (counter << 6); } + return 0; } auto APU::Noise::write(uint addr, uint8 byte) -> void { diff --git a/higan/gba/apu/sequencer.cpp b/higan/gba/apu/sequencer.cpp index 071c0149..dcc4e370 100644 --- a/higan/gba/apu/sequencer.cpp +++ b/higan/gba/apu/sequencer.cpp @@ -69,6 +69,7 @@ auto APU::Sequencer::read(uint addr) const -> uint8 { | (masterenable << 7) ); } + return 0; } auto APU::Sequencer::write(uint addr, uint8 byte) -> void { diff --git a/higan/gba/apu/square1.cpp b/higan/gba/apu/square1.cpp index aca6d06a..efd556da 100644 --- a/higan/gba/apu/square1.cpp +++ b/higan/gba/apu/square1.cpp @@ -30,6 +30,7 @@ auto APU::Square1::read(uint addr) const -> uint8 { case 3: return 0; case 4: return (counter << 6); } + return 0; } auto APU::Square1::write(uint addr, uint8 byte) -> void { diff --git a/higan/gba/apu/square2.cpp b/higan/gba/apu/square2.cpp index 4d23fe26..acbb1dec 100644 --- a/higan/gba/apu/square2.cpp +++ b/higan/gba/apu/square2.cpp @@ -5,6 +5,7 @@ auto APU::Square2::read(uint addr) const -> uint8 { case 3: return 0; case 4: return (counter << 6); } + return 0; } auto APU::Square2::write(uint addr, uint8 byte) -> void { diff --git a/higan/gba/apu/wave.cpp b/higan/gba/apu/wave.cpp index 070cd88c..6d12a7af 100644 --- a/higan/gba/apu/wave.cpp +++ b/higan/gba/apu/wave.cpp @@ -25,6 +25,7 @@ auto APU::Wave::read(uint addr) const -> uint8 { case 3: return 0; case 4: return (counter << 6); } + return 0; } auto APU::Wave::write(uint addr, uint8 byte) -> void { diff --git a/higan/gba/cartridge/cartridge.cpp b/higan/gba/cartridge/cartridge.cpp index 2186d052..549ac472 100644 --- a/higan/gba/cartridge/cartridge.cpp +++ b/higan/gba/cartridge/cartridge.cpp @@ -27,7 +27,7 @@ auto Cartridge::load() -> bool { information = Information(); if(auto loaded = platform->load(ID::GameBoyAdvance, "Game Boy Advance", "gba")) { - information.pathID = loaded.pathID(); + information.pathID = loaded.pathID; } else return false; if(auto fp = platform->open(pathID(), "manifest.bml", File::Read, File::Required)) { diff --git a/higan/gba/cartridge/cartridge.hpp b/higan/gba/cartridge/cartridge.hpp index cdbd9675..44970b07 100644 --- a/higan/gba/cartridge/cartridge.hpp +++ b/higan/gba/cartridge/cartridge.hpp @@ -2,7 +2,7 @@ struct Cartridge { #include "memory.hpp" auto pathID() const -> uint { return information.pathID; } - auto sha256() const -> string { return information.sha256; } + auto hash() const -> string { return information.sha256; } auto manifest() const -> string { return information.manifest; } auto title() const -> string { return information.title; } diff --git a/higan/gba/interface/interface.cpp b/higan/gba/interface/interface.cpp index bd629da8..1365d62f 100644 --- a/higan/gba/interface/interface.cpp +++ b/higan/gba/interface/interface.cpp @@ -2,38 +2,32 @@ namespace GameBoyAdvance { -#define returns(T) T { return ([&] { struct With : T { With() { -#define $ }}; return With(); })(); } - Settings settings; -auto Interface::information() -> returns(Information) { - manufacturer = "Nintendo"; - name = "Game Boy Advance"; -}$ - -auto Interface::manifest() -> string { - return cartridge.manifest(); +auto Interface::information() -> Information { + Information information; + information.manufacturer = "Nintendo"; + information.name = "Game Boy Advance"; + information.extension = "gba"; + return information; } -auto Interface::title() -> string { - return cartridge.title(); -} - -auto Interface::display() -> returns(Display) { - type = Display::Type::LCD; - colors = 1 << 15; - width = 240; - height = 160; - internalWidth = 240; - internalHeight = 160; - aspectCorrection = 1.0; - refreshRate = system.frequency() / (228.0 * 1232.0); +auto Interface::displays() -> vector { + Display display; + display.type = Display::Type::LCD; + display.colors = 1 << 15; + display.width = 240; + display.height = 160; + display.internalWidth = 240; + display.internalHeight = 160; + display.aspectCorrection = 1.0; + display.refreshRate = system.frequency() / (228.0 * 1232.0); if(settings.rotateLeft) { - swap(width, height); - swap(internalWidth, internalHeight); + swap(display.width, display.height); + swap(display.internalWidth, display.internalHeight); } -}$ + return {display}; +} auto Interface::color(uint32 color) -> uint64 { uint R = color.bits( 0, 4); @@ -61,6 +55,18 @@ auto Interface::loaded() -> bool { return system.loaded(); } +auto Interface::hashes() -> vector { + return {cartridge.hash()}; +} + +auto Interface::manifests() -> vector { + return {cartridge.manifest()}; +} + +auto Interface::titles() -> vector { + return {cartridge.title()}; +} + auto Interface::load() -> bool { return system.load(this); } @@ -159,7 +165,4 @@ auto Interface::set(const string& name, const any& value) -> bool { return false; } -#undef returns -#undef $ - } diff --git a/higan/gba/interface/interface.hpp b/higan/gba/interface/interface.hpp index 1281f71b..6fe128de 100644 --- a/higan/gba/interface/interface.hpp +++ b/higan/gba/interface/interface.hpp @@ -1,3 +1,5 @@ +#if defined(CORE_GBA) + namespace GameBoyAdvance { struct ID { @@ -16,17 +18,15 @@ struct ID { }; struct Interface : Emulator::Interface { - using Emulator::Interface::load; - auto information() -> Information override; - auto manifest() -> string override; - auto title() -> string override; - - auto display() -> Display override; + auto displays() -> vector override; auto color(uint32 color) -> uint64 override; auto loaded() -> bool override; + auto hashes() -> vector override; + auto manifests() -> vector override; + auto titles() -> vector override; auto load() -> bool override; auto save() -> void override; auto unload() -> void override; @@ -55,3 +55,5 @@ struct Settings { extern Settings settings; } + +#endif diff --git a/higan/gba/ppu/memory.cpp b/higan/gba/ppu/memory.cpp index 5d8c23c9..b74ccd9f 100644 --- a/higan/gba/ppu/memory.cpp +++ b/higan/gba/ppu/memory.cpp @@ -101,6 +101,8 @@ auto PPU::readOAM(uint mode, uint32 addr) -> uint32 { } } + + unreachable; } auto PPU::writeOAM(uint mode, uint32 addr, uint32 word) -> void { diff --git a/higan/gba/system/serialization.cpp b/higan/gba/system/serialization.cpp index fd2056ea..c4778c54 100644 --- a/higan/gba/system/serialization.cpp +++ b/higan/gba/system/serialization.cpp @@ -3,14 +3,11 @@ auto System::serialize() -> serializer { uint signature = 0x31545342; char version[16] = {0}; - char hash[64] = {0}; char description[512] = {0}; memory::copy(&version, (const char*)Emulator::SerializerVersion, Emulator::SerializerVersion.size()); - memory::copy(&hash, (const char*)cartridge.sha256(), 64); s.integer(signature); s.array(version); - s.array(hash); s.array(description); serializeAll(s); @@ -20,12 +17,10 @@ auto System::serialize() -> serializer { auto System::unserialize(serializer& s) -> bool { uint signature = 0; char version[16] = {0}; - char hash[64] = {0}; char description[512] = {0}; s.integer(signature); s.array(version); - s.array(hash); s.array(description); if(signature != 0x31545342) return false; @@ -55,12 +50,10 @@ auto System::serializeInit() -> void { uint signature = 0; char version[16] = {0}; - char hash[64] = {0}; char description[512] = {0}; s.integer(signature); s.array(version); - s.array(hash); s.array(description); serializeAll(s); diff --git a/higan/md/apu/bus.cpp b/higan/md/apu/bus.cpp index f1678597..a408d6a1 100644 --- a/higan/md/apu/bus.cpp +++ b/higan/md/apu/bus.cpp @@ -11,6 +11,8 @@ auto APU::read(uint16 addr) -> uint8 { if((addr & 0x8000) == 0x8000) { return cartridge.read(io.bank << 15 | (addr & 0x7ffe)).byte(!addr.bit(0)); } + + return 0x00; } auto APU::write(uint16 addr, uint8 data) -> void { diff --git a/higan/md/cartridge/cartridge.cpp b/higan/md/cartridge/cartridge.cpp index 2e21c2e5..9f01ddaa 100644 --- a/higan/md/cartridge/cartridge.cpp +++ b/higan/md/cartridge/cartridge.cpp @@ -5,54 +5,160 @@ namespace MegaDrive { Cartridge cartridge; #include "serialization.cpp" +auto Cartridge::region() const -> string { + return game.region; +} + +auto Cartridge::hashes() const -> vector { + vector hashes; + hashes.append(game.hash); + if(lockOn.hash) hashes.append(lockOn.hash); + return hashes; +} + +auto Cartridge::manifests() const -> vector { + vector manifests; + manifests.append(game.manifest); + if(lockOn.manifest) manifests.append(lockOn.manifest); + return manifests; +} + +auto Cartridge::titles() const -> vector { + vector titles; + titles.append(game.title); + if(lockOn.title) titles.append(lockOn.title); + return titles; +} + auto Cartridge::load() -> bool { - information = {}; + game = {}; + lockOn = {}; + read.reset(); + write.reset(); + if(!loadGame()) { + game = {}; + return false; + } + + read = {&Cartridge::readGame, this}; + write = {&Cartridge::writeGame, this}; + + if(game.patch.size) { + read = {&Cartridge::readLockOn, this}; + write = {&Cartridge::writeLockOn, this}; + if(!loadLockOn()) lockOn = {}; + } + + return true; +} + +auto Cartridge::loadGame() -> bool { if(auto loaded = platform->load(ID::MegaDrive, "Mega Drive", "md", {"Auto", "NTSC-J", "NTSC-U", "PAL"})) { - information.pathID = loaded.pathID(); - information.region = loaded.option(); + game.pathID = loaded.pathID; + game.region = loaded.option; } else return false; - if(auto fp = platform->open(pathID(), "manifest.bml", File::Read, File::Required)) { - information.manifest = fp->reads(); + if(auto fp = platform->open(game.pathID, "manifest.bml", File::Read, File::Required)) { + game.manifest = fp->reads(); } else return false; - auto document = BML::unserialize(information.manifest); - information.title = document["game/label"].text(); + game.document = BML::unserialize(game.manifest); + game.hash = game.document["game/sha256"].text(); + game.title = game.document["game/label"].text(); - if(information.region == "Auto") { - if(auto region = document["game/region"].text()) { - information.region = region.upcase(); + if(!loadROM(game.rom, game.pathID, game.document["game/board/memory(type=ROM,content=Program)"])) { + game.rom.reset(); + return false; + } + + if(!loadROM(game.patch, game.pathID, game.document["game/board/memory(type=ROM,content=Patch)"])) { + game.patch.reset(); + } + + if(!loadRAM(game.ram, game.pathID, game.document["game/board/memory(type=RAM,content=Save)"])) { + game.ram.reset(); + } + + if(game.region == "Auto") { + if(auto region = game.document["game/region"].text()) { + game.region = region.upcase(); } else { - information.region = "NTSC-J"; + game.region = "NTSC-J"; } } - if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=ROM,content=Program)"]}) { - rom.size = memory.size >> 1; - rom.mask = bit::round(rom.size) - 1; - rom.data = new uint16[rom.mask + 1](); - if(auto fp = platform->open(pathID(), memory.name(), File::Read, File::Required)) { - for(uint n : range(rom.size)) rom.data[n] = fp->readm(2); - } + return true; +} + +auto Cartridge::loadLockOn() -> bool { + if(auto loaded = platform->load(ID::MegaDrive, "Mega Drive", "md")) { + lockOn.pathID = loaded.pathID; + } else return false; + + if(auto fp = platform->open(lockOn.pathID, "manifest.bml", File::Read, File::Required)) { + lockOn.manifest = fp->reads(); + } else return false; + + lockOn.document = BML::unserialize(lockOn.manifest); + lockOn.hash = lockOn.document["game/sha256"].text(); + lockOn.title = lockOn.document["game/label"].text(); + + if(!loadROM(lockOn.rom, lockOn.pathID, lockOn.document["game/board/memory(type=ROM,content=Program)"])) { + lockOn.rom.reset(); + return false; } - //todo: handle mode, offset in Emulator::Game::Memory - if(auto memory = document["game/board/memory(type=RAM,content=Save)"]) { - if(auto mode = memory["mode"].text()) { - if(mode == "lo" ) ram.bits = 0x00ff; - if(mode == "hi" ) ram.bits = 0xff00; - if(mode == "word") ram.bits = 0xffff; + if(!loadRAM(lockOn.ram, lockOn.pathID, lockOn.document["game/board/memory(type=RAM,content=Save)"])) { + lockOn.ram.reset(); + } + + if(lockOn.rom.size >= 0x200) { + string name; + name.resize(48); + for(uint n : range(24)) { + name.get()[n * 2 + 0] = lockOn.rom.data[0x120 / 2 + n].byte(1); + name.get()[n * 2 + 1] = lockOn.rom.data[0x120 / 2 + n].byte(0); } - ram.size = memory["size"].natural() >> (ram.bits == 0xffff); - ram.mask = bit::round(ram.size) - 1; - ram.data = new uint16[ram.mask + 1](); - if(!(bool)memory["volatile"]) { - if(auto fp = platform->open(pathID(), "save.ram", File::Read)) { - for(uint n : range(ram.size)) { - if(ram.bits != 0xffff) ram.data[n] = fp->readm(1) * 0x0101; - if(ram.bits == 0xffff) ram.data[n] = fp->readm(2); - } + name.strip(); + while(name.find(" ")) name.replace(" ", " "); + lockOn.patch = name == "SONIC THE HEDGEHOG 2"; + } + + return true; +} + +auto Cartridge::loadROM(Memory& rom, uint pathID, Markup::Node memory) -> bool { + if(!memory) return false; + + auto name = string{memory["content"].text(), ".", memory["type"].text()}.downcase(); + rom.size = memory["size"].natural() >> 1; + rom.mask = bit::round(rom.size) - 1; + rom.data = new uint16[rom.mask + 1](); + if(auto fp = platform->open(pathID, name, File::Read, File::Required)) { + for(uint n : range(rom.size)) rom.data[n] = fp->readm(2); + } else return false; + + return true; +} + +auto Cartridge::loadRAM(Memory& ram, uint pathID, Markup::Node memory) -> bool { + if(!memory) return false; + + auto name = string{memory["content"].text(), ".", memory["type"].text()}.downcase(); + if(auto mode = memory["mode"].text()) { + if(mode == "lo" ) ram.bits = 0x00ff; + if(mode == "hi" ) ram.bits = 0xff00; + if(mode == "word") ram.bits = 0xffff; + } + ram.size = memory["size"].natural() >> (ram.bits == 0xffff); + ram.mask = bit::round(ram.size) - 1; + ram.data = new uint16[ram.mask + 1](); + if(!(bool)memory["volatile"]) { + if(auto fp = platform->open(pathID, name, File::Read)) { + for(uint n : range(ram.size)) { + if(ram.bits != 0xffff) ram.data[n] = fp->readm(1) * 0x0101; + if(ram.bits == 0xffff) ram.data[n] = fp->readm(2); } } } @@ -61,25 +167,34 @@ auto Cartridge::load() -> bool { } auto Cartridge::save() -> void { - auto document = BML::unserialize(information.manifest); + saveRAM(game.ram, game.pathID, game.document["game/board/memory(type=RAM,content=Save)"]); + saveRAM(lockOn.ram, lockOn.pathID, lockOn.document["game/board/memory(type=RAM,content=Save)"]); +} - if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RAM,content=Save)"]}) { - if(memory.nonVolatile) { - if(auto fp = platform->open(pathID(), memory.name(), File::Write)) { - for(uint n : range(ram.size)) { - if(ram.bits != 0xffff) fp->writem(ram.data[n], 1); - if(ram.bits == 0xffff) fp->writem(ram.data[n], 2); - } - } +auto Cartridge::saveRAM(Memory& ram, uint pathID, Markup::Node memory) -> bool { + if(!memory) return false; + if((bool)memory["volatile"]) return true; + + auto name = string{memory["content"].text(), ".", memory["type"].text()}.downcase(); + if(auto fp = platform->open(pathID, name, File::Write)) { + for(uint n : range(ram.size)) { + if(ram.bits != 0xffff) fp->writem(ram.data[n], 1); + if(ram.bits == 0xffff) fp->writem(ram.data[n], 2); } - } + } else return false; + + return true; } auto Cartridge::unload() -> void { - delete[] rom.data; - delete[] ram.data; - rom = {}; - ram = {}; + game.rom.reset(); + game.patch.reset(); + game.ram.reset(); + game = {}; + + lockOn.rom.reset(); + lockOn.ram.reset(); + lockOn = {}; } auto Cartridge::power() -> void { @@ -88,37 +203,81 @@ auto Cartridge::power() -> void { for(auto n : range(8)) bank[n] = n; } -auto Cartridge::read(uint24 address) -> uint16 { - if(address.bit(21) && ram.size && ramEnable) { - return ram.data[address >> 1 & ram.mask]; - } else { - address = bank[address.bits(19,21)] << 19 | address.bits(0,18); - return rom.data[address >> 1 & rom.mask]; - } -} +// -auto Cartridge::write(uint24 address, uint16 data) -> void { - //emulating RAM write protect bit breaks some commercial software - if(address.bit(21) && ram.size && ramEnable /* && ramWritable */) { - if(ram.bits == 0x00ff) data = data.byte(0) * 0x0101; - if(ram.bits == 0xff00) data = data.byte(1) * 0x0101; - ram.data[address >> 1 & ram.mask] = data; - } -} - -auto Cartridge::readIO(uint24 addr) -> uint16 { +auto Cartridge::readIO(uint24 address) -> uint16 { return 0x0000; } -auto Cartridge::writeIO(uint24 addr, uint16 data) -> void { - if(addr == 0xa130f1) ramEnable = data.bit(0), ramWritable = data.bit(1); - if(addr == 0xa130f3) bank[1] = data; - if(addr == 0xa130f5) bank[2] = data; - if(addr == 0xa130f7) bank[3] = data; - if(addr == 0xa130f9) bank[4] = data; - if(addr == 0xa130fb) bank[5] = data; - if(addr == 0xa130fd) bank[6] = data; - if(addr == 0xa130ff) bank[7] = data; +auto Cartridge::writeIO(uint24 address, uint16 data) -> void { + if(address == 0xa130f1) ramEnable = data.bit(0), ramWritable = data.bit(1); + if(address == 0xa130f3) bank[1] = data; + if(address == 0xa130f5) bank[2] = data; + if(address == 0xa130f7) bank[3] = data; + if(address == 0xa130f9) bank[4] = data; + if(address == 0xa130fb) bank[5] = data; + if(address == 0xa130fd) bank[6] = data; + if(address == 0xa130ff) bank[7] = data; +} + +// + +auto Cartridge::readGame(uint24 address) -> uint16 { + if(address >= 0x200000 && game.ram.size && ramEnable) { + return game.ram.data[address >> 1 & game.ram.mask]; + } else { + address = bank[address.bits(19,21)] << 19 | address.bits(0,18); + return game.rom.data[address >> 1 & game.rom.mask]; + } +} + +auto Cartridge::writeGame(uint24 address, uint16 data) -> void { + //emulating RAM write protect bit breaks some commercial software + if(address >= 0x200000 && game.ram.size && ramEnable /* && ramWritable */) { + if(game.ram.bits == 0x00ff) data = data.byte(0) * 0x0101; + if(game.ram.bits == 0xff00) data = data.byte(1) * 0x0101; + game.ram.data[address >> 1 & game.ram.mask] = data; + } +} + +// + +auto Cartridge::readLockOn(uint24 address) -> uint16 { + if(address >= 0x200000 && lockOn.ram.size && ramEnable) { + return lockOn.ram.data[address >> 1 & lockOn.ram.mask]; + } + + if(address >= 0x300000 && lockOn.patch) { + return game.patch.data[address >> 1 & game.patch.mask]; + } + + if(address >= 0x200000 && lockOn.rom.data) { + return lockOn.rom.data[address >> 1 & lockOn.rom.mask]; + } + + if(address >= 0x200000) { + return 0x00; + } + + return game.rom.data[address >> 1 & game.rom.mask]; +} + +auto Cartridge::writeLockOn(uint24 address, uint16 data) -> void { + if(address >= 0x200000 && lockOn.ram.size && ramEnable) { + if(lockOn.ram.bits == 0x00ff) data = data.byte(0) * 0x0101; + if(lockOn.ram.bits == 0xff00) data = data.byte(1) * 0x0101; + lockOn.ram.data[address >> 1 & lockOn.ram.mask] = data; + } +} + +// + +auto Cartridge::Memory::reset() -> void { + delete[] data; + data = nullptr; + size = 0; + mask = 0; + bits = 0; } } diff --git a/higan/md/cartridge/cartridge.hpp b/higan/md/cartridge/cartridge.hpp index 22d2bea4..c707880b 100644 --- a/higan/md/cartridge/cartridge.hpp +++ b/higan/md/cartridge/cartridge.hpp @@ -1,41 +1,69 @@ struct Cartridge { - auto pathID() const -> uint { return information.pathID; } - auto region() const -> string { return information.region; } - auto sha256() const -> string { return information.sha256; } - auto manifest() const -> string { return information.manifest; } - auto title() const -> string { return information.title; } + auto region() const -> string; + auto hashes() const -> vector; + auto manifests() const -> vector; + auto titles() const -> vector; + struct Memory; auto load() -> bool; + auto loadGame() -> bool; + auto loadLockOn() -> bool; + auto loadROM(Memory& rom, uint pathID, Markup::Node memory) -> bool; + auto loadRAM(Memory& ram, uint pathID, Markup::Node memory) -> bool; auto save() -> void; + auto saveRAM(Memory& ram, uint pathID, Markup::Node memory) -> bool; auto unload() -> void; auto power() -> void; - auto read(uint24 addr) -> uint16; - auto write(uint24 addr, uint16 data) -> void; + function read; + function write; - auto readIO(uint24 addr) -> uint16; - auto writeIO(uint24 addr, uint16 data) -> void; + auto readIO(uint24 address) -> uint16; + auto writeIO(uint24 address, uint16 data) -> void; + + auto readGame(uint24 address) -> uint16; + auto writeGame(uint24 address, uint16 data) -> void; + + auto readLockOn(uint24 address) -> uint16; + auto writeLockOn(uint24 address, uint16 data) -> void; //serialization.cpp auto serialize(serializer&) -> void; - struct Information { - uint pathID = 0; - string region; - string sha256; - string manifest; - string title; - } information; - struct Memory { + auto reset() -> void; + uint16* data = nullptr; uint size = 0; uint mask = 0; uint bits = 0; }; - Memory rom; - Memory ram; + struct Game { + uint pathID = 0; + string region; + string hash; + string manifest; + string title; + + Markup::Node document; + Memory rom; + Memory patch; + Memory ram; + } game; + + struct LockOn { + uint pathID = 0; + string hash; + string manifest; + string title; + + Markup::Node document; + Memory rom; + Memory ram; + + bool patch = false; + } lockOn; uint1 ramEnable; uint1 ramWritable; diff --git a/higan/md/cartridge/serialization.cpp b/higan/md/cartridge/serialization.cpp index 602e2ad2..f983669f 100644 --- a/higan/md/cartridge/serialization.cpp +++ b/higan/md/cartridge/serialization.cpp @@ -1,3 +1,4 @@ auto Cartridge::serialize(serializer& s) -> void { - if(ram.size) s.array(ram.data, ram.size); + if(game.ram.size) s.array(game.ram.data, game.ram.size); + if(lockOn.ram.size) s.array(lockOn.ram.data, lockOn.ram.size); } diff --git a/higan/md/interface/interface.cpp b/higan/md/interface/interface.cpp index 790cfc3d..c27b24a3 100644 --- a/higan/md/interface/interface.cpp +++ b/higan/md/interface/interface.cpp @@ -2,36 +2,30 @@ namespace MegaDrive { -#define returns(T) T { return ([&] { struct With : T { With() { -#define $ }}; return With(); })(); } - Settings settings; -auto Interface::information() -> returns(Information) { - manufacturer = "Sega"; - name = "Mega Drive"; - resettable = true; -}$ - -auto Interface::manifest() -> string { - return cartridge.manifest(); +auto Interface::information() -> Information { + Information information; + information.manufacturer = "Sega"; + information.name = "Mega Drive"; + information.extension = "md"; + information.resettable = true; + return information; } -auto Interface::title() -> string { - return cartridge.title(); +auto Interface::displays() -> vector { + Display display; + display.type = Display::Type::CRT; + display.colors = 3 * (1 << 9); + display.width = 320; + display.height = 240; + display.internalWidth = 1280; + display.internalHeight = 480; + display.aspectCorrection = 1.0; + display.refreshRate = (system.frequency() / 2.0) / (vdp.frameHeight() * 1710.0); + return {display}; } -auto Interface::display() -> returns(Display) { - type = Display::Type::CRT; - colors = 3 * (1 << 9); - width = 320; - height = 240; - internalWidth = 1280; - internalHeight = 480; - aspectCorrection = 1.0; - refreshRate = (system.frequency() / 2.0) / (vdp.frameHeight() * 1710.0); -}$ - auto Interface::color(uint32 color) -> uint64 { uint R = color.bits(0, 2); uint G = color.bits(3, 5); @@ -55,6 +49,18 @@ auto Interface::loaded() -> bool { return system.loaded(); } +auto Interface::hashes() -> vector { + return cartridge.hashes(); +} + +auto Interface::manifests() -> vector { + return cartridge.manifests(); +} + +auto Interface::titles() -> vector { + return cartridge.titles(); +} + auto Interface::load() -> bool { return system.load(this); } @@ -163,7 +169,7 @@ auto Interface::unserialize(serializer& s) -> bool { return system.unserialize(s); } -auto Interface::cheatSet(const string_vector& list) -> void { +auto Interface::cheats(const vector& list) -> void { cheat.assign(list); } @@ -179,7 +185,4 @@ auto Interface::set(const string& name, const any& value) -> bool { return false; } -#undef returns -#undef $ - } diff --git a/higan/md/interface/interface.hpp b/higan/md/interface/interface.hpp index 89ad0696..85f8be88 100644 --- a/higan/md/interface/interface.hpp +++ b/higan/md/interface/interface.hpp @@ -1,3 +1,5 @@ +#if defined(CORE_MD) + namespace MegaDrive { struct ID { @@ -20,17 +22,15 @@ struct ID { }; struct Interface : Emulator::Interface { - using Emulator::Interface::load; - auto information() -> Information override; - auto manifest() -> string override; - auto title() -> string override; - - auto display() -> Display override; + auto displays() -> vector override; auto color(uint32 color) -> uint64 override; auto loaded() -> bool override; + auto hashes() -> vector override; + auto manifests() -> vector override; + auto titles() -> vector override; auto load() -> bool override; auto save() -> void override; auto unload() -> void override; @@ -48,7 +48,7 @@ struct Interface : Emulator::Interface { auto serialize() -> serializer override; auto unserialize(serializer&) -> bool override; - auto cheatSet(const string_vector& list) -> void override; + auto cheats(const vector& list) -> void override; auto cap(const string& name) -> bool override; auto get(const string& name) -> any override; @@ -64,3 +64,5 @@ struct Settings { extern Settings settings; } + +#endif diff --git a/higan/md/system/serialization.cpp b/higan/md/system/serialization.cpp index ccad3ccf..430f579a 100644 --- a/higan/md/system/serialization.cpp +++ b/higan/md/system/serialization.cpp @@ -3,12 +3,10 @@ auto System::serializeInit() -> void { uint signature = 0; char version[16] = {0}; - char hash[64] = {0}; char description[512] = {0}; s.integer(signature); s.array(version); - s.array(hash); s.array(description); serializeAll(s); @@ -20,14 +18,11 @@ auto System::serialize() -> serializer { uint signature = 0x31545342; char version[16] = {0}; - char hash[64] = {0}; char description[512] = {0}; memory::copy(&version, (const char*)Emulator::SerializerVersion, Emulator::SerializerVersion.size()); - memory::copy(&hash, (const char*)cartridge.sha256(), 64); s.integer(signature); s.array(version); - s.array(hash); s.array(description); serializeAll(s); @@ -37,12 +32,10 @@ auto System::serialize() -> serializer { auto System::unserialize(serializer& s) -> bool { uint signature = 0; char version[16] = {0}; - char hash[64] = {0}; char description[512] = {0}; s.integer(signature); s.array(version); - s.array(hash); s.array(description); if(signature != 0x31545342) return false; diff --git a/higan/ms/cartridge/cartridge.cpp b/higan/ms/cartridge/cartridge.cpp index c435ecd6..81611903 100644 --- a/higan/ms/cartridge/cartridge.cpp +++ b/higan/ms/cartridge/cartridge.cpp @@ -11,14 +11,14 @@ auto Cartridge::load() -> bool { if(Model::MasterSystem()) { if(auto loaded = platform->load(ID::MasterSystem, "Master System", "ms", {"NTSC", "PAL"})) { - information.pathID = loaded.pathID(); - information.region = loaded.option(); + information.pathID = loaded.pathID; + information.region = loaded.option; } else return false; } if(Model::GameGear()) { if(auto loaded = platform->load(ID::GameGear, "Game Gear", "gg", {"NTSC"})) { - information.pathID = loaded.pathID(); + information.pathID = loaded.pathID; } else return false; } diff --git a/higan/ms/cartridge/cartridge.hpp b/higan/ms/cartridge/cartridge.hpp index 855e89db..fef917aa 100644 --- a/higan/ms/cartridge/cartridge.hpp +++ b/higan/ms/cartridge/cartridge.hpp @@ -1,7 +1,7 @@ struct Cartridge { auto pathID() const -> uint { return information.pathID; } auto region() const -> string { return information.region; } - auto sha256() const -> string { return information.sha256; } + auto hash() const -> string { return information.sha256; } auto manifest() const -> string { return information.manifest; } auto title() const -> string { return information.title; } diff --git a/higan/ms/interface/game-gear.cpp b/higan/ms/interface/game-gear.cpp index 4865a401..b8c4c9aa 100644 --- a/higan/ms/interface/game-gear.cpp +++ b/higan/ms/interface/game-gear.cpp @@ -1,42 +1,25 @@ -GameGearInterface::GameGearInterface() { +auto GameGearInterface::information() -> Information { + Information information; information.manufacturer = "Sega"; information.name = "Game Gear"; - information.overscan = false; - - media.append({ID::GameGear, "Game Gear", "gg"}); - - Port hardware{ID::Port::Hardware, "Hardware"}; - - { Device device{ID::Device::GameGearControls, "Controls"}; - device.inputs.append({0, "Up"}); - device.inputs.append({0, "Down"}); - device.inputs.append({0, "Left"}); - device.inputs.append({0, "Right"}); - device.inputs.append({0, "1"}); - device.inputs.append({0, "2"}); - device.inputs.append({0, "Start"}); - hardware.devices.append(device); - } - - ports.append(move(hardware)); + information.extension = "gg"; + return information; } -auto GameGearInterface::videoInformation() -> VideoInformation { - VideoInformation vi; - vi.width = 160; - vi.height = 144; - vi.internalWidth = 160; - vi.internalHeight = 144; - vi.aspectCorrection = 1.0; - vi.refreshRate = (system.colorburst() * 15.0 / 5.0) / (262.0 * 684.0); - return vi; +auto GameGearInterface::displays() -> vector { + Display display; + display.type = Display::Type::LCD; + display.colors = 1 << 12; + display.width = 160; + display.height = 144; + display.internalWidth = 160; + display.internalHeight = 144; + display.aspectCorrection = 1.0; + display.refreshRate = (system.colorburst() * 15.0 / 5.0) / (262.0 * 684.0); + return {display}; } -auto GameGearInterface::videoColors() -> uint32 { - return 1 << 12; -} - -auto GameGearInterface::videoColor(uint32 color) -> uint64 { +auto GameGearInterface::color(uint32 color) -> uint64 { uint4 B = color >> 8; uint4 G = color >> 4; uint4 R = color >> 0; @@ -48,7 +31,34 @@ auto GameGearInterface::videoColor(uint32 color) -> uint64 { return r << 32 | g << 16 | b << 0; } -auto GameGearInterface::load(uint id) -> bool { - if(id == ID::GameGear) return system.load(this, System::Model::GameGear); - return false; +auto GameGearInterface::ports() -> vector { return { + {ID::Port::Hardware, "Hardware"}}; +} + +auto GameGearInterface::devices(uint port) -> vector { + if(port == ID::Port::Hardware) return { + {ID::Device::GameGearControls, "Controls"} + }; + + return {}; +} + +auto GameGearInterface::inputs(uint device) -> vector { + using Type = Input::Type; + + if(device == ID::Device::GameGearControls) return { + {Type::Hat, "Up" }, + {Type::Hat, "Down" }, + {Type::Hat, "Left" }, + {Type::Hat, "Right"}, + {Type::Button, "1" }, + {Type::Button, "2" }, + {Type::Control, "Start"} + }; + + return {}; +} + +auto GameGearInterface::load() -> bool { + return system.load(this, System::Model::GameGear); } diff --git a/higan/ms/interface/interface.cpp b/higan/ms/interface/interface.cpp index 28adc687..e7d55251 100644 --- a/higan/ms/interface/interface.cpp +++ b/higan/ms/interface/interface.cpp @@ -6,21 +6,22 @@ Settings settings; #include "master-system.cpp" #include "game-gear.cpp" -Interface::Interface() { -} - -auto Interface::manifest() -> string { - return cartridge.manifest(); -} - -auto Interface::title() -> string { - return cartridge.title(); -} - auto Interface::loaded() -> bool { return system.loaded(); } +auto Interface::hashes() -> vector { + return {cartridge.hash()}; +} + +auto Interface::manifests() -> vector { + return {cartridge.manifest()}; +} + +auto Interface::titles() -> vector { + return {cartridge.title()}; +} + auto Interface::save() -> void { system.save(); } @@ -47,7 +48,7 @@ auto Interface::unserialize(serializer& s) -> bool { return system.unserialize(s); } -auto Interface::cheatSet(const string_vector& list) -> void { +auto Interface::cheats(const vector& list) -> void { cheat.assign(list); } diff --git a/higan/ms/interface/interface.hpp b/higan/ms/interface/interface.hpp index 6e20cc66..c2d2e537 100644 --- a/higan/ms/interface/interface.hpp +++ b/higan/ms/interface/interface.hpp @@ -1,3 +1,5 @@ +#if defined(CORE_MS) + namespace MasterSystem { struct ID { @@ -22,12 +24,10 @@ struct ID { }; struct Interface : Emulator::Interface { - Interface(); - - auto manifest() -> string override; - auto title() -> string override; - auto loaded() -> bool override; + auto hashes() -> vector override; + auto manifests() -> vector override; + auto titles() -> vector override; auto save() -> void override; auto unload() -> void override; @@ -37,7 +37,7 @@ struct Interface : Emulator::Interface { auto serialize() -> serializer override; auto unserialize(serializer&) -> bool override; - auto cheatSet(const string_vector&) -> void override; + auto cheats(const vector& list) -> void override; auto cap(const string& name) -> bool override; auto get(const string& name) -> any override; @@ -45,36 +45,41 @@ struct Interface : Emulator::Interface { }; struct MasterSystemInterface : Interface { - using Emulator::Interface::load; + auto information() -> Information override; - MasterSystemInterface(); + auto displays() -> vector override; + auto color(uint32 color) -> uint64 override; - auto videoInformation() -> VideoInformation override; - auto videoColors() -> uint32 override; - auto videoColor(uint32 color) -> uint64 override; + auto ports() -> vector override; + auto devices(uint port) -> vector override; + auto inputs(uint device) -> vector override; - auto load(uint id) -> bool override; + auto load() -> bool override; + auto connected(uint port) -> uint override; auto connect(uint port, uint device) -> void override; }; struct GameGearInterface : Interface { - using Emulator::Interface::load; + auto information() -> Information override; - GameGearInterface(); + auto displays() -> vector override; + auto color(uint32 color) -> uint64 override; - auto videoInformation() -> VideoInformation override; - auto videoColors() -> uint32 override; - auto videoColor(uint32 color) -> uint64 override; + auto ports() -> vector override; + auto devices(uint port) -> vector override; + auto inputs(uint device) -> vector override; - auto load(uint id) -> bool override; + auto load() -> bool override; }; struct Settings { - uint controllerPort1 = 0; - uint controllerPort2 = 0; + uint controllerPort1 = ID::Device::Gamepad; + uint controllerPort2 = ID::Device::Gamepad; }; extern Settings settings; } + +#endif diff --git a/higan/ms/interface/master-system.cpp b/higan/ms/interface/master-system.cpp index 25c6d62c..0bd23f4f 100644 --- a/higan/ms/interface/master-system.cpp +++ b/higan/ms/interface/master-system.cpp @@ -1,58 +1,26 @@ -MasterSystemInterface::MasterSystemInterface() { +auto MasterSystemInterface::information() -> Information { + Information information; information.manufacturer = "Sega"; information.name = "Master System"; - information.overscan = true; - - media.append({ID::MasterSystem, "Master System", "ms"}); - - Port controllerPort1{ID::Port::Controller1, "Controller Port 1"}; - Port controllerPort2{ID::Port::Controller2, "Controller Port 2"}; - Port hardware{ID::Port::Hardware, "Hardware"}; - - { Device device{ID::Device::None, "None"}; - controllerPort1.devices.append(device); - controllerPort2.devices.append(device); - } - - { Device device{ID::Device::Gamepad, "Gamepad"}; - device.inputs.append({0, "Up"}); - device.inputs.append({0, "Down"}); - device.inputs.append({0, "Left"}); - device.inputs.append({0, "Right"}); - device.inputs.append({0, "1"}); - device.inputs.append({0, "2"}); - controllerPort1.devices.append(device); - controllerPort2.devices.append(device); - } - - { Device device{ID::Device::MasterSystemControls, "Controls"}; - device.inputs.append({0, "Reset"}); - device.inputs.append({0, "Pause"}); - hardware.devices.append(device); - } - - ports.append(move(controllerPort1)); - ports.append(move(controllerPort2)); - ports.append(move(hardware)); + information.extension = "ms"; + return information; } -auto MasterSystemInterface::videoInformation() -> VideoInformation { - VideoInformation vi; - vi.width = 256; - vi.height = 240; - vi.internalWidth = 256; - vi.internalHeight = 240; - vi.aspectCorrection = 8.0 / 7.0; - if(Region::NTSC()) vi.refreshRate = (system.colorburst() * 15.0 / 5.0) / (262.0 * 684.0); - if(Region::PAL()) vi.refreshRate = (system.colorburst() * 15.0 / 5.0) / (312.0 * 684.0); - return vi; +auto MasterSystemInterface::displays() -> vector { + Display display; + display.type = Display::Type::CRT; + display.colors = 1 << 6; + display.width = 256; + display.height = 240; + display.internalWidth = 256; + display.internalHeight = 240; + display.aspectCorrection = 8.0 / 7.0; + if(Region::NTSC()) display.refreshRate = (system.colorburst() * 15.0 / 5.0) / (262.0 * 684.0); + if(Region::PAL()) display.refreshRate = (system.colorburst() * 15.0 / 5.0) / (312.0 * 684.0); + return {display}; } -auto MasterSystemInterface::videoColors() -> uint32 { - return 1 << 6; -} - -auto MasterSystemInterface::videoColor(uint32 color) -> uint64 { +auto MasterSystemInterface::color(uint32 color) -> uint64 { uint2 B = color >> 4; uint2 G = color >> 2; uint2 R = color >> 0; @@ -64,9 +32,62 @@ auto MasterSystemInterface::videoColor(uint32 color) -> uint64 { return r << 32 | g << 16 | b << 0; } -auto MasterSystemInterface::load(uint id) -> bool { - if(id == ID::MasterSystem) return system.load(this, System::Model::MasterSystem); - return false; +auto MasterSystemInterface::ports() -> vector { return { + {ID::Port::Controller1, "Controller Port 1"}, + {ID::Port::Controller2, "Controller Port 2"}, + {ID::Port::Hardware, "Hardware" }}; +} + +auto MasterSystemInterface::devices(uint port) -> vector { + if(port == ID::Port::Controller1) return { + {ID::Device::None, "None" }, + {ID::Device::Gamepad, "Gamepad"} + }; + + if(port == ID::Port::Controller2) return { + {ID::Device::None, "None" }, + {ID::Device::Gamepad, "Gamepad"} + }; + + if(port == ID::Port::Hardware) return { + {ID::Device::MasterSystemControls, "Controls"} + }; + + return {}; +} + +auto MasterSystemInterface::inputs(uint device) -> vector { + using Type = Input::Type; + + if(device == ID::Device::None) return { + }; + + if(device == ID::Device::Gamepad) return { + {Type::Hat, "Up" }, + {Type::Hat, "Down" }, + {Type::Hat, "Left" }, + {Type::Hat, "Right"}, + {Type::Button, "1" }, + {Type::Button, "2" } + }; + + if(device == ID::Device::MasterSystemControls) return { + {Type::Control, "Reset"}, + {Type::Control, "Power"} + }; + + return {}; +} + +auto MasterSystemInterface::load() -> bool { + return system.load(this, System::Model::MasterSystem); +} + +auto MasterSystemInterface::connected(uint port) -> uint { + if(port == ID::Port::Controller1) return settings.controllerPort1; + if(port == ID::Port::Controller2) return settings.controllerPort2; + if(port == ID::Port::Hardware) return ID::Device::MasterSystemControls; + return 0; } auto MasterSystemInterface::connect(uint port, uint device) -> void { diff --git a/higan/ms/system/serialization.cpp b/higan/ms/system/serialization.cpp index 7966fc91..3b2d9350 100644 --- a/higan/ms/system/serialization.cpp +++ b/higan/ms/system/serialization.cpp @@ -3,12 +3,10 @@ auto System::serializeInit() -> void { uint signature = 0; char version[16] = {0}; - char hash[64] = {0}; char description[512] = {0}; s.integer(signature); s.array(version); - s.array(hash); s.array(description); serializeAll(s); @@ -20,14 +18,11 @@ auto System::serialize() -> serializer { uint signature = 0x31545342; char version[16] = {0}; - char hash[64] = {0}; char description[512] = {0}; memory::copy(&version, (const char*)Emulator::SerializerVersion, Emulator::SerializerVersion.size()); - memory::copy(&hash, (const char*)cartridge.sha256(), 64); s.integer(signature); s.array(version); - s.array(hash); s.array(description); serializeAll(s); @@ -37,12 +32,10 @@ auto System::serialize() -> serializer { auto System::unserialize(serializer& s) -> bool { uint signature = 0; char version[16] = {0}; - char hash[64] = {0}; char description[512] = {0}; s.integer(signature); s.array(version); - s.array(hash); s.array(description); if(signature != 0x31545342) return false; diff --git a/higan/pce/cartridge/cartridge.cpp b/higan/pce/cartridge/cartridge.cpp index 6dfa3d44..9f3704db 100644 --- a/higan/pce/cartridge/cartridge.cpp +++ b/higan/pce/cartridge/cartridge.cpp @@ -9,13 +9,13 @@ auto Cartridge::load() -> bool { if(Model::PCEngine()) { if(auto loaded = platform->load(ID::PCEngine, "PC Engine", "pce")) { - information.pathID = loaded.pathID(); + information.pathID = loaded.pathID; } else return false; } if(Model::SuperGrafx()) { if(auto loaded = platform->load(ID::SuperGrafx, "SuperGrafx", "sg")) { - information.pathID = loaded.pathID(); + information.pathID = loaded.pathID; } else return false; } diff --git a/higan/pce/cartridge/cartridge.hpp b/higan/pce/cartridge/cartridge.hpp index 085067e9..613bb0ed 100644 --- a/higan/pce/cartridge/cartridge.hpp +++ b/higan/pce/cartridge/cartridge.hpp @@ -1,6 +1,6 @@ struct Cartridge { auto pathID() const -> uint { return information.pathID; } - auto sha256() const -> string { return information.sha256; } + auto hash() const -> string { return information.sha256; } auto manifest() const -> string { return information.manifest; } auto title() const -> string { return information.title; } diff --git a/higan/pce/interface/interface.cpp b/higan/pce/interface/interface.cpp index 1b72600b..383b8e0d 100644 --- a/higan/pce/interface/interface.cpp +++ b/higan/pce/interface/interface.cpp @@ -7,54 +7,20 @@ Settings settings; #include "pc-engine.cpp" #include "supergrafx.cpp" -Interface::Interface() { - information.overscan = true; - - Port controllerPort{ID::Port::Controller, "Controller Port"}; - - { Device device{ID::Device::None, "None"}; - controllerPort.devices.append(device); - } - - { Device device{ID::Device::Gamepad, "Gamepad"}; - device.inputs.append({0, "Up"}); - device.inputs.append({0, "Down"}); - device.inputs.append({0, "Left"}); - device.inputs.append({0, "Right"}); - device.inputs.append({0, "II"}); - device.inputs.append({0, "I"}); - device.inputs.append({0, "Select"}); - device.inputs.append({0, "Run"}); - controllerPort.devices.append(device); - } - - ports.append(move(controllerPort)); +auto Interface::displays() -> vector { + Display display; + display.type = Display::Type::CRT; + display.colors = 1 << 9; + display.width = 280; + display.height = 240; + display.internalWidth = 1120; + display.internalHeight = 240; + display.aspectCorrection = 8.0 / 7.0; + display.refreshRate = (system.colorburst() * 6.0) / (262.0 * 1365.0); + return {display}; } -auto Interface::manifest() -> string { - return cartridge.manifest(); -} - -auto Interface::title() -> string { - return cartridge.title(); -} - -auto Interface::videoInformation() -> VideoInformation { - VideoInformation vi; - vi.width = 280; - vi.height = 240; - vi.internalWidth = 1120; - vi.internalHeight = 240; - vi.aspectCorrection = 8.0 / 7.0; - vi.refreshRate = (system.colorburst() * 6.0) / (262.0 * 1365.0); - return vi; -} - -auto Interface::videoColors() -> uint32 { - return 1 << 9; -} - -auto Interface::videoColor(uint32 color) -> uint64 { +auto Interface::color(uint32 color) -> uint64 { uint3 B = color.bits(0,2); uint3 R = color.bits(3,5); uint3 G = color.bits(6,8); @@ -70,8 +36,16 @@ auto Interface::loaded() -> bool { return system.loaded(); } -auto Interface::sha256() -> string { - return cartridge.sha256(); +auto Interface::hashes() -> vector { + return {cartridge.hash()}; +} + +auto Interface::manifests() -> vector { + return {cartridge.manifest()}; +} + +auto Interface::titles() -> vector { + return {cartridge.title()}; } auto Interface::save() -> void { @@ -83,6 +57,35 @@ auto Interface::unload() -> void { system.unload(); } +auto Interface::ports() -> vector { return { + {ID::Port::Controller, "Controller"}}; +} + +auto Interface::devices(uint port) -> vector { + if(port == ID::Port::Controller) return { + {ID::Device::Gamepad, "Gamepad"} + }; + + return {}; +} + +auto Interface::inputs(uint device) -> vector { + using Type = Input::Type; + + if(device == ID::Device::Gamepad) return { + {Type::Hat, "Up" }, + {Type::Hat, "Down" }, + {Type::Hat, "Left" }, + {Type::Hat, "Right" }, + {Type::Button, "II" }, + {Type::Button, "I" }, + {Type::Control, "Select"}, + {Type::Control, "Run" } + }; + + return {}; +} + auto Interface::connected(uint port) -> uint { if(port == ID::Port::Controller) return settings.controllerPort; return 0; @@ -109,7 +112,7 @@ auto Interface::unserialize(serializer& s) -> bool { return system.unserialize(s); } -auto Interface::cheatSet(const string_vector& list) -> void { +auto Interface::cheats(const vector& list) -> void { cheat.assign(list); } diff --git a/higan/pce/interface/interface.hpp b/higan/pce/interface/interface.hpp index 27e7f999..ff01287f 100644 --- a/higan/pce/interface/interface.hpp +++ b/higan/pce/interface/interface.hpp @@ -1,3 +1,5 @@ +#if defined(CORE_PCE) + namespace PCEngine { struct ID { @@ -18,20 +20,20 @@ struct ID { }; struct Interface : Emulator::Interface { - Interface(); - - auto manifest() -> string override; - auto title() -> string override; - - auto videoInformation() -> VideoInformation override; - auto videoColors() -> uint32 override; - auto videoColor(uint32 color) -> uint64 override; + auto displays() -> vector override; + auto color(uint32 color) -> uint64 override; auto loaded() -> bool override; - auto sha256() -> string override; + auto hashes() -> vector override; + auto manifests() -> vector override; + auto titles() -> vector override; auto save() -> void override; auto unload() -> void override; + auto ports() -> vector override; + auto devices(uint port) -> vector override; + auto inputs(uint device) -> vector override; + auto connected(uint port) -> uint override; auto connect(uint port, uint device) -> void override; auto power() -> void override; @@ -40,7 +42,7 @@ struct Interface : Emulator::Interface { auto serialize() -> serializer override; auto unserialize(serializer&) -> bool override; - auto cheatSet(const string_vector&) -> void override; + auto cheats(const vector& list) -> void override; auto cap(const string& name) -> bool override; auto get(const string& name) -> any override; @@ -48,15 +50,15 @@ struct Interface : Emulator::Interface { }; struct PCEngineInterface : Interface { - PCEngineInterface(); + auto information() -> Information override; - auto load(uint id) -> bool override; + auto load() -> bool override; }; struct SuperGrafxInterface : Interface { - SuperGrafxInterface(); + auto information() -> Information override; - auto load(uint id) -> bool override; + auto load() -> bool override; }; struct Settings { @@ -66,3 +68,5 @@ struct Settings { extern Settings settings; } + +#endif diff --git a/higan/pce/interface/pc-engine.cpp b/higan/pce/interface/pc-engine.cpp index afa3d923..8cad36fa 100644 --- a/higan/pce/interface/pc-engine.cpp +++ b/higan/pce/interface/pc-engine.cpp @@ -1,11 +1,11 @@ -PCEngineInterface::PCEngineInterface() { +auto PCEngineInterface::information() -> Information { + Information information; information.manufacturer = "NEC"; information.name = "PC Engine"; - - media.append({ID::PCEngine, "PC Engine", "pce"}); + information.extension = "pce"; + return information; } -auto PCEngineInterface::load(uint id) -> bool { - if(id == ID::PCEngine) return system.load(this, System::Model::PCEngine); - return false; +auto PCEngineInterface::load() -> bool { + return system.load(this, System::Model::PCEngine); } diff --git a/higan/pce/interface/supergrafx.cpp b/higan/pce/interface/supergrafx.cpp index c8024d50..884933eb 100644 --- a/higan/pce/interface/supergrafx.cpp +++ b/higan/pce/interface/supergrafx.cpp @@ -1,11 +1,11 @@ -SuperGrafxInterface::SuperGrafxInterface() { +auto SuperGrafxInterface::information() -> Information { + Information information; information.manufacturer = "NEC"; information.name = "SuperGrafx"; - - media.append({ID::SuperGrafx, "SuperGrafx", "sg"}); + information.extension = "sg"; + return information; } -auto SuperGrafxInterface::load(uint id) -> bool { - if(id == ID::SuperGrafx) return system.load(this, System::Model::SuperGrafx); - return false; +auto SuperGrafxInterface::load() -> bool { + return system.load(this, System::Model::SuperGrafx); } diff --git a/higan/pce/system/serialization.cpp b/higan/pce/system/serialization.cpp index 2eb1e9ad..3aba85f1 100644 --- a/higan/pce/system/serialization.cpp +++ b/higan/pce/system/serialization.cpp @@ -3,12 +3,10 @@ auto System::serializeInit() -> void { uint signature = 0; char version[16] = {0}; - char hash[64] = {0}; char description[512] = {0}; s.integer(signature); s.array(version); - s.array(hash); s.array(description); serializeAll(s); @@ -20,14 +18,11 @@ auto System::serialize() -> serializer { uint signature = 0x31545342; char version[16] = {0}; - char hash[64] = {0}; char description[512] = {0}; memory::copy(&version, (const char*)Emulator::SerializerVersion, Emulator::SerializerVersion.size()); - memory::copy(&hash, (const char*)cartridge.sha256(), 64); s.integer(signature); s.array(version); - s.array(hash); s.array(description); serializeAll(s); @@ -37,12 +32,10 @@ auto System::serialize() -> serializer { auto System::unserialize(serializer& s) -> bool { uint signature = 0; char version[16] = {0}; - char hash[64] = {0}; char description[512] = {0}; s.integer(signature); s.array(version); - s.array(hash); s.array(description); if(signature != 0x31545342) return false; diff --git a/higan/pce/vdc/io.cpp b/higan/pce/vdc/io.cpp index 90152cc6..3d03198f 100644 --- a/higan/pce/vdc/io.cpp +++ b/higan/pce/vdc/io.cpp @@ -25,6 +25,8 @@ auto VDC::read(uint2 addr) -> uint8 { return data; } } + + return 0x00; } auto VDC::write(uint2 addr, uint8 data) -> void { diff --git a/higan/processor/huc6280/disassembler.cpp b/higan/processor/huc6280/disassembler.cpp index d5d468b0..b858007c 100644 --- a/higan/processor/huc6280/disassembler.cpp +++ b/higan/processor/huc6280/disassembler.cpp @@ -62,7 +62,7 @@ auto HuC6280::disassemble(uint16 pc) -> string { uint8 opcode = readByte(); - #define op(id, name, ...) case id: o = {name, " ", string_vector{__VA_ARGS__}.merge(",")}; break; + #define op(id, name, ...) case id: o = {name, " ", vector{__VA_ARGS__}.merge(",")}; break; string o; if(T == 1) switch(opcode) { diff --git a/higan/processor/z80/disassembler.cpp b/higan/processor/z80/disassembler.cpp index 29fac128..dcbe4d63 100644 --- a/higan/processor/z80/disassembler.cpp +++ b/higan/processor/z80/disassembler.cpp @@ -48,7 +48,7 @@ auto Z80::disassemble(uint16 pc) -> string { return s; } -#define op(id, name, ...) case id: return {name, " ", string_vector{__VA_ARGS__}.merge(",")}; +#define op(id, name, ...) case id: return {name, " ", vector{__VA_ARGS__}.merge(",")}; #define N string{"$", hex(byte(), 2L)} #define IN string{"(", N, ")"} diff --git a/higan/sfc/cartridge/cartridge.cpp b/higan/sfc/cartridge/cartridge.cpp index 17fbc337..f65215db 100644 --- a/higan/sfc/cartridge/cartridge.cpp +++ b/higan/sfc/cartridge/cartridge.cpp @@ -7,23 +7,34 @@ namespace SuperFamicom { #include "serialization.cpp" Cartridge cartridge; -auto Cartridge::manifest() const -> string { - string manifest = BML::serialize(game.document); - manifest.append("\n", BML::serialize(board)); - if(slotGameBoy.document) manifest.append("\n", BML::serialize(slotGameBoy.document)); - if(slotBSMemory.document) manifest.append("\n", BML::serialize(slotBSMemory.document)); - if(slotSufamiTurboA.document) manifest.append("\n", BML::serialize(slotSufamiTurboA.document)); - if(slotSufamiTurboB.document) manifest.append("\n", BML::serialize(slotSufamiTurboB.document)); - return manifest; +auto Cartridge::hashes() const -> vector { + vector hashes; + hashes.append(game.sha256); + if(slotGameBoy.sha256) hashes.append(slotGameBoy.sha256); + if(slotBSMemory.sha256) hashes.append(slotBSMemory.sha256); + if(slotSufamiTurboA.sha256) hashes.append(slotSufamiTurboA.sha256); + if(slotSufamiTurboB.sha256) hashes.append(slotSufamiTurboB.sha256); + return hashes; } -auto Cartridge::title() const -> string { - auto label = game.label; - if(slotGameBoy.label) label.append(" + ", slotGameBoy.label); - if(slotBSMemory.label) label.append(" + ", slotBSMemory.label); - if(slotSufamiTurboA.label) label.append(" + ", slotSufamiTurboA.label); - if(slotSufamiTurboB.label) label.append(" + ", slotSufamiTurboB.label); - return label; +auto Cartridge::manifests() const -> vector { + vector manifests; + manifests.append(string{BML::serialize(game.document), "\n", BML::serialize(board)}); + if(slotGameBoy.document) manifests.append(BML::serialize(slotGameBoy.document)); + if(slotBSMemory.document) manifests.append(BML::serialize(slotBSMemory.document)); + if(slotSufamiTurboA.document) manifests.append(BML::serialize(slotSufamiTurboA.document)); + if(slotSufamiTurboB.document) manifests.append(BML::serialize(slotSufamiTurboB.document)); + return manifests; +} + +auto Cartridge::titles() const -> vector { + vector titles; + titles.append(game.label); + if(slotGameBoy.label) titles.append(slotGameBoy.label); + if(slotBSMemory.label) titles.append(slotBSMemory.label); + if(slotSufamiTurboA.label) titles.append(slotSufamiTurboA.label); + if(slotSufamiTurboB.label) titles.append(slotSufamiTurboB.label); + return titles; } auto Cartridge::load() -> bool { @@ -36,8 +47,8 @@ auto Cartridge::load() -> bool { slotSufamiTurboB = {}; if(auto loaded = platform->load(ID::SuperFamicom, "Super Famicom", "sfc", {"Auto", "NTSC", "PAL"})) { - information.pathID = loaded.pathID(); - information.region = loaded.option(); + information.pathID = loaded.pathID; + information.region = loaded.option; } else return false; if(auto fp = platform->open(ID::SuperFamicom, "manifest.bml", File::Read, File::Required)) { @@ -93,9 +104,9 @@ auto Cartridge::load() -> bool { } auto Cartridge::loadGameBoy() -> bool { - #if defined(SFC_SUPERGAMEBOY) + #if defined(CORE_GB) //invoked from ICD::load() - information.sha256 = GameBoy::cartridge.sha256(); + information.sha256 = GameBoy::cartridge.hash(); slotGameBoy.load(GameBoy::cartridge.manifest()); loadCartridgeGameBoy(slotGameBoy.document); return true; diff --git a/higan/sfc/cartridge/cartridge.hpp b/higan/sfc/cartridge/cartridge.hpp index e440d708..93c83f0e 100644 --- a/higan/sfc/cartridge/cartridge.hpp +++ b/higan/sfc/cartridge/cartridge.hpp @@ -1,9 +1,10 @@ struct Cartridge { auto pathID() const -> uint { return information.pathID; } auto region() const -> string { return information.region; } - auto sha256() const -> string { return information.sha256; } - auto manifest() const -> string; - auto title() const -> string; + + auto hashes() const -> vector; + auto manifests() const -> vector; + auto titles() const -> vector; auto load() -> bool; auto save() -> void; diff --git a/higan/sfc/cartridge/load.cpp b/higan/sfc/cartridge/load.cpp index 2f6d5e8f..f94074ff 100644 --- a/higan/sfc/cartridge/load.cpp +++ b/higan/sfc/cartridge/load.cpp @@ -211,7 +211,7 @@ auto Cartridge::loadBSMemory(Markup::Node node) -> void { has.BSMemorySlot = true; if(auto loaded = platform->load(ID::BSMemory, "BS Memory", "bs")) { - bsmemory.pathID = loaded.pathID(); + bsmemory.pathID = loaded.pathID; loadBSMemory(); for(auto map : node.find("map")) { @@ -225,7 +225,7 @@ auto Cartridge::loadSufamiTurboA(Markup::Node node) -> void { has.SufamiTurboSlotA = true; if(auto loaded = platform->load(ID::SufamiTurboA, "Sufami Turbo", "st")) { - sufamiturboA.pathID = loaded.pathID(); + sufamiturboA.pathID = loaded.pathID; loadSufamiTurboA(); for(auto map : node.find("rom/map")) { @@ -243,7 +243,7 @@ auto Cartridge::loadSufamiTurboB(Markup::Node node) -> void { has.SufamiTurboSlotB = true; if(auto loaded = platform->load(ID::SufamiTurboB, "Sufami Turbo", "st")) { - sufamiturboB.pathID = loaded.pathID(); + sufamiturboB.pathID = loaded.pathID; loadSufamiTurboB(); for(auto map : node.find("rom/map")) { diff --git a/higan/sfc/controller/justifier/justifier.cpp b/higan/sfc/controller/justifier/justifier.cpp index 82ce55ed..29365cef 100644 --- a/higan/sfc/controller/justifier/justifier.cpp +++ b/higan/sfc/controller/justifier/justifier.cpp @@ -130,6 +130,8 @@ auto Justifier::data() -> uint2 { case 30: return 0; case 31: return 0; } + + unreachable; } auto Justifier::latch(bool data) -> void { diff --git a/higan/sfc/controller/super-scope/super-scope.cpp b/higan/sfc/controller/super-scope/super-scope.cpp index a46578c2..6e852afa 100644 --- a/higan/sfc/controller/super-scope/super-scope.cpp +++ b/higan/sfc/controller/super-scope/super-scope.cpp @@ -118,6 +118,8 @@ auto SuperScope::data() -> uint2 { case 6: return offscreen; case 7: return 0; //noise (1 = yes) } + + unreachable; } auto SuperScope::latch(bool data) -> void { diff --git a/higan/sfc/coprocessor/epsonrtc/epsonrtc.cpp b/higan/sfc/coprocessor/epsonrtc/epsonrtc.cpp index d4002ba2..4d9837e6 100644 --- a/higan/sfc/coprocessor/epsonrtc/epsonrtc.cpp +++ b/higan/sfc/coprocessor/epsonrtc/epsonrtc.cpp @@ -85,8 +85,8 @@ auto EpsonRTC::power() -> void { holdtick = 0; } -auto EpsonRTC::sync() -> void { - time_t systime = time(0); +auto EpsonRTC::synchronize(uint64 timestamp) -> void { + time_t systime = timestamp; tm* timeinfo = localtime(&systime); uint second = min(59, timeinfo->tm_sec); diff --git a/higan/sfc/coprocessor/epsonrtc/epsonrtc.hpp b/higan/sfc/coprocessor/epsonrtc/epsonrtc.hpp index 581c7921..34c36f24 100644 --- a/higan/sfc/coprocessor/epsonrtc/epsonrtc.hpp +++ b/higan/sfc/coprocessor/epsonrtc/epsonrtc.hpp @@ -1,12 +1,14 @@ //Epson RTC-4513 Real-Time Clock struct EpsonRTC : Thread { + using Thread::synchronize; + static auto Enter() -> void; auto main() -> void; auto initialize() -> void; auto power() -> void; - auto sync() -> void; + auto synchronize(uint64 timestamp) -> void; auto read(uint24 addr, uint8 data) -> uint8; auto write(uint24 addr, uint8 data) -> void; diff --git a/higan/sfc/coprocessor/icd/icd.cpp b/higan/sfc/coprocessor/icd/icd.cpp index 7467018d..e1a0bae9 100644 --- a/higan/sfc/coprocessor/icd/icd.cpp +++ b/higan/sfc/coprocessor/icd/icd.cpp @@ -4,7 +4,7 @@ namespace SuperFamicom { ICD icd; -#if defined(SFC_SUPERGAMEBOY) +#if defined(CORE_GB) #include "platform.cpp" #include "interface.cpp" diff --git a/higan/sfc/coprocessor/icd/icd.hpp b/higan/sfc/coprocessor/icd/icd.hpp index a407787c..9aeeff82 100644 --- a/higan/sfc/coprocessor/icd/icd.hpp +++ b/higan/sfc/coprocessor/icd/icd.hpp @@ -1,4 +1,4 @@ -#if defined(SFC_SUPERGAMEBOY) +#if defined(CORE_GB) struct ICD : Emulator::Platform, GameBoy::SuperGameBoyInterface, Thread { shared_pointer stream; diff --git a/higan/sfc/coprocessor/msu1/msu1.cpp b/higan/sfc/coprocessor/msu1/msu1.cpp index e5060dfa..7f691035 100644 --- a/higan/sfc/coprocessor/msu1/msu1.cpp +++ b/higan/sfc/coprocessor/msu1/msu1.cpp @@ -123,6 +123,8 @@ auto MSU1::readIO(uint24 addr, uint8) -> uint8 { case 0x2006: return 'U'; case 0x2007: return '1'; } + + unreachable; } auto MSU1::writeIO(uint24 addr, uint8 data) -> void { diff --git a/higan/sfc/coprocessor/sa1/memory.cpp b/higan/sfc/coprocessor/sa1/memory.cpp index 6050a8eb..5f282b1b 100644 --- a/higan/sfc/coprocessor/sa1/memory.cpp +++ b/higan/sfc/coprocessor/sa1/memory.cpp @@ -242,6 +242,7 @@ auto SA1::bitmapRead(uint addr, uint8 data) -> uint8 { case 3: return (bwram.read(addr) >> 6) & 3; } } + unreachable; } auto SA1::bitmapWrite(uint addr, uint8 data) -> void { diff --git a/higan/sfc/coprocessor/sdd1/decompressor.cpp b/higan/sfc/coprocessor/sdd1/decompressor.cpp index 66fb6098..edce9e73 100644 --- a/higan/sfc/coprocessor/sdd1/decompressor.cpp +++ b/higan/sfc/coprocessor/sdd1/decompressor.cpp @@ -253,6 +253,8 @@ auto SDD1::Decompressor::OL::decompress() -> uint8 { } return r1; } + + return 0; //unreachable? } //core diff --git a/higan/sfc/coprocessor/sharprtc/sharprtc.cpp b/higan/sfc/coprocessor/sharprtc/sharprtc.cpp index 162725ca..2f13e5d4 100644 --- a/higan/sfc/coprocessor/sharprtc/sharprtc.cpp +++ b/higan/sfc/coprocessor/sharprtc/sharprtc.cpp @@ -35,8 +35,8 @@ auto SharpRTC::power() -> void { index = -1; } -auto SharpRTC::sync() -> void { - time_t systime = time(0); +auto SharpRTC::synchronize(uint64 timestamp) -> void { + time_t systime = timestamp; tm* timeinfo = localtime(&systime); second = min(59, timeinfo->tm_sec); diff --git a/higan/sfc/coprocessor/sharprtc/sharprtc.hpp b/higan/sfc/coprocessor/sharprtc/sharprtc.hpp index f0f5a843..91f7e744 100644 --- a/higan/sfc/coprocessor/sharprtc/sharprtc.hpp +++ b/higan/sfc/coprocessor/sharprtc/sharprtc.hpp @@ -1,10 +1,12 @@ struct SharpRTC : Thread { + using Thread::synchronize; + static auto Enter() -> void; auto main() -> void; auto initialize() -> void; auto power() -> void; - auto sync() -> void; + auto synchronize(uint64 timestamp) -> void; auto read(uint24 addr, uint8 data) -> uint8; auto write(uint24 addr, uint8 data) -> void; diff --git a/higan/sfc/expansion/21fx/21fx.hpp b/higan/sfc/expansion/21fx/21fx.hpp index 50eb7d85..6ed01edb 100644 --- a/higan/sfc/expansion/21fx/21fx.hpp +++ b/higan/sfc/expansion/21fx/21fx.hpp @@ -30,7 +30,7 @@ private: function, //read function //write )> linkInit; - function linkMain; + function)> linkMain; vector snesBuffer; //SNES -> Link vector linkBuffer; //Link -> SNES diff --git a/higan/sfc/interface/interface.cpp b/higan/sfc/interface/interface.cpp index 113d24db..34d8979f 100644 --- a/higan/sfc/interface/interface.cpp +++ b/higan/sfc/interface/interface.cpp @@ -2,38 +2,31 @@ namespace SuperFamicom { -#define returns(T) T { return ([&] { struct With : T { With() { -#define $ }}; return With(); })(); } - Settings settings; -auto Interface::information() -> returns(Information) { - manufacturer = "Nintendo"; - name = "Super Famicom"; - extension = "sfc"; - resettable = true; -}$ - -auto Interface::manifest() -> string { - return cartridge.manifest(); +auto Interface::information() -> Information { + Information information; + information.manufacturer = "Nintendo"; + information.name = "Super Famicom"; + information.extension = "sfc"; + information.resettable = true; + return information; } -auto Interface::title() -> string { - return cartridge.title(); +auto Interface::displays() -> vector { + Display display; + display.type = Display::Type::CRT; + display.colors = 1 << 19; + display.width = 256; + display.height = 240; + display.internalWidth = 512; + display.internalHeight = 480; + display.aspectCorrection = 8.0 / 7.0; + if(Region::NTSC()) display.refreshRate = system.cpuFrequency() / (262.0 * 1364.0); + if(Region::PAL()) display.refreshRate = system.cpuFrequency() / (312.0 * 1364.0); + return {display}; } -auto Interface::display() -> returns(Display) { - type = Display::Type::CRT; - colors = 1 << 19; - width = 256; - height = 240; - internalWidth = 512; - internalHeight = 480; - aspectCorrection = 8.0 / 7.0; - if(Region::NTSC()) refreshRate = system.cpuFrequency() / (262.0 * 1364.0); - if(Region::PAL()) refreshRate = system.cpuFrequency() / (312.0 * 1364.0); -}$ - auto Interface::color(uint32 color) -> uint64 { uint r = color.bits( 0, 4); uint g = color.bits( 5, 9); @@ -66,8 +59,16 @@ auto Interface::loaded() -> bool { return system.loaded(); } -auto Interface::sha256() -> string { - return cartridge.sha256(); +auto Interface::hashes() -> vector { + return cartridge.hashes(); +} + +auto Interface::manifests() -> vector { + return cartridge.manifests(); +} + +auto Interface::titles() -> vector { + return cartridge.titles(); } auto Interface::load() -> bool { @@ -229,9 +230,10 @@ auto Interface::rtc() -> bool { return false; } -auto Interface::rtcSynchronize() -> void { - if(cartridge.has.EpsonRTC) epsonrtc.sync(); - if(cartridge.has.SharpRTC) sharprtc.sync(); +auto Interface::synchronize(uint64 timestamp) -> void { + if(!timestamp) timestamp = chrono::timestamp(); + if(cartridge.has.EpsonRTC) epsonrtc.synchronize(timestamp); + if(cartridge.has.SharpRTC) sharprtc.synchronize(timestamp); } auto Interface::serialize() -> serializer { @@ -243,9 +245,9 @@ auto Interface::unserialize(serializer& s) -> bool { return system.unserialize(s); } -auto Interface::cheatSet(const string_vector& list) -> void { +auto Interface::cheats(const vector& list) -> void { cheat.reset(); - #if defined(SFC_SUPERGAMEBOY) + #if defined(CORE_GB) if(cartridge.has.ICD) return GameBoy::cheat.assign(list); #endif cheat.assign(list); @@ -307,7 +309,4 @@ auto Interface::set(const string& name, const any& value) -> bool { return false; } -#undef returns -#undef $ - } diff --git a/higan/sfc/interface/interface.hpp b/higan/sfc/interface/interface.hpp index 9be79c42..e3aa397a 100644 --- a/higan/sfc/interface/interface.hpp +++ b/higan/sfc/interface/interface.hpp @@ -1,3 +1,5 @@ +#if defined(CORE_SFC) + namespace SuperFamicom { struct ID { @@ -31,17 +33,15 @@ struct ID { }; struct Interface : Emulator::Interface { - using Emulator::Interface::load; - auto information() -> Information; - auto manifest() -> string override; - auto title() -> string override; - auto display() -> Display override; + auto displays() -> vector override; auto color(uint32 color) -> uint64 override; auto loaded() -> bool override; - auto sha256() -> string override; + auto hashes() -> vector override; + auto manifests() -> vector override; + auto titles() -> vector override; auto load() -> bool override; auto save() -> void override; auto unload() -> void override; @@ -57,12 +57,12 @@ struct Interface : Emulator::Interface { auto run() -> void override; auto rtc() -> bool override; - auto rtcSynchronize() -> void override; + auto synchronize(uint64 timestamp) -> void override; auto serialize() -> serializer override; auto unserialize(serializer&) -> bool override; - auto cheatSet(const string_vector&) -> void override; + auto cheats(const vector&) -> void override; auto cap(const string& name) -> bool override; auto get(const string& name) -> any override; @@ -88,3 +88,5 @@ struct Settings { extern Settings settings; } + +#endif diff --git a/higan/sfc/sfc.hpp b/higan/sfc/sfc.hpp index 289d06f1..07aea368 100644 --- a/higan/sfc/sfc.hpp +++ b/higan/sfc/sfc.hpp @@ -16,7 +16,7 @@ #include #include -#if defined(SFC_SUPERGAMEBOY) +#if defined(CORE_GB) #include #endif diff --git a/higan/sfc/system/serialization.cpp b/higan/sfc/system/serialization.cpp index 72253ac3..af698c6a 100644 --- a/higan/sfc/system/serialization.cpp +++ b/higan/sfc/system/serialization.cpp @@ -3,14 +3,11 @@ auto System::serialize() -> serializer { uint signature = 0x31545342; char version[16] = {}; - char hash[64] = {}; char description[512] = {}; memory::copy(&version, (const char*)Emulator::SerializerVersion, Emulator::SerializerVersion.size()); - memory::copy(&hash, (const char*)cartridge.sha256(), 64); s.integer(signature); s.array(version); - s.array(hash); s.array(description); s.boolean(hacks.fastPPU); @@ -23,12 +20,10 @@ auto System::serialize() -> serializer { auto System::unserialize(serializer& s) -> bool { uint signature = 0; char version[16] = {}; - char hash[64] = {}; char description[512] = {}; s.integer(signature); s.array(version); - s.array(hash); s.array(description); if(signature != 0x31545342) return false; @@ -92,12 +87,10 @@ auto System::serializeInit() -> void { uint signature = 0; char version[16] = {}; - char hash[64] = {}; char description[512] = {}; s.integer(signature); s.array(version); - s.array(hash); s.array(description); s.boolean(hacks.fastPPU); diff --git a/higan/systems/Super Famicom.sys/boards.bml b/higan/systems/Super Famicom.sys/boards.bml index 27dd2bad..387cdc4d 100644 --- a/higan/systems/Super Famicom.sys/boards.bml +++ b/higan/systems/Super Famicom.sys/boards.bml @@ -1,5 +1,5 @@ database - revision: 2018-06-25 + revision: 2018-07-25 //Boards (Production) @@ -565,7 +565,7 @@ board: SHVC-YJ0N-01 //Boards (Generic) database - revision: 2018-06-25 + revision: 2018-07-25 board: ARM-LOROM-RAM memory type=ROM content=Program @@ -768,18 +768,18 @@ board: LOROM memory type=ROM content=Program map address=00-7d,80-ff:8000-ffff mask=0x8000 +board: LOROM-RAM + memory type=ROM content=Program + map address=00-7d,80-ff:8000-ffff mask=0x8000 + memory type=RAM content=Save + map address=70-7d,f0-ff:0000-7fff mask=0x8000 + board: LOROM-RAM#A memory type=ROM content=Program map address=00-3f,80-bf:8000-ffff mask=0x8000 memory type=RAM content=Save map address=70-7d,f0-ff:0000-ffff mask=0x8000 -board: LOROM-RAM#B - memory type=ROM content=Program - map address=00-7d,80-ff:8000-ffff mask=0x8000 - memory type=RAM content=Save - map address=70-7d,f0-ff:0000-7fff mask=0x8000 - board: NEC-HIROM memory type=ROM content=Program map address=00-3f,80-bf:8000-ffff @@ -814,6 +814,18 @@ board: NEC-LOROM memory type=RAM content=Data architecture=uPD7725 oscillator +board: NEC-LOROM-RAM + memory type=ROM content=Program + map address=00-3f,80-bf:8000-ffff mask=0x8000 + memory type=RAM content=Save + map address=70-7d,f0-ff:0000-7fff mask=0x8000 + processor architecture=uPD7725 + map address=60-6f,e0-ef:0000-7fff mask=0x3fff + memory type=ROM content=Program architecture=uPD7725 + memory type=ROM content=Data architecture=uPD7725 + memory type=RAM content=Data architecture=uPD7725 + oscillator + board: NEC-LOROM-RAM#A memory type=ROM content=Program map address=00-1f,80-9f:8000-ffff mask=0x8000 @@ -826,18 +838,6 @@ board: NEC-LOROM-RAM#A memory type=RAM content=Data architecture=uPD7725 oscillator -board: NEC-LOROM-RAM#B - memory type=ROM content=Program - map address=00-3f,80-bf:8000-ffff mask=0x8000 - memory type=RAM content=Save - map address=70-7d,f0-ff:0000-7fff mask=0x8000 - processor architecture=uPD7725 - map address=60-6f,e0-ef:0000-7fff mask=0x3fff - memory type=ROM content=Program architecture=uPD7725 - memory type=ROM content=Data architecture=uPD7725 - memory type=RAM content=Data architecture=uPD7725 - oscillator - board: OBC1-LOROM-RAM memory type=ROM content=Program map address=00-3f,80-bf:8000-ffff mask=0x8000 diff --git a/higan/target-bsnes/GNUmakefile b/higan/target-bsnes/GNUmakefile index 64b45cb0..a00a0d29 100644 --- a/higan/target-bsnes/GNUmakefile +++ b/higan/target-bsnes/GNUmakefile @@ -1,9 +1,4 @@ name := bsnes -flags += -DSFC_SUPERGAMEBOY - -include sfc/GNUmakefile -include gb/GNUmakefile -include processor/GNUmakefile hiro.path := ../hiro hiro.resource := $(ui)/resource/bsnes.rc diff --git a/higan/target-bsnes/bsnes.cpp b/higan/target-bsnes/bsnes.cpp index b00a06ba..2b6f9650 100644 --- a/higan/target-bsnes/bsnes.cpp +++ b/higan/target-bsnes/bsnes.cpp @@ -19,7 +19,7 @@ auto locate(string name) -> string { } #include -auto nall::main(string_vector arguments) -> void { +auto nall::main(vector arguments) -> void { string locale; // = "日本語"; for(auto argument : arguments) { if(argument.beginsWith("--locale=")) { diff --git a/higan/target-bsnes/presentation/presentation.cpp b/higan/target-bsnes/presentation/presentation.cpp index 8f4bf138..dcfe5675 100644 --- a/higan/target-bsnes/presentation/presentation.cpp +++ b/higan/target-bsnes/presentation/presentation.cpp @@ -132,7 +132,7 @@ Presentation::Presentation() { aboutWindow->setCentered(*this).setVisible().setFocused(); }); - viewport.setDroppable().onDrop([&](string_vector locations) { + viewport.setDroppable().onDrop([&](vector locations) { program->gameQueue = locations; program->load(); setFocused(); diff --git a/higan/target-bsnes/program/game.cpp b/higan/target-bsnes/program/game.cpp index caf28c1c..9af43dc6 100644 --- a/higan/target-bsnes/program/game.cpp +++ b/higan/target-bsnes/program/game.cpp @@ -6,15 +6,18 @@ auto Program::load() -> void { screenshot = {}; frameAdvance = false; if(!verified() && settingsWindow->advanced.warnOnUnverifiedGames.checked()) { - //todo: MessageDialog crashes with GTK+; unsure the reason why this happens - //once MessageDialog functions, add an "Always" option - if(MessageWindow( - "Warning: this game image is unverified. Running it *may* be a security risk.\n\n" + auto response = MessageDialog( + "Warning: this game image is unverified.\n" + "Running it *may* be a security risk.\n\n" "Do you wish to run the game anyway?" - ).setParent(*presentation).question() == MessageWindow::Response::No) { + ).setParent(*presentation).question({"Always", "Yes", "No"}); + if(response == "No") { emulator->unload(); return showMessage("Game loading cancelled"); } + if(response == "Always") { + settingsWindow->advanced.warnOnUnverifiedGames.setChecked(false).doToggle(); + } } hackCompatibility(); emulator->power(); @@ -25,7 +28,7 @@ auto Program::load() -> void { verified() ? "Verified game loaded" : "Game loaded", appliedPatch() ? " and patch applied" : "" }); - presentation->setTitle(emulator->title()); + presentation->setTitle(emulator->titles().merge(" + ")); presentation->resetSystem.setEnabled(true); presentation->unloadGame.setEnabled(true); presentation->toolsMenu.setVisible(true); @@ -38,10 +41,10 @@ auto Program::load() -> void { toolsWindow->manifestViewer.loadManifest(); string locations = superFamicom.location; - if(auto location = gameBoy.location) locations.append("|", location); - if(auto location = bsMemory.location) locations.append("|", location); - if(auto location = sufamiTurboA.location) locations.append("|", location); - if(auto location = sufamiTurboB.location) locations.append("|", location); + if(auto& location = gameBoy.location) locations.append("|", location); + if(auto& location = bsMemory.location) locations.append("|", location); + if(auto& location = sufamiTurboA.location) locations.append("|", location); + if(auto& location = sufamiTurboB.location) locations.append("|", location); presentation->addRecentGame(locations); updateVideoPalette(); @@ -75,9 +78,9 @@ auto Program::loadSuperFamicom(string location) -> bool { rom.append(file::read({location, "program.rom"})); rom.append(file::read({location, "data.rom"})); rom.append(file::read({location, "expansion.rom"})); - for(auto filename : directory::files(location, "*.boot.rom" )) rom.append(file::read({location, filename})); - for(auto filename : directory::files(location, "*.program.rom")) rom.append(file::read({location, filename})); - for(auto filename : directory::files(location, "*.data.rom" )) rom.append(file::read({location, filename})); + for(auto& filename : directory::files(location, "*.boot.rom" )) rom.append(file::read({location, filename})); + for(auto& filename : directory::files(location, "*.program.rom")) rom.append(file::read({location, filename})); + for(auto& filename : directory::files(location, "*.data.rom" )) rom.append(file::read({location, filename})); } else { manifest = file::read({Location::notsuffix(location), ".bml"}); rom = loadFile(location); diff --git a/higan/target-bsnes/program/platform.cpp b/higan/target-bsnes/program/platform.cpp index f76e4386..ee28e40c 100644 --- a/higan/target-bsnes/program/platform.cpp +++ b/higan/target-bsnes/program/platform.cpp @@ -103,7 +103,7 @@ auto Program::open(uint id, string name, vfs::file::mode mode, bool required) -> return result; } -auto Program::load(uint id, string name, string type, string_vector options) -> Emulator::Platform::Load { +auto Program::load(uint id, string name, string type, vector options) -> Emulator::Platform::Load { BrowserDialog dialog; dialog.setParent(*presentation); dialog.setOptions(options); @@ -196,7 +196,7 @@ auto Program::load(uint id, string name, string type, string_vector options) -> return {}; } -auto Program::videoRefresh(const uint32* data, uint pitch, uint width, uint height) -> void { +auto Program::videoRefresh(uint display, const uint32* data, uint pitch, uint width, uint height) -> void { uint32_t* output; uint length; diff --git a/higan/target-bsnes/program/program.cpp b/higan/target-bsnes/program/program.cpp index edb96dc0..1a2f56f3 100644 --- a/higan/target-bsnes/program/program.cpp +++ b/higan/target-bsnes/program/program.cpp @@ -13,7 +13,7 @@ #include "hacks.cpp" unique_pointer program; -Program::Program(string_vector arguments) { +Program::Program(vector arguments) { program = this; Emulator::platform = this; @@ -89,5 +89,5 @@ auto Program::quit() -> void { video.reset(); audio.reset(); input.reset(); - Application::quit(); + Application::kill(); } diff --git a/higan/target-bsnes/program/program.hpp b/higan/target-bsnes/program/program.hpp index b31ca758..cf0d5dea 100644 --- a/higan/target-bsnes/program/program.hpp +++ b/higan/target-bsnes/program/program.hpp @@ -2,14 +2,14 @@ struct Program : Emulator::Platform { Application::Namespace tr{"Program"}; //program.cpp - Program(string_vector arguments); + Program(vector arguments); auto main() -> void; auto quit() -> void; //platform.cpp auto open(uint id, string name, vfs::file::mode mode, bool required) -> vfs::shared::file override; - auto load(uint id, string name, string type, string_vector options = {}) -> Emulator::Platform::Load override; - auto videoRefresh(const uint32* data, uint pitch, uint width, uint height) -> void override; + auto load(uint id, string name, string type, vector options = {}) -> Emulator::Platform::Load override; + auto videoRefresh(uint display, const uint32* data, uint pitch, uint width, uint height) -> void override; auto audioSample(const double* samples, uint channels) -> void override; auto inputPoll(uint port, uint device, uint input) -> int16 override; auto inputRumble(uint port, uint device, uint input, bool enable) -> void override; @@ -49,7 +49,7 @@ struct Program : Emulator::Platform { auto screenshotPath() -> string; //states.cpp - auto managedStates() -> string_vector; + auto managedStates() -> vector; auto loadState(string filename) -> bool; auto saveState(string filename) -> bool; auto saveUndoState() -> bool; @@ -124,7 +124,7 @@ public: vector program; } sufamiTurboA, sufamiTurboB; - string_vector gameQueue; + vector gameQueue; struct Screenshot { const uint32* data = nullptr; diff --git a/higan/target-bsnes/program/states.cpp b/higan/target-bsnes/program/states.cpp index 0fbc1675..33156a02 100644 --- a/higan/target-bsnes/program/states.cpp +++ b/higan/target-bsnes/program/states.cpp @@ -1,4 +1,4 @@ -auto Program::managedStates() -> string_vector { +auto Program::managedStates() -> vector { if(!emulator->loaded()) return {}; if(gamePath().endsWith("/")) { @@ -6,7 +6,7 @@ auto Program::managedStates() -> string_vector { } else { Decode::ZIP input; if(input.open(statePath())) { - string_vector filenames; + vector filenames; for(auto& file : input.file) { if(file.name.match("managed/*.bst")) filenames.append(file.name.trimLeft("managed/", 1L)); } diff --git a/higan/target-bsnes/resource/resource.cpp b/higan/target-bsnes/resource/resource.cpp index 3206d06f..ef38ee88 100644 --- a/higan/target-bsnes/resource/resource.cpp +++ b/higan/target-bsnes/resource/resource.cpp @@ -863,8 +863,8 @@ const nall::vector Manifest = { //size: 334 115,112,10,32,32,32,32,114,97,109,32,110,97,109,101,61,97,112,117,46,114,97,109,32,115,105,122,101,61,48,120,49, 48,48,48,48,32,118,111,108,97,116,105,108,101,10, }; -const nall::vector Boards = { //size: 30186 - 100,97,116,97,98,97,115,101,10,32,32,114,101,118,105,115,105,111,110,58,32,50,48,49,56,45,48,54,45,50,53,10, +const nall::vector Boards = { //size: 30182 + 100,97,116,97,98,97,115,101,10,32,32,114,101,118,105,115,105,111,110,58,32,50,48,49,56,45,48,55,45,50,53,10, 10,47,47,66,111,97,114,100,115,32,40,80,114,111,100,117,99,116,105,111,110,41,10,10,100,97,116,97,98,97,115,101, 10,32,32,114,101,118,105,115,105,111,110,58,32,50,48,49,56,45,48,53,45,49,54,10,10,98,111,97,114,100,58,32, 66,65,78,68,65,73,45,80,84,45,57,50,51,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32, @@ -1437,7 +1437,7 @@ const nall::vector Boards = { //size: 30186 32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,10,32, 32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,52,48,45,55,100,44,99,48,45,102,102,58,48,48,48,48,45, 102,102,102,102,10,10,47,47,66,111,97,114,100,115,32,40,71,101,110,101,114,105,99,41,10,10,100,97,116,97,98,97, - 115,101,10,32,32,114,101,118,105,115,105,111,110,58,32,50,48,49,56,45,48,54,45,50,53,10,10,98,111,97,114,100, + 115,101,10,32,32,114,101,118,105,115,105,111,110,58,32,50,48,49,56,45,48,55,45,50,53,10,10,98,111,97,114,100, 58,32,65,82,77,45,76,79,82,79,77,45,82,65,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79, 77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115, 115,61,48,48,45,55,100,44,56,48,45,102,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56, @@ -1651,51 +1651,65 @@ const nall::vector Boards = { //size: 30186 108,97,116,111,114,10,10,98,111,97,114,100,58,32,76,79,82,79,77,10,32,32,109,101,109,111,114,121,32,116,121,112, 101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100, 100,114,101,115,115,61,48,48,45,55,100,44,56,48,45,102,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107, - 61,48,120,56,48,48,48,10,10,98,111,97,114,100,58,32,76,79,82,79,77,45,82,65,77,35,65,10,32,32,109,101, + 61,48,120,56,48,48,48,10,10,98,111,97,114,100,58,32,76,79,82,79,77,45,82,65,77,10,32,32,109,101,109,111, + 114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32, + 109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,55,100,44,56,48,45,102,102,58,56,48,48,48,45,102,102,102, + 102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32, + 99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55,48,45, + 55,100,44,102,48,45,102,102,58,48,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,10, + 98,111,97,114,100,58,32,76,79,82,79,77,45,82,65,77,35,65,10,32,32,109,101,109,111,114,121,32,116,121,112,101, + 61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100, + 114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61, + 48,120,56,48,48,48,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116, + 61,83,97,118,101,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55,48,45,55,100,44,102,48,45,102, + 102,58,48,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,10,98,111,97,114,100,58,32, + 78,69,67,45,72,73,82,79,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116, + 101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51, + 102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115, + 115,61,52,48,45,55,100,44,99,48,45,102,102,58,48,48,48,48,45,102,102,102,102,10,32,32,112,114,111,99,101,115, + 115,111,114,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,97,112, + 32,97,100,100,114,101,115,115,61,48,48,45,49,102,44,56,48,45,57,102,58,54,48,48,48,45,55,102,102,102,32,109, + 97,115,107,61,48,120,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111, + 110,116,101,110,116,61,80,114,111,103,114,97,109,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55, + 50,53,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,68, + 97,116,97,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,101,109, + 111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,114,99,104,105,116, + 101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,111,115,99,105,108,108,97,116,111,114,10,10,98, + 111,97,114,100,58,32,78,69,67,45,72,73,82,79,77,45,82,65,77,10,32,32,109,101,109,111,114,121,32,116,121,112, + 101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100, + 100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,10,32,32,32,32, + 109,97,112,32,97,100,100,114,101,115,115,61,52,48,45,55,100,44,99,48,45,102,102,58,48,48,48,48,45,102,102,102, + 102,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101, + 10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,50,48,45,51,102,44,97,48,45,98,102,58,54,48,48, + 48,45,55,102,102,102,32,109,97,115,107,61,48,120,101,48,48,48,10,32,32,112,114,111,99,101,115,115,111,114,32,97, + 114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,97,112,32,97,100,100,114, + 101,115,115,61,48,48,45,49,102,44,56,48,45,57,102,58,54,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48, + 120,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116, + 61,80,114,111,103,114,97,109,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32, + 32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32,97, + 114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,101,109,111,114,121,32,116, + 121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,114,99,104,105,116,101,99,116,117,114, + 101,61,117,80,68,55,55,50,53,10,32,32,32,32,111,115,99,105,108,108,97,116,111,114,10,10,98,111,97,114,100,58, + 32,78,69,67,45,76,79,82,79,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110, + 116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45, + 49,102,44,56,48,45,57,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32, + 32,112,114,111,99,101,115,115,111,114,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10, + 32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,51,48,45,51,102,44,98,48,45,98,102,58,56,48,48,48, + 45,102,102,102,102,32,109,97,115,107,61,48,120,51,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112, + 101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,32,97,114,99,104,105,116,101,99,116,117, + 114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99, + 111,110,116,101,110,116,61,68,97,116,97,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53, + 10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,68,97,116, + 97,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,111,115,99,105,108, + 108,97,116,111,114,10,10,98,111,97,114,100,58,32,78,69,67,45,76,79,82,79,77,45,82,65,77,10,32,32,109,101, 109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32, 32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102, 102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65, 77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55, - 48,45,55,100,44,102,48,45,102,102,58,48,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48, - 10,10,98,111,97,114,100,58,32,76,79,82,79,77,45,82,65,77,35,66,10,32,32,109,101,109,111,114,121,32,116,121, - 112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97, - 100,100,114,101,115,115,61,48,48,45,55,100,44,56,48,45,102,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115, - 107,61,48,120,56,48,48,48,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101, - 110,116,61,83,97,118,101,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55,48,45,55,100,44,102,48, - 45,102,102,58,48,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,10,98,111,97,114,100, - 58,32,78,69,67,45,72,73,82,79,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111, - 110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48, - 45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,10,32,32,32,32,109,97,112,32,97,100,100,114, - 101,115,115,61,52,48,45,55,100,44,99,48,45,102,102,58,48,48,48,48,45,102,102,102,102,10,32,32,112,114,111,99, - 101,115,115,111,114,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109, - 97,112,32,97,100,100,114,101,115,115,61,48,48,45,49,102,44,56,48,45,57,102,58,54,48,48,48,45,55,102,102,102, - 32,109,97,115,107,61,48,120,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32, - 99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68, - 55,55,50,53,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116, - 61,68,97,116,97,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109, - 101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,114,99,104, - 105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,111,115,99,105,108,108,97,116,111,114,10, - 10,98,111,97,114,100,58,32,78,69,67,45,72,73,82,79,77,45,82,65,77,10,32,32,109,101,109,111,114,121,32,116, - 121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32, - 97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,10,32,32, - 32,32,109,97,112,32,97,100,100,114,101,115,115,61,52,48,45,55,100,44,99,48,45,102,102,58,48,48,48,48,45,102, - 102,102,102,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97, - 118,101,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,50,48,45,51,102,44,97,48,45,98,102,58,54, - 48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,101,48,48,48,10,32,32,112,114,111,99,101,115,115,111,114, - 32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,97,112,32,97,100, - 100,114,101,115,115,61,48,48,45,49,102,44,56,48,45,57,102,58,54,48,48,48,45,55,102,102,102,32,109,97,115,107, - 61,48,120,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101, - 110,116,61,80,114,111,103,114,97,109,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10, - 32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,68,97,116,97, - 32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,101,109,111,114,121, - 32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,114,99,104,105,116,101,99,116, - 117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,111,115,99,105,108,108,97,116,111,114,10,10,98,111,97,114, - 100,58,32,78,69,67,45,76,79,82,79,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99, - 111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48, - 48,45,49,102,44,56,48,45,57,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48, + 48,45,55,100,44,102,48,45,102,102,58,48,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48, 10,32,32,112,114,111,99,101,115,115,111,114,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50, - 53,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,51,48,45,51,102,44,98,48,45,98,102,58,56,48, - 48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,51,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116, + 53,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,54,48,45,54,102,44,101,48,45,101,102,58,48,48, + 48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,51,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116, 121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,32,97,114,99,104,105,116,101,99, 116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77, 32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55, @@ -1715,99 +1729,85 @@ const nall::vector Boards = { //size: 30186 61,68,97,116,97,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109, 101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,114,99,104, 105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,111,115,99,105,108,108,97,116,111,114,10, - 10,98,111,97,114,100,58,32,78,69,67,45,76,79,82,79,77,45,82,65,77,35,66,10,32,32,109,101,109,111,114,121, - 32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97, - 112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,32, - 109,97,115,107,61,48,120,56,48,48,48,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111, - 110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55,48,45,55,100, - 44,102,48,45,102,102,58,48,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,112, - 114,111,99,101,115,115,111,114,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32, - 32,32,109,97,112,32,97,100,100,114,101,115,115,61,54,48,45,54,102,44,101,48,45,101,102,58,48,48,48,48,45,55, - 102,102,102,32,109,97,115,107,61,48,120,51,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61, - 82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,32,97,114,99,104,105,116,101,99,116,117,114,101, - 61,117,80,68,55,55,50,53,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110, - 116,101,110,116,61,68,97,116,97,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32, - 32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32, - 97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,111,115,99,105,108,108,97, - 116,111,114,10,10,98,111,97,114,100,58,32,79,66,67,49,45,76,79,82,79,77,45,82,65,77,10,32,32,109,101,109, - 111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32, - 32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102, - 102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,112,114,111,99,101,115,115,111,114,32,105,100,101,110,116, - 105,102,105,101,114,61,79,66,67,49,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102, - 44,56,48,45,98,102,58,54,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,101,48,48,48,10,32,32,32, - 32,109,97,112,32,97,100,100,114,101,115,115,61,55,48,45,55,49,44,102,48,45,102,49,58,54,48,48,48,45,55,102, - 102,102,44,101,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,101,48,48,48,10,32,32,32,32,109,101,109, - 111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,10,98,111,97,114,100, - 58,32,83,65,49,45,82,65,77,10,32,32,112,114,111,99,101,115,115,111,114,32,97,114,99,104,105,116,101,99,116,117, - 114,101,61,87,54,53,67,56,49,54,83,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51, - 102,44,56,48,45,98,102,58,50,50,48,48,45,50,51,102,102,10,32,32,32,32,109,99,117,10,32,32,32,32,32,32, - 109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102, - 102,32,109,97,115,107,61,48,120,52,48,56,48,48,48,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115, - 115,61,99,48,45,102,102,58,48,48,48,48,45,102,102,102,102,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116, - 121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,101,109,111, - 114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,32,32,109, - 97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,54,48,48,48,45,55,102,102,102, - 32,115,105,122,101,61,48,120,50,48,48,48,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,52, - 48,45,52,102,58,48,48,48,48,45,102,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82, - 65,77,32,99,111,110,116,101,110,116,61,73,110,116,101,114,110,97,108,10,32,32,32,32,32,32,109,97,112,32,97,100, - 100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,51,48,48,48,45,51,55,102,102,32,115,105,122,101, - 61,48,120,56,48,48,10,10,98,111,97,114,100,58,32,83,68,68,49,10,32,32,112,114,111,99,101,115,115,111,114,32, - 105,100,101,110,116,105,102,105,101,114,61,83,68,68,49,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61, - 48,48,45,51,102,44,56,48,45,98,102,58,52,56,48,48,45,52,56,48,102,10,32,32,32,32,109,99,117,10,32,32, - 32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48, - 45,102,102,102,102,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,99,48,45,102,102,58,48,48, - 48,48,45,102,102,102,102,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111, - 110,116,101,110,116,61,80,114,111,103,114,97,109,10,10,98,111,97,114,100,58,32,83,68,68,49,45,82,65,77,10,32, - 32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,32,32, - 32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,54,48,48,48,45,55, - 102,102,102,32,109,97,115,107,61,48,120,101,48,48,48,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61, - 55,48,45,55,51,58,48,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,112,114, - 111,99,101,115,115,111,114,32,105,100,101,110,116,105,102,105,101,114,61,83,68,68,49,10,32,32,32,32,109,97,112,32, - 97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,52,56,48,48,45,52,56,48,102,10,32,32, - 32,32,109,99,117,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48, - 45,98,102,58,56,48,48,48,45,102,102,102,102,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61, - 99,48,45,102,102,58,48,48,48,48,45,102,102,102,102,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112, - 101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,10,98,111,97,114,100,58,32,83,80, - 67,55,49,49,48,45,82,65,77,10,32,32,112,114,111,99,101,115,115,111,114,32,105,100,101,110,116,105,102,105,101,114, - 61,83,80,67,55,49,49,48,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56, - 48,45,98,102,58,52,56,48,48,45,52,56,51,102,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,53, - 48,44,53,56,58,48,48,48,48,45,102,102,102,102,10,32,32,32,32,109,99,117,10,32,32,32,32,32,32,109,97,112, + 10,98,111,97,114,100,58,32,79,66,67,49,45,76,79,82,79,77,45,82,65,77,10,32,32,109,101,109,111,114,121,32, + 116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112, 32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,32,109, - 97,115,107,61,48,120,56,48,48,48,48,48,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,99, - 48,45,102,102,58,48,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,99,48,48,48,48,48,10,32,32,32, - 32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114, - 97,109,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116, - 61,68,97,116,97,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110, - 116,61,83,97,118,101,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56, - 48,45,98,102,58,54,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,101,48,48,48,10,10,98,111,97,114, - 100,58,32,83,80,67,55,49,49,48,45,82,65,77,45,69,80,83,79,78,82,84,67,10,32,32,112,114,111,99,101,115, - 115,111,114,32,105,100,101,110,116,105,102,105,101,114,61,83,80,67,55,49,49,48,10,32,32,32,32,109,97,112,32,97, - 100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,52,56,48,48,45,52,56,51,102,10,32,32,32, - 32,109,97,112,32,97,100,100,114,101,115,115,61,53,48,44,53,56,58,48,48,48,48,45,102,102,102,102,10,32,32,32, - 32,109,99,117,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45, - 98,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,48,48,10,32,32,32,32,32, - 32,109,97,112,32,97,100,100,114,101,115,115,61,99,48,45,102,102,58,48,48,48,48,45,102,102,102,102,32,109,97,115, - 107,61,48,120,99,48,48,48,48,48,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77, - 32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121, - 112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,68,97,116,97,10,32,32,32,32,109,101,109,111,114,121,32,116, + 97,115,107,61,48,120,56,48,48,48,10,32,32,112,114,111,99,101,115,115,111,114,32,105,100,101,110,116,105,102,105,101, + 114,61,79,66,67,49,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45, + 98,102,58,54,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,101,48,48,48,10,32,32,32,32,109,97,112, + 32,97,100,100,114,101,115,115,61,55,48,45,55,49,44,102,48,45,102,49,58,54,48,48,48,45,55,102,102,102,44,101, + 48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,101,48,48,48,10,32,32,32,32,109,101,109,111,114,121,32, + 116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,10,98,111,97,114,100,58,32,83,65, + 49,45,82,65,77,10,32,32,112,114,111,99,101,115,115,111,114,32,97,114,99,104,105,116,101,99,116,117,114,101,61,87, + 54,53,67,56,49,54,83,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48, + 45,98,102,58,50,50,48,48,45,50,51,102,102,10,32,32,32,32,109,99,117,10,32,32,32,32,32,32,109,97,112,32, + 97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,32,109,97, + 115,107,61,48,120,52,48,56,48,48,48,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,99,48, + 45,102,102,58,48,48,48,48,45,102,102,102,102,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61, + 82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,101,109,111,114,121,32,116, 121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,32,32,109,97,112,32,97, - 100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,54,48,48,48,45,55,102,102,102,32,109,97,115, - 107,61,48,120,101,48,48,48,10,32,32,114,116,99,32,109,97,110,117,102,97,99,116,117,114,101,114,61,69,112,115,111, - 110,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,52,56, - 52,48,45,52,56,52,50,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,84,67,32,99,111,110,116, - 101,110,116,61,84,105,109,101,32,109,97,110,117,102,97,99,116,117,114,101,114,61,69,112,115,111,110,10,10,98,111,97, - 114,100,58,32,83,84,45,76,79,82,79,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99, - 111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48, - 48,45,49,102,44,56,48,45,57,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48, + 100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,54,48,48,48,45,55,102,102,102,32,115,105,122, + 101,61,48,120,50,48,48,48,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,52,48,45,52,102, + 58,48,48,48,48,45,102,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99, + 111,110,116,101,110,116,61,73,110,116,101,114,110,97,108,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115, + 115,61,48,48,45,51,102,44,56,48,45,98,102,58,51,48,48,48,45,51,55,102,102,32,115,105,122,101,61,48,120,56, + 48,48,10,10,98,111,97,114,100,58,32,83,68,68,49,10,32,32,112,114,111,99,101,115,115,111,114,32,105,100,101,110, + 116,105,102,105,101,114,61,83,68,68,49,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51, + 102,44,56,48,45,98,102,58,52,56,48,48,45,52,56,48,102,10,32,32,32,32,109,99,117,10,32,32,32,32,32,32, + 109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102, + 102,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,99,48,45,102,102,58,48,48,48,48,45,102, + 102,102,102,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110, + 116,61,80,114,111,103,114,97,109,10,10,98,111,97,114,100,58,32,83,68,68,49,45,82,65,77,10,32,32,109,101,109, + 111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,109,97, + 112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,54,48,48,48,45,55,102,102,102,32, + 109,97,115,107,61,48,120,101,48,48,48,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55,48,45,55, + 51,58,48,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,112,114,111,99,101,115, + 115,111,114,32,105,100,101,110,116,105,102,105,101,114,61,83,68,68,49,10,32,32,32,32,109,97,112,32,97,100,100,114, + 101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,52,56,48,48,45,52,56,48,102,10,32,32,32,32,109,99, + 117,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58, + 56,48,48,48,45,102,102,102,102,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,99,48,45,102, + 102,58,48,48,48,48,45,102,102,102,102,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79, + 77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,10,98,111,97,114,100,58,32,83,80,67,55,49,49, + 48,45,82,65,77,10,32,32,112,114,111,99,101,115,115,111,114,32,105,100,101,110,116,105,102,105,101,114,61,83,80,67, + 55,49,49,48,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102, + 58,52,56,48,48,45,52,56,51,102,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,53,48,44,53,56, + 58,48,48,48,48,45,102,102,102,102,10,32,32,32,32,109,99,117,10,32,32,32,32,32,32,109,97,112,32,97,100,100, + 114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61, + 48,120,56,48,48,48,48,48,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,99,48,45,102,102, + 58,48,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,99,48,48,48,48,48,10,32,32,32,32,32,32,109, + 101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32, + 32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,68,97,116, + 97,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97, + 118,101,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102, + 58,54,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,101,48,48,48,10,10,98,111,97,114,100,58,32,83, + 80,67,55,49,49,48,45,82,65,77,45,69,80,83,79,78,82,84,67,10,32,32,112,114,111,99,101,115,115,111,114,32, + 105,100,101,110,116,105,102,105,101,114,61,83,80,67,55,49,49,48,10,32,32,32,32,109,97,112,32,97,100,100,114,101, + 115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,52,56,48,48,45,52,56,51,102,10,32,32,32,32,109,97,112, + 32,97,100,100,114,101,115,115,61,53,48,44,53,56,58,48,48,48,48,45,102,102,102,102,10,32,32,32,32,109,99,117, + 10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56, + 48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,48,48,10,32,32,32,32,32,32,109,97,112, + 32,97,100,100,114,101,115,115,61,99,48,45,102,102,58,48,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120, + 99,48,48,48,48,48,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110, + 116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82, + 79,77,32,99,111,110,116,101,110,116,61,68,97,116,97,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61, + 82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101, + 115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,54,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120, + 101,48,48,48,10,32,32,114,116,99,32,109,97,110,117,102,97,99,116,117,114,101,114,61,69,112,115,111,110,10,32,32, + 32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,52,56,52,48,45,52, + 56,52,50,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,84,67,32,99,111,110,116,101,110,116,61, + 84,105,109,101,32,109,97,110,117,102,97,99,116,117,114,101,114,61,69,112,115,111,110,10,10,98,111,97,114,100,58,32, + 83,84,45,76,79,82,79,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101, + 110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,49,102, + 44,56,48,45,57,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,115, + 108,111,116,32,116,121,112,101,61,83,117,102,97,109,105,84,117,114,98,111,10,32,32,32,32,114,111,109,10,32,32,32, + 32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,50,48,45,51,102,44,97,48,45,98,102,58,56,48,48,48,45, + 102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,32,32,114,97,109,10,32,32,32,32,32,32,109, + 97,112,32,97,100,100,114,101,115,115,61,54,48,45,54,102,44,101,48,45,101,102,58,48,48,48,48,45,102,102,102,102, 10,32,32,115,108,111,116,32,116,121,112,101,61,83,117,102,97,109,105,84,117,114,98,111,10,32,32,32,32,114,111,109, - 10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,50,48,45,51,102,44,97,48,45,98,102,58,56, + 10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,52,48,45,53,102,44,99,48,45,100,102,58,48, 48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,32,32,114,97,109,10,32,32,32, - 32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,54,48,45,54,102,44,101,48,45,101,102,58,48,48,48,48,45, - 102,102,102,102,10,32,32,115,108,111,116,32,116,121,112,101,61,83,117,102,97,109,105,84,117,114,98,111,10,32,32,32, - 32,114,111,109,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,52,48,45,53,102,44,99,48,45, - 100,102,58,48,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,32,32,114,97,109, - 10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55,48,45,55,100,44,102,48,45,102,102,58,48, - 48,48,48,45,102,102,102,102,10,10, + 32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55,48,45,55,100,44,102,48,45,102,102,58,48,48,48,48,45, + 102,102,102,102,10,10, }; const nall::vector IPLROM = { //size: 64 205,239,189,232,0,198,29,208,252,143,170,244,143,187,245,120,204,244,208,251,47,25,235,244,208,252,126,244,208,11,228,245, diff --git a/higan/target-bsnes/tools/cheat-editor.cpp b/higan/target-bsnes/tools/cheat-editor.cpp index 7fc21990..9dc188b8 100644 --- a/higan/target-bsnes/tools/cheat-editor.cpp +++ b/higan/target-bsnes/tools/cheat-editor.cpp @@ -18,7 +18,7 @@ CheatDatabase::CheatDatabase() { } auto CheatDatabase::findCheats() -> void { - auto sha256 = emulator->sha256(); + auto sha256 = emulator->hashes()[0]; auto document = BML::unserialize(string::read(locate("cheats.bml"))); for(auto game : document.find("cartridge")) { @@ -232,11 +232,11 @@ auto CheatEditor::saveCheats() -> void { } auto CheatEditor::synchronizeCodes() -> void { - string_vector codes; + vector codes; if(enableCheats.checked()) { for(auto& cheat : cheats) { if(cheat.enable) codes.append(cheat.code); } } - emulator->cheatSet(codes); + emulator->cheats(codes); } diff --git a/higan/target-bsnes/tools/manifest-viewer.cpp b/higan/target-bsnes/tools/manifest-viewer.cpp index 1b27e52c..d9f79191 100644 --- a/higan/target-bsnes/tools/manifest-viewer.cpp +++ b/higan/target-bsnes/tools/manifest-viewer.cpp @@ -14,7 +14,7 @@ auto ManifestViewer::loadManifest() -> void { return; } - manifestView.setText(emulator->manifest()); + manifestView.setText(emulator->manifests().merge("\n")); verifiedIcon.setIcon(program->verified() ? Icon::Emblem::Program : Icon::Emblem::Binary); verifiedLabel.setText(program->verified() ? "Verified" : "Unverified"); } diff --git a/higan/target-higan/GNUmakefile b/higan/target-higan/GNUmakefile index c2e656b3..851cdd62 100644 --- a/higan/target-higan/GNUmakefile +++ b/higan/target-higan/GNUmakefile @@ -1,15 +1,4 @@ name := higan -flags += -DSFC_SUPERGAMEBOY - -include fc/GNUmakefile -include sfc/GNUmakefile -#include ms/GNUmakefile -include md/GNUmakefile -#include pce/GNUmakefile -include gb/GNUmakefile -include gba/GNUmakefile -#include ws/GNUmakefile -include processor/GNUmakefile hiro.path := ../hiro hiro.resource := $(ui)/resource/higan.rc diff --git a/higan/target-higan/higan.cpp b/higan/target-higan/higan.cpp index 67c4dcc3..4d3d67d4 100644 --- a/higan/target-higan/higan.cpp +++ b/higan/target-higan/higan.cpp @@ -13,9 +13,9 @@ auto locate(string name) -> string { } #include -auto nall::main(string_vector args) -> void { +auto nall::main(vector arguments) -> void { Application::setName("higan"); Application::setScreenSaver(false); - new Program(args); + new Program(arguments); Application::run(); } diff --git a/higan/target-higan/presentation/presentation.cpp b/higan/target-higan/presentation/presentation.cpp index 43704ce5..abe7c1b0 100644 --- a/higan/target-higan/presentation/presentation.cpp +++ b/higan/target-higan/presentation/presentation.cpp @@ -286,7 +286,7 @@ auto Presentation::resizeViewport(bool resizeWindow) -> void { double emulatorHeight = 240; double aspectCorrection = 1.0; if(emulator) { - auto display = emulator->display(); + auto display = emulator->displays()[0]; emulatorWidth = display.width; emulatorHeight = display.height; aspectCorrection = display.aspectCorrection; diff --git a/higan/target-higan/program/game.cpp b/higan/target-higan/program/game.cpp index 70236046..12510f8e 100644 --- a/higan/target-higan/program/game.cpp +++ b/higan/target-higan/program/game.cpp @@ -33,7 +33,7 @@ auto Program::load(Emulator::Interface& interface) -> void { updateAudioEffects(); presentation->resizeViewport(); - presentation->setTitle(emulator->title()); + presentation->setTitle(emulator->titles().merge(" + ")); presentation->systemMenu.setText(information.name).setVisible(true); presentation->toolsMenu.setVisible(true); toolsManager->cheatEditor.loadCheats(); diff --git a/higan/target-higan/program/platform.cpp b/higan/target-higan/program/platform.cpp index 7e75b15d..2dea3cd2 100644 --- a/higan/target-higan/program/platform.cpp +++ b/higan/target-higan/program/platform.cpp @@ -23,7 +23,7 @@ auto Program::open(uint id, string name, vfs::file::mode mode, bool required) -> return {}; } -auto Program::load(uint id, string name, string type, string_vector options) -> Emulator::Platform::Load { +auto Program::load(uint id, string name, string type, vector options) -> Emulator::Platform::Load { string location, option; if(gameQueue) { auto entry = gameQueue.takeLeft().split("|", 1L); @@ -50,13 +50,13 @@ auto Program::load(uint id, string name, string type, string_vector options) -> return {pathID, option}; } -auto Program::videoRefresh(const uint32* data, uint pitch, uint width, uint height) -> void { +auto Program::videoRefresh(uint displayID, const uint32* data, uint pitch, uint width, uint height) -> void { uint32_t* output; uint length; pitch >>= 2; - auto display = emulator->display(); + auto display = emulator->displays()[displayID]; if(display.type == Emulator::Interface::Display::Type::CRT) { uint overscanHorizontal = settings["Video/Overscan/Horizontal"].natural(); uint overscanVertical = settings["Video/Overscan/Vertical"].natural(); diff --git a/higan/target-higan/program/program.cpp b/higan/target-higan/program/program.cpp index 46687087..f27b3025 100644 --- a/higan/target-higan/program/program.cpp +++ b/higan/target-higan/program/program.cpp @@ -1,35 +1,62 @@ #include "../higan.hpp" #include #include -//#include +#include #include -//#include +#include #include #include -//#include +#include #include "platform.cpp" #include "game.cpp" #include "state.cpp" #include "utility.cpp" unique_pointer program; -Program::Program(string_vector args) { +Program::Program(vector arguments) { program = this; Emulator::platform = this; + +#ifdef CORE_FC emulators.append(new Famicom::Interface); +#endif +#ifdef CORE_SFC emulators.append(new SuperFamicom::Interface); -// emulators.append(new MasterSystem::MasterSystemInterface); +#endif +#ifdef CORE_MS + emulators.append(new MasterSystem::MasterSystemInterface); +#endif +#ifdef CORE_MD emulators.append(new MegaDrive::Interface); -// emulators.append(new PCEngine::PCEngineInterface); -// emulators.append(new PCEngine::SuperGrafxInterface); +#endif +#ifdef CORE_PCE + emulators.append(new PCEngine::PCEngineInterface); +#endif +#ifdef CORE_PCE + emulators.append(new PCEngine::SuperGrafxInterface); +#endif +#ifdef CORE_GB emulators.append(new GameBoy::GameBoyInterface); +#endif +#ifdef CORE_GB emulators.append(new GameBoy::GameBoyColorInterface); +#endif +#ifdef CORE_GBA emulators.append(new GameBoyAdvance::Interface); -// emulators.append(new MasterSystem::GameGearInterface); -// emulators.append(new WonderSwan::WonderSwanInterface); -// emulators.append(new WonderSwan::WonderSwanColorInterface); -// emulators.append(new WonderSwan::PocketChallengeV2Interface); +#endif +#ifdef CORE_MS + emulators.append(new MasterSystem::GameGearInterface); +#endif +#ifdef CORE_WS + emulators.append(new WonderSwan::WonderSwanInterface); +#endif +#ifdef CORE_WS + emulators.append(new WonderSwan::WonderSwanColorInterface); +#endif +#ifdef CORE_WS + emulators.append(new WonderSwan::PocketChallengeV2Interface); +#endif new Presentation; presentation->setVisible(); @@ -62,8 +89,8 @@ Program::Program(string_vector args) { updateAudioDriver(); updateAudioEffects(); - args.takeLeft(); //ignore program location in argument parsing - for(auto& argument : args) { + arguments.takeLeft(); //ignore program location in argument parsing + for(auto& argument : arguments) { if(argument == "--fullscreen") { presentation->toggleFullScreen(); } else if(directory::exists(argument.split("|", 1L).right())) { @@ -113,5 +140,5 @@ auto Program::quit() -> void { video.reset(); audio.reset(); input.reset(); - Application::quit(); + Application::kill(); } diff --git a/higan/target-higan/program/program.hpp b/higan/target-higan/program/program.hpp index 224e4c50..42032e49 100644 --- a/higan/target-higan/program/program.hpp +++ b/higan/target-higan/program/program.hpp @@ -1,14 +1,14 @@ struct Program : Emulator::Platform { //program.cpp - Program(string_vector args); + Program(vector arguments); auto main() -> void; auto quit() -> void; //platform.cpp auto path(uint id) -> string override; auto open(uint id, string name, vfs::file::mode mode, bool required) -> vfs::shared::file override; - auto load(uint id, string name, string type, string_vector options = {}) -> Emulator::Platform::Load override; - auto videoRefresh(const uint32* data, uint pitch, uint width, uint height) -> void override; + auto load(uint id, string name, string type, vector options = {}) -> Emulator::Platform::Load override; + auto videoRefresh(uint display, const uint32* data, uint pitch, uint width, uint height) -> void override; auto audioSample(const double* samples, uint channels) -> void override; auto inputPoll(uint port, uint device, uint input) -> int16 override; auto inputRumble(uint port, uint device, uint input, bool enable) -> void override; diff --git a/higan/target-higan/tools/cheat-database.cpp b/higan/target-higan/tools/cheat-database.cpp index 8e240eba..559a41bf 100644 --- a/higan/target-higan/tools/cheat-database.cpp +++ b/higan/target-higan/tools/cheat-database.cpp @@ -17,7 +17,7 @@ CheatDatabase::CheatDatabase() { auto CheatDatabase::findCodes() -> void { if(!emulator) return; - auto sha256 = emulator->sha256(); + auto sha256 = emulator->hashes().left(); auto contents = string::read(locate("cheats.bml")); auto document = BML::unserialize(contents); diff --git a/higan/target-higan/tools/cheat-editor.cpp b/higan/target-higan/tools/cheat-editor.cpp index 95fddd6c..d9ca1499 100644 --- a/higan/target-higan/tools/cheat-editor.cpp +++ b/higan/target-higan/tools/cheat-editor.cpp @@ -100,13 +100,13 @@ auto CheatEditor::doErase() -> void { auto CheatEditor::synchronizeCodes() -> void { if(!emulator) return; - string_vector codes; + vector codes; for(auto& cheat : cheats) { if(!cheat.enabled || !cheat.code) continue; codes.append(cheat.code); } - emulator->cheatSet(codes); + emulator->cheats(codes); } //returns true if code was added @@ -136,7 +136,7 @@ auto CheatEditor::loadCheats() -> void { auto CheatEditor::saveCheats() -> void { if(!emulator) return; - string document = {"cartridge sha256:", emulator->sha256(), "\n"}; + string document = {"cartridge sha256:", emulator->hashes().left(), "\n"}; uint count = 0; for(auto& cheat : cheats) { if(!cheat.code && !cheat.description) continue; diff --git a/higan/target-higan/tools/manifest-viewer.cpp b/higan/target-higan/tools/manifest-viewer.cpp index 0e1af963..58984e4b 100644 --- a/higan/target-higan/tools/manifest-viewer.cpp +++ b/higan/target-higan/tools/manifest-viewer.cpp @@ -8,5 +8,5 @@ ManifestViewer::ManifestViewer(TabFrame* parent) : TabFrameItem(parent) { auto ManifestViewer::doRefresh() -> void { manifestView.setText(""); - if(emulator) manifestView.setText(emulator->manifest()); + if(emulator) manifestView.setText(emulator->manifests().merge("\n")); } diff --git a/higan/video/video.cpp b/higan/video/video.cpp index 84a07de3..323afac8 100644 --- a/higan/video/video.cpp +++ b/higan/video/video.cpp @@ -30,7 +30,7 @@ auto Video::setPalette() -> void { if(!interface) return; delete palette; - colors = interface->display().colors; + colors = interface->displays()[0].colors; palette = new uint32[colors]; for(auto index : range(colors)) { uint64 color = interface->color(index); @@ -178,7 +178,7 @@ auto Video::refresh(uint32* input, uint pitch, uint width, uint height) -> void } } - platform->videoRefresh(output, width * sizeof(uint32), width, height); + platform->videoRefresh(0, output, width * sizeof(uint32), width, height); } } diff --git a/higan/ws/apu/apu.cpp b/higan/ws/apu/apu.cpp index 322a1f5a..f7285061 100644 --- a/higan/ws/apu/apu.cpp +++ b/higan/ws/apu/apu.cpp @@ -32,6 +32,7 @@ auto APU::sample(uint channel, uint5 index) -> uint4 { uint8 data = iram.read((r.waveBase << 6) + (--channel << 4) + (index >> 1)); if(index.bit(0) == 0) return data.bits(0,3); if(index.bit(0) == 1) return data.bits(4,7); + unreachable; } auto APU::dacRun() -> void { diff --git a/higan/ws/cartridge/cartridge.cpp b/higan/ws/cartridge/cartridge.cpp index 4777ee97..2300409b 100644 --- a/higan/ws/cartridge/cartridge.cpp +++ b/higan/ws/cartridge/cartridge.cpp @@ -41,19 +41,19 @@ auto Cartridge::load() -> bool { if(Model::WonderSwan()) { if(auto loaded = platform->load(ID::WonderSwan, "WonderSwan", "ws")) { - information.pathID = loaded.pathID(); + information.pathID = loaded.pathID; } else return false; } if(Model::WonderSwanColor() || Model::SwanCrystal()) { if(auto loaded = platform->load(ID::WonderSwanColor, "WonderSwan Color", "wsc")) { - information.pathID = loaded.pathID(); + information.pathID = loaded.pathID; } else return false; } if(Model::PocketChallengeV2()) { if(auto loaded = platform->load(ID::PocketChallengeV2, "Pocket Challenge V2", "pc2")) { - information.pathID = loaded.pathID(); + information.pathID = loaded.pathID; } else return false; } diff --git a/higan/ws/cartridge/cartridge.hpp b/higan/ws/cartridge/cartridge.hpp index 35d0b3f7..8d273ef6 100644 --- a/higan/ws/cartridge/cartridge.hpp +++ b/higan/ws/cartridge/cartridge.hpp @@ -1,5 +1,8 @@ struct Cartridge : Thread, IO { auto pathID() const -> uint { return information.pathID; } + auto hash() const -> string { return information.sha256; } + auto manifest() const -> string { return information.manifest; } + auto title() const -> string { return information.title; } static auto Enter() -> void; auto main() -> void; diff --git a/higan/ws/interface/interface.cpp b/higan/ws/interface/interface.cpp index c57a1b39..abb35834 100644 --- a/higan/ws/interface/interface.cpp +++ b/higan/ws/interface/interface.cpp @@ -7,56 +7,93 @@ Settings settings; #include "wonderswan-color.cpp" #include "pocket-challenge-v2.cpp" -Interface::Interface() { - Port hardwarePort{ID::Port::Hardware, "Hardware"}; - - { Device device{ID::Device::Controls, "Controls"}; - device.inputs.append({0, "Y1"}); - device.inputs.append({0, "Y2"}); - device.inputs.append({0, "Y3"}); - device.inputs.append({0, "Y4"}); - device.inputs.append({0, "X1"}); - device.inputs.append({0, "X2"}); - device.inputs.append({0, "X3"}); - device.inputs.append({0, "X4"}); - device.inputs.append({0, "B"}); - device.inputs.append({0, "A"}); - device.inputs.append({0, "Start"}); - hardwarePort.devices.append(device); - } - - ports.append(move(hardwarePort)); -} - -auto Interface::manifest() -> string { - return cartridge.information.manifest; -} - -auto Interface::title() -> string { - return cartridge.information.title; -} - -auto Interface::videoInformation() -> VideoInformation { - VideoInformation vi; - vi.width = 224; - vi.height = 144; - vi.internalWidth = 224; - vi.internalHeight = 144; - vi.aspectCorrection = 1.0; - vi.refreshRate = 3'072'000.0 / (159.0 * 256.0); +auto Interface::displays() -> vector { + Display display; + display.type = Display::Type::LCD; + display.colors = 1 << 12; + display.width = 224; + display.height = 144; + display.internalWidth = 224; + display.internalHeight = 144; + display.aspectCorrection = 1.0; + display.refreshRate = 3'072'000.0 / (159.0 * 256.0); if(settings.rotateLeft) { - swap(vi.width, vi.height); - swap(vi.internalWidth, vi.internalHeight); + swap(display.width, display.height); + swap(display.internalWidth, display.internalHeight); } - return vi; + return {display}; +} + +//todo: the WonderSwan and PocketChallengeV2 interfaces should be generating grayscale shades +//instead, the PPU is currently selecting grayscale shades from the WonderSwanColor palette + +auto Interface::color(uint32 color) -> uint64 { + uint b = color.bits(0, 3); + uint g = color.bits(4, 7); + uint r = color.bits(8,11); + + uint64_t R = image::normalize(r, 4, 16); + uint64_t G = image::normalize(g, 4, 16); + uint64_t B = image::normalize(b, 4, 16); + + if(settings.colorEmulation) { + R = (r * 26 + g * 4 + b * 2); + G = ( g * 24 + b * 8); + B = (r * 6 + g * 4 + b * 22); + R = image::normalize(min(480, R), 9, 16); + G = image::normalize(min(480, G), 9, 16); + B = image::normalize(min(480, B), 9, 16); + } + + return R << 32 | G << 16 | B << 0; +} + +auto Interface::ports() -> vector { return { + {ID::Port::Hardware, "Hardware"}}; +} + +auto Interface::devices(uint port) -> vector { + if(port == ID::Port::Hardware) return { + {ID::Device::Controls, "Controls"} + }; + + return {}; +} + +auto Interface::inputs(uint device) -> vector { + using Type = Input::Type; + + if(device == ID::Device::Controls) return { + {Type::Hat, "Y1" }, + {Type::Hat, "Y2" }, + {Type::Hat, "Y3" }, + {Type::Hat, "Y4" }, + {Type::Hat, "X1" }, + {Type::Hat, "X2" }, + {Type::Hat, "X3" }, + {Type::Hat, "X4" }, + {Type::Button, "B" }, + {Type::Button, "A" }, + {Type::Control, "Start"} + }; + + return {}; } auto Interface::loaded() -> bool { return system.loaded(); } -auto Interface::sha256() -> string { - return cartridge.information.sha256; +auto Interface::hashes() -> vector { + return {cartridge.hash()}; +} + +auto Interface::manifests() -> vector { + return {cartridge.manifest()}; +} + +auto Interface::titles() -> vector { + return {cartridge.title()}; } auto Interface::save() -> void { @@ -85,7 +122,7 @@ auto Interface::unserialize(serializer& s) -> bool { return system.unserialize(s); } -auto Interface::cheatSet(const string_vector& list) -> void { +auto Interface::cheats(const vector& list) -> void { cheat.assign(list); } diff --git a/higan/ws/interface/interface.hpp b/higan/ws/interface/interface.hpp index 079a6b24..aa467858 100644 --- a/higan/ws/interface/interface.hpp +++ b/higan/ws/interface/interface.hpp @@ -1,3 +1,5 @@ +#if defined(CORE_WS) + namespace WonderSwan { struct ID { @@ -18,15 +20,17 @@ struct ID { }; struct Interface : Emulator::Interface { - Interface(); + auto displays() -> vector override; + auto color(uint32 color) -> uint64 override; - auto manifest() -> string override; - auto title() -> string override; - - auto videoInformation() -> VideoInformation override; + auto ports() -> vector override; + auto devices(uint ports) -> vector override; + auto inputs(uint devices) -> vector override; auto loaded() -> bool override; - auto sha256() -> string override; + auto hashes() -> vector override; + auto manifests() -> vector override; + auto titles() -> vector override; auto save() -> void override; auto unload() -> void override; @@ -36,7 +40,7 @@ struct Interface : Emulator::Interface { auto serialize() -> serializer override; auto unserialize(serializer&) -> bool override; - auto cheatSet(const string_vector&) -> void override; + auto cheats(const vector& list) -> void override; auto cap(const string& name) -> bool override; auto get(const string& name) -> any override; @@ -44,36 +48,21 @@ struct Interface : Emulator::Interface { }; struct WonderSwanInterface : Interface { - using Emulator::Interface::load; + auto information() -> Information override; - WonderSwanInterface(); - - auto videoColors() -> uint32 override; - auto videoColor(uint32 color) -> uint64 override; - - auto load(uint id) -> bool override; + auto load() -> bool override; }; struct WonderSwanColorInterface : Interface { - using Emulator::Interface::load; + auto information() -> Information override; - WonderSwanColorInterface(); - - auto videoColors() -> uint32 override; - auto videoColor(uint32 color) -> uint64 override; - - auto load(uint id) -> bool override; + auto load() -> bool override; }; struct PocketChallengeV2Interface : Interface { - using Emulator::Interface::load; + auto information() -> Information override; - PocketChallengeV2Interface(); - - auto videoColors() -> uint32 override; - auto videoColor(uint32 color) -> uint64 override; - - auto load(uint id) -> bool override; + auto load() -> bool override; }; struct Settings { @@ -85,3 +74,5 @@ struct Settings { extern Settings settings; } + +#endif diff --git a/higan/ws/interface/pocket-challenge-v2.cpp b/higan/ws/interface/pocket-challenge-v2.cpp index 5be62257..ce882aff 100644 --- a/higan/ws/interface/pocket-challenge-v2.cpp +++ b/higan/ws/interface/pocket-challenge-v2.cpp @@ -1,40 +1,11 @@ -PocketChallengeV2Interface::PocketChallengeV2Interface() { +auto PocketChallengeV2Interface::information() -> Information { + Information information; information.manufacturer = "Benesse"; information.name = "Pocket Challenge V2"; - information.overscan = false; - - media.append({ID::PocketChallengeV2, "Pocket Challenge V2", "pc2"}); + information.extension = "pc2"; + return information; } -//todo: this should be generating grayscale colors -//instead, the PPU is selecting grayscale colors from the color palette - -auto PocketChallengeV2Interface::videoColors() -> uint32 { - return 1 << 12; -} - -auto PocketChallengeV2Interface::videoColor(uint32 color) -> uint64 { - uint b = color.bits(0, 3); - uint g = color.bits(4, 7); - uint r = color.bits(8,11); - - uint64_t R = image::normalize(r, 4, 16); - uint64_t G = image::normalize(g, 4, 16); - uint64_t B = image::normalize(b, 4, 16); - - if(settings.colorEmulation) { - R = (r * 26 + g * 4 + b * 2); - G = ( g * 24 + b * 8); - B = (r * 6 + g * 4 + b * 22); - R = image::normalize(min(480, R), 9, 16); - G = image::normalize(min(480, G), 9, 16); - B = image::normalize(min(480, B), 9, 16); - } - - return R << 32 | G << 16 | B << 0; -} - -auto PocketChallengeV2Interface::load(uint id) -> bool { - if(id == ID::PocketChallengeV2) return system.load(this, System::Model::PocketChallengeV2); - return false; +auto PocketChallengeV2Interface::load() -> bool { + return system.load(this, System::Model::PocketChallengeV2); } diff --git a/higan/ws/interface/wonderswan-color.cpp b/higan/ws/interface/wonderswan-color.cpp index 1197fbc4..9e75fc60 100644 --- a/higan/ws/interface/wonderswan-color.cpp +++ b/higan/ws/interface/wonderswan-color.cpp @@ -1,37 +1,11 @@ -WonderSwanColorInterface::WonderSwanColorInterface() { +auto WonderSwanColorInterface::information() -> Information { + Information information; information.manufacturer = "Bandai"; information.name = "WonderSwan Color"; - information.overscan = false; - - media.append({ID::WonderSwanColor, "WonderSwan Color", "wsc"}); + information.extension = "wsc"; + return information; } -auto WonderSwanColorInterface::videoColors() -> uint32 { - return 1 << 12; -} - -auto WonderSwanColorInterface::videoColor(uint32 color) -> uint64 { - uint b = color.bits(0, 3); - uint g = color.bits(4, 7); - uint r = color.bits(8,11); - - uint64_t R = image::normalize(r, 4, 16); - uint64_t G = image::normalize(g, 4, 16); - uint64_t B = image::normalize(b, 4, 16); - - if(settings.colorEmulation) { - R = (r * 26 + g * 4 + b * 2); - G = ( g * 24 + b * 8); - B = (r * 6 + g * 4 + b * 22); - R = image::normalize(min(480, R), 9, 16); - G = image::normalize(min(480, G), 9, 16); - B = image::normalize(min(480, B), 9, 16); - } - - return R << 32 | G << 16 | B << 0; -} - -auto WonderSwanColorInterface::load(uint id) -> bool { - if(id == ID::WonderSwanColor) return system.load(this, System::Model::WonderSwanColor); - return false; +auto WonderSwanColorInterface::load() -> bool { + return system.load(this, System::Model::WonderSwanColor); } diff --git a/higan/ws/interface/wonderswan.cpp b/higan/ws/interface/wonderswan.cpp index 90426109..1f326109 100644 --- a/higan/ws/interface/wonderswan.cpp +++ b/higan/ws/interface/wonderswan.cpp @@ -1,40 +1,11 @@ -WonderSwanInterface::WonderSwanInterface() { +auto WonderSwanInterface::information() -> Information { + Information information; information.manufacturer = "Bandai"; information.name = "WonderSwan"; - information.overscan = false; - - media.append({ID::WonderSwan, "WonderSwan", "ws"}); + information.extension = "ws"; + return information; } -//todo: this should be generating grayscale colors -//instead, the PPU is selecting grayscale colors from the color palette - -auto WonderSwanInterface::videoColors() -> uint32 { - return 1 << 12; -} - -auto WonderSwanInterface::videoColor(uint32 color) -> uint64 { - uint b = color.bits(0, 3); - uint g = color.bits(4, 7); - uint r = color.bits(8,11); - - uint64_t R = image::normalize(r, 4, 16); - uint64_t G = image::normalize(g, 4, 16); - uint64_t B = image::normalize(b, 4, 16); - - if(settings.colorEmulation) { - R = (r * 26 + g * 4 + b * 2); - G = ( g * 24 + b * 8); - B = (r * 6 + g * 4 + b * 22); - R = image::normalize(min(480, R), 9, 16); - G = image::normalize(min(480, G), 9, 16); - B = image::normalize(min(480, B), 9, 16); - } - - return R << 32 | G << 16 | B << 0; -} - -auto WonderSwanInterface::load(uint id) -> bool { - if(id == ID::WonderSwan) return system.load(this, System::Model::WonderSwan); - return false; +auto WonderSwanInterface::load() -> bool { + return system.load(this, System::Model::WonderSwan); } diff --git a/higan/ws/system/io.cpp b/higan/ws/system/io.cpp index af4c2680..f2d0cc0e 100644 --- a/higan/ws/system/io.cpp +++ b/higan/ws/system/io.cpp @@ -17,6 +17,8 @@ auto System::portRead(uint16 addr) -> uint8 { //IEEP_CMD if(addr == 0x00be) return eeprom.read(EEPROM::Status); + + return 0x00; } auto System::portWrite(uint16 addr, uint8 data) -> void { diff --git a/higan/ws/system/serialization.cpp b/higan/ws/system/serialization.cpp index 2b56a245..a7c744b9 100644 --- a/higan/ws/system/serialization.cpp +++ b/higan/ws/system/serialization.cpp @@ -3,12 +3,10 @@ auto System::serializeInit() -> void { uint signature = 0; char version[16] = {0}; - char hash[64] = {0}; char description[512] = {0}; s.integer(signature); s.array(version); - s.array(hash); s.array(description); serializeAll(s); @@ -20,14 +18,11 @@ auto System::serialize() -> serializer { uint signature = 0x31545342; char version[16] = {0}; - char hash[64] = {0}; char description[512] = {0}; memory::copy(&version, (const char*)Emulator::SerializerVersion, Emulator::SerializerVersion.size()); - memory::copy(&hash, (const char*)cartridge.information.sha256, 64); s.integer(signature); s.array(version); - s.array(hash); s.array(description); serializeAll(s); @@ -37,12 +32,10 @@ auto System::serialize() -> serializer { auto System::unserialize(serializer& s) -> bool { uint signature = 0; char version[16] = {0}; - char hash[64] = {0}; char description[512] = {0}; s.integer(signature); s.array(version); - s.array(hash); s.array(description); if(signature != 0x31545342) return false; diff --git a/hiro/core/application.cpp b/hiro/core/application.cpp index 039b56c2..db79ff5f 100644 --- a/hiro/core/application.cpp +++ b/hiro/core/application.cpp @@ -10,6 +10,11 @@ auto Application::font() -> Font { return state.font; } +auto Application::kill() -> void { + quit(); + exit(EXIT_SUCCESS); +} + auto Application::locale() -> Locale& { return state.locale; } diff --git a/hiro/core/application.hpp b/hiro/core/application.hpp index bc626c41..ff1ecea9 100644 --- a/hiro/core/application.hpp +++ b/hiro/core/application.hpp @@ -4,6 +4,7 @@ struct Application { static auto doMain() -> void; static auto font() -> Font; + static auto kill() -> void; static auto locale() -> Locale&; static auto modal() -> bool; static auto name() -> string; diff --git a/hiro/core/browser-window.cpp b/hiro/core/browser-window.cpp index a774126e..dc3c49e9 100644 --- a/hiro/core/browser-window.cpp +++ b/hiro/core/browser-window.cpp @@ -12,7 +12,7 @@ auto BrowserWindow::save() -> string { return pBrowserWindow::save(state); } -auto BrowserWindow::setFilters(const string_vector& filters) -> type& { +auto BrowserWindow::setFilters(const vector& filters) -> type& { state.filters = filters; return *this; } diff --git a/hiro/core/core.hpp b/hiro/core/core.hpp index 0e404fbd..3921f5f1 100644 --- a/hiro/core/core.hpp +++ b/hiro/core/core.hpp @@ -25,7 +25,6 @@ using nall::set; using nall::shared_pointer; using nall::shared_pointer_weak; using nall::string; -using nall::string_vector; using nall::vector; namespace hiro { @@ -427,14 +426,14 @@ struct BrowserWindow { auto directory() -> string; auto open() -> string; auto save() -> string; - auto setFilters(const string_vector& filters = {"*"}) -> type&; + auto setFilters(const vector& filters = {"*"}) -> type&; auto setParent(sWindow parent) -> type&; auto setPath(const string& path = "") -> type&; auto setTitle(const string& title = "") -> type&; //private: struct State { - string_vector filters; + vector filters; sWindow parent; string path; string title; @@ -619,7 +618,7 @@ struct mWindow : mObject { auto backgroundColor() const -> Color; auto dismissable() const -> bool; auto doClose() const -> void; - auto doDrop(string_vector) const -> void; + auto doDrop(vector) const -> void; auto doKeyPress(int) const -> void; auto doKeyRelease(int) const -> void; auto doMove() const -> void; @@ -635,7 +634,7 @@ struct mWindow : mObject { auto minimumSize() const -> Size; auto modal() const -> bool; auto onClose(const function& callback = {}) -> type&; - auto onDrop(const function& callback = {}) -> type&; + auto onDrop(const function)>& callback = {}) -> type&; auto onKeyPress(const function& callback = {}) -> type&; auto onKeyRelease(const function& callback = {}) -> type&; auto onMove(const function& callback = {}) -> type&; @@ -683,7 +682,7 @@ struct mWindow : mObject { sMenuBar menuBar; bool modal = false; function onClose; - function onDrop; + function)> onDrop; function onKeyPress; function onKeyRelease; function onMove; @@ -934,14 +933,14 @@ struct mCanvas : mWidget { auto color() const -> Color; auto data() -> uint32_t*; auto droppable() const -> bool; - auto doDrop(string_vector names) const -> void; + auto doDrop(vector names) const -> void; auto doMouseLeave() const -> void; auto doMouseMove(Position position) const -> void; auto doMousePress(Mouse::Button button) const -> void; auto doMouseRelease(Mouse::Button button) const -> void; auto gradient() const -> Gradient; auto icon() const -> image; - auto onDrop(const function& callback = {}) -> type&; + auto onDrop(const function)>& callback = {}) -> type&; auto onMouseLeave(const function& callback = {}) -> type&; auto onMouseMove(const function& callback = {}) -> type&; auto onMousePress(const function& callback = {}) -> type&; @@ -960,7 +959,7 @@ struct mCanvas : mWidget { bool droppable = false; Gradient gradient; image icon; - function onDrop; + function)> onDrop; function onMouseLeave; function onMouseMove; function onMousePress; @@ -1908,14 +1907,14 @@ struct mVerticalSlider : mWidget { struct mViewport : mWidget { Declare(Viewport) - auto doDrop(string_vector names) const -> void; + auto doDrop(vector names) const -> void; auto doMouseLeave() const -> void; auto doMouseMove(Position position) const -> void; auto doMousePress(Mouse::Button button) const -> void; auto doMouseRelease(Mouse::Button button) const -> void; auto droppable() const -> bool; auto handle() const -> uintptr_t; - auto onDrop(const function& callback = {}) -> type&; + auto onDrop(const function)>& callback = {}) -> type&; auto onMouseLeave(const function& callback = {}) -> type&; auto onMouseMove(const function& callback = {}) -> type&; auto onMousePress(const function& callback = {}) -> type&; @@ -1925,7 +1924,7 @@ struct mViewport : mWidget { //private: struct State { bool droppable = false; - function onDrop; + function)> onDrop; function onMouseLeave; function onMouseMove; function onMousePress; diff --git a/hiro/core/shared.hpp b/hiro/core/shared.hpp index 04fc1909..1940b2f0 100644 --- a/hiro/core/shared.hpp +++ b/hiro/core/shared.hpp @@ -217,14 +217,14 @@ struct Canvas : sCanvas { auto color() const { return self().color(); } auto data() { return self().data(); } auto droppable() const { return self().droppable(); } - auto doDrop(string_vector names) { return self().doDrop(names); } + auto doDrop(vector names) { return self().doDrop(names); } auto doMouseLeave() const { return self().doMouseLeave(); } auto doMouseMove(Position position) const { return self().doMouseMove(position); } auto doMousePress(Mouse::Button button) const { return self().doMousePress(button); } auto doMouseRelease(Mouse::Button button) const { return self().doMouseRelease(button); } auto gradient() const { return self().gradient(); } auto icon() const { return self().icon(); } - auto onDrop(const function& callback = {}) { return self().onDrop(callback), *this; } + auto onDrop(const function)>& callback = {}) { return self().onDrop(callback), *this; } auto onMouseLeave(const function& callback = {}) { return self().onMouseLeave(callback), *this; } auto onMouseMove(const function& callback = {}) { return self().onMouseMove(callback), *this; } auto onMousePress(const function& callback = {}) { return self().onMousePress(callback), *this; } @@ -864,14 +864,14 @@ struct Viewport : sViewport { DeclareSharedWidget(Viewport) using internalType = mViewport; - auto doDrop(string_vector names) const { return self().doDrop(names); } + auto doDrop(vector names) const { return self().doDrop(names); } auto doMouseLeave() const { return self().doMouseLeave(); } auto doMouseMove(Position position) const { return self().doMouseMove(position); } auto doMousePress(Mouse::Button button) const { return self().doMousePress(button); } auto doMouseRelease(Mouse::Button button) const { return self().doMouseRelease(button); } auto droppable() const { return self().droppable(); } auto handle() const { return self().handle(); } - auto onDrop(const function& callback = {}) { return self().onDrop(callback), *this; } + auto onDrop(const function)>& callback = {}) { return self().onDrop(callback), *this; } auto onMouseLeave(const function& callback = {}) { return self().onMouseLeave(callback), *this; } auto onMouseMove(const function& callback = {}) { return self().onMouseMove(callback), *this; } auto onMousePress(const function& callback = {}) { return self().onMousePress(callback), *this; } @@ -929,7 +929,7 @@ struct Window : sWindow { auto backgroundColor() const { return self().backgroundColor(); } auto dismissable() const { return self().dismissable(); } auto doClose() const { return self().doClose(); } - auto doDrop(string_vector names) const { return self().doDrop(names); } + auto doDrop(vector names) const { return self().doDrop(names); } auto doKeyPress(signed key) const { return self().doKeyPress(key); } auto doKeyRelease(signed key) const { return self().doKeyRelease(key); } auto doMove() const { return self().doMove(); } @@ -945,7 +945,7 @@ struct Window : sWindow { auto minimumSize() const { return self().minimumSize(); } auto modal() const { return self().modal(); } auto onClose(const function& callback = {}) { return self().onClose(callback), *this; } - auto onDrop(const function& callback = {}) { return self().onDrop(callback), *this; } + auto onDrop(const function)>& callback = {}) { return self().onDrop(callback), *this; } auto onKeyPress(const function& callback = {}) { return self().onKeyPress(callback), *this; } auto onKeyRelease(const function& callback = {}) { return self().onKeyRelease(callback), *this; } auto onMove(const function& callback = {}) { return self().onMove(callback), *this; } diff --git a/hiro/core/widget/canvas.cpp b/hiro/core/widget/canvas.cpp index 4b82d654..bbde8dd9 100644 --- a/hiro/core/widget/canvas.cpp +++ b/hiro/core/widget/canvas.cpp @@ -18,7 +18,7 @@ auto mCanvas::droppable() const -> bool { return state.droppable; } -auto mCanvas::doDrop(string_vector names) const -> void { +auto mCanvas::doDrop(vector names) const -> void { if(state.onDrop) return state.onDrop(names); } @@ -46,7 +46,7 @@ auto mCanvas::icon() const -> image { return state.icon; } -auto mCanvas::onDrop(const function& callback) -> type& { +auto mCanvas::onDrop(const function)>& callback) -> type& { state.onDrop = callback; return *this; } diff --git a/hiro/core/widget/tree-view-item.cpp b/hiro/core/widget/tree-view-item.cpp index c3e9ea8c..94c742f1 100644 --- a/hiro/core/widget/tree-view-item.cpp +++ b/hiro/core/widget/tree-view-item.cpp @@ -147,6 +147,7 @@ auto mTreeViewItem::setParent(mObject* parent, signed offset) -> type& { for(auto& item : reverse(state.items)) item->destruct(); mObject::setParent(parent, offset); for(auto& item : state.items) item->setParent(this, item->offset()); + return *this; } auto mTreeViewItem::setSelected() -> type& { diff --git a/hiro/core/widget/viewport.cpp b/hiro/core/widget/viewport.cpp index 2faa881a..03ad19ae 100644 --- a/hiro/core/widget/viewport.cpp +++ b/hiro/core/widget/viewport.cpp @@ -6,7 +6,7 @@ auto mViewport::allocate() -> pObject* { // -auto mViewport::doDrop(string_vector names) const -> void { +auto mViewport::doDrop(vector names) const -> void { if(state.onDrop) return state.onDrop(names); } @@ -34,7 +34,7 @@ auto mViewport::handle() const -> uintptr_t { return signal(handle); } -auto mViewport::onDrop(const function& callback) -> type& { +auto mViewport::onDrop(const function)>& callback) -> type& { state.onDrop = callback; return *this; } diff --git a/hiro/core/window.cpp b/hiro/core/window.cpp index 9c5f1a78..745f7c93 100644 --- a/hiro/core/window.cpp +++ b/hiro/core/window.cpp @@ -53,7 +53,7 @@ auto mWindow::doClose() const -> void { if(state.onClose) return state.onClose(); } -auto mWindow::doDrop(string_vector names) const -> void { +auto mWindow::doDrop(vector names) const -> void { if(state.onDrop) return state.onDrop(names); } @@ -122,7 +122,7 @@ auto mWindow::onClose(const function& callback) -> type& { return *this; } -auto mWindow::onDrop(const function& callback) -> type& { +auto mWindow::onDrop(const function)>& callback) -> type& { state.onDrop = callback; return *this; } @@ -282,13 +282,13 @@ auto mWindow::setMinimumSize(Size size) -> type& { auto mWindow::setModal(bool modal) -> type& { state.modal = modal; - signal(setModal, modal); if(modal) { Application::state.modal++; } else { Application::state.modal--; assert(Application::state.modal >= 0); } + signal(setModal, modal); return *this; } diff --git a/hiro/extension/browser-dialog.cpp b/hiro/extension/browser-dialog.cpp index adc0cd47..94082d61 100644 --- a/hiro/extension/browser-dialog.cpp +++ b/hiro/extension/browser-dialog.cpp @@ -30,7 +30,7 @@ private: BrowserDialog::State& state; BrowserDialog::Response response; - vector filters; + vector> filters; }; //accept button clicked, or enter pressed on file name line edit @@ -248,7 +248,7 @@ auto BrowserDialog::openFile() -> string { return {}; } -auto BrowserDialog::openFiles() -> string_vector { +auto BrowserDialog::openFiles() -> vector { state.action = "openFiles"; if(!state.title) state.title = "Open Files"; if(auto result = _run()) return result; @@ -280,7 +280,7 @@ auto BrowserDialog::saveFile() -> string { return {}; } -auto BrowserDialog::selected() -> string_vector { +auto BrowserDialog::selected() -> vector { return response.selected; } @@ -291,12 +291,12 @@ auto BrowserDialog::selectFolder() -> string { return {}; } -auto BrowserDialog::setFilters(const string_vector& filters) -> type& { +auto BrowserDialog::setFilters(const vector& filters) -> type& { state.filters = filters; return *this; } -auto BrowserDialog::setOptions(const string_vector& options) -> type& { +auto BrowserDialog::setOptions(const vector& options) -> type& { state.options = options; return *this; } @@ -316,7 +316,7 @@ auto BrowserDialog::setTitle(const string& title) -> type& { return *this; } -auto BrowserDialog::_run() -> string_vector { +auto BrowserDialog::_run() -> vector { if(!state.path) state.path = Path::user(); response = BrowserDialogWindow(state).run(); return response.selected; diff --git a/hiro/extension/browser-dialog.hpp b/hiro/extension/browser-dialog.hpp index ff150e5c..8ba3cd25 100644 --- a/hiro/extension/browser-dialog.hpp +++ b/hiro/extension/browser-dialog.hpp @@ -6,16 +6,16 @@ struct BrowserDialog { using type = BrowserDialog; BrowserDialog(); - auto openFile() -> string; //one existing file - auto openFiles() -> string_vector; //any existing files - auto openFolder() -> string; //one existing folder - auto openObject() -> string; //one existing file or folder + auto openFile() -> string; //one existing file + auto openFiles() -> vector; //any existing files + auto openFolder() -> string; //one existing folder + auto openObject() -> string; //one existing file or folder auto option() -> string; - auto saveFile() -> string; //one file - auto selected() -> string_vector; - auto selectFolder() -> string; //one existing folder - auto setFilters(const string_vector& filters = {}) -> type&; - auto setOptions(const string_vector& options = {}) -> type&; + auto saveFile() -> string; //one file + auto selected() -> vector; + auto selectFolder() -> string; //one existing folder + auto setFilters(const vector& filters = {}) -> type&; + auto setOptions(const vector& options = {}) -> type&; auto setParent(const sWindow& parent) -> type&; auto setPath(const string& path = "") -> type&; auto setTitle(const string& title = "") -> type&; @@ -23,8 +23,8 @@ struct BrowserDialog { private: struct State { string action; - string_vector filters = {"*"}; - string_vector options; + vector filters = {"*"}; + vector options; sWindow parent; string path; string title; @@ -32,10 +32,10 @@ private: struct Response { string option; - string_vector selected; + vector selected; } response; - auto _run() -> string_vector; + auto _run() -> vector; friend class BrowserDialogWindow; }; diff --git a/hiro/extension/message-dialog.cpp b/hiro/extension/message-dialog.cpp index c86461f1..fe0caa01 100644 --- a/hiro/extension/message-dialog.cpp +++ b/hiro/extension/message-dialog.cpp @@ -4,19 +4,19 @@ MessageDialog::MessageDialog(const string& text) { state.text = text; } -auto MessageDialog::error(const string_vector& buttons) -> string { +auto MessageDialog::error(const vector& buttons) -> string { state.buttons = buttons; state.icon = Icon::Prompt::Error; return _run(); } -auto MessageDialog::information(const string_vector& buttons) -> string { +auto MessageDialog::information(const vector& buttons) -> string { state.buttons = buttons; state.icon = Icon::Prompt::Information; return _run(); } -auto MessageDialog::question(const string_vector& buttons) -> string { +auto MessageDialog::question(const vector& buttons) -> string { state.buttons = buttons; state.icon = Icon::Prompt::Question; return _run(); @@ -37,7 +37,7 @@ auto MessageDialog::setTitle(const string& title) -> type& { return *this; } -auto MessageDialog::warning(const string_vector& buttons) -> string { +auto MessageDialog::warning(const vector& buttons) -> string { state.buttons = buttons; state.icon = Icon::Prompt::Warning; return _run(); diff --git a/hiro/extension/message-dialog.hpp b/hiro/extension/message-dialog.hpp index 4373d99d..f9f901b1 100644 --- a/hiro/extension/message-dialog.hpp +++ b/hiro/extension/message-dialog.hpp @@ -4,17 +4,17 @@ struct MessageDialog { using type = MessageDialog; MessageDialog(const string& text = ""); - auto error(const string_vector& buttons = {"Ok"}) -> string; - auto information(const string_vector& buttons = {"Ok"}) -> string; - auto question(const string_vector& buttons = {"Yes", "No"}) -> string; + auto error(const vector& buttons = {"Ok"}) -> string; + auto information(const vector& buttons = {"Ok"}) -> string; + auto question(const vector& buttons = {"Yes", "No"}) -> string; auto setParent(sWindow parent = {}) -> type&; auto setText(const string& text = "") -> type&; auto setTitle(const string& title = "") -> type&; - auto warning(const string_vector& buttons = {"Ok"}) -> string; + auto warning(const vector& buttons = {"Ok"}) -> string; private: struct State { - string_vector buttons; + vector buttons; vector icon; sWindow parent; string response; diff --git a/hiro/gtk/browser-window.cpp b/hiro/gtk/browser-window.cpp index b788411f..55f35b58 100644 --- a/hiro/gtk/browser-window.cpp +++ b/hiro/gtk/browser-window.cpp @@ -2,7 +2,7 @@ namespace hiro { -static auto BrowserWindow_addFilters(GtkWidget* dialog, string_vector filters) -> void { +static auto BrowserWindow_addFilters(GtkWidget* dialog, vector filters) -> void { for(auto& filter : filters) { GtkFileFilter* gtkFilter = gtk_file_filter_new(); gtk_file_filter_set_name(gtkFilter, filter); diff --git a/hiro/gtk/utility.cpp b/hiro/gtk/utility.cpp index 4ce2078f..bf6996b0 100644 --- a/hiro/gtk/utility.cpp +++ b/hiro/gtk/utility.cpp @@ -36,11 +36,11 @@ static auto CreateImage(const image& icon, bool scale = false) -> GtkImage* { return gtkIcon; } -static auto DropPaths(GtkSelectionData* data) -> string_vector { +static auto DropPaths(GtkSelectionData* data) -> vector { gchar** uris = gtk_selection_data_get_uris(data); if(uris == nullptr) return {}; - string_vector paths; + vector paths; for(unsigned n = 0; uris[n] != nullptr; n++) { gchar* pathname = g_filename_from_uri(uris[n], nullptr, nullptr); if(pathname == nullptr) continue; diff --git a/hiro/gtk/widget/console.hpp b/hiro/gtk/widget/console.hpp index 5b6053b6..b5bbbbcc 100644 --- a/hiro/gtk/widget/console.hpp +++ b/hiro/gtk/widget/console.hpp @@ -11,15 +11,15 @@ struct pConsole : pWidget { auto setForegroundColor(Color color) -> void; auto setPrompt(const string& prompt) -> void; - auto _keyPress(unsigned scancode, unsigned mask) -> bool; + auto _keyPress(uint scancode, uint mask) -> bool; auto _seekToEnd() -> void; auto _seekToMark() -> void; GtkWidget* subWidget = nullptr; GtkTextBuffer* textBuffer = nullptr; string previousPrompt; - string_vector history; - unsigned historyOffset = 0; + vector history; + uint historyOffset = 0; }; } diff --git a/hiro/qt/browser-window.cpp b/hiro/qt/browser-window.cpp index 62329829..87fe9eb6 100644 --- a/hiro/qt/browser-window.cpp +++ b/hiro/qt/browser-window.cpp @@ -3,6 +3,7 @@ namespace hiro { auto pBrowserWindow::directory(BrowserWindow::State& state) -> string { + return {}; /* QString directory = QFileDialog::getExistingDirectory( state.parent ? state.parent->p.qtWindow : nullptr, @@ -16,6 +17,7 @@ auto pBrowserWindow::directory(BrowserWindow::State& state) -> string { } auto pBrowserWindow::open(BrowserWindow::State& state) -> string { + return {}; /* string filters = state.filters.merge(";;"); @@ -38,6 +40,7 @@ auto pBrowserWindow::open(BrowserWindow::State& state) -> string { } auto pBrowserWindow::save(BrowserWindow::State& state) -> string { + return {}; /* string filters = state.filters.merge(";;"); diff --git a/hiro/qt/message-window.cpp b/hiro/qt/message-window.cpp index f214b8ad..c81243a2 100644 --- a/hiro/qt/message-window.cpp +++ b/hiro/qt/message-window.cpp @@ -27,6 +27,7 @@ static auto MessageWindow_response(MessageWindow::Buttons buttons, QMessageBox:: } auto pMessageWindow::error(MessageWindow::State& state) -> MessageWindow::Response { + return {}; // return MessageWindow_response( // state.buttons, QMessageBox::critical(state.parent ? state.parent->p.qtWindow : nullptr, state.title ? state.title : " ", // QString::fromUtf8(state.text), MessageWindow_buttons(state.buttons)) @@ -34,6 +35,7 @@ auto pMessageWindow::error(MessageWindow::State& state) -> MessageWindow::Respon } auto pMessageWindow::information(MessageWindow::State& state) -> MessageWindow::Response { + return {}; // return MessageWindow_response( // state.buttons, QMessageBox::information(state.parent ? state.parent->p.qtWindow : nullptr, state.title ? state.title : " ", // QString::fromUtf8(state.text), MessageWindow_buttons(state.buttons)) @@ -41,6 +43,7 @@ auto pMessageWindow::information(MessageWindow::State& state) -> MessageWindow:: } auto pMessageWindow::question(MessageWindow::State& state) -> MessageWindow::Response { + return {}; // return MessageWindow_response( // state.buttons, QMessageBox::question(state.parent ? state.parent->p.qtWindow : nullptr, state.title ? state.title : " ", // QString::fromUtf8(state.text), MessageWindow_buttons(state.buttons)) @@ -48,6 +51,7 @@ auto pMessageWindow::question(MessageWindow::State& state) -> MessageWindow::Res } auto pMessageWindow::warning(MessageWindow::State& state) -> MessageWindow::Response { + return {}; // return MessageWindow_response( // state.buttons, QMessageBox::warning(state.parent ? state.parent->p.qtWindow : nullptr, state.title ? state.title : " ", // QString::fromUtf8(state.text), MessageWindow_buttons(state.buttons)) diff --git a/icarus/core/core.cpp b/icarus/core/core.cpp index 18cfcf9f..bd6e57e0 100644 --- a/icarus/core/core.cpp +++ b/icarus/core/core.cpp @@ -20,7 +20,7 @@ auto Icarus::error() const -> string { return errorMessage; } -auto Icarus::missing() const -> string_vector { +auto Icarus::missing() const -> vector { return missingFiles; } diff --git a/icarus/core/core.hpp b/icarus/core/core.hpp index 98d8b558..c6edc0a1 100644 --- a/icarus/core/core.hpp +++ b/icarus/core/core.hpp @@ -27,7 +27,7 @@ struct Icarus { Icarus(); auto error() const -> string; - auto missing() const -> string_vector; + auto missing() const -> vector; auto success(string location) -> string; auto failure(string message) -> string; @@ -113,7 +113,7 @@ struct Icarus { private: string errorMessage; - string_vector missingFiles; + vector missingFiles; }; namespace Database { diff --git a/icarus/core/mega-drive.cpp b/icarus/core/mega-drive.cpp index 7e85b259..b110c06a 100644 --- a/icarus/core/mega-drive.cpp +++ b/icarus/core/mega-drive.cpp @@ -1,6 +1,7 @@ auto Icarus::megaDriveManifest(string location) -> string { vector buffer; concatenate(buffer, {location, "program.rom"}); + concatenate(buffer, {location, "patch.rom" }); return megaDriveManifest(buffer, location); } @@ -34,6 +35,18 @@ auto Icarus::megaDriveImport(vector& buffer, string location) -> string } if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest); - write({target, "program.rom"}, buffer); + uint offset = 0; + auto document = BML::unserialize(manifest); + for(auto rom : document.find("game/board/memory(type=ROM)")) { + auto name = string{rom["content"].text(), ".rom"}.downcase(); + auto size = rom["size"].natural(); + if(size > buffer.size() - offset) { + missingFiles.append(name); + continue; + } + write({target, name}, buffer.data() + offset, size); + offset += size; + } + if(missingFiles) return failure({"ROM image is missing data: ", missingFiles.merge("; ")}); return success(target); } diff --git a/icarus/core/super-famicom.cpp b/icarus/core/super-famicom.cpp index c6c3d23c..8b49c8c0 100644 --- a/icarus/core/super-famicom.cpp +++ b/icarus/core/super-famicom.cpp @@ -41,8 +41,7 @@ auto Icarus::superFamicomImport(vector& buffer, string location) -> str if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest); uint offset = 0; auto document = BML::unserialize(manifest); - for(auto rom : document.find("game/board/memory")) { - if(rom["type"].text() != "ROM") continue; + for(auto rom : document.find("game/board/memory(type=ROM)")) { auto name = string{rom["architecture"].text(), ".", rom["content"].text(), ".rom"}.trimLeft(".", 1L).downcase(); auto size = rom["size"].natural(); if(size > buffer.size() - offset) { diff --git a/icarus/heuristics/game-boy-advance.cpp b/icarus/heuristics/game-boy-advance.cpp index 2a450d6f..1353deb0 100644 --- a/icarus/heuristics/game-boy-advance.cpp +++ b/icarus/heuristics/game-boy-advance.cpp @@ -20,7 +20,7 @@ GameBoyAdvance::operator bool() const { auto GameBoyAdvance::manifest() const -> string { if(!operator bool()) return {}; - string_vector identifiers = { + vector identifiers = { "SRAM_V", "SRAM_F_V", "EEPROM_V", @@ -29,7 +29,7 @@ auto GameBoyAdvance::manifest() const -> string { "FLASH1M_V", }; - string_vector list; + vector list; for(auto& identifier : identifiers) { for(int n : range(data.size() - 16)) { if(!memory::compare(&data[n], identifier.data(), identifier.size())) { diff --git a/icarus/heuristics/mega-drive.cpp b/icarus/heuristics/mega-drive.cpp index 3e267240..f4cfaff6 100644 --- a/icarus/heuristics/mega-drive.cpp +++ b/icarus/heuristics/mega-drive.cpp @@ -46,7 +46,7 @@ auto MegaDrive::manifest() const -> string { if(ramMode != "none") ramSize = bit::round(min(0x20000, ramSize)); if(ramMode == "none") ramSize = 0; - string_vector regions; + vector regions; string region = slice((const char*)&data[0x1f0], 0, 16).trimRight(" "); if(!regions) { if(region == "JAPAN" ) regions.append("NTSC-J"); @@ -68,6 +68,16 @@ auto MegaDrive::manifest() const -> string { regions.append("NTSC-J"); } + string domesticName; + domesticName.resize(48); + memory::copy(domesticName.get(), &data[0x0120], domesticName.size()); + domesticName.strip(); + + string internationalName; + internationalName.resize(48); + memory::copy(internationalName.get(), &data[0x0150], internationalName.size()); + internationalName.strip(); + string output; output.append("game\n"); output.append(" sha256: ", Hash::SHA256(data).digest(), "\n"); @@ -75,7 +85,12 @@ auto MegaDrive::manifest() const -> string { output.append(" name: ", Location::prefix(location), "\n"); output.append(" region: ", regions.left(), "\n"); output.append(" board\n"); - output.append(Memory{}.type("ROM").size(data.size()).content("Program").text()); + if(domesticName == "SONIC & KNUCKLES") { + output.append(Memory{}.type("ROM").size(0x200000).content("Program").text()); + output.append(Memory{}.type("ROM").size( 0x40000).content("Patch").text()); + } else { + output.append(Memory{}.type("ROM").size(data.size()).content("Program").text()); + } if(ramSize && ramMode != "none") { output.append(Memory{}.type("RAM").size(ramSize).content("Save").text()); output.append(" mode: ", ramMode, "\n"); diff --git a/icarus/heuristics/super-famicom.cpp b/icarus/heuristics/super-famicom.cpp index 100797e0..7de976ae 100644 --- a/icarus/heuristics/super-famicom.cpp +++ b/icarus/heuristics/super-famicom.cpp @@ -71,7 +71,7 @@ auto SuperFamicom::manifest() const -> string { output.append(" revision: ", revision(), "\n"); output.append(" board: ", board(), "\n"); - auto board = this->board().trimRight("#A", 1L).trimRight("#B", 1L).split("-"); + auto board = this->board().trimRight("#A", 1L).split("-"); if(auto size = romSize()) { if(board(0) == "SPC7110" && size > 0x100000) { @@ -283,8 +283,8 @@ auto SuperFamicom::board() const -> string { board.trimRight("-", 1L); - if(board.beginsWith( "LOROM-RAM")) board.append(romSize() <= 0x200000 ? "#A" : "#B"); - if(board.beginsWith("NEC-LOROM-RAM")) board.append(romSize() <= 0x100000 ? "#A" : "#B"); + if(board.beginsWith( "LOROM-RAM") && romSize() <= 0x200000) board.append("#A"); + if(board.beginsWith("NEC-LOROM-RAM") && romSize() <= 0x100000) board.append("#A"); //Tengai Makyou Zero (fan translation) if(board.beginsWith("SPC7110-") && data.size() == 0x700000) board.prepend("EX"); diff --git a/icarus/icarus.cpp b/icarus/icarus.cpp index 0394f4d4..355b5ff2 100644 --- a/icarus/icarus.cpp +++ b/icarus/icarus.cpp @@ -58,25 +58,25 @@ Icarus icarus; #include "ui/error-dialog.cpp" #include -auto nall::main(string_vector args) -> void { +auto nall::main(vector arguments) -> void { Application::setName("icarus"); - if(args.size() == 2 && args[1] == "--name") { + if(arguments.size() == 2 && arguments[1] == "--name") { return print("icarus"); } - if(args.size() == 3 && args[1] == "--manifest" && directory::exists(args[2])) { - return print(icarus.manifest(args[2])); + if(arguments.size() == 3 && arguments[1] == "--manifest" && directory::exists(arguments[2])) { + return print(icarus.manifest(arguments[2])); } - if(args.size() == 3 && args[1] == "--import" && file::exists(args[2])) { - if(string target = icarus.import(args[2])) { + if(arguments.size() == 3 && arguments[1] == "--import" && file::exists(arguments[2])) { + if(string target = icarus.import(arguments[2])) { return print(target, "\n"); } return; } - if(args.size() == 2 && args[1] == "--import") { + if(arguments.size() == 2 && arguments[1] == "--import") { if(string source = BrowserDialog() .setTitle("Load ROM File") .setPath(settings["icarus/Path"].text()) diff --git a/icarus/ui/import-dialog.cpp b/icarus/ui/import-dialog.cpp index 6fd8f553..959e773e 100644 --- a/icarus/ui/import-dialog.cpp +++ b/icarus/ui/import-dialog.cpp @@ -13,7 +13,7 @@ ImportDialog::ImportDialog() { setCentered(); } -auto ImportDialog::run(string_vector locations) -> void { +auto ImportDialog::run(vector locations) -> void { abort = false; errors.reset(); unsigned position = 0; diff --git a/icarus/ui/scan-dialog.cpp b/icarus/ui/scan-dialog.cpp index 158acc4c..5c60212e 100644 --- a/icarus/ui/scan-dialog.cpp +++ b/icarus/ui/scan-dialog.cpp @@ -82,7 +82,7 @@ auto ScanDialog::activate() -> void { } auto ScanDialog::import() -> void { - string_vector filenames; + vector filenames; for(auto& item : scanList.items()) { if(item.checked()) { filenames.append(string{settings["icarus/Path"].text(), item.text()}); diff --git a/icarus/ui/ui.hpp b/icarus/ui/ui.hpp index b5ac0e31..4cadd8b0 100644 --- a/icarus/ui/ui.hpp +++ b/icarus/ui/ui.hpp @@ -38,10 +38,10 @@ struct SettingsDialog : Window { struct ImportDialog : Window { ImportDialog(); - auto run(string_vector locations) -> void; + auto run(vector locations) -> void; bool abort; - string_vector errors; + vector errors; VerticalLayout layout{this}; Label statusLabel{&layout, Size{~0, 0}}; diff --git a/nall/directory.hpp b/nall/directory.hpp index 04eaf4b4..3b202661 100644 --- a/nall/directory.hpp +++ b/nall/directory.hpp @@ -22,19 +22,19 @@ struct directory : inode { static auto remove(const string& pathname) -> bool; //recursive static auto exists(const string& pathname) -> bool; - static auto folders(const string& pathname, const string& pattern = "*") -> string_vector { + static auto folders(const string& pathname, const string& pattern = "*") -> vector { auto folders = directory::ufolders(pathname, pattern); folders.sort(); return folders; } - static auto files(const string& pathname, const string& pattern = "*") -> string_vector { + static auto files(const string& pathname, const string& pattern = "*") -> vector { auto files = directory::ufiles(pathname, pattern); files.sort(); return files; } - static auto contents(const string& pathname, const string& pattern = "*") -> string_vector { + static auto contents(const string& pathname, const string& pattern = "*") -> vector { auto folders = directory::ufolders(pathname); //pattern search of contents should only filter files auto files = directory::ufiles(pathname, pattern); folders.sort(); @@ -43,19 +43,19 @@ struct directory : inode { return folders; } - static auto ifolders(const string& pathname, const string& pattern = "*") -> string_vector { + static auto ifolders(const string& pathname, const string& pattern = "*") -> vector { auto folders = ufolders(pathname, pattern); folders.isort(); return folders; } - static auto ifiles(const string& pathname, const string& pattern = "*") -> string_vector { + static auto ifiles(const string& pathname, const string& pattern = "*") -> vector { auto files = ufiles(pathname, pattern); files.isort(); return files; } - static auto icontents(const string& pathname, const string& pattern = "*") -> string_vector { + static auto icontents(const string& pathname, const string& pattern = "*") -> vector { auto folders = directory::ufolders(pathname); //pattern search of contents should only filter files auto files = directory::ufiles(pathname, pattern); folders.isort(); @@ -66,8 +66,8 @@ struct directory : inode { private: //internal functions; these return unsorted lists - static auto ufolders(const string& pathname, const string& pattern = "*") -> string_vector; - static auto ufiles(const string& pathname, const string& pattern = "*") -> string_vector; + static auto ufolders(const string& pathname, const string& pattern = "*") -> vector; + static auto ufiles(const string& pathname, const string& pattern = "*") -> vector; }; #if defined(PLATFORM_WINDOWS) @@ -100,7 +100,7 @@ private: return (result & FILE_ATTRIBUTE_DIRECTORY); } - inline auto directory::ufolders(const string& pathname, const string& pattern) -> string_vector { + inline auto directory::ufolders(const string& pathname, const string& pattern) -> vector { if(!pathname) { //special root pseudo-folder (return list of drives) wchar_t drives[PATH_MAX] = {0}; @@ -113,7 +113,7 @@ private: return string{(const char*)utf8_t(drives)}.replace("\\", "/").split(";"); } - string_vector list; + vector list; string path = pathname; path.transform("/", "\\"); if(!path.endsWith("\\")) path.append("\\"); @@ -142,10 +142,10 @@ private: return list; } - inline auto directory::ufiles(const string& pathname, const string& pattern) -> string_vector { + inline auto directory::ufiles(const string& pathname, const string& pattern) -> vector { if(!pathname) return {}; - string_vector list; + vector list; string path = pathname; path.transform("/", "\\"); if(!path.endsWith("\\")) path.append("\\"); @@ -207,10 +207,10 @@ private: return S_ISDIR(data.st_mode); } - inline auto directory::ufolders(const string& pathname, const string& pattern) -> string_vector { - if(!pathname) return string_vector{"/"}; + inline auto directory::ufolders(const string& pathname, const string& pattern) -> vector { + if(!pathname) return vector{"/"}; - string_vector list; + vector list; DIR* dp; struct dirent* ep; dp = opendir(pathname); @@ -228,10 +228,10 @@ private: return list; } - inline auto directory::ufiles(const string& pathname, const string& pattern) -> string_vector { + inline auto directory::ufiles(const string& pathname, const string& pattern) -> vector { if(!pathname) return {}; - string_vector list; + vector list; DIR* dp; struct dirent* ep; dp = opendir(pathname); diff --git a/nall/intrinsics.hpp b/nall/intrinsics.hpp index a2c5c44f..00ac58c6 100644 --- a/nall/intrinsics.hpp +++ b/nall/intrinsics.hpp @@ -28,10 +28,10 @@ namespace nall { #define COMPILER_CLANG constexpr auto compiler() -> Compiler { return Compiler::Clang; } + #pragma clang diagnostic warning "-Wreturn-type" #pragma clang diagnostic ignored "-Wunknown-pragmas" #pragma clang diagnostic ignored "-Wempty-body" #pragma clang diagnostic ignored "-Wparentheses" - #pragma clang diagnostic ignored "-Wreturn-type" #pragma clang diagnostic ignored "-Wswitch" #pragma clang diagnostic ignored "-Wswitch-bool" #pragma clang diagnostic ignored "-Wtautological-compare" @@ -44,6 +44,7 @@ namespace nall { #define COMPILER_GCC constexpr auto compiler() -> Compiler { return Compiler::GCC; } + #pragma GCC diagnostic warning "-Wreturn-type" #pragma GCC diagnostic ignored "-Wunknown-pragmas" #pragma GCC diagnostic ignored "-Wpragmas" #pragma GCC diagnostic ignored "-Wswitch-bool" diff --git a/nall/locale.hpp b/nall/locale.hpp index b112556a..c143f31f 100644 --- a/nall/locale.hpp +++ b/nall/locale.hpp @@ -21,8 +21,8 @@ struct Locale { } } - auto available() const -> string_vector { - string_vector result; + auto available() const -> vector { + vector result; for(auto& dictionary : dictionaries) { result.append(dictionary.language); } @@ -34,14 +34,15 @@ struct Locale { for(auto& dictionary : dictionaries) { if(dictionary.language == language) { selected = dictionary; - break; + return true; } } + return false; } template auto operator()(string ns, string input, P&&... p) const -> string { - string_vector arguments{forward

(p)...}; + vector arguments{forward

(p)...}; if(selected) { for(auto node : selected().document) { if(node.name() == "namespace" && node.text() == ns) { diff --git a/nall/location.hpp b/nall/location.hpp index 59910aad..361d0c01 100644 --- a/nall/location.hpp +++ b/nall/location.hpp @@ -4,7 +4,7 @@ namespace nall { namespace Location { // (/parent/child.type/) // (/parent/child.type/)name.type -inline auto path(string_view self) -> string { +inline auto path(view self) -> string { const char* p = self.data() + self.size() - 1; for(int offset = self.size() - 1; offset >= 0; offset--, p--) { if(*p == '/') return slice(self, 0, offset + 1); @@ -14,7 +14,7 @@ inline auto path(string_view self) -> string { // /parent/child.type/() // /parent/child.type/(name.type) -inline auto file(string_view self) -> string { +inline auto file(view self) -> string { const char* p = self.data() + self.size() - 1; for(int offset = self.size() - 1; offset >= 0; offset--, p--) { if(*p == '/') return slice(self, offset + 1); @@ -24,7 +24,7 @@ inline auto file(string_view self) -> string { // (/parent/)child.type/ // (/parent/child.type/)name.type -inline auto dir(string_view self) -> string { +inline auto dir(view self) -> string { const char* p = self.data() + self.size() - 1, *last = p; for(int offset = self.size() - 1; offset >= 0; offset--, p--) { if(*p == '/' && p == last) continue; @@ -35,7 +35,7 @@ inline auto dir(string_view self) -> string { // /parent/(child.type/) // /parent/child.type/(name.type) -inline auto base(string_view self) -> string { +inline auto base(view self) -> string { const char* p = self.data() + self.size() - 1, *last = p; for(int offset = self.size() - 1; offset >= 0; offset--, p--) { if(*p == '/' && p == last) continue; @@ -46,7 +46,7 @@ inline auto base(string_view self) -> string { // /parent/(child).type/ // /parent/child.type/(name).type -inline auto prefix(string_view self) -> string { +inline auto prefix(view self) -> string { const char* p = self.data() + self.size() - 1, *last = p; for(int offset = self.size() - 1, suffix = -1; offset >= 0; offset--, p--) { if(*p == '/' && p == last) continue; @@ -59,7 +59,7 @@ inline auto prefix(string_view self) -> string { // /parent/child(.type)/ // /parent/child.type/name(.type) -inline auto suffix(string_view self) -> string { +inline auto suffix(view self) -> string { const char* p = self.data() + self.size() - 1, *last = p; for(int offset = self.size() - 1; offset >= 0; offset--, p--) { if(*p == '/' && p == last) continue; @@ -69,7 +69,7 @@ inline auto suffix(string_view self) -> string { return ""; //no suffix found } -inline auto notsuffix(string_view self) -> string { +inline auto notsuffix(view self) -> string { return {path(self), prefix(self)}; } diff --git a/nall/main.hpp b/nall/main.hpp index 81042f97..4579424c 100644 --- a/nall/main.hpp +++ b/nall/main.hpp @@ -4,7 +4,7 @@ #include namespace nall { - auto main(string_vector arguments) -> void; + auto main(vector arguments) -> void; auto main(int argc, char** argv) -> int { #if defined(PLATFORM_WINDOWS) @@ -17,7 +17,7 @@ namespace nall { utf8_args(argc, argv); #endif - string_vector arguments; + vector arguments; for(auto n : range(argc)) { string argument = argv[n]; diff --git a/nall/nall.hpp b/nall/nall.hpp index 8592407d..b8680e46 100644 --- a/nall/nall.hpp +++ b/nall/nall.hpp @@ -61,6 +61,7 @@ #include #include #include +#include #include #include #include diff --git a/nall/path.hpp b/nall/path.hpp index ed4d148c..2b49e155 100644 --- a/nall/path.hpp +++ b/nall/path.hpp @@ -14,7 +14,7 @@ inline auto active() -> string { return result; } -inline auto real(string_view name) -> string { +inline auto real(view name) -> string { string result; char path[PATH_MAX] = ""; if(::realpath(name, path)) result = Location::path(string{path}.transform("\\", "/")); diff --git a/nall/run.hpp b/nall/run.hpp index dc705f59..2c11a8bf 100644 --- a/nall/run.hpp +++ b/nall/run.hpp @@ -36,7 +36,7 @@ template inline auto execute(const string& name, P&&... p) -> exe if(pid == 0) { const char* argv[1 + sizeof...(p) + 1]; const char** argp = argv; - string_vector argl(forward

(p)...); + vector argl(forward

(p)...); *argp++ = (const char*)name; for(auto& arg : argl) *argp++ = (const char*)arg; *argp++ = nullptr; @@ -92,7 +92,7 @@ template inline auto invoke(const string& name, P&&... p) -> void if(pid == 0) { const char* argv[1 + sizeof...(p) + 1]; const char** argp = argv; - string_vector argl(forward

(p)...); + vector argl(forward

(p)...); *argp++ = (const char*)name; for(auto& arg : argl) *argp++ = (const char*)arg; *argp++ = nullptr; @@ -107,7 +107,7 @@ template inline auto invoke(const string& name, P&&... p) -> void #elif defined(PLATFORM_WINDOWS) template inline auto execute(const string& name, P&&... p) -> execute_result_t { - string_vector argl(name, forward

(p)...); + vector argl(name, forward

(p)...); for(auto& arg : argl) if(arg.find(" ")) arg = {"\"", arg, "\""}; string arguments = argl.merge(" "); @@ -189,7 +189,7 @@ template inline auto execute(const string& name, P&&... p) -> exe } template inline auto invoke(const string& name, P&&... p) -> void { - string_vector argl(forward

(p)...); + vector argl(forward

(p)...); for(auto& arg : argl) if(arg.find(" ")) arg = {"\"", arg, "\""}; string arguments = argl.merge(" "); string directory = Path::program().replace("/", "\\"); diff --git a/nall/string.hpp b/nall/string.hpp index 11641d2c..9b48fc9c 100644 --- a/nall/string.hpp +++ b/nall/string.hpp @@ -20,26 +20,32 @@ #include #include #include +#include namespace nall { struct string; -struct string_view; -struct string_vector; struct string_format; -struct string_view { - inline string_view(); - inline string_view(const string_view& source); - inline string_view(string_view&& source); - inline string_view(const char* data); - inline string_view(const char* data, uint size); - inline string_view(const string& source); - template inline string_view(P&&... p); - inline ~string_view(); +//temporary compatibility shim +using string_vector = vector; +using string_view = view; - inline auto operator=(const string_view& source) -> string_view&; - inline auto operator=(string_view&& source) -> string_view&; +template<> struct view { + using type = view; + + //view.hpp + inline view(); + inline view(const view& source); + inline view(view&& source); + inline view(const char* data); + inline view(const char* data, uint size); + inline view(const string& source); + template inline view(P&&... p); + inline ~view(); + + inline auto operator=(const view& source) -> view&; + inline auto operator=(view&& source) -> view&; inline operator const char*() const; inline auto data() const -> const char*; @@ -51,6 +57,8 @@ protected: mutable int _size; }; +//using string_view = view; + #define NALL_STRING_ALLOCATOR_ADAPTIVE //#define NALL_STRING_ALLOCATOR_COPY_ON_WRITE //#define NALL_STRING_ALLOCATOR_SMALL_STRING_OPTIMIZATION @@ -69,10 +77,10 @@ inline auto binary(uintmax value, long precision = 0, char padchar = '0') -> str //match.hpp inline auto tokenize(const char* s, const char* p) -> bool; -inline auto tokenize(string_vector& list, const char* s, const char* p) -> bool; +inline auto tokenize(vector& list, const char* s, const char* p) -> bool; //utility.hpp -inline auto slice(string_view self, int offset = 0, int length = -1) -> string; +inline auto slice(view self, int offset = 0, int length = -1) -> string; template inline auto fromInteger(char* result, T value) -> char*; template inline auto fromNatural(char* result, T value) -> char*; template inline auto fromReal(char* str, T value) -> uint; @@ -150,12 +158,12 @@ public: auto operator==(const char* source) const -> bool { return strcmp(data(), source) == 0; } auto operator!=(const char* source) const -> bool { return strcmp(data(), source) != 0; } - auto operator==(string_view source) const -> bool { return compare(source) == 0; } - auto operator!=(string_view source) const -> bool { return compare(source) != 0; } - auto operator< (string_view source) const -> bool { return compare(source) < 0; } - auto operator<=(string_view source) const -> bool { return compare(source) <= 0; } - auto operator> (string_view source) const -> bool { return compare(source) > 0; } - auto operator>=(string_view source) const -> bool { return compare(source) >= 0; } + auto operator==(view source) const -> bool { return compare(source) == 0; } + auto operator!=(view source) const -> bool { return compare(source) != 0; } + auto operator< (view source) const -> bool { return compare(source) < 0; } + auto operator<=(view source) const -> bool { return compare(source) <= 0; } + auto operator> (view source) const -> bool { return compare(source) > 0; } + auto operator>=(view source) const -> bool { return compare(source) >= 0; } string(const string& source) : string() { operator=(source); } string(string&& source) : string() { operator=(move(source)); } @@ -186,15 +194,15 @@ public: inline auto length() const -> uint; //find.hpp - template inline auto _find(int, string_view) const -> maybe; + template inline auto _find(int, view) const -> maybe; - inline auto find(string_view source) const -> maybe; - inline auto ifind(string_view source) const -> maybe; - inline auto qfind(string_view source) const -> maybe; - inline auto iqfind(string_view source) const -> maybe; + inline auto find(view source) const -> maybe; + inline auto ifind(view source) const -> maybe; + inline auto qfind(view source) const -> maybe; + inline auto iqfind(view source) const -> maybe; - inline auto findFrom(int offset, string_view source) const -> maybe; - inline auto ifindFrom(int offset, string_view source) const -> maybe; + inline auto findFrom(int offset, view source) const -> maybe; + inline auto ifindFrom(int offset, view source) const -> maybe; //format.hpp inline auto format(const nall::string_format& params) -> type&; @@ -202,20 +210,20 @@ public: //compare.hpp template inline static auto _compare(const char*, uint, const char*, uint) -> int; - inline static auto compare(string_view, string_view) -> int; - inline static auto icompare(string_view, string_view) -> int; + inline static auto compare(view, view) -> int; + inline static auto icompare(view, view) -> int; - inline auto compare(string_view source) const -> int; - inline auto icompare(string_view source) const -> int; + inline auto compare(view source) const -> int; + inline auto icompare(view source) const -> int; - inline auto equals(string_view source) const -> bool; - inline auto iequals(string_view source) const -> bool; + inline auto equals(view source) const -> bool; + inline auto iequals(view source) const -> bool; - inline auto beginsWith(string_view source) const -> bool; - inline auto ibeginsWith(string_view source) const -> bool; + inline auto beginsWith(view source) const -> bool; + inline auto ibeginsWith(view source) const -> bool; - inline auto endsWith(string_view source) const -> bool; - inline auto iendsWith(string_view source) const -> bool; + inline auto endsWith(view source) const -> bool; + inline auto iendsWith(view source) const -> bool; //convert.hpp inline auto downcase() -> type&; @@ -224,41 +232,41 @@ public: inline auto qdowncase() -> type&; inline auto qupcase() -> type&; - inline auto transform(string_view from, string_view to) -> type&; + inline auto transform(view from, viewto) -> type&; //match.hpp - inline auto match(string_view source) const -> bool; - inline auto imatch(string_view source) const -> bool; + inline auto match(view source) const -> bool; + inline auto imatch(view source) const -> bool; //replace.hpp - template inline auto _replace(string_view, string_view, long) -> type&; - inline auto replace(string_view from, string_view to, long limit = LONG_MAX) -> type&; - inline auto ireplace(string_view from, string_view to, long limit = LONG_MAX) -> type&; - inline auto qreplace(string_view from, string_view to, long limit = LONG_MAX) -> type&; - inline auto iqreplace(string_view from, string_view to, long limit = LONG_MAX) -> type&; + template inline auto _replace(view, view, long) -> type&; + inline auto replace(view from, view to, long limit = LONG_MAX) -> type&; + inline auto ireplace(view from, view to, long limit = LONG_MAX) -> type&; + inline auto qreplace(view from, view to, long limit = LONG_MAX) -> type&; + inline auto iqreplace(view from, view to, long limit = LONG_MAX) -> type&; //split.hpp - inline auto split(string_view key, long limit = LONG_MAX) const -> string_vector; - inline auto isplit(string_view key, long limit = LONG_MAX) const -> string_vector; - inline auto qsplit(string_view key, long limit = LONG_MAX) const -> string_vector; - inline auto iqsplit(string_view key, long limit = LONG_MAX) const -> string_vector; + inline auto split(view key, long limit = LONG_MAX) const -> vector; + inline auto isplit(view key, long limit = LONG_MAX) const -> vector; + inline auto qsplit(view key, long limit = LONG_MAX) const -> vector; + inline auto iqsplit(view key, long limit = LONG_MAX) const -> vector; //trim.hpp - inline auto trim(string_view lhs, string_view rhs, long limit = LONG_MAX) -> type&; - inline auto trimLeft(string_view lhs, long limit = LONG_MAX) -> type&; - inline auto trimRight(string_view rhs, long limit = LONG_MAX) -> type&; + inline auto trim(view lhs, view rhs, long limit = LONG_MAX) -> type&; + inline auto trimLeft(view lhs, long limit = LONG_MAX) -> type&; + inline auto trimRight(view rhs, long limit = LONG_MAX) -> type&; - inline auto itrim(string_view lhs, string_view rhs, long limit = LONG_MAX) -> type&; - inline auto itrimLeft(string_view lhs, long limit = LONG_MAX) -> type&; - inline auto itrimRight(string_view rhs, long limit = LONG_MAX) -> type&; + inline auto itrim(view lhs, view rhs, long limit = LONG_MAX) -> type&; + inline auto itrimLeft(view lhs, long limit = LONG_MAX) -> type&; + inline auto itrimRight(view rhs, long limit = LONG_MAX) -> type&; inline auto strip() -> type&; inline auto stripLeft() -> type&; inline auto stripRight() -> type&; //utility.hpp - inline static auto read(string_view filename) -> string; - inline static auto repeat(string_view pattern, uint times) -> string; + inline static auto read(view filename) -> string; + inline static auto repeat(view pattern, uint times) -> string; inline auto fill(char fill = ' ') -> type&; inline auto hash() const -> uint; inline auto remove(uint offset, uint length) -> type&; @@ -266,35 +274,32 @@ public: inline auto size(int length, char fill = ' ') -> type&; }; -struct string_vector : vector { - using type = string_vector; +template<> struct vector : vector_base { + using type = vector; + using vector_base::vector_base; - string_vector(const string_vector& source) { vector::operator=(source); } - string_vector(string_vector& source) { vector::operator=(source); } - string_vector(string_vector&& source) { vector::operator=(move(source)); } - template string_vector(P&&... p) { append(forward

(p)...); } + vector(const vector& source) { vector_base::operator=(source); } + vector(vector& source) { vector_base::operator=(source); } + vector(vector&& source) { vector_base::operator=(move(source)); } + template vector(P&&... p) { append(forward

(p)...); } + + inline auto operator=(const vector& source) -> type& { return vector_base::operator=(source), *this; } + inline auto operator=(vector& source) -> type& { return vector_base::operator=(source), *this; } + inline auto operator=(vector&& source) -> type& { return vector_base::operator=(move(source)), *this; } //list.hpp - inline auto operator==(const string_vector&) const -> bool; - inline auto operator!=(const string_vector&) const -> bool; - - inline auto operator=(const string_vector& source) -> type& { return vector::operator=(source), *this; } - inline auto operator=(string_vector& source) -> type& { return vector::operator=(source), *this; } - inline auto operator=(string_vector&& source) -> type& { return vector::operator=(move(source)), *this; } - - inline auto isort() -> type&; - template inline auto append(const string&, P&&...) -> type&; inline auto append() -> type&; - inline auto find(string_view source) const -> maybe; - inline auto ifind(string_view source) const -> maybe; - inline auto match(string_view pattern) const -> string_vector; - inline auto merge(string_view separator) const -> string; + inline auto isort() -> type&; + inline auto find(view source) const -> maybe; + inline auto ifind(view source) const -> maybe; + inline auto match(view pattern) const -> vector; + inline auto merge(view separator) const -> string; inline auto strip() -> type&; //split.hpp - template inline auto _split(string_view, string_view, long) -> type&; + template inline auto _split(view, view, long) -> type&; }; struct string_format : vector { @@ -315,12 +320,12 @@ struct string_format : vector { #include #include #include -#include #include #include #include #include #include +#include #include #include #include diff --git a/nall/string/cast.hpp b/nall/string/cast.hpp index dc3e0826..669dfca4 100644 --- a/nall/string/cast.hpp +++ b/nall/string/cast.hpp @@ -220,18 +220,18 @@ template<> struct stringify { const string& _text; }; -template<> struct stringify { - stringify(const string_view& source) : _view(source) {} +template<> struct stringify> { + stringify(const view& source) : _view(source) {} auto data() const -> const char* { return _view.data(); } auto size() const -> uint { return _view.size(); } - const string_view& _view; + const view& _view; }; -template<> struct stringify { - stringify(const string_view& source) : _view(source) {} +template<> struct stringify&> { + stringify(const view& source) : _view(source) {} auto data() const -> const char* { return _view.data(); } auto size() const -> uint { return _view.size(); } - const string_view& _view; + const view& _view; }; //pointers diff --git a/nall/string/compare.hpp b/nall/string/compare.hpp index 08479ba2..65fecf8c 100644 --- a/nall/string/compare.hpp +++ b/nall/string/compare.hpp @@ -9,48 +9,48 @@ auto string::_compare(const char* target, uint capacity, const char* source, uin } //size() + 1 includes null-terminator; required to properly compare strings of differing lengths -auto string::compare(string_view x, string_view y) -> int { +auto string::compare(view x, view y) -> int { return memory::compare(x.data(), x.size() + 1, y.data(), y.size() + 1); } -auto string::icompare(string_view x, string_view y) -> int { +auto string::icompare(view x, view y) -> int { return memory::icompare(x.data(), x.size() + 1, y.data(), y.size() + 1); } -auto string::compare(string_view source) const -> int { +auto string::compare(view source) const -> int { return memory::compare(data(), size() + 1, source.data(), source.size() + 1); } -auto string::icompare(string_view source) const -> int { +auto string::icompare(view source) const -> int { return memory::icompare(data(), size() + 1, source.data(), source.size() + 1); } -auto string::equals(string_view source) const -> bool { +auto string::equals(view source) const -> bool { if(size() != source.size()) return false; return memory::compare(data(), source.data(), source.size()) == 0; } -auto string::iequals(string_view source) const -> bool { +auto string::iequals(view source) const -> bool { if(size() != source.size()) return false; return memory::icompare(data(), source.data(), source.size()) == 0; } -auto string::beginsWith(string_view source) const -> bool { +auto string::beginsWith(view source) const -> bool { if(source.size() > size()) return false; return memory::compare(data(), source.data(), source.size()) == 0; } -auto string::ibeginsWith(string_view source) const -> bool { +auto string::ibeginsWith(view source) const -> bool { if(source.size() > size()) return false; return memory::icompare(data(), source.data(), source.size()) == 0; } -auto string::endsWith(string_view source) const -> bool { +auto string::endsWith(view source) const -> bool { if(source.size() > size()) return false; return memory::compare(data() + size() - source.size(), source.data(), source.size()) == 0; } -auto string::iendsWith(string_view source) const -> bool { +auto string::iendsWith(view source) const -> bool { if(source.size() > size()) return false; return memory::icompare(data() + size() - source.size(), source.data(), source.size()) == 0; } diff --git a/nall/string/convert.hpp b/nall/string/convert.hpp index 4c7d4abf..406592dd 100644 --- a/nall/string/convert.hpp +++ b/nall/string/convert.hpp @@ -36,7 +36,7 @@ auto string::qupcase() -> string& { return *this; } -auto string::transform(string_view from, string_view to) -> string& { +auto string::transform(view from, view to) -> string& { if(from.size() != to.size() || from.size() == 0) return *this; //patterns must be the same length char* p = get(); for(uint n = 0; n < size(); n++) { diff --git a/nall/string/find.hpp b/nall/string/find.hpp index d8d9a48c..f3b16785 100644 --- a/nall/string/find.hpp +++ b/nall/string/find.hpp @@ -2,7 +2,7 @@ namespace nall { -template auto string::_find(int offset, string_view source) const -> maybe { +template auto string::_find(int offset, view source) const -> maybe { if(source.size() == 0) return nothing; auto p = data(); @@ -15,12 +15,12 @@ template auto string::_find(int offset, string_vi return nothing; } -auto string::find(string_view source) const -> maybe { return _find<0, 0>(0, source); } -auto string::ifind(string_view source) const -> maybe { return _find<1, 0>(0, source); } -auto string::qfind(string_view source) const -> maybe { return _find<0, 1>(0, source); } -auto string::iqfind(string_view source) const -> maybe { return _find<1, 1>(0, source); } +auto string::find(view source) const -> maybe { return _find<0, 0>(0, source); } +auto string::ifind(view source) const -> maybe { return _find<1, 0>(0, source); } +auto string::qfind(view source) const -> maybe { return _find<0, 1>(0, source); } +auto string::iqfind(view source) const -> maybe { return _find<1, 1>(0, source); } -auto string::findFrom(int offset, string_view source) const -> maybe { return _find<0, 0>(offset, source); } -auto string::ifindFrom(int offset, string_view source) const -> maybe { return _find<1, 0>(offset, source); } +auto string::findFrom(int offset, view source) const -> maybe { return _find<0, 0>(offset, source); } +auto string::ifindFrom(int offset, view source) const -> maybe { return _find<1, 0>(offset, source); } } diff --git a/nall/string/list.hpp b/nall/string/list.hpp deleted file mode 100644 index 72cace5a..00000000 --- a/nall/string/list.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once - -namespace nall { - -auto string_vector::operator==(const string_vector& source) const -> bool { - if(this == &source) return true; - if(size() != source.size()) return false; - for(uint n = 0; n < size(); n++) { - if(operator[](n) != source[n]) return false; - } - return true; -} - -auto string_vector::operator!=(const string_vector& source) const -> bool { - return !operator==(source); -} - -auto string_vector::isort() -> type& { - sort([](const string& x, const string& y) { - return memory::icompare(x.data(), x.size(), y.data(), y.size()) < 0; - }); - return *this; -} - -template auto string_vector::append(const string& data, P&&... p) -> type& { - vector::append(data); - append(forward

(p)...); - return *this; -} - -auto string_vector::append() -> type& { - return *this; -} - -auto string_vector::find(string_view source) const -> maybe { - for(uint n = 0; n < size(); n++) { - if(operator[](n).equals(source)) return n; - } - return nothing; -} - -auto string_vector::ifind(string_view source) const -> maybe { - for(uint n = 0; n < size(); n++) { - if(operator[](n).iequals(source)) return n; - } - return nothing; -} - -auto string_vector::match(string_view pattern) const -> type { - string_vector result; - for(uint n = 0; n < size(); n++) { - if(operator[](n).match(pattern)) result.append(operator[](n)); - } - return result; -} - -auto string_vector::merge(string_view separator) const -> string { - string output; - for(uint n = 0; n < size(); n++) { - output.append(operator[](n)); - if(n < size() - 1) output.append(separator.data()); - } - return output; -} - -auto string_vector::strip() -> type& { - for(uint n = 0; n < size(); n++) { - operator[](n).strip(); - } - return *this; -} - -} diff --git a/nall/string/markup/bml.hpp b/nall/string/markup/bml.hpp index 631a6125..55b9c914 100644 --- a/nall/string/markup/bml.hpp +++ b/nall/string/markup/bml.hpp @@ -80,7 +80,7 @@ protected: } //read a node and all of its child nodes - auto parseNode(const string_vector& text, uint& y) -> void { + auto parseNode(const vector& text, uint& y) -> void { const char* p = text[y++]; _metadata = parseDepth(p); parseName(p); @@ -166,7 +166,7 @@ inline auto serialize(const Markup::Node& node, uint depth = 0) -> string { padding.resize(depth * 2); for(auto& byte : padding) byte = ' '; - string_vector lines; + vector lines; if(auto value = node.value()) lines = value.split("\n"); string result; diff --git a/nall/string/markup/find.hpp b/nall/string/markup/find.hpp index 021abf88..8cbdd4fc 100644 --- a/nall/string/markup/find.hpp +++ b/nall/string/markup/find.hpp @@ -20,7 +20,7 @@ auto ManagedNode::_evaluate(string query) const -> bool { return false; } - string_vector side; + vector side; switch(comparator) { case Comparator::EQ: side = rule.split ("=", 1L); break; case Comparator::NE: side = rule.split("!=", 1L); break; diff --git a/nall/string/match.hpp b/nall/string/match.hpp index ecd9fb4c..0be483df 100644 --- a/nall/string/match.hpp +++ b/nall/string/match.hpp @@ -4,7 +4,7 @@ namespace nall { //todo: these functions are not binary-safe -auto string::match(string_view source) const -> bool { +auto string::match(view source) const -> bool { const char* s = data(); const char* p = source.data(); @@ -28,7 +28,7 @@ auto string::match(string_view source) const -> bool { return !*p; } -auto string::imatch(string_view source) const -> bool { +auto string::imatch(view source) const -> bool { static auto chrlower = [](char c) -> char { return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c; }; @@ -68,7 +68,7 @@ auto tokenize(const char* s, const char* p) -> bool { return !*p; } -auto tokenize(string_vector& list, const char* s, const char* p) -> bool { +auto tokenize(vector& list, const char* s, const char* p) -> bool { while(*s) { if(*p == '*') { const char* b = s; diff --git a/nall/string/replace.hpp b/nall/string/replace.hpp index d8143a15..078a7e0b 100644 --- a/nall/string/replace.hpp +++ b/nall/string/replace.hpp @@ -3,7 +3,7 @@ namespace nall { template -auto string::_replace(string_view from, string_view to, long limit) -> string& { +auto string::_replace(view from, view to, long limit) -> string& { if(limit <= 0 || from.size() == 0) return *this; int size = this->size(); @@ -86,9 +86,9 @@ auto string::_replace(string_view from, string_view to, long limit) -> string& { return *this; } -auto string::replace(string_view from, string_view to, long limit) -> string& { return _replace<0, 0>(from, to, limit); } -auto string::ireplace(string_view from, string_view to, long limit) -> string& { return _replace<1, 0>(from, to, limit); } -auto string::qreplace(string_view from, string_view to, long limit) -> string& { return _replace<0, 1>(from, to, limit); } -auto string::iqreplace(string_view from, string_view to, long limit) -> string& { return _replace<1, 1>(from, to, limit); } +auto string::replace(view from, view to, long limit) -> string& { return _replace<0, 0>(from, to, limit); } +auto string::ireplace(view from, view to, long limit) -> string& { return _replace<1, 0>(from, to, limit); } +auto string::qreplace(view from, view to, long limit) -> string& { return _replace<0, 1>(from, to, limit); } +auto string::iqreplace(view from, view to, long limit) -> string& { return _replace<1, 1>(from, to, limit); } }; diff --git a/nall/string/split.hpp b/nall/string/split.hpp index a8520111..f6a14cbf 100644 --- a/nall/string/split.hpp +++ b/nall/string/split.hpp @@ -3,7 +3,7 @@ namespace nall { template -auto string_vector::_split(string_view source, string_view find, long limit) -> string_vector& { +auto vector::_split(view source, view find, long limit) -> type& { reset(); if(limit <= 0 || find.size() == 0) return *this; @@ -33,9 +33,9 @@ auto string_vector::_split(string_view source, string_view find, long limit) -> return *this; } -auto string::split(string_view on, long limit) const -> string_vector { return string_vector()._split<0, 0>(*this, on, limit); } -auto string::isplit(string_view on, long limit) const -> string_vector { return string_vector()._split<1, 0>(*this, on, limit); } -auto string::qsplit(string_view on, long limit) const -> string_vector { return string_vector()._split<0, 1>(*this, on, limit); } -auto string::iqsplit(string_view on, long limit) const -> string_vector { return string_vector()._split<1, 1>(*this, on, limit); } +auto string::split(view on, long limit) const -> vector { return vector()._split<0, 0>(*this, on, limit); } +auto string::isplit(view on, long limit) const -> vector { return vector()._split<1, 0>(*this, on, limit); } +auto string::qsplit(view on, long limit) const -> vector { return vector()._split<0, 1>(*this, on, limit); } +auto string::iqsplit(view on, long limit) const -> vector { return vector()._split<1, 1>(*this, on, limit); } } diff --git a/nall/string/trim.hpp b/nall/string/trim.hpp index 17823a7d..952a12fa 100644 --- a/nall/string/trim.hpp +++ b/nall/string/trim.hpp @@ -2,13 +2,13 @@ namespace nall { -auto string::trim(string_view lhs, string_view rhs, long limit) -> string& { +auto string::trim(view lhs, view rhs, long limit) -> string& { trimRight(rhs, limit); trimLeft(lhs, limit); return *this; } -auto string::trimLeft(string_view lhs, long limit) -> string& { +auto string::trimLeft(view lhs, long limit) -> string& { if(lhs.size() == 0) return *this; long matches = 0; while(matches < limit) { @@ -22,7 +22,7 @@ auto string::trimLeft(string_view lhs, long limit) -> string& { return *this; } -auto string::trimRight(string_view rhs, long limit) -> string& { +auto string::trimRight(view rhs, long limit) -> string& { if(rhs.size() == 0) return *this; long matches = 0; while(matches < limit) { @@ -36,13 +36,13 @@ auto string::trimRight(string_view rhs, long limit) -> string& { return *this; } -auto string::itrim(string_view lhs, string_view rhs, long limit) -> string& { +auto string::itrim(view lhs, view rhs, long limit) -> string& { itrimRight(rhs, limit); itrimLeft(lhs, limit); return *this; } -auto string::itrimLeft(string_view lhs, long limit) -> string& { +auto string::itrimLeft(view lhs, long limit) -> string& { if(lhs.size() == 0) return *this; long matches = 0; while(matches < limit) { @@ -56,7 +56,7 @@ auto string::itrimLeft(string_view lhs, long limit) -> string& { return *this; } -auto string::itrimRight(string_view rhs, long limit) -> string& { +auto string::itrimRight(view rhs, long limit) -> string& { if(rhs.size() == 0) return *this; long matches = 0; while(matches < limit) { diff --git a/nall/string/utility.hpp b/nall/string/utility.hpp index e1dc320a..4dd255f6 100644 --- a/nall/string/utility.hpp +++ b/nall/string/utility.hpp @@ -2,7 +2,7 @@ namespace nall { -auto string::read(string_view filename) -> string { +auto string::read(view filename) -> string { #if !defined(_WIN32) FILE* fp = fopen(filename, "rb"); #else @@ -22,7 +22,7 @@ auto string::read(string_view filename) -> string { return fclose(fp), result; } -auto string::repeat(string_view pattern, uint times) -> string { +auto string::repeat(view pattern, uint times) -> string { string result; while(times--) result.append(pattern.data()); return result; @@ -82,7 +82,7 @@ auto string::size(int length, char fill) -> string& { return *this; } -auto slice(string_view self, int offset, int length) -> string { +auto slice(view self, int offset, int length) -> string { string result; if(offset < 0) offset = self.size() - abs(offset); if(offset >= 0 && offset < self.size()) { diff --git a/nall/string/vector.hpp b/nall/string/vector.hpp new file mode 100644 index 00000000..0182eeda --- /dev/null +++ b/nall/string/vector.hpp @@ -0,0 +1,60 @@ +#pragma once + +namespace nall { + +template auto vector::append(const string& data, P&&... p) -> type& { + vector_base::append(data); + append(forward

(p)...); + return *this; +} + +auto vector::append() -> type& { + return *this; +} + +auto vector::isort() -> type& { + sort([](const string& x, const string& y) { + return memory::icompare(x.data(), x.size(), y.data(), y.size()) < 0; + }); + return *this; +} + +auto vector::find(view source) const -> maybe { + for(uint n = 0; n < size(); n++) { + if(operator[](n).equals(source)) return n; + } + return {}; +} + +auto vector::ifind(view source) const -> maybe { + for(uint n = 0; n < size(); n++) { + if(operator[](n).iequals(source)) return n; + } + return {}; +} + +auto vector::match(view pattern) const -> vector { + vector result; + for(uint n = 0; n < size(); n++) { + if(operator[](n).match(pattern)) result.append(operator[](n)); + } + return result; +} + +auto vector::merge(view separator) const -> string { + string output; + for(uint n = 0; n < size(); n++) { + output.append(operator[](n)); + if(n < size() - 1) output.append(separator.data()); + } + return output; +} + +auto vector::strip() -> type& { + for(uint n = 0; n < size(); n++) { + operator[](n).strip(); + } + return *this; +} + +} diff --git a/nall/string/view.hpp b/nall/string/view.hpp index 0c8a175e..fa6b5380 100644 --- a/nall/string/view.hpp +++ b/nall/string/view.hpp @@ -2,20 +2,20 @@ namespace nall { -string_view::string_view() { +view::view() { _string = nullptr; _data = ""; _size = 0; } -string_view::string_view(const string_view& source) { +view::view(const view& source) { if(this == &source) return; _string = nullptr; _data = source._data; _size = source._size; } -string_view::string_view(string_view&& source) { +view::view(view&& source) { if(this == &source) return; _string = source._string; _data = source._data; @@ -23,36 +23,36 @@ string_view::string_view(string_view&& source) { source._string = nullptr; } -string_view::string_view(const char* data) { +view::view(const char* data) { _string = nullptr; _data = data; _size = -1; //defer length calculation, as it is often unnecessary } -string_view::string_view(const char* data, uint size) { +view::view(const char* data, uint size) { _string = nullptr; _data = data; _size = size; } -string_view::string_view(const string& source) { +view::view(const string& source) { _string = nullptr; _data = source.data(); _size = source.size(); } template -string_view::string_view(P&&... p) { +view::view(P&&... p) { _string = new string{forward

(p)...}; _data = _string->data(); _size = _string->size(); } -string_view::~string_view() { +view::~view() { if(_string) delete _string; } -auto string_view::operator=(const string_view& source) -> string_view& { +auto view::operator=(const view& source) -> view& { if(this == &source) return *this; _string = nullptr; _data = source._data; @@ -60,7 +60,7 @@ auto string_view::operator=(const string_view& source) -> string_view& { return *this; }; -auto string_view::operator=(string_view&& source) -> string_view& { +auto view::operator=(view&& source) -> view& { if(this == &source) return *this; _string = source._string; _data = source._data; @@ -69,15 +69,15 @@ auto string_view::operator=(string_view&& source) -> string_view& { return *this; }; -string_view::operator const char*() const { +view::operator const char*() const { return _data; } -auto string_view::data() const -> const char* { +auto view::data() const -> const char* { return _data; } -auto string_view::size() const -> uint { +auto view::size() const -> uint { if(_size < 0) _size = strlen(_data); return _size; } diff --git a/nall/vector.hpp b/nall/vector.hpp index 2ccbfd1f..5312ab71 100644 --- a/nall/vector.hpp +++ b/nall/vector.hpp @@ -19,13 +19,15 @@ template struct vector_iterator_reverse; template struct vector_iterator_reverse_const; template -struct vector { +struct vector_base { + using type = vector_base; + //core.hpp - vector() = default; - vector(const initializer_list& values); - vector(const vector& source); - vector(vector&& source); - ~vector(); + vector_base() = default; + vector_base(const initializer_list& values); + vector_base(const type& source); + vector_base(type&& source); + ~vector_base(); explicit operator bool() const; auto capacity() const -> uint; @@ -34,8 +36,12 @@ struct vector { auto data() const -> const T*; //assign.hpp - auto operator=(const vector& source) -> vector&; - auto operator=(vector&& source) -> vector&; + auto operator=(const type& source) -> type&; + auto operator=(type&& source) -> type&; + + //compare.hpp + auto operator==(const type& source) const -> bool; + auto operator!=(const type& source) const -> bool; //memory.hpp auto reset() -> void; @@ -65,13 +71,13 @@ struct vector { //modify.hpp auto prepend(const T& value) -> void; auto prepend(T&& value) -> void; - auto prepend(const vector& values) -> void; - auto prepend(vector&& values) -> void; + auto prepend(const type& values) -> void; + auto prepend(type&& values) -> void; auto append(const T& value) -> void; auto append(T&& value) -> void; - auto append(const vector& values) -> void; - auto append(vector&& values) -> void; + auto append(const type& values) -> void; + auto append(type&& values) -> void; auto insert(uint offset, const T& value) -> void; @@ -109,10 +115,19 @@ private: } +#define vector vector_base #include #include +#include #include #include #include #include #include +#undef vector + +namespace nall { + template struct vector : vector_base { + using vector_base::vector_base; + }; +} diff --git a/nall/vector/compare.hpp b/nall/vector/compare.hpp new file mode 100644 index 00000000..5400dc8a --- /dev/null +++ b/nall/vector/compare.hpp @@ -0,0 +1,18 @@ +#pragma once + +namespace nall { + +template auto vector::operator==(const vector& source) const -> bool { + if(this == &source) return true; + if(size() != source.size()) return false; + for(uint n = 0; n < size(); n++) { + if(operator[](n) != source[n]) return false; + } + return true; +} + +template auto vector::operator!=(const vector& source) const -> bool { + return !operator==(source); +} + +} diff --git a/nall/view.hpp b/nall/view.hpp new file mode 100644 index 00000000..ce874ce4 --- /dev/null +++ b/nall/view.hpp @@ -0,0 +1,7 @@ +#pragma once + +namespace nall { + +template struct view; + +} diff --git a/ruby/audio/openal.cpp b/ruby/audio/openal.cpp index c606eaba..b7749315 100644 --- a/ruby/audio/openal.cpp +++ b/ruby/audio/openal.cpp @@ -10,8 +10,8 @@ struct AudioOpenAL : Audio { AudioOpenAL() { initialize(); } ~AudioOpenAL() { terminate(); } - auto availableDevices() -> string_vector { - string_vector devices; + auto availableDevices() -> vector { + vector devices; for(auto& device : queryDevices()) devices.append(device); return devices; } @@ -163,8 +163,8 @@ private: _buffer = nullptr; } - auto queryDevices() -> string_vector { - string_vector result; + auto queryDevices() -> vector { + vector result; const char* list = alcGetString(nullptr, ALC_DEVICE_SPECIFIER); if(!list) return result; diff --git a/ruby/audio/oss.cpp b/ruby/audio/oss.cpp index 4527123f..63a6e529 100644 --- a/ruby/audio/oss.cpp +++ b/ruby/audio/oss.cpp @@ -17,8 +17,8 @@ struct AudioOSS : Audio { AudioOSS() { initialize(); } ~AudioOSS() { terminate(); } - auto availableDevices() -> string_vector { - string_vector devices; + auto availableDevices() -> vector { + vector devices; devices.append("/dev/dsp"); for(auto& device : directory::files("/dev/", "dsp?*")) devices.append(string{"/dev/", device}); return devices; diff --git a/ruby/ruby.cpp b/ruby/ruby.cpp index 6c397053..cb7065d7 100644 --- a/ruby/ruby.cpp +++ b/ruby/ruby.cpp @@ -159,7 +159,7 @@ auto Video::safestDriver() -> string { #endif } -auto Video::availableDrivers() -> string_vector { +auto Video::availableDrivers() -> vector { return { #if defined(VIDEO_WGL) @@ -348,7 +348,7 @@ auto Audio::safestDriver() -> string { #endif } -auto Audio::availableDrivers() -> string_vector { +auto Audio::availableDrivers() -> vector { return { #if defined(AUDIO_ASIO) @@ -493,7 +493,7 @@ auto Input::safestDriver() -> string { #endif } -auto Input::availableDrivers() -> string_vector { +auto Input::availableDrivers() -> vector { return { #if defined(INPUT_WINDOWS) diff --git a/ruby/ruby.hpp b/ruby/ruby.hpp index 59af2962..074e0e1c 100644 --- a/ruby/ruby.hpp +++ b/ruby/ruby.hpp @@ -8,7 +8,7 @@ struct Video { static auto create(nall::string driver = "") -> Video*; static auto optimalDriver() -> nall::string; static auto safestDriver() -> nall::string; - static auto availableDrivers() -> nall::string_vector; + static auto availableDrivers() -> nall::vector; virtual ~Video() = default; @@ -49,11 +49,11 @@ struct Audio { static auto create(nall::string driver = "") -> Audio*; static auto optimalDriver() -> nall::string; static auto safestDriver() -> nall::string; - static auto availableDrivers() -> nall::string_vector; + static auto availableDrivers() -> nall::vector; virtual ~Audio() = default; - virtual auto availableDevices() -> nall::string_vector { return {"Default"}; } + virtual auto availableDevices() -> nall::vector { return {"Default"}; } virtual auto availableFrequencies() -> nall::vector { return {44100.0}; } virtual auto availableLatencies() -> nall::vector { return {0}; } virtual auto availableChannels() -> nall::vector { return {2}; } @@ -88,7 +88,7 @@ struct Input { static auto create(nall::string driver = "") -> Input*; static auto optimalDriver() -> nall::string; static auto safestDriver() -> nall::string; - static auto availableDrivers() -> nall::string_vector; + static auto availableDrivers() -> nall::vector; virtual ~Input() = default;