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 { string markup; string digest = Hash::SHA256(buffer.data(), buffer.size()).digest(); if(settings["icarus/UseDatabase"].boolean() && !markup) { for(auto node : database.gameBoyAdvance) { if(node["sha256"].text() == digest) { markup.append(node.text(), "\n sha256: ", digest, "\n"); break; } } } if(settings["icarus/UseHeuristics"].boolean() && !markup) { GameBoyAdvanceCartridge cartridge{buffer.data(), buffer.size()}; if(markup = cartridge.markup) { markup.append("\n"); markup.append("information\n"); markup.append(" title: ", Location::prefix(location), "\n"); markup.append(" sha256: ", digest, "\n"); markup.append(" note: ", "heuristically generated by icarus\n"); } } return markup; } 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 markup = gameBoyAdvanceManifest(buffer, location); if(!markup) 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"}, markup); write({target, "program.rom"}, buffer); return success(target); }