diff --git a/.cirrus.yml b/.cirrus.yml index 1a5fc413..ccc267c3 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -14,7 +14,6 @@ linux-x86_64-binaries_task: - mkdir bsnes-nightly/Firmware - cp -a bsnes/out/bsnes bsnes-nightly/bsnes - cp -a bsnes/Database/* bsnes-nightly/Database - - cp -a icarus/Database/* bsnes-nightly/Database - cp -a GPLv3.txt bsnes-nightly - zip -r bsnes-nightly.zip bsnes-nightly @@ -37,7 +36,6 @@ freebsd-x86_64-binaries_task: - mkdir bsnes-nightly/Firmware - cp -a bsnes/out/bsnes bsnes-nightly/bsnes - cp -a bsnes/Database/* bsnes-nightly/Database - - cp -a icarus/Database/* bsnes-nightly/Database - cp -a GPLv3.txt bsnes-nightly - zip -r bsnes-nightly.zip bsnes-nightly @@ -60,7 +58,6 @@ windows-x86_64-binaries_task: - mkdir bsnes-nightly/Firmware - cp -a bsnes/out/bsnes bsnes-nightly/bsnes.exe - cp -a bsnes/Database/* bsnes-nightly/Database - - cp -a icarus/Database/* bsnes-nightly/Database - cp -a GPLv3.txt bsnes-nightly - zip -r bsnes-nightly.zip bsnes-nightly diff --git a/icarus/Database/BS Memory.bml b/bsnes/Database/BS Memory.bml similarity index 100% rename from icarus/Database/BS Memory.bml rename to bsnes/Database/BS Memory.bml diff --git a/icarus/Database/Sufami Turbo.bml b/bsnes/Database/Sufami Turbo.bml similarity index 100% rename from icarus/Database/Sufami Turbo.bml rename to bsnes/Database/Sufami Turbo.bml diff --git a/icarus/Database/Super Famicom.bml b/bsnes/Database/Super Famicom.bml similarity index 100% rename from icarus/Database/Super Famicom.bml rename to bsnes/Database/Super Famicom.bml diff --git a/icarus/heuristics/bs-memory.cpp b/bsnes/heuristics/bs-memory.cpp similarity index 100% rename from icarus/heuristics/bs-memory.cpp rename to bsnes/heuristics/bs-memory.cpp diff --git a/icarus/heuristics/game-boy.cpp b/bsnes/heuristics/game-boy.cpp similarity index 100% rename from icarus/heuristics/game-boy.cpp rename to bsnes/heuristics/game-boy.cpp diff --git a/icarus/heuristics/heuristics.cpp b/bsnes/heuristics/heuristics.cpp similarity index 100% rename from icarus/heuristics/heuristics.cpp rename to bsnes/heuristics/heuristics.cpp diff --git a/icarus/heuristics/heuristics.hpp b/bsnes/heuristics/heuristics.hpp similarity index 100% rename from icarus/heuristics/heuristics.hpp rename to bsnes/heuristics/heuristics.hpp diff --git a/icarus/heuristics/sufami-turbo.cpp b/bsnes/heuristics/sufami-turbo.cpp similarity index 100% rename from icarus/heuristics/sufami-turbo.cpp rename to bsnes/heuristics/sufami-turbo.cpp diff --git a/icarus/heuristics/super-famicom.cpp b/bsnes/heuristics/super-famicom.cpp similarity index 100% rename from icarus/heuristics/super-famicom.cpp rename to bsnes/heuristics/super-famicom.cpp diff --git a/bsnes/target-bsnes/GNUmakefile b/bsnes/target-bsnes/GNUmakefile index d9f219cf..79a3a705 100644 --- a/bsnes/target-bsnes/GNUmakefile +++ b/bsnes/target-bsnes/GNUmakefile @@ -30,7 +30,6 @@ ifeq ($(platform),macos) mkdir -p out/$(name).app/Contents/Resources/ mv out/$(name) out/$(name).app/Contents/MacOS/$(name) cp Database/* out/$(name).app/Contents/MacOS/Database/ - cp ../icarus/Database/* out/$(name).app/Contents/MacOS/Database/ cp $(ui)/resource/$(name).plist out/$(name).app/Contents/Info.plist sips -s format icns $(ui)/resource/$(name).png --out out/$(name).app/Contents/Resources/$(name).icns endif @@ -58,7 +57,6 @@ else ifneq ($(filter $(platform),linux bsd),) cp $(ui)/resource/$(name).desktop $(prefix)/share/applications/$(name).desktop cp $(ui)/resource/$(name).png $(prefix)/share/icons/$(name).png cp Database/* $(prefix)/share/$(name)/Database/ - cp ../icarus/Database/* $(prefix)/share/$(name)/Database/ cp Locale/* $(prefix)/share/$(name)/Locale/ endif diff --git a/bsnes/target-bsnes/program/platform.cpp b/bsnes/target-bsnes/program/platform.cpp index d1e803b4..9b7f5723 100644 --- a/bsnes/target-bsnes/program/platform.cpp +++ b/bsnes/target-bsnes/program/platform.cpp @@ -1,10 +1,10 @@ #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include //ROM data is held in memory to support compressed archives, soft-patching, and game hacks auto Program::open(uint id, string name, vfs::file::mode mode, bool required) -> vfs::shared::file { diff --git a/icarus/Firmware/cx4.data.rom b/icarus/Firmware/cx4.data.rom deleted file mode 100644 index 31c8c44d..00000000 Binary files a/icarus/Firmware/cx4.data.rom and /dev/null differ diff --git a/icarus/Firmware/sgb1.boot.rom b/icarus/Firmware/sgb1.boot.rom deleted file mode 100644 index 2bece748..00000000 Binary files a/icarus/Firmware/sgb1.boot.rom and /dev/null differ diff --git a/icarus/Firmware/sgb2.boot.rom b/icarus/Firmware/sgb2.boot.rom deleted file mode 100644 index 96d22b34..00000000 Binary files a/icarus/Firmware/sgb2.boot.rom and /dev/null differ diff --git a/icarus/core/bs-memory.cpp b/icarus/core/bs-memory.cpp deleted file mode 100644 index 99876fcf..00000000 --- a/icarus/core/bs-memory.cpp +++ /dev/null @@ -1,38 +0,0 @@ -auto Icarus::bsMemoryManifest(string location) -> string { - vector buffer; - //only one of these should exist - concatenate(buffer, {location, "program.rom"}); - concatenate(buffer, {location, "program.flash"}); - return bsMemoryManifest(buffer, location); -} - -auto Icarus::bsMemoryManifest(vector& buffer, string location) -> string { - if(settings["icarus/UseDatabase"].boolean()) { - auto digest = Hash::SHA256(buffer).digest(); - for(auto game : Database::BSMemory.find("game")) { - if(game["sha256"].text() == digest) return BML::serialize(game); - } - } - - if(settings["icarus/UseHeuristics"].boolean()) { - Heuristics::BSMemory game{buffer, location}; - if(auto manifest = game.manifest()) return manifest; - } - - return {}; -} - -auto Icarus::bsMemoryImport(vector& buffer, string location) -> string { - auto name = Location::prefix(location); - auto source = Location::path(location); - string target{settings["Library/Location"].text(), "BS Memory/", name, ".bs/"}; - - auto manifest = bsMemoryManifest(buffer, location); - if(!manifest) return failure("failed to parse ROM image"); - - if(!create(target)) return failure("library path unwritable"); - - if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest); - write({target, "program.rom"}, buffer); - return success(target); -} diff --git a/icarus/core/colecovision.cpp b/icarus/core/colecovision.cpp deleted file mode 100644 index 2931afdb..00000000 --- a/icarus/core/colecovision.cpp +++ /dev/null @@ -1,39 +0,0 @@ -auto Icarus::colecoVisionManifest(string location) -> string { - vector buffer; - concatenate(buffer, {location, "program.rom"}); - return colecoVisionManifest(buffer, location); -} - -auto Icarus::colecoVisionManifest(vector& buffer, string location) -> string { - if(settings["icarus/UseDatabase"].boolean()) { - auto digest = Hash::SHA256(buffer).digest(); - for(auto game : Database::ColecoVision.find("game")) { - if(game["sha256"].text() == digest) return BML::serialize(game); - } - } - - if(settings["icarus/UseHeuristics"].boolean()) { - Heuristics::ColecoVision game{buffer, location}; - if(auto manifest = game.manifest()) return manifest; - } - - return {}; -} - -auto Icarus::colecoVisionImport(vector& buffer, string location) -> string { - auto name = Location::prefix(location); - auto source = Location::path(location); - string target{settings["Library/Location"].text(), "ColecoVision/", name, ".cv/"}; - - auto manifest = colecoVisionManifest(buffer, location); - if(!manifest) return failure("failed to parse ROM image"); - - if(!create(target)) return failure("library path unwritable"); - if(exists({source, name, ".sav"}) && !exists({target, "save.ram"})) { - copy({source, name, ".sav"}, {target, "save.ram"}); - } - - if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest); - write({target, "program.rom"}, buffer); - return success(target); -} diff --git a/icarus/core/core.cpp b/icarus/core/core.cpp deleted file mode 100644 index b06d328a..00000000 --- a/icarus/core/core.cpp +++ /dev/null @@ -1,129 +0,0 @@ -Icarus::Icarus() { - Database::Famicom = BML::unserialize(string::read(locate("Database/Famicom.bml"))); - Database::SuperFamicom = BML::unserialize(string::read(locate("Database/Super Famicom.bml"))); - Database::SG1000 = BML::unserialize(string::read(locate("Database/SG-1000.bml"))); - Database::SC3000 = BML::unserialize(string::read(locate("Database/SC-3000.bml"))); - Database::MasterSystem = BML::unserialize(string::read(locate("Database/Master System.bml"))); - Database::MegaDrive = BML::unserialize(string::read(locate("Database/Mega Drive.bml"))); - Database::PCEngine = BML::unserialize(string::read(locate("Database/PC Engine.bml"))); - Database::SuperGrafx = BML::unserialize(string::read(locate("Database/SuperGrafx.bml"))); - Database::ColecoVision = BML::unserialize(string::read(locate("Database/ColecoVision.bml"))); - Database::MSX = BML::unserialize(string::read(locate("Database/MSX.bml"))); - Database::GameBoy = BML::unserialize(string::read(locate("Database/Game Boy.bml"))); - Database::GameBoyColor = BML::unserialize(string::read(locate("Database/Game Boy Color.bml"))); - Database::GameBoyAdvance = BML::unserialize(string::read(locate("Database/Game Boy Advance.bml"))); - Database::GameGear = BML::unserialize(string::read(locate("Database/Game Gear.bml"))); - Database::WonderSwan = BML::unserialize(string::read(locate("Database/WonderSwan.bml"))); - Database::WonderSwanColor = BML::unserialize(string::read(locate("Database/WonderSwan Color.bml"))); - Database::PocketChallengeV2 = BML::unserialize(string::read(locate("Database/Pocket Challenge V2.bml"))); - Database::NeoGeoPocket = BML::unserialize(string::read(locate("Database/Neo Geo Pocket.bml"))); - Database::NeoGeoPocketColor = BML::unserialize(string::read(locate("Database/Neo Geo Pocket Color.bml"))); - Database::BSMemory = BML::unserialize(string::read(locate("Database/BS Memory.bml"))); - Database::SufamiTurbo = BML::unserialize(string::read(locate("Database/Sufami Turbo.bml"))); -} - -auto Icarus::error() const -> string { - return errorMessage; -} - -auto Icarus::missing() const -> vector { - return missingFiles; -} - -auto Icarus::success(string location) -> string { - errorMessage = ""; - return location; -} - -auto Icarus::failure(string message) -> string { - errorMessage = message; - return {}; -} - -auto Icarus::manifest(string location) -> string { - location.transform("\\", "/").trimRight("/").append("/"); - if(!directory::exists(location)) return {}; - - auto type = Location::suffix(location).downcase(); - if(type == ".fc") return famicomManifest(location); - if(type == ".sfc") return superFamicomManifest(location); - if(type == ".sg1000") return sg1000Manifest(location); - if(type == ".sc3000") return sc3000Manifest(location); - if(type == ".ms") return masterSystemManifest(location); - if(type == ".md") return megaDriveManifest(location); - if(type == ".pce") return pcEngineManifest(location); - if(type == ".sgx") return superGrafxManifest(location); - if(type == ".cv") return colecoVisionManifest(location); - if(type == ".msx") return msxManifest(location); - if(type == ".gb") return gameBoyManifest(location); - if(type == ".gbc") return gameBoyColorManifest(location); - if(type == ".gba") return gameBoyAdvanceManifest(location); - if(type == ".gg") return gameGearManifest(location); - if(type == ".ws") return wonderSwanManifest(location); - if(type == ".wsc") return wonderSwanColorManifest(location); - if(type == ".pc2") return pocketChallengeV2Manifest(location); - if(type == ".ngp") return neoGeoPocketManifest(location); - if(type == ".ngpc") return neoGeoPocketColorManifest(location); - if(type == ".bs") return bsMemoryManifest(location); - if(type == ".st") return sufamiTurboManifest(location); - - return {}; -} - -auto Icarus::import(string location) -> string { - errorMessage = {}; - missingFiles = {}; - - location.transform("\\", "/").trimRight("/"); - if(!file::exists(location)) return failure("file does not exist"); - if(!file::readable(location)) return failure("file is unreadable"); - - auto name = Location::prefix(location); - auto type = Location::suffix(location).downcase(); - if(!name || !type) return failure("invalid file name"); - - auto buffer = file::read(location); - if(!buffer) return failure("file is empty"); - - if(type == ".zip") { - Decode::ZIP zip; - if(!zip.open(location)) return failure("ZIP archive is invalid"); - if(!zip.file) return failure("ZIP archive is empty"); - - name = Location::prefix(zip.file[0].name); - type = Location::suffix(zip.file[0].name).downcase(); - buffer = zip.extract(zip.file[0]); - } - - if(type == ".fc" || type == ".nes") return famicomImport(buffer, location); - if(type == ".sfc" || type == ".smc") return superFamicomImport(buffer, location); - if(type == ".sg1000" || type == ".sg") return sg1000Import(buffer, location); - if(type == ".sc3000" || type == ".sc") return sc3000Import(buffer, location); - if(type == ".ms" || type == ".sms") return masterSystemImport(buffer, location); - if(type == ".md" || type == ".smd" || type == ".gen") return megaDriveImport(buffer, location); - if(type == ".pce") return pcEngineImport(buffer, location); - if(type == ".sgx") return superGrafxImport(buffer, location); - if(type == ".cv" || type == ".col") return colecoVisionImport(buffer, location); - if(type == ".msx") return msxImport(buffer, location); - if(type == ".gb") return gameBoyImport(buffer, location); - if(type == ".gbc") return gameBoyColorImport(buffer, location); - if(type == ".gba") return gameBoyAdvanceImport(buffer, location); - if(type == ".gg") return gameGearImport(buffer, location); - if(type == ".ws") return wonderSwanImport(buffer, location); - if(type == ".wsc") return wonderSwanColorImport(buffer, location); - if(type == ".pc2") return pocketChallengeV2Import(buffer, location); - if(type == ".ngp") return neoGeoPocketImport(buffer, location); - if(type == ".ngpc" || type == ".ngc") return neoGeoPocketColorImport(buffer, location); - if(type == ".bs") return bsMemoryImport(buffer, location); - if(type == ".st") return sufamiTurboImport(buffer, location); - - return failure("unrecognized file extension"); -} - -auto Icarus::concatenate(vector& output, string location) -> void { - if(auto input = file::read(location)) { - auto size = output.size(); - output.resize(size + input.size()); - memory::copy(output.data() + size, input.data(), input.size()); - } -} diff --git a/icarus/core/core.hpp b/icarus/core/core.hpp deleted file mode 100644 index bacbc16d..00000000 --- a/icarus/core/core.hpp +++ /dev/null @@ -1,171 +0,0 @@ -struct Icarus { - virtual auto create(const string& pathname) -> bool { - return directory::create(pathname); - } - - virtual auto exists(const string& filename) -> bool { - return file::exists(filename); - } - - virtual auto copy(const string& target, const string& source) -> bool { - return file::copy(target, source); - } - - virtual auto write(const string& filename, const uint8_t* data, uint size) -> bool { - return file::write(filename, {data, size}); - } - - auto write(const string& filename, const vector& buffer) -> bool { - return write(filename, buffer.data(), buffer.size()); - } - - auto write(const string& filename, const string& text) -> bool { - return write(filename, (const uint8_t*)text.data(), text.size()); - } - - //core.cpp - Icarus(); - - auto error() const -> string; - auto missing() const -> vector; - auto success(string location) -> string; - auto failure(string message) -> string; - - auto manifest(string location) -> string; - auto import(string location) -> string; - - auto concatenate(vector& output, string location) -> void; - - //famicom.cpp - auto famicomManifest(string location) -> string; - auto famicomManifest(vector& buffer, string location) -> string; - auto famicomImport(vector& buffer, string location) -> string; - - //super-famicom.cpp - auto superFamicomManifest(string location) -> string; - auto superFamicomManifest(vector& buffer, string location) -> string; - auto superFamicomImport(vector& buffer, string location) -> string; - - //sg-1000.cpp - auto sg1000Manifest(string location) -> string; - auto sg1000Manifest(vector& buffer, string location) -> string; - auto sg1000Import(vector& buffer, string location) -> string; - - //sc-3000.cpp - auto sc3000Manifest(string location) -> string; - auto sc3000Manifest(vector& buffer, string location) -> string; - auto sc3000Import(vector& buffer, string location) -> string; - - //master-system.cpp - auto masterSystemManifest(string location) -> string; - auto masterSystemManifest(vector& buffer, string location) -> string; - auto masterSystemImport(vector& buffer, string location) -> string; - - //mega-drive.cpp - auto megaDriveManifest(string location) -> string; - auto megaDriveManifest(vector& buffer, string location) -> string; - auto megaDriveImport(vector& buffer, string location) -> string; - - //pc-engine.cpp - auto pcEngineManifest(string location) -> string; - auto pcEngineManifest(vector& buffer, string location) -> string; - auto pcEngineImport(vector& buffer, string location) -> string; - - //supergrafx.cpp - auto superGrafxManifest(string location) -> string; - auto superGrafxManifest(vector& buffer, string location) -> string; - auto superGrafxImport(vector& buffer, string location) -> string; - - //colecovision.cpp - auto colecoVisionManifest(string location) -> string; - auto colecoVisionManifest(vector& buffer, string location) -> string; - auto colecoVisionImport(vector& buffer, string location) -> string; - - //msx.cpp - auto msxManifest(string location) -> string; - auto msxManifest(vector& buffer, string location) -> string; - auto msxImport(vector& buffer, string location) -> string; - - //game-boy.cpp - auto gameBoyManifest(string location) -> string; - auto gameBoyManifest(vector& buffer, string location) -> string; - auto gameBoyImport(vector& buffer, string location) -> string; - - //game-boy-color.cpp - auto gameBoyColorManifest(string location) -> string; - auto gameBoyColorManifest(vector& buffer, string location) -> string; - auto gameBoyColorImport(vector& buffer, string location) -> string; - - //game-boy-advance.cpp - auto gameBoyAdvanceManifest(string location) -> string; - auto gameBoyAdvanceManifest(vector& buffer, string location) -> string; - auto gameBoyAdvanceImport(vector& buffer, string location) -> string; - - //game-gear.cpp - auto gameGearManifest(string location) -> string; - auto gameGearManifest(vector& buffer, string location) -> string; - auto gameGearImport(vector& buffer, string location) -> string; - - //wonderswan.cpp - auto wonderSwanManifest(string location) -> string; - auto wonderSwanManifest(vector& buffer, string location) -> string; - auto wonderSwanImport(vector& buffer, string location) -> string; - - //wonderswan-color.cpp - auto wonderSwanColorManifest(string location) -> string; - auto wonderSwanColorManifest(vector& buffer, string location) -> string; - auto wonderSwanColorImport(vector& buffer, string location) -> string; - - //pocket-challenge-v2.cpp - auto pocketChallengeV2Manifest(string location) -> string; - auto pocketChallengeV2Manifest(vector& buffer, string location) -> string; - auto pocketChallengeV2Import(vector& buffer, string location) -> string; - - //neo-geo-pocket.cpp - auto neoGeoPocketManifest(string location) -> string; - auto neoGeoPocketManifest(vector& buffer, string location) -> string; - auto neoGeoPocketImport(vector& buffer, string location) -> string; - - //neo-geo-pocket-color.cpp - auto neoGeoPocketColorManifest(string location) -> string; - auto neoGeoPocketColorManifest(vector& buffer, string location) -> string; - auto neoGeoPocketColorImport(vector& buffer, string location) -> string; - - //bs-memory.cpp - auto bsMemoryManifest(string location) -> string; - auto bsMemoryManifest(vector& buffer, string location) -> string; - auto bsMemoryImport(vector& buffer, string location) -> string; - - //sufami-turbo.cpp - auto sufamiTurboManifest(string location) -> string; - auto sufamiTurboManifest(vector& buffer, string location) -> string; - auto sufamiTurboImport(vector& buffer, string location) -> string; - -private: - string errorMessage; - vector missingFiles; -}; - -namespace Database { - Markup::Node Famicom; - Markup::Node SuperFamicom; - Markup::Node SG1000; - Markup::Node SC3000; - Markup::Node MasterSystem; - Markup::Node MegaDrive; - Markup::Node PCEngine; - Markup::Node SuperGrafx; - Markup::Node ColecoVision; - Markup::Node MSX; - Markup::Node GameBoy; - Markup::Node GameBoyColor; - Markup::Node GameBoyAdvance; - Markup::Node GameGear; - Markup::Node WonderSwan; - Markup::Node WonderSwanColor; - Markup::Node PocketChallengeV2; - Markup::Node NeoGeoPocket; - Markup::Node NeoGeoPocketColor; - Markup::Node BSMemory; - Markup::Node SufamiTurbo; -}; diff --git a/icarus/core/famicom.cpp b/icarus/core/famicom.cpp deleted file mode 100644 index 877c7c58..00000000 --- a/icarus/core/famicom.cpp +++ /dev/null @@ -1,58 +0,0 @@ -auto Icarus::famicomManifest(string location) -> string { - vector buffer; - concatenate(buffer, {location, "ines.rom"}); - concatenate(buffer, {location, "program.rom"}); - concatenate(buffer, {location, "character.rom"}); - return famicomManifest(buffer, location); -} - -auto Icarus::famicomManifest(vector& buffer, string location) -> string { - if(settings["icarus/UseDatabase"].boolean()) { - auto digest = Hash::SHA256(buffer).digest(); - for(auto game : Database::Famicom.find("game")) { - if(game["sha256"].text() == digest) return BML::serialize(game); - } - } - - if(settings["icarus/UseHeuristics"].boolean()) { - Heuristics::Famicom game{buffer, location}; - if(auto manifest = game.manifest()) return manifest; - } - - return {}; -} - -auto Icarus::famicomImport(vector& buffer, string location) -> string { - auto name = Location::prefix(location); - auto source = Location::path(location); - string target{settings["Library/Location"].text(), "Famicom/", name, ".fc/"}; - - auto manifest = famicomManifest(buffer, location); - if(!manifest) return failure("failed to parse ROM image"); - - if(!create(target)) return failure("library path unwritable"); - if(exists({source, name, ".sav"}) && !exists({target, "save.ram"})) { - copy({source, name, ".sav"}, {target, "save.ram"}); - } - - if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest); - auto document = BML::unserialize(manifest); - uint offset = 0; - if(true) { - //todo: support images without iNES headers (via database lookup) - uint size = 16; - write({target, "ines.rom"}, &buffer[offset], size); - offset += size; - } - if(auto program = document["game/board/memory(type=ROM,content=Program)"]) { - uint size = program["size"].natural(); - write({target, "program.rom"}, &buffer[offset], size); - offset += size; - } - if(auto character = document["game/board/memory(type=ROM,content=Character)"]) { - uint size = character["size"].natural(); - write({target, "character.rom"}, &buffer[offset], size); - offset += size; - } - return success(target); -} diff --git a/icarus/core/game-boy-advance.cpp b/icarus/core/game-boy-advance.cpp deleted file mode 100644 index cf17d4df..00000000 --- a/icarus/core/game-boy-advance.cpp +++ /dev/null @@ -1,39 +0,0 @@ -auto Icarus::gameBoyAdvanceManifest(string location) -> string { - vector buffer; - concatenate(buffer, {location, "program.rom"}); - return gameBoyAdvanceManifest(buffer, location); -} - -auto Icarus::gameBoyAdvanceManifest(vector& buffer, string location) -> string { - if(settings["icarus/UseDatabase"].boolean()) { - auto digest = Hash::SHA256(buffer).digest(); - for(auto game : Database::GameBoyAdvance.find("game")) { - if(game["sha256"].text() == digest) return BML::serialize(game); - } - } - - if(settings["icarus/UseHeuristics"].boolean()) { - Heuristics::GameBoyAdvance game{buffer, location}; - if(auto manifest = game.manifest()) return manifest; - } - - return {}; -} - -auto Icarus::gameBoyAdvanceImport(vector& buffer, string location) -> string { - auto name = Location::prefix(location); - auto source = Location::path(location); - string target{settings["Library/Location"].text(), "Game Boy Advance/", name, ".gba/"}; - - auto manifest = gameBoyAdvanceManifest(buffer, location); - if(!manifest) return failure("failed to parse ROM image"); - - if(!create(target)) return failure("library path unwritable"); - if(exists({source, name, ".sav"}) && !exists({target, "save.ram"})) { - copy({source, name, ".sav"}, {target, "save.ram"}); - } - - if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest); - write({target, "program.rom"}, buffer); - return success(target); -} diff --git a/icarus/core/game-boy-color.cpp b/icarus/core/game-boy-color.cpp deleted file mode 100644 index aa25f019..00000000 --- a/icarus/core/game-boy-color.cpp +++ /dev/null @@ -1,40 +0,0 @@ -auto Icarus::gameBoyColorManifest(string location) -> string { - vector buffer; - concatenate(buffer, {location, "program.rom"}); - return gameBoyColorManifest(buffer, location); -} - -auto Icarus::gameBoyColorManifest(vector& buffer, string location) -> string { - auto digest = Hash::SHA256(buffer).digest(); - - if(settings["icarus/UseDatabase"].boolean()) { - for(auto game : Database::GameBoyColor.find("game")) { - if(game["sha256"].text() == digest) return BML::serialize(game); - } - } - - if(settings["icarus/UseHeuristics"].boolean()) { - Heuristics::GameBoy game{buffer, location}; - if(auto manifest = game.manifest()) return manifest; - } - - return {}; -} - -auto Icarus::gameBoyColorImport(vector& buffer, string location) -> string { - auto name = Location::prefix(location); - auto source = Location::path(location); - string target{settings["Library/Location"].text(), "Game Boy Color/", name, ".gbc/"}; - - auto manifest = gameBoyColorManifest(buffer, location); - if(!manifest) return failure("failed to parse ROM image"); - - if(!create(target)) return failure("library path unwritable"); - if(exists({source, name, ".sav"}) && !exists({target, "save.ram"})) { - copy({source, name, ".sav"}, {target, "save.ram"}); - } - - if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest); - write({target, "program.rom"}, buffer); - return success(target); -} diff --git a/icarus/core/game-boy.cpp b/icarus/core/game-boy.cpp deleted file mode 100644 index d358a423..00000000 --- a/icarus/core/game-boy.cpp +++ /dev/null @@ -1,40 +0,0 @@ -auto Icarus::gameBoyManifest(string location) -> string { - vector buffer; - concatenate(buffer, {location, "program.rom"}); - return gameBoyManifest(buffer, location); -} - -auto Icarus::gameBoyManifest(vector& buffer, string location) -> string { - auto digest = Hash::SHA256(buffer).digest(); - - if(settings["icarus/UseDatabase"].boolean()) { - for(auto game : Database::GameBoy.find("game")) { - if(game["sha256"].text() == digest) return BML::serialize(game); - } - } - - if(settings["icarus/UseHeuristics"].boolean()) { - Heuristics::GameBoy game{buffer, location}; - if(auto manifest = game.manifest()) return manifest; - } - - return {}; -} - -auto Icarus::gameBoyImport(vector& buffer, string location) -> string { - auto name = Location::prefix(location); - auto source = Location::path(location); - string target{settings["Library/Location"].text(), "Game Boy/", name, ".gb/"}; - - auto manifest = gameBoyManifest(buffer, location); - if(!manifest) return failure("failed to parse ROM image"); - - if(!create(target)) return failure("library path unwritable"); - if(exists({source, name, ".sav"}) && !exists({target, "save.ram"})) { - copy({source, name, ".sav"}, {target, "save.ram"}); - } - - if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest); - write({target, "program.rom"}, buffer); - return success(target); -} diff --git a/icarus/core/game-gear.cpp b/icarus/core/game-gear.cpp deleted file mode 100644 index f02c40a1..00000000 --- a/icarus/core/game-gear.cpp +++ /dev/null @@ -1,39 +0,0 @@ -auto Icarus::gameGearManifest(string location) -> string { - vector buffer; - concatenate(buffer, {location, "program.rom"}); - return gameGearManifest(buffer, location); -} - -auto Icarus::gameGearManifest(vector& buffer, string location) -> string { - if(settings["icarus/UseDatabase"].boolean()) { - auto digest = Hash::SHA256(buffer).digest(); - for(auto game : Database::GameGear.find("game")) { - if(game["sha256"].text() == digest) return BML::serialize(game); - } - } - - if(settings["icarus/UseHeuristics"].boolean()) { - Heuristics::GameGear game{buffer, location}; - if(auto manifest = game.manifest()) return manifest; - } - - return {}; -} - -auto Icarus::gameGearImport(vector& buffer, string location) -> string { - auto name = Location::prefix(location); - auto source = Location::path(location); - string target{settings["Library/Location"].text(), "Game Gear/", name, ".gg/"}; - - auto manifest = gameGearManifest(buffer, location); - if(!manifest) return failure("failed to parse ROM image"); - - if(!create(target)) return failure("library path unwritable"); - if(exists({source, name, ".sav"}) && !exists({target, "save.ram"})) { - copy({source, name, ".sav"}, {target, "save.ram"}); - } - - if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest); - write({target, "program.rom"}, buffer); - return success(target); -} diff --git a/icarus/core/master-system.cpp b/icarus/core/master-system.cpp deleted file mode 100644 index 28796adf..00000000 --- a/icarus/core/master-system.cpp +++ /dev/null @@ -1,39 +0,0 @@ -auto Icarus::masterSystemManifest(string location) -> string { - vector buffer; - concatenate(buffer, {location, "program.rom"}); - return masterSystemManifest(buffer, location); -} - -auto Icarus::masterSystemManifest(vector& buffer, string location) -> string { - if(settings["icarus/UseDatabase"].boolean()) { - auto digest = Hash::SHA256(buffer).digest(); - for(auto game : Database::MasterSystem.find("game")) { - if(game["sha256"].text() == digest) return BML::serialize(game); - } - } - - if(settings["icarus/UseHeuristics"].boolean()) { - Heuristics::MasterSystem game{buffer, location}; - if(auto manifest = game.manifest()) return manifest; - } - - return {}; -} - -auto Icarus::masterSystemImport(vector& buffer, string location) -> string { - auto name = Location::prefix(location); - auto source = Location::path(location); - string target{settings["Library/Location"].text(), "Master System/", name, ".ms/"}; - - auto manifest = masterSystemManifest(buffer, location); - if(!manifest) return failure("failed to parse ROM image"); - - if(!create(target)) return failure("library path unwritable"); - if(exists({source, name, ".sav"}) && !exists({target, "save.ram"})) { - copy({source, name, ".sav"}, {target, "save.ram"}); - } - - if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest); - write({target, "program.rom"}, buffer); - return success(target); -} diff --git a/icarus/core/mega-drive.cpp b/icarus/core/mega-drive.cpp deleted file mode 100644 index b110c06a..00000000 --- a/icarus/core/mega-drive.cpp +++ /dev/null @@ -1,52 +0,0 @@ -auto Icarus::megaDriveManifest(string location) -> string { - vector buffer; - concatenate(buffer, {location, "program.rom"}); - concatenate(buffer, {location, "patch.rom" }); - return megaDriveManifest(buffer, location); -} - -auto Icarus::megaDriveManifest(vector& buffer, string location) -> string { - if(settings["icarus/UseDatabase"].boolean()) { - auto digest = Hash::SHA256(buffer).digest(); - for(auto game : Database::MegaDrive.find("game")) { - if(game["sha256"].text() == digest) return BML::serialize(game); - } - } - - if(settings["icarus/UseHeuristics"].boolean()) { - Heuristics::MegaDrive game{buffer, location}; - if(auto manifest = game.manifest()) return manifest; - } - - return {}; -} - -auto Icarus::megaDriveImport(vector& buffer, string location) -> string { - auto name = Location::prefix(location); - auto source = Location::path(location); - string target{settings["Library/Location"].text(), "Mega Drive/", name, ".md/"}; - - auto manifest = megaDriveManifest(buffer, location); - if(!manifest) return failure("failed to parse ROM image"); - - if(!create(target)) return failure("library path unwritable"); - if(exists({source, name, ".sav"}) && !exists({target, "save.ram"})) { - copy({source, name, ".sav"}, {target, "save.ram"}); - } - - 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(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/msx.cpp b/icarus/core/msx.cpp deleted file mode 100644 index b9d00a55..00000000 --- a/icarus/core/msx.cpp +++ /dev/null @@ -1,39 +0,0 @@ -auto Icarus::msxManifest(string location) -> string { - vector buffer; - concatenate(buffer, {location, "program.rom"}); - return msxManifest(buffer, location); -} - -auto Icarus::msxManifest(vector& buffer, string location) -> string { - if(settings["icarus/UseDatabase"].boolean()) { - auto digest = Hash::SHA256(buffer).digest(); - for(auto game : Database::MSX.find("game")) { - if(game["sha256"].text() == digest) return BML::serialize(game); - } - } - - if(settings["icarus/UseHeuristics"].boolean()) { - Heuristics::MSX game{buffer, location}; - if(auto manifest = game.manifest()) return manifest; - } - - return {}; -} - -auto Icarus::msxImport(vector& buffer, string location) -> string { - auto name = Location::prefix(location); - auto source = Location::path(location); - string target{settings["Library/Location"].text(), "MSX/", name, ".msx/"}; - - auto manifest = msxManifest(buffer, location); - if(!manifest) return failure("failed to parse ROM image"); - - if(!create(target)) return failure("library path unwritable"); - if(exists({source, name, ".sav"}) && !exists({target, "save.ram"})) { - copy({source, name, ".sav"}, {target, "save.ram"}); - } - - if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest); - write({target, "program.rom"}, buffer); - return success(target); -} diff --git a/icarus/core/neo-geo-pocket-color.cpp b/icarus/core/neo-geo-pocket-color.cpp deleted file mode 100644 index 749a372c..00000000 --- a/icarus/core/neo-geo-pocket-color.cpp +++ /dev/null @@ -1,39 +0,0 @@ -auto Icarus::neoGeoPocketColorManifest(string location) -> string { - vector buffer; - concatenate(buffer, {location, "program.rom"}); - return neoGeoPocketColorManifest(buffer, location); -} - -auto Icarus::neoGeoPocketColorManifest(vector& buffer, string location) -> string { - if(settings["icarus/UseDatabase"].boolean()) { - auto digest = Hash::SHA256(buffer).digest(); - for(auto game : Database::NeoGeoPocketColor.find("game")) { - if(game["sha256"].text() == digest) return BML::serialize(game); - } - } - - if(settings["icarus/UseHeuristics"].boolean()) { - Heuristics::NeoGeoPocketColor game{buffer, location}; - if(auto manifest = game.manifest()) return manifest; - } - - return {}; -} - -auto Icarus::neoGeoPocketColorImport(vector& buffer, string location) -> string { - auto name = Location::prefix(location); - auto source = Location::path(location); - string target{settings["Library/Location"].text(), "Neo Geo Pocket Color/", name, ".ngpc/"}; - - auto manifest = neoGeoPocketColorManifest(buffer, location); - if(!manifest) return failure("failed to parse ROM image"); - - if(!create(target)) return failure("library path unwritable"); - if(exists({source, name, ".sav"}) && !exists({target, "save.ram"})) { - copy({source, name, ".sav"}, {target, "save.ram"}); - } - - if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest); - write({target, "program.rom"}, buffer); - return success(target); -} diff --git a/icarus/core/neo-geo-pocket.cpp b/icarus/core/neo-geo-pocket.cpp deleted file mode 100644 index f0646e41..00000000 --- a/icarus/core/neo-geo-pocket.cpp +++ /dev/null @@ -1,39 +0,0 @@ -auto Icarus::neoGeoPocketManifest(string location) -> string { - vector buffer; - concatenate(buffer, {location, "program.rom"}); - return neoGeoPocketManifest(buffer, location); -} - -auto Icarus::neoGeoPocketManifest(vector& buffer, string location) -> string { - if(settings["icarus/UseDatabase"].boolean()) { - auto digest = Hash::SHA256(buffer).digest(); - for(auto game : Database::NeoGeoPocket.find("game")) { - if(game["sha256"].text() == digest) return BML::serialize(game); - } - } - - if(settings["icarus/UseHeuristics"].boolean()) { - Heuristics::NeoGeoPocket game{buffer, location}; - if(auto manifest = game.manifest()) return manifest; - } - - return {}; -} - -auto Icarus::neoGeoPocketImport(vector& buffer, string location) -> string { - auto name = Location::prefix(location); - auto source = Location::path(location); - string target{settings["Library/Location"].text(), "Neo Geo Pocket/", name, ".ngp/"}; - - auto manifest = neoGeoPocketManifest(buffer, location); - if(!manifest) return failure("failed to parse ROM image"); - - if(!create(target)) return failure("library path unwritable"); - if(exists({source, name, ".sav"}) && !exists({target, "save.ram"})) { - copy({source, name, ".sav"}, {target, "save.ram"}); - } - - if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest); - write({target, "program.rom"}, buffer); - return success(target); -} diff --git a/icarus/core/pc-engine.cpp b/icarus/core/pc-engine.cpp deleted file mode 100644 index 5f9940f5..00000000 --- a/icarus/core/pc-engine.cpp +++ /dev/null @@ -1,39 +0,0 @@ -auto Icarus::pcEngineManifest(string location) -> string { - vector buffer; - concatenate(buffer, {location, "program.rom"}); - return pcEngineManifest(buffer, location); -} - -auto Icarus::pcEngineManifest(vector& buffer, string location) -> string { - if(settings["icarus/UseDatabase"].boolean()) { - auto digest = Hash::SHA256(buffer).digest(); - for(auto game : Database::PCEngine.find("game")) { - if(game["sha256"].text() == digest) return BML::serialize(game); - } - } - - if(settings["icarus/UseHeuristics"].boolean()) { - Heuristics::PCEngine game{buffer, location}; - if(auto manifest = game.manifest()) return manifest; - } - - return {}; -} - -auto Icarus::pcEngineImport(vector& buffer, string location) -> string { - auto name = Location::prefix(location); - auto source = Location::path(location); - string target{settings["Library/Location"].text(), "PC Engine/", name, ".pce/"}; - - auto manifest = pcEngineManifest(buffer, location); - if(!manifest) return failure("failed to parse ROM image"); - - if(!create(target)) return failure("library path unwritable"); - if(exists({source, name, ".sav"}) && !exists({target, "save.ram"})) { - copy({source, name, ".sav"}, {target, "save.ram"}); - } - - if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest); - write({target, "program.rom"}, buffer); - return success(target); -} diff --git a/icarus/core/pocket-challenge-v2.cpp b/icarus/core/pocket-challenge-v2.cpp deleted file mode 100644 index 6028166b..00000000 --- a/icarus/core/pocket-challenge-v2.cpp +++ /dev/null @@ -1,39 +0,0 @@ -auto Icarus::pocketChallengeV2Manifest(string location) -> string { - vector buffer; - concatenate(buffer, {location, "program.rom"}); - return pocketChallengeV2Manifest(buffer, location); -} - -auto Icarus::pocketChallengeV2Manifest(vector& buffer, string location) -> string { - if(settings["icarus/UseDatabase"].boolean()) { - auto digest = Hash::SHA256(buffer).digest(); - for(auto game : Database::PocketChallengeV2.find("game")) { - if(game["sha256"].text() == digest) return BML::serialize(game); - } - } - - if(settings["icarus/UseHeuristics"].boolean()) { - Heuristics::WonderSwan game{buffer, location}; - if(auto manifest = game.manifest()) return manifest; - } - - return {}; -} - -auto Icarus::pocketChallengeV2Import(vector& buffer, string location) -> string { - auto name = Location::prefix(location); - auto source = Location::path(location); - string target{settings["Library/Location"].text(), "Pocket Challenge V2/", name, ".pc2/"}; - - auto manifest = pocketChallengeV2Manifest(buffer, location); - if(!manifest) return failure("failed to parse ROM image"); - - if(!create(target)) return failure("library path unwritable"); - if(exists({source, name, ".sav"}) && !exists({target, "save.ram"})) { - copy({source, name, ".sav"}, {target, "save.ram"}); - } - - if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest); - write({target, "program.rom"}, buffer); - return success(target); -} diff --git a/icarus/core/sc-3000.cpp b/icarus/core/sc-3000.cpp deleted file mode 100644 index eb9d8906..00000000 --- a/icarus/core/sc-3000.cpp +++ /dev/null @@ -1,39 +0,0 @@ -auto Icarus::sc3000Manifest(string location) -> string { - vector buffer; - concatenate(buffer, {location, "program.rom"}); - return sc3000Manifest(buffer, location); -} - -auto Icarus::sc3000Manifest(vector& buffer, string location) -> string { - if(settings["icarus/UseDatabase"].boolean()) { - auto digest = Hash::SHA256(buffer).digest(); - for(auto game : Database::SC3000.find("game")) { - if(game["sha256"].text() == digest) return BML::serialize(game); - } - } - - if(settings["icarus/UseHeuristics"].boolean()) { - Heuristics::SC3000 game{buffer, location}; - if(auto manifest = game.manifest()) return manifest; - } - - return {}; -} - -auto Icarus::sc3000Import(vector& buffer, string location) -> string { - auto name = Location::prefix(location); - auto source = Location::path(location); - string target{settings["Library/Location"].text(), "SC-3000/", name, ".sc3000/"}; - - auto manifest = sc3000Manifest(buffer, location); - if(!manifest) return failure("failed to parse ROM image"); - - if(!create(target)) return failure("library path unwritable"); - if(exists({source, name, ".sav"}) && !exists({target, "save.ram"})) { - copy({source, name, ".sav"}, {target, "save.ram"}); - } - - if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest); - write({target, "program.rom"}, buffer); - return success(target); -} diff --git a/icarus/core/sg-1000.cpp b/icarus/core/sg-1000.cpp deleted file mode 100644 index 73b58291..00000000 --- a/icarus/core/sg-1000.cpp +++ /dev/null @@ -1,39 +0,0 @@ -auto Icarus::sg1000Manifest(string location) -> string { - vector buffer; - concatenate(buffer, {location, "program.rom"}); - return sg1000Manifest(buffer, location); -} - -auto Icarus::sg1000Manifest(vector& buffer, string location) -> string { - if(settings["icarus/UseDatabase"].boolean()) { - auto digest = Hash::SHA256(buffer).digest(); - for(auto game : Database::SG1000.find("game")) { - if(game["sha256"].text() == digest) return BML::serialize(game); - } - } - - if(settings["icarus/UseHeuristics"].boolean()) { - Heuristics::SG1000 game{buffer, location}; - if(auto manifest = game.manifest()) return manifest; - } - - return {}; -} - -auto Icarus::sg1000Import(vector& buffer, string location) -> string { - auto name = Location::prefix(location); - auto source = Location::path(location); - string target{settings["Library/Location"].text(), "SG-1000/", name, ".sg1000/"}; - - auto manifest = sg1000Manifest(buffer, location); - if(!manifest) return failure("failed to parse ROM image"); - - if(!create(target)) return failure("library path unwritable"); - if(exists({source, name, ".sav"}) && !exists({target, "save.ram"})) { - copy({source, name, ".sav"}, {target, "save.ram"}); - } - - if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest); - write({target, "program.rom"}, buffer); - return success(target); -} diff --git a/icarus/core/sufami-turbo.cpp b/icarus/core/sufami-turbo.cpp deleted file mode 100644 index 2bfce8ec..00000000 --- a/icarus/core/sufami-turbo.cpp +++ /dev/null @@ -1,39 +0,0 @@ -auto Icarus::sufamiTurboManifest(string location) -> string { - vector buffer; - concatenate(buffer, {location, "program.rom"}); - return sufamiTurboManifest(buffer, location); -} - -auto Icarus::sufamiTurboManifest(vector& buffer, string location) -> string { - if(settings["icarus/UseDatabase"].boolean()) { - auto digest = Hash::SHA256(buffer).digest(); - for(auto game : Database::SufamiTurbo.find("game")) { - if(game["sha256"].text() == digest) return BML::serialize(game); - } - } - - if(settings["icarus/UseHeuristics"].boolean()) { - Heuristics::SufamiTurbo game{buffer, location}; - if(auto manifest = game.manifest()) return manifest; - } - - return {}; -} - -auto Icarus::sufamiTurboImport(vector& buffer, string location) -> string { - auto name = Location::prefix(location); - auto source = Location::path(location); - string target{settings["Library/Location"].text(), "Sufami Turbo/", name, ".st/"}; - - auto manifest = sufamiTurboManifest(buffer, location); - if(!manifest) return failure("failed to parse ROM image"); - - if(!create(target)) return failure("library path unwritable"); - if(exists({source, name, ".sav"}) && !exists({target, "save.ram"})) { - copy({source, name, ".sav"}, {target, "save.ram"}); - } - - if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest); - write({target, "program.rom"}, buffer); - return success(target); -} diff --git a/icarus/core/super-famicom.cpp b/icarus/core/super-famicom.cpp deleted file mode 100644 index 0aac6c7b..00000000 --- a/icarus/core/super-famicom.cpp +++ /dev/null @@ -1,62 +0,0 @@ -auto Icarus::superFamicomManifest(string location) -> string { - vector buffer; - auto files = directory::files(location, "*.rom"); - concatenate(buffer, {location, "program.rom"}); - concatenate(buffer, {location, "data.rom" }); - for(auto& file : files.match("*.program.rom")) concatenate(buffer, {location, file}); - for(auto& file : files.match("*.data.rom" )) concatenate(buffer, {location, file}); - for(auto& file : files.match("*.boot.rom" )) concatenate(buffer, {location, file}); - return superFamicomManifest(buffer, location); -} - -auto Icarus::superFamicomManifest(vector& buffer, string location) -> string { - if(settings["icarus/UseDatabase"].boolean()) { - auto digest = Hash::SHA256(buffer).digest(); - for(auto game : Database::SuperFamicom.find("game")) { - if(game["sha256"].text() == digest) return BML::serialize(game); - } - } - - if(settings["icarus/UseHeuristics"].boolean()) { - Heuristics::SuperFamicom game{buffer, location}; - if(auto manifest = game.manifest()) return manifest; - } - - return {}; -} - -auto Icarus::superFamicomImport(vector& buffer, string location) -> string { - auto name = Location::prefix(location); - auto source = Location::path(location); - string target{settings["Library/Location"].text(), "Super Famicom/", name, ".sfc/"}; - - auto manifest = superFamicomManifest(buffer, location); - if(!manifest) return failure("failed to parse ROM image"); - - if(!create(target)) return failure("library path unwritable"); - if(exists({source, name, ".srm"}) && !exists({target, "save.ram"})) { - copy({source, name, ".srm"}, {target, "save.ram"}); - } - - 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(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) { - auto firmware = string{rom["identifier"].text(), ".", rom["content"].text(), ".rom"}.trimLeft(".", 1L).downcase(); - auto location = locate({"Firmware/", firmware}); - if(location && file::size(location) == size) { - write({target, name}, file::read(location)); - } else { - missingFiles.append(firmware); - } - 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/supergrafx.cpp b/icarus/core/supergrafx.cpp deleted file mode 100644 index 10969bc0..00000000 --- a/icarus/core/supergrafx.cpp +++ /dev/null @@ -1,39 +0,0 @@ -auto Icarus::superGrafxManifest(string location) -> string { - vector buffer; - concatenate(buffer, {location, "program.rom"}); - return superGrafxManifest(buffer, location); -} - -auto Icarus::superGrafxManifest(vector& buffer, string location) -> string { - if(settings["icarus/UseDatabase"].boolean()) { - auto digest = Hash::SHA256(buffer).digest(); - for(auto game : Database::SuperGrafx.find("game")) { - if(game["sha256"].text() == digest) return BML::serialize(game); - } - } - - if(settings["icarus/UseHeuristics"].boolean()) { - Heuristics::SuperGrafx game{buffer, location}; - if(auto manifest = game.manifest()) return manifest; - } - - return {}; -} - -auto Icarus::superGrafxImport(vector& buffer, string location) -> string { - auto name = Location::prefix(location); - auto source = Location::path(location); - string target{settings["Library/Location"].text(), "SuperGrafx/", name, ".sg/"}; - - auto manifest = superGrafxManifest(buffer, location); - if(!manifest) return failure("failed to parse ROM image"); - - if(!create(target)) return failure("library path unwritable"); - if(exists({source, name, ".sav"}) && !exists({target, "save.ram"})) { - copy({source, name, ".sav"}, {target, "save.ram"}); - } - - if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest); - write({target, "program.rom"}, buffer); - return success(target); -} diff --git a/icarus/core/wonderswan-color.cpp b/icarus/core/wonderswan-color.cpp deleted file mode 100644 index e3a48a8c..00000000 --- a/icarus/core/wonderswan-color.cpp +++ /dev/null @@ -1,39 +0,0 @@ -auto Icarus::wonderSwanColorManifest(string location) -> string { - vector buffer; - concatenate(buffer, {location, "program.rom"}); - return wonderSwanColorManifest(buffer, location); -} - -auto Icarus::wonderSwanColorManifest(vector& buffer, string location) -> string { - if(settings["icarus/UseDatabase"].boolean()) { - auto digest = Hash::SHA256(buffer).digest(); - for(auto game : Database::WonderSwanColor.find("game")) { - if(game["sha256"].text() == digest) return BML::serialize(game); - } - } - - if(settings["icarus/UseHeuristics"].boolean()) { - Heuristics::WonderSwan game{buffer, location}; - if(auto manifest = game.manifest()) return manifest; - } - - return {}; -} - -auto Icarus::wonderSwanColorImport(vector& buffer, string location) -> string { - auto name = Location::prefix(location); - auto source = Location::path(location); - string target{settings["Library/Location"].text(), "WonderSwan Color/", name, ".wsc/"}; - - auto manifest = wonderSwanColorManifest(buffer, location); - if(!manifest) return failure("failed to parse ROM image"); - - if(!create(target)) return failure("library path unwritable"); - if(exists({source, name, ".sav"}) && !exists({target, "save.ram"})) { - copy({source, name, ".sav"}, {target, "save.ram"}); - } - - if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest); - write({target, "program.rom"}, buffer); - return success(target); -} diff --git a/icarus/core/wonderswan.cpp b/icarus/core/wonderswan.cpp deleted file mode 100644 index 356c325d..00000000 --- a/icarus/core/wonderswan.cpp +++ /dev/null @@ -1,39 +0,0 @@ -auto Icarus::wonderSwanManifest(string location) -> string { - vector buffer; - concatenate(buffer, {location, "program.rom"}); - return wonderSwanManifest(buffer, location); -} - -auto Icarus::wonderSwanManifest(vector& buffer, string location) -> string { - if(settings["icarus/UseDatabase"].boolean()) { - auto digest = Hash::SHA256(buffer).digest(); - for(auto game : Database::WonderSwan.find("game")) { - if(game["sha256"].text() == digest) return BML::serialize(game); - } - } - - if(settings["icarus/UseHeuristics"].boolean()) { - Heuristics::WonderSwan game{buffer, location}; - if(auto manifest = game.manifest()) return manifest; - } - - return {}; -} - -auto Icarus::wonderSwanImport(vector& buffer, string location) -> string { - auto name = Location::prefix(location); - auto source = Location::path(location); - string target{settings["Library/Location"].text(), "WonderSwan/", name, ".ws/"}; - - auto manifest = wonderSwanManifest(buffer, location); - if(!manifest) return failure("failed to parse ROM image"); - - if(!create(target)) return failure("library path unwritable"); - if(exists({source, name, ".sav"}) && !exists({target, "save.ram"})) { - copy({source, name, ".sav"}, {target, "save.ram"}); - } - - if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest); - write({target, "program.rom"}, buffer); - return success(target); -} diff --git a/icarus/data/icarus.Manifest b/icarus/data/icarus.Manifest deleted file mode 100644 index 3f6f1d8d..00000000 --- a/icarus/data/icarus.Manifest +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - false - - - diff --git a/icarus/data/icarus.desktop b/icarus/data/icarus.desktop deleted file mode 100644 index 71f0fe03..00000000 --- a/icarus/data/icarus.desktop +++ /dev/null @@ -1,8 +0,0 @@ -[Desktop Entry] -Name=icarus -Comment=Emulator -Exec=icarus -Icon=icarus -Terminal=false -Type=Application -Categories=Game;Emulator; diff --git a/icarus/data/icarus.ico b/icarus/data/icarus.ico deleted file mode 100644 index b5859acf..00000000 Binary files a/icarus/data/icarus.ico and /dev/null differ diff --git a/icarus/data/icarus.plist b/icarus/data/icarus.plist deleted file mode 100644 index 7253f500..00000000 --- a/icarus/data/icarus.plist +++ /dev/null @@ -1,18 +0,0 @@ - - - - - CFBundleIdentifier - org.byuu.icarus - CFBundleDisplayName - icarus - CFBundleExecutable - icarus - CFBundleIconFile - icarus.icns - NSHighResolutionCapable - - NSSupportsAutomaticGraphicsSwitching - - - diff --git a/icarus/data/icarus.png b/icarus/data/icarus.png deleted file mode 100644 index b32718b1..00000000 Binary files a/icarus/data/icarus.png and /dev/null differ diff --git a/icarus/data/icarus.rc b/icarus/data/icarus.rc deleted file mode 100644 index 3f104857..00000000 --- a/icarus/data/icarus.rc +++ /dev/null @@ -1,2 +0,0 @@ -1 24 "icarus.Manifest" -2 ICON DISCARDABLE "icarus.ico" diff --git a/icarus/data/icarus.svg b/icarus/data/icarus.svg deleted file mode 100644 index aaa7c846..00000000 --- a/icarus/data/icarus.svg +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - diff --git a/icarus/heuristics/colecovision.cpp b/icarus/heuristics/colecovision.cpp deleted file mode 100644 index 89baa3aa..00000000 --- a/icarus/heuristics/colecovision.cpp +++ /dev/null @@ -1,32 +0,0 @@ -namespace Heuristics { - -struct ColecoVision { - ColecoVision(vector& data, string location); - explicit operator bool() const; - auto manifest() const -> string; - -private: - vector& data; - string location; -}; - -ColecoVision::ColecoVision(vector& data, string location) : data(data), location(location) { -} - -ColecoVision::operator bool() const { - return (bool)data; -} - -auto ColecoVision::manifest() const -> string { - string output; - output.append("game\n"); - output.append(" sha256: ", Hash::SHA256(data).digest(), "\n"); - output.append(" label: ", Location::prefix(location), "\n"); - output.append(" name: ", Location::prefix(location), "\n"); - output.append(" board\n"); - output.append(Memory{}.type("ROM").size(data.size()).content("Program").text()); - output.append(Memory{}.type("RAM").size(0x8000).content("Save").text()); - return output; -} - -} diff --git a/icarus/heuristics/famicom.cpp b/icarus/heuristics/famicom.cpp deleted file mode 100644 index 903605bb..00000000 --- a/icarus/heuristics/famicom.cpp +++ /dev/null @@ -1,173 +0,0 @@ -namespace Heuristics { - -struct Famicom { - Famicom(vector& data, string location); - explicit operator bool() const; - auto manifest() const -> string; - -private: - vector& data; - string location; -}; - -Famicom::Famicom(vector& data, string location) : data(data), location(location) { -} - -Famicom::operator bool() const { - if(data.size() < 16) return false; - if(data[0] != 'N') return false; - if(data[1] != 'E') return false; - if(data[2] != 'S') return false; - if(data[3] != 26) return false; - return true; -} - -auto Famicom::manifest() const -> string { - if(!operator bool()) return {}; - - uint mapper = ((data[7] >> 4) << 4) | (data[6] >> 4); - uint mirror = ((data[6] & 0x08) >> 2) | (data[6] & 0x01); - uint prgrom = data[4] * 0x4000; - uint chrrom = data[5] * 0x2000; - uint prgram = 0u; - uint chrram = chrrom == 0u ? 8192u : 0u; - - string output; - output.append("game\n"); - output.append(" sha256: ", Hash::SHA256({&data[16], data.size() - 16}).digest(), "\n"); - output.append(" label: ", Location::prefix(location), "\n"); - output.append(" name: ", Location::prefix(location), "\n"); - - switch(mapper) { - default: - output.append(" board: NES-NROM-256\n"); - output.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n"); - break; - - case 1: - output.append(" board: NES-SXROM\n"); - output.append(" chip type=MMC1B2\n"); - prgram = 8192; - break; - - case 2: - output.append(" board: NES-UOROM\n"); - output.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n"); - break; - - case 3: - output.append(" board: NES-CNROM\n"); - output.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n"); - break; - - case 4: - //MMC3 - output.append(" board: NES-TLROM\n"); - output.append(" chip type=MMC3B\n"); - prgram = 8192; - //MMC6 - //output.append(" board: NES-HKROM\n"); - //output.append(" chip type=MMC6\n"); - //prgram = 1024; - break; - - case 5: - output.append(" board: NES-ELROM\n"); - output.append(" chip type=MMC5\n"); - prgram = 65536; - break; - - case 7: - output.append(" board: NES-AOROM\n"); - break; - - case 9: - output.append(" board: NES-PNROM\n"); - output.append(" chip type=MMC2\n"); - prgram = 8192; - break; - - case 10: - output.append(" board: NES-FKROM\n"); - output.append(" chip type=MMC4\n"); - prgram = 8192; - break; - - case 16: - output.append(" board: BANDAI-FCG\n"); - output.append(" chip type=LZ93D50\n"); - break; - - case 21: - case 23: - case 25: - //VRC4 - output.append(" board: KONAMI-VRC-4\n"); - output.append(" chip type=VRC4\n"); - output.append(" pinout a0=1 a1=0\n"); - prgram = 8192; - break; - - case 22: - //VRC2 - output.append(" board: KONAMI-VRC-2\n"); - output.append(" chip type=VRC2\n"); - output.append(" pinout a0=0 a1=1\n"); - break; - - case 24: - output.append(" board: KONAMI-VRC-6\n"); - output.append(" chip type=VRC6\n"); - break; - - case 26: - output.append(" board: KONAMI-VRC-6\n"); - output.append(" chip type=VRC6\n"); - prgram = 8192; - break; - - case 34: - output.append(" board: NES-BNROM\n"); - output.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n"); - break; - - case 66: - output.append(" board: NES-GNROM\n"); - output.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n"); - break; - - case 69: - output.append(" board: SUNSOFT-5B\n"); - output.append(" chip type=5B\n"); - prgram = 8192; - break; - - case 73: - output.append(" board: KONAMI-VRC-3\n"); - output.append(" chip type=VRC3\n"); - output.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n"); - prgram = 8192; - break; - - case 75: - output.append(" board: KONAMI-VRC-1\n"); - output.append(" chip type=VRC1\n"); - break; - - case 85: - output.append(" board: KONAMI-VRC-7\n"); - output.append(" chip type=VRC7\n"); - prgram = 8192; - break; - } - - if(prgrom) output.append(Memory{}.type("ROM").size(prgrom).content("Program").text()); - if(prgram) output.append(Memory{}.type("RAM").size(prgram).content("Save").text()); - - if(chrrom) output.append(Memory{}.type("ROM").size(chrrom).content("Character").text()); - if(chrram) output.append(Memory{}.type("RAM").size(chrram).content("Character").isVolatile().text()); - - return output; -} - -} diff --git a/icarus/heuristics/game-boy-advance.cpp b/icarus/heuristics/game-boy-advance.cpp deleted file mode 100644 index 1353deb0..00000000 --- a/icarus/heuristics/game-boy-advance.cpp +++ /dev/null @@ -1,67 +0,0 @@ -namespace Heuristics { - -struct GameBoyAdvance { - GameBoyAdvance(vector& buffer, string location); - explicit operator bool() const; - auto manifest() const -> string; - -private: - vector& data; - string location; -}; - -GameBoyAdvance::GameBoyAdvance(vector& data, string location) : data(data), location(location) { -} - -GameBoyAdvance::operator bool() const { - return (bool)data; -} - -auto GameBoyAdvance::manifest() const -> string { - if(!operator bool()) return {}; - - vector identifiers = { - "SRAM_V", - "SRAM_F_V", - "EEPROM_V", - "FLASH_V", - "FLASH512_V", - "FLASH1M_V", - }; - - vector list; - for(auto& identifier : identifiers) { - for(int n : range(data.size() - 16)) { - if(!memory::compare(&data[n], identifier.data(), identifier.size())) { - auto p = (const char*)&data[n + identifier.size()]; - if(p[0] >= '0' && p[0] <= '9' - && p[1] >= '0' && p[1] <= '9' - && p[2] >= '0' && p[2] <= '9' - ) { - char text[16]; - memory::copy(text, &data[n], identifier.size() + 3); - text[identifier.size() + 3] = 0; - if(!list.find(text)) list.append(text); - } - } - } - } - - string output; - output.append("game\n"); - output.append(" sha256: ", Hash::SHA256(data).digest(), "\n"); - output.append(" label: ", Location::prefix(location), "\n"); - output.append(" name: ", Location::prefix(location), "\n"); - output.append(" board\n"); - output.append(Memory{}.type("ROM").size(data.size()).content("Program").text()); - if(!list); - else if(list.left().beginsWith("SRAM_V" )) output.append(Memory{}.type("RAM" ).size( 0x8000).content("Save").text()); - else if(list.left().beginsWith("SRAM_F_V" )) output.append(Memory{}.type("RAM" ).size( 0x8000).content("Save").text()); - else if(list.left().beginsWith("EEPROM_V" )) output.append(Memory{}.type("EEPROM").size( 0x0).content("Save").text()); - else if(list.left().beginsWith("FLASH_V" )) output.append(Memory{}.type("Flash" ).size(0x10000).content("Save").manufacturer("Macronix").text()); - else if(list.left().beginsWith("FLASH512_V")) output.append(Memory{}.type("Flash" ).size(0x10000).content("Save").manufacturer("Macronix").text()); - else if(list.left().beginsWith("FLASH1M_V" )) output.append(Memory{}.type("Flash" ).size(0x20000).content("Save").manufacturer("Macronix").text()); - return output; -} - -} diff --git a/icarus/heuristics/game-gear.cpp b/icarus/heuristics/game-gear.cpp deleted file mode 100644 index 5897c90f..00000000 --- a/icarus/heuristics/game-gear.cpp +++ /dev/null @@ -1,32 +0,0 @@ -namespace Heuristics { - -struct GameGear { - GameGear(vector& data, string location); - explicit operator bool() const; - auto manifest() const -> string; - -private: - vector& data; - string location; -}; - -GameGear::GameGear(vector& data, string location) : data(data), location(location) { -} - -GameGear::operator bool() const { - return (bool)data; -} - -auto GameGear::manifest() const -> string { - string output; - output.append("game\n"); - output.append(" sha256: ", Hash::SHA256(data).digest(), "\n"); - output.append(" label: ", Location::prefix(location), "\n"); - output.append(" name: ", Location::prefix(location), "\n"); - output.append(" board\n"); - output.append(Memory{}.type("ROM").size(data.size()).content("Program").text()); - output.append(Memory{}.type("RAM").size(0x8000).content("Save").text()); - return output; -} - -} diff --git a/icarus/heuristics/master-system.cpp b/icarus/heuristics/master-system.cpp deleted file mode 100644 index 450ebaac..00000000 --- a/icarus/heuristics/master-system.cpp +++ /dev/null @@ -1,32 +0,0 @@ -namespace Heuristics { - -struct MasterSystem { - MasterSystem(vector& data, string location); - explicit operator bool() const; - auto manifest() const -> string; - -private: - vector& data; - string location; -}; - -MasterSystem::MasterSystem(vector& data, string location) : data(data), location(location) { -} - -MasterSystem::operator bool() const { - return (bool)data; -} - -auto MasterSystem::manifest() const -> string { - string output; - output.append("game\n"); - output.append(" sha256: ", Hash::SHA256(data).digest(), "\n"); - output.append(" label: ", Location::prefix(location), "\n"); - output.append(" name: ", Location::prefix(location), "\n"); - output.append(" board\n"); - output.append(Memory{}.type("ROM").size(data.size()).content("Program").text()); - output.append(Memory{}.type("RAM").size(0x8000).content("Save").text()); - return output; -} - -} diff --git a/icarus/heuristics/mega-drive.cpp b/icarus/heuristics/mega-drive.cpp deleted file mode 100644 index 24d4d9e8..00000000 --- a/icarus/heuristics/mega-drive.cpp +++ /dev/null @@ -1,111 +0,0 @@ -namespace Heuristics { - -struct MegaDrive { - MegaDrive(vector& data, string location); - explicit operator bool() const; - auto manifest() const -> string; - -private: - vector& data; - string location; -}; - -MegaDrive::MegaDrive(vector& data, string location) : data(data), location(location) { -} - -MegaDrive::operator bool() const { - return data.size() >= 0x200; -} - -auto MegaDrive::manifest() const -> string { - if(!operator bool()) return {}; - - string ramMode = "none"; - - uint32_t ramFrom = 0; - ramFrom |= data[0x01b4] << 24; - ramFrom |= data[0x01b5] << 16; - ramFrom |= data[0x01b6] << 8; - ramFrom |= data[0x01b7] << 0; - - uint32_t ramTo = 0; - ramTo |= data[0x01b8] << 24; - ramTo |= data[0x01b9] << 16; - ramTo |= data[0x01ba] << 8; - ramTo |= data[0x01bb] << 0; - - if(!(ramFrom & 1) && !(ramTo & 1)) ramMode = "hi"; - if( (ramFrom & 1) && (ramTo & 1)) ramMode = "lo"; - if(!(ramFrom & 1) && (ramTo & 1)) ramMode = "word"; - if(data[0x01b0] != 'R' || data[0x01b1] != 'A') ramMode = "none"; - - uint32_t ramSize = ramTo - ramFrom + 1; - if(ramMode == "hi") ramSize = (ramTo >> 1) - (ramFrom >> 1) + 1; - if(ramMode == "lo") ramSize = (ramTo >> 1) - (ramFrom >> 1) + 1; - if(ramMode == "word") ramSize = ramTo - ramFrom + 1; - if(ramMode != "none") ramSize = bit::round(min(0x20000, ramSize)); - if(ramMode == "none") ramSize = 0; - - vector regions; - string region = slice((const char*)&data[0x1f0], 0, 16).trimRight(" "); - if(!regions) { - if(region == "JAPAN" ) regions.append("NTSC-J"); - if(region == "EUROPE") regions.append("PAL"); - } - if(!regions) { - if(region.find("J")) regions.append("NTSC-J"); - if(region.find("U")) regions.append("NTSC-U"); - if(region.find("E")) regions.append("PAL"); - if(region.find("W")) regions.append("NTSC-J", "NTSC-U", "PAL"); - } - if(!regions && region.size() == 1) { - uint8_t field = region.hex(); - if(field & 0x01) regions.append("NTSC-J"); - if(field & 0x04) regions.append("NTSC-U"); - if(field & 0x08) regions.append("PAL"); - } - if(!regions) { - regions.append("NTSC-J"); - } - - string domesticName; - domesticName.resize(48); - memory::copy(domesticName.get(), &data[0x0120], domesticName.size()); - for(auto& c : domesticName) if(c < 0x20 || c > 0x7e) c = ' '; - while(domesticName.find(" ")) domesticName.replace(" ", " "); - domesticName.strip(); - - string internationalName; - internationalName.resize(48); - memory::copy(internationalName.get(), &data[0x0150], internationalName.size()); - for(auto& c : internationalName) if(c < 0x20 || c > 0x7e) c = ' '; - while(internationalName.find(" ")) internationalName.replace(" ", " "); - internationalName.strip(); - - string output; - output.append("game\n"); - output.append(" sha256: ", Hash::SHA256(data).digest(), "\n"); - output.append(" label: ", Location::prefix(location), "\n"); - output.append(" name: ", Location::prefix(location), "\n"); - output.append(" title: ", domesticName, "\n"); - output.append(" region: ", regions.left(), "\n"); - output.append(" board\n"); - if(domesticName == "Game Genie") { - output.append(Memory{}.type("ROM").size(data.size()).content("Program").text()); - output.append(Slot{}.type("MegaDrive").text()); - } else if(domesticName == "SONIC & KNUCKLES") { - output.append(Memory{}.type("ROM").size(0x200000).content("Program").text()); - output.append(Memory{}.type("ROM").size( 0x40000).content("Patch").text()); - output.append(Slot{}.type("MegaDrive").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"); - output.append(" offset: 0x", hex(ramFrom), "\n"); - } - return output; -} - -} diff --git a/icarus/heuristics/msx.cpp b/icarus/heuristics/msx.cpp deleted file mode 100644 index 6470cef3..00000000 --- a/icarus/heuristics/msx.cpp +++ /dev/null @@ -1,31 +0,0 @@ -namespace Heuristics { - -struct MSX { - MSX(vector& data, string location); - explicit operator bool() const; - auto manifest() const -> string; - -private: - vector& data; - string location; -}; - -MSX::MSX(vector& data, string location) : data(data), location(location) { -} - -MSX::operator bool() const { - return (bool)data; -} - -auto MSX::manifest() const -> string { - string output; - output.append("game\n"); - output.append(" sha256: ", Hash::SHA256(data).digest(), "\n"); - output.append(" label: ", Location::prefix(location), "\n"); - output.append(" name: ", Location::prefix(location), "\n"); - output.append(" board\n"); - output.append(Memory{}.type("ROM").size(data.size()).content("Program").text()); - return output; -} - -} diff --git a/icarus/heuristics/neo-geo-pocket-color.cpp b/icarus/heuristics/neo-geo-pocket-color.cpp deleted file mode 100644 index 6390f166..00000000 --- a/icarus/heuristics/neo-geo-pocket-color.cpp +++ /dev/null @@ -1,55 +0,0 @@ -namespace Heuristics { - -struct NeoGeoPocketColor { - NeoGeoPocketColor(vector& data, string location); - explicit operator bool() const; - auto manifest() const -> string; - auto title() const -> string; - -private: - vector& data; - string location; -}; - -NeoGeoPocketColor::NeoGeoPocketColor(vector& data, string location) : data(data), location(location) { -} - -NeoGeoPocketColor::operator bool() const { - switch(data.size()) { - case 0x080000: return true; // 4mbit - case 0x100000: return true; // 8mbit - case 0x200000: return true; //16mbit - case 0x280000: return true; //20mbit - case 0x300000: return true; //24mbit - case 0x400000: return true; //32mbit - } - return false; -} - -auto NeoGeoPocketColor::manifest() const -> string { - if(!operator bool()) return {}; - - string output; - output.append("game\n"); - output.append(" sha256: ", Hash::SHA256(data).digest(), "\n"); - output.append(" label: ", Location::prefix(location), "\n"); - output.append(" name: ", Location::prefix(location), "\n"); - output.append(" title: ", title(), "\n"); - output.append(" board\n"); - output.append(Memory{}.type("ROM").size(data.size()).content("Program").text()); - return output; -} - -auto NeoGeoPocketColor::title() const -> string { - if(!operator bool()) return {}; - - string title; - title.size(12); - for(uint index : range(12)) { - char letter = data[0x24 + index]; - if(letter >= 0x20 && letter <= 0x7e) title.get()[index] = letter; - } - return title.strip(); -} - -} diff --git a/icarus/heuristics/neo-geo-pocket.cpp b/icarus/heuristics/neo-geo-pocket.cpp deleted file mode 100644 index 46b014e9..00000000 --- a/icarus/heuristics/neo-geo-pocket.cpp +++ /dev/null @@ -1,55 +0,0 @@ -namespace Heuristics { - -struct NeoGeoPocket { - NeoGeoPocket(vector& data, string location); - explicit operator bool() const; - auto manifest() const -> string; - auto title() const -> string; - -private: - vector& data; - string location; -}; - -NeoGeoPocket::NeoGeoPocket(vector& data, string location) : data(data), location(location) { -} - -NeoGeoPocket::operator bool() const { - switch(data.size()) { - case 0x080000: return true; // 4mbit - case 0x100000: return true; // 8mbit - case 0x200000: return true; //16mbit - case 0x280000: return true; //20mbit - case 0x300000: return true; //24mbit - case 0x400000: return true; //32mbit - } - return false; -} - -auto NeoGeoPocket::manifest() const -> string { - if(!operator bool()) return {}; - - string output; - output.append("game\n"); - output.append(" sha256: ", Hash::SHA256(data).digest(), "\n"); - output.append(" label: ", Location::prefix(location), "\n"); - output.append(" name: ", Location::prefix(location), "\n"); - output.append(" title: ", title(), "\n"); - output.append(" board\n"); - output.append(Memory{}.type("ROM").size(data.size()).content("Program").text()); - return output; -} - -auto NeoGeoPocket::title() const -> string { - if(!operator bool()) return {}; - - string title; - title.size(12); - for(uint index : range(12)) { - char letter = data[0x24 + index]; - if(letter >= 0x20 && letter <= 0x7e) title.get()[index] = letter; - } - return title.strip(); -} - -} diff --git a/icarus/heuristics/pc-engine.cpp b/icarus/heuristics/pc-engine.cpp deleted file mode 100644 index 2106bc50..00000000 --- a/icarus/heuristics/pc-engine.cpp +++ /dev/null @@ -1,36 +0,0 @@ -namespace Heuristics { - -struct PCEngine { - PCEngine(vector& data, string location); - explicit operator bool() const; - auto manifest() const -> string; - -private: - vector& data; - string location; -}; - -PCEngine::PCEngine(vector& data, string location) : data(data), location(location) { - if((data.size() & 0x1fff) == 512) { - //remove header if present - memory::move(&data[0], &data[512], data.size() - 512); - data.resize(data.size() - 512); - } -} - -PCEngine::operator bool() const { - return (bool)data; -} - -auto PCEngine::manifest() const -> string { - string output; - output.append("game\n"); - output.append(" sha256: ", Hash::SHA256(data).digest(), "\n"); - output.append(" label: ", Location::prefix(location), "\n"); - output.append(" name: ", Location::prefix(location), "\n"); - output.append(" board\n"); - output.append(Memory{}.type("ROM").size(data.size()).content("Program").text()); - return output; -} - -} diff --git a/icarus/heuristics/sc-3000.cpp b/icarus/heuristics/sc-3000.cpp deleted file mode 100644 index 6f24f26c..00000000 --- a/icarus/heuristics/sc-3000.cpp +++ /dev/null @@ -1,32 +0,0 @@ -namespace Heuristics { - -struct SC3000 { - SC3000(vector& data, string location); - explicit operator bool() const; - auto manifest() const -> string; - -private: - vector& data; - string location; -}; - -SC3000::SC3000(vector& data, string location) : data(data), location(location) { -} - -SC3000::operator bool() const { - return (bool)data; -} - -auto SC3000::manifest() const -> string { - string output; - output.append("game\n"); - output.append(" sha256: ", Hash::SHA256(data).digest(), "\n"); - output.append(" label: ", Location::prefix(location), "\n"); - output.append(" name: ", Location::prefix(location), "\n"); - output.append(" board\n"); - output.append(Memory{}.type("ROM").size(data.size()).content("Program").text()); - output.append(Memory{}.type("RAM").size(0x8000).content("Save").text()); - return output; -} - -} diff --git a/icarus/heuristics/sg-1000.cpp b/icarus/heuristics/sg-1000.cpp deleted file mode 100644 index 1a5f24ed..00000000 --- a/icarus/heuristics/sg-1000.cpp +++ /dev/null @@ -1,32 +0,0 @@ -namespace Heuristics { - -struct SG1000 { - SG1000(vector& data, string location); - explicit operator bool() const; - auto manifest() const -> string; - -private: - vector& data; - string location; -}; - -SG1000::SG1000(vector& data, string location) : data(data), location(location) { -} - -SG1000::operator bool() const { - return (bool)data; -} - -auto SG1000::manifest() const -> string { - string output; - output.append("game\n"); - output.append(" sha256: ", Hash::SHA256(data).digest(), "\n"); - output.append(" label: ", Location::prefix(location), "\n"); - output.append(" name: ", Location::prefix(location), "\n"); - output.append(" board\n"); - output.append(Memory{}.type("ROM").size(data.size()).content("Program").text()); - output.append(Memory{}.type("RAM").size(0x8000).content("Save").text()); - return output; -} - -} diff --git a/icarus/heuristics/supergrafx.cpp b/icarus/heuristics/supergrafx.cpp deleted file mode 100644 index 9ceab33c..00000000 --- a/icarus/heuristics/supergrafx.cpp +++ /dev/null @@ -1,31 +0,0 @@ -namespace Heuristics { - -struct SuperGrafx { - SuperGrafx(vector& data, string location); - explicit operator bool() const; - auto manifest() const -> string; - -private: - vector& data; - string location; -}; - -SuperGrafx::operator bool() const { - return (bool)data; -} - -SuperGrafx::SuperGrafx(vector& data, string location) : data(data), location(location) { -} - -auto SuperGrafx::manifest() const -> string { - string output; - output.append("game\n"); - output.append(" sha256: ", Hash::SHA256(data).digest(), "\n"); - output.append(" label: ", Location::prefix(location), "\n"); - output.append(" name: ", Location::prefix(location), "\n"); - output.append(" board\n"); - output.append(Memory{}.type("ROM").size(data.size()).content("Program").text()); - return output; -} - -} diff --git a/icarus/heuristics/wonderswan.cpp b/icarus/heuristics/wonderswan.cpp deleted file mode 100644 index fd14007e..00000000 --- a/icarus/heuristics/wonderswan.cpp +++ /dev/null @@ -1,58 +0,0 @@ -namespace Heuristics { - -struct WonderSwan { - WonderSwan(vector& buffer, string location); - explicit operator bool() const; - auto manifest() const -> string; - -private: - vector& data; - string location; -}; - -WonderSwan::WonderSwan(vector& data, string location) : data(data), location(location) { -} - -WonderSwan::operator bool() const { - return data.size() >= 0x10000; -} - -auto WonderSwan::manifest() const -> string { - if(!operator bool()) return {}; - - auto metadata = &data[data.size() - 16]; - - bool color = metadata[7]; - - string ramType; - uint ramSize = 0; - switch(metadata[11]) { - case 0x01: ramType = "RAM"; ramSize = 8 * 1024; break; - case 0x02: ramType = "RAM"; ramSize = 32 * 1024; break; - case 0x03: ramType = "RAM"; ramSize = 128 * 1024; break; - case 0x04: ramType = "RAM"; ramSize = 256 * 1024; break; - case 0x05: ramType = "RAM"; ramSize = 512 * 1024; break; - case 0x10: ramType = "EEPROM"; ramSize = 128; break; - case 0x20: ramType = "EEPROM"; ramSize = 2048; break; - case 0x50: ramType = "EEPROM"; ramSize = 1024; break; - } - - bool orientation = metadata[12] & 1; //0 = horizontal; 1 = vertical - bool hasRTC = metadata[13] & 1; - - string output; - output.append("game\n"); - output.append(" sha256: ", Hash::SHA256(data).digest(), "\n"); - output.append(" label: ", Location::prefix(location), "\n"); - output.append(" name: ", Location::prefix(location), "\n"); - output.append(" orientation: ", !orientation ? "horizontal" : "vertical", "\n"); - output.append(" board\n"); - output.append(Memory{}.type("ROM").size(data.size()).content("Program").text()); -if(ramType && ramSize) - output.append(Memory{}.type(ramType).size(ramSize).content("Save").text()); -if(hasRTC) - output.append(Memory{}.type("RTC").size(0x10).content("Time").text()); - return output; -} - -} diff --git a/icarus/icarus.cpp b/icarus/icarus.cpp deleted file mode 100644 index b7548bfc..00000000 --- a/icarus/icarus.cpp +++ /dev/null @@ -1,159 +0,0 @@ -#include -using namespace nall; - -#include -using namespace hiro; - -auto locate(string name) -> string { - string location = {Path::program(), name}; - if(inode::exists(location)) return location; - - location = {Path::userData(), "bsnes/"}; - if(inode::exists(location)) return location; - - directory::create({Path::userSettings(), "bsnes/"}); - return {Path::userSettings(), "bsnes/", name}; -} - -#include "settings.cpp" -Settings settings; - -#include "heuristics/heuristics.hpp" -#include "heuristics/heuristics.cpp" -#include "heuristics/famicom.cpp" -#include "heuristics/super-famicom.cpp" -#include "heuristics/sg-1000.cpp" -#include "heuristics/sc-3000.cpp" -#include "heuristics/master-system.cpp" -#include "heuristics/mega-drive.cpp" -#include "heuristics/pc-engine.cpp" -#include "heuristics/supergrafx.cpp" -#include "heuristics/colecovision.cpp" -#include "heuristics/msx.cpp" -#include "heuristics/game-boy.cpp" -#include "heuristics/game-boy-advance.cpp" -#include "heuristics/game-gear.cpp" -#include "heuristics/wonderswan.cpp" -#include "heuristics/neo-geo-pocket.cpp" -#include "heuristics/neo-geo-pocket-color.cpp" -#include "heuristics/bs-memory.cpp" -#include "heuristics/sufami-turbo.cpp" - -#include "core/core.hpp" -#include "core/core.cpp" -#include "core/famicom.cpp" -#include "core/super-famicom.cpp" -#include "core/sg-1000.cpp" -#include "core/sc-3000.cpp" -#include "core/master-system.cpp" -#include "core/mega-drive.cpp" -#include "core/pc-engine.cpp" -#include "core/supergrafx.cpp" -#include "core/colecovision.cpp" -#include "core/msx.cpp" -#include "core/game-boy.cpp" -#include "core/game-boy-color.cpp" -#include "core/game-boy-advance.cpp" -#include "core/game-gear.cpp" -#include "core/wonderswan.cpp" -#include "core/wonderswan-color.cpp" -#include "core/neo-geo-pocket.cpp" -#include "core/neo-geo-pocket-color.cpp" -#include "core/pocket-challenge-v2.cpp" -#include "core/bs-memory.cpp" -#include "core/sufami-turbo.cpp" - -#if !defined(ICARUS_LIBRARY) - -Icarus icarus; -#include "ui/ui.hpp" -#include "ui/scan-dialog.cpp" -#include "ui/settings-dialog.cpp" -#include "ui/import-dialog.cpp" -#include "ui/error-dialog.cpp" - -auto hiro::initialize() -> void { - Application::setName("icarus"); -} - -#include -auto nall::main(Arguments arguments) -> void { - if(arguments.size() == 1 && arguments[0] == "--name") { - return print("icarus"); - } - - if(arguments.size() == 2 && arguments[0] == "--manifest" && directory::exists(arguments[1])) { - return print(icarus.manifest(arguments[1])); - } - - if(arguments.size() == 2 && arguments[0] == "--import" && file::exists(arguments[1])) { - if(string target = icarus.import(arguments[1])) { - return print(target, "\n"); - } - return; - } - - if(arguments.size() == 1 && arguments[0] == "--import") { - if(string source = BrowserDialog() - .setTitle("Load ROM File") - .setPath(settings["icarus/Path"].text()) - .setFilters("ROM Files|" - "*.fc:*.nes:" - "*.sfc:*.smc:" - "*.sg1000:*.sg:" - "*.sc3000:*.sc:" - "*.ms:*.sms:" - "*.md:*.smd:*.gen:" - "*.pce:" - "*.sgx:" - "*.cv:*.col:" - "*.msx:" - "*.gb:" - "*.gbc:" - "*.gba:" - "*.gg:" - "*.ws:" - "*.wsc:" - "*.pc2:" - "*.ngp:" - "*.ngpc:*.ngc:" - "*.bs:" - "*.st:" - "*.zip" - ).openFile()) { - if(string target = icarus.import(source)) { - settings["icarus/Path"].setValue(Location::path(source)); - return print(target, "\n"); - } - } - return; - } - - new ScanDialog; - new SettingsDialog; - new ImportDialog; - new ErrorDialog; - - #if defined(PLATFORM_MACOS) - Application::Cocoa::onAbout([&] { - MessageDialog().setTitle("About icarus").setText({ - "icarus\n\n" - "Author: byuu\n" - "License: GPLv3\n" - "Website: https://byuu.org/\n" - }).information(); - }); - Application::Cocoa::onPreferences([&] { - scanDialog->settingsButton.doActivate(); - }); - Application::Cocoa::onQuit([&] { - Application::quit(); - }); - #endif - - scanDialog->show(); - Application::run(); - settings.save(); -} - -#endif diff --git a/icarus/settings.cpp b/icarus/settings.cpp deleted file mode 100644 index 462d9cb2..00000000 --- a/icarus/settings.cpp +++ /dev/null @@ -1,24 +0,0 @@ -struct Settings : Markup::Node { - Settings(); - auto save() -> void; -}; - -Settings::Settings() { - Markup::Node::operator=(BML::unserialize(string::read(locate("settings.bml")))); - - auto set = [&](const string& name, const string& value) { - //create node and set to default value only if it does not already exist - if(!operator[](name)) operator()(name).setValue(value); - }; - - set("Library/Location", {Path::user(), "Emulation/"}); - - set("icarus/Path", Path::user()); - set("icarus/CreateManifests", false); - set("icarus/UseDatabase", true); - set("icarus/UseHeuristics", true); -} - -auto Settings::save() -> void { - file::write(locate("settings.bml"), BML::serialize(*this)); -} diff --git a/icarus/ui/error-dialog.cpp b/icarus/ui/error-dialog.cpp deleted file mode 100644 index 847efb08..00000000 --- a/icarus/ui/error-dialog.cpp +++ /dev/null @@ -1,16 +0,0 @@ -ErrorDialog::ErrorDialog() { - errorDialog = this; - - onClose([&] { setVisible(false); scanDialog->show(); }); - layout.setPadding(5); - errorLog.setEditable(false); - closeButton.setText("Close").onActivate([&] { doClose(); }); - - setSize({800, 360}); - setCentered(); -} - -auto ErrorDialog::show(const string& text) -> void { - errorLog.setText(text); - setVisible(); -} diff --git a/icarus/ui/import-dialog.cpp b/icarus/ui/import-dialog.cpp deleted file mode 100644 index 959e773e..00000000 --- a/icarus/ui/import-dialog.cpp +++ /dev/null @@ -1,52 +0,0 @@ -ImportDialog::ImportDialog() { - importDialog = this; - - onClose([&] { - stopButton.setEnabled(false).setText("Stopping ..."); - abort = true; - }); - layout.setPadding(5); - stopButton.setText("Stop").onActivate([&] { doClose(); }); - - setTitle("icarus - Importing ..."); - setSize({480, layout.minimumSize().height()}); - setCentered(); -} - -auto ImportDialog::run(vector locations) -> void { - abort = false; - errors.reset(); - unsigned position = 0; - - setVisible(true); - for(auto& location : locations) { - auto name = Location::base(location); - - if(abort) { - errors.append(string{"[", name, "] aborted"}); - continue; - } - - statusLabel.setText(name); - double progress = 100.0 * (double)position++ / (double)locations.size() + 0.5; - progressBar.setPosition((unsigned)progress); - Application::processEvents(); - - if(!icarus.import(location)) { - errors.append(string{"[", name, "] ", icarus.error()}); - } - } - setVisible(false); - - if(errors) { - string message{"Import completed, but with ", errors.size(), " error", errors.size() ? "s" : "", ". View log?"}; - if(MessageDialog().setTitle("icarus").setText(message).question() == "Yes") { - errorDialog->show(errors.merge("\n")); - } else { - scanDialog->show(); - } - } else { - MessageDialog().setTitle("icarus").setText("Import completed successfully.").information(); - scanDialog->show(); - } -} diff --git a/icarus/ui/scan-dialog.cpp b/icarus/ui/scan-dialog.cpp deleted file mode 100644 index fb80bdac..00000000 --- a/icarus/ui/scan-dialog.cpp +++ /dev/null @@ -1,147 +0,0 @@ -ScanDialog::ScanDialog() { - scanDialog = this; - - onClose(&Application::quit); - layout.setPadding(5); - pathEdit.onActivate([&] { refresh(); }); - refreshButton.setIcon(Icon::Action::Refresh).setBordered(false).onActivate([&] { - pathEdit.setText(settings["icarus/Path"].text()); - refresh(); - }); - homeButton.setIcon(Icon::Go::Home).setBordered(false).onActivate([&] { - pathEdit.setText(Path::user()); - refresh(); - }); - upButton.setIcon(Icon::Go::Up).setBordered(false).onActivate([&] { - pathEdit.setText(Location::dir(settings["icarus/Path"].text())); - refresh(); - }); - scanList.onActivate([&] { activate(); }); - selectAllButton.setText("Select All").onActivate([&] { - for(auto& item : scanList.items()) { - if(item.checkable()) item.setChecked(true); - } - }); - unselectAllButton.setText("Unselect All").onActivate([&] { - for(auto& item : scanList.items()) { - if(item.checkable()) item.setChecked(false); - } - }); - settingsButton.setText("Settings ...").onActivate([&] { - settingsDialog->setCentered(*this); - settingsDialog->setVisible(); - settingsDialog->setFocused(); - }); - importButton.setText("Import ...").onActivate([&] { import(); }); - - setTitle("icarus"); - setSize({800, 480}); - setCentered(); -} - -auto ScanDialog::show() -> void { - setVisible(); - pathEdit.setText(settings["icarus/Path"].text()); - refresh(); -} - -auto ScanDialog::refresh() -> void { - scanList.reset(); - - auto pathname = pathEdit.text().transform("\\", "/"); - if((pathname || Path::root() == "/") && !pathname.endsWith("/")) pathname.append("/"); - - settings["icarus/Path"].setValue(pathname); - pathEdit.setText(pathname); - auto contents = directory::icontents(pathname); - - for(auto& name : contents) { - if(!name.endsWith("/")) continue; - if(gamePakType(Location::suffix(name))) continue; - scanList.append(ListViewItem().setIcon(Icon::Emblem::Folder).setText(name.trimRight("/"))); - } - - for(auto& name : contents) { - if(name.endsWith("/")) continue; - if(!gameRomType(Location::suffix(name).downcase())) continue; - scanList.append(ListViewItem().setCheckable().setIcon(Icon::Emblem::File).setText(name)); - } - - Application::processEvents(); - scanList.setFocused(); -} - -auto ScanDialog::activate() -> void { - if(auto item = scanList.selected()) { - string location{settings["icarus/Path"].text(), item.text()}; - if(!gamePakType(Location::suffix(location))) { - pathEdit.setText(location); - refresh(); - } - } -} - -auto ScanDialog::import() -> void { - vector filenames; - for(auto& item : scanList.items()) { - if(item.checked()) { - filenames.append(string{settings["icarus/Path"].text(), item.text()}); - } - } - - if(!filenames) { - MessageDialog().setParent(*this).setText("Nothing selected to import.").error(); - return; - } - - setVisible(false); - importDialog->run(filenames); -} - -auto ScanDialog::gamePakType(const string& type) -> bool { - return type == ".sys" - || type == ".fc" - || type == ".sfc" - || type == ".sg1000" - || type == ".sc3000" - || type == ".ms" - || type == ".md" - || type == ".pce" - || type == ".sgx" - || type == ".msx" - || type == ".gb" - || type == ".gbc" - || type == ".gba" - || type == ".gg" - || type == ".ws" - || type == ".wsc" - || type == ".pc2" - || type == ".ngp" - || type == ".ngpc" - || type == ".bs" - || type == ".st"; -} - -auto ScanDialog::gameRomType(const string& type) -> bool { - return type == ".zip" - || type == ".fc" || type == ".nes" - || type == ".sfc" || type == ".smc" - || type == ".sg1000" || type == ".sg" - || type == ".sc3000" || type == ".sc" - || type == ".ms" || type == ".sms" - || type == ".md" || type == ".smd" || type == ".gen" - || type == ".pce" - || type == ".sgx" - || type == ".msx" - || type == ".gb" - || type == ".gbc" - || type == ".gba" - || type == ".gg" - || type == ".ws" - || type == ".wsc" - || type == ".pc2" - || type == ".ngp" - || type == ".ngpc" || type == ".ngc" - || type == ".bs" - || type == ".st"; -} diff --git a/icarus/ui/settings-dialog.cpp b/icarus/ui/settings-dialog.cpp deleted file mode 100644 index 5dfabaef..00000000 --- a/icarus/ui/settings-dialog.cpp +++ /dev/null @@ -1,24 +0,0 @@ -SettingsDialog::SettingsDialog() { - settingsDialog = this; - - layout.setPadding(5); - locationLabel.setText("Library Location:"); - locationEdit.setEditable(false).setText(settings["Library/Location"].text()); - changeLocationButton.setText("Change ...").onActivate([&] { - if(auto location = BrowserDialog().setParent(*this).setTitle("Select Library Location").selectFolder()) { - settings["Library/Location"].setValue(location); - locationEdit.setText(location); - } - }); - createManifestsOption.setText("Create Manifests (not recommended; breaks backward-compatibility)") - .setChecked(settings["icarus/CreateManifests"].boolean()).onToggle([&] { - settings["icarus/CreateManifests"].setValue(createManifestsOption.checked()); - }); - useDatabaseOption.setText("Use Database (highly recommended; provides bit-perfect memory mapping)") - .setChecked(settings["icarus/UseDatabase"].boolean()).onToggle([&] { - settings["icarus/UseDatabase"].setValue(useDatabaseOption.checked()); - }); - - setTitle("Settings"); - setSize({480, layout.minimumSize().height()}); -} diff --git a/icarus/ui/ui.hpp b/icarus/ui/ui.hpp deleted file mode 100644 index 4cadd8b0..00000000 --- a/icarus/ui/ui.hpp +++ /dev/null @@ -1,68 +0,0 @@ -struct ScanDialog : Window { - ScanDialog(); - - auto show() -> void; - auto refresh() -> void; - auto activate() -> void; - auto import() -> void; - - auto gamePakType(const string& type) -> bool; - auto gameRomType(const string& type) -> bool; - - VerticalLayout layout{this}; - HorizontalLayout pathLayout{&layout, Size{~0, 0}}; - LineEdit pathEdit{&pathLayout, Size{~0, 0}, 0}; - Button refreshButton{&pathLayout, Size{0, 0}, 0}; - Button homeButton{&pathLayout, Size{0, 0}, 0}; - Button upButton{&pathLayout, Size{0, 0}, 0}; - ListView scanList{&layout, Size{~0, ~0}}; - HorizontalLayout controlLayout{&layout, Size{~0, 0}}; - Button selectAllButton{&controlLayout, Size{100, 0}}; - Button unselectAllButton{&controlLayout, Size{100, 0}}; - Widget controlSpacer{&controlLayout, Size{~0, 0}}; - Button settingsButton{&controlLayout, Size{100, 0}}; - Button importButton{&controlLayout, Size{100, 0}}; -}; - -struct SettingsDialog : Window { - SettingsDialog(); - - VerticalLayout layout{this}; - HorizontalLayout locationLayout{&layout, Size{~0, 0}}; - Label locationLabel{&locationLayout, Size{0, 0}}; - LineEdit locationEdit{&locationLayout, Size{~0, 0}}; - Button changeLocationButton{&locationLayout, Size{80, 0}}; - CheckLabel createManifestsOption{&layout, Size{~0, 0}, 2}; - CheckLabel useDatabaseOption{&layout, Size{~0, 0}}; -}; - -struct ImportDialog : Window { - ImportDialog(); - auto run(vector locations) -> void; - - bool abort; - vector errors; - - VerticalLayout layout{this}; - Label statusLabel{&layout, Size{~0, 0}}; - ProgressBar progressBar{&layout, Size{~0, 0}}; - HorizontalLayout controlLayout{&layout, Size{~0, 0}}; - Widget spacer{&controlLayout, Size{~0, 0}}; - Button stopButton{&controlLayout, Size{80, 0}}; -}; - -struct ErrorDialog : Window { - ErrorDialog(); - auto show(const string& text) -> void; - - VerticalLayout layout{this}; - TextEdit errorLog{&layout, Size{~0, ~0}}; - HorizontalLayout controlLayout{&layout, Size{~0, 0}}; - Widget spacer{&controlLayout, Size{~0, 0}}; - Button closeButton{&controlLayout, Size{80, 0}}; -}; - -ScanDialog* scanDialog = nullptr; -SettingsDialog* settingsDialog = nullptr; -ImportDialog* importDialog = nullptr; -ErrorDialog* errorDialog = nullptr;