mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-02-24 15:12:23 +01:00
byuu says: higan supports Event mapping again. Further, icarus can now detect Event ROMs and MSU1 games. Event ROMs must be named "program.rom", "slot-(1,2,3).rom" MSU1 games must contain "msu1.rom"; and tracks must be named "track-#.pcm" When importing the CC'92, PF'94 ROMs, the program.rom and slot-(1,2,3).rom files must be concatenated. The DSP firmware can optionally be separate, but I'd recommend you go ahead and merge it all to one file. Especially since that common "higan DSP pack" floating around on the web left out the DSP1 ROMs (only has DSP1B) for god knows what reason. There is no support for loading "game.sfc+game.msu+game-*.pcm", because I'm not going to support trying to pull in all of those files through importing. Games will have to be distributed as game folders to use MSU1. The MSU1 icarus support is simply so your game folders won't require an unstable manifest.bml file to be played. So once they're in there, they are good for life. Note: the Event sizes in icarus' SFC heuristics are wrong for appended firmware. Change from 0xXX8000 to 0xXX2000 and it works fine. Will be fixed in r18. Added Sintendo's flickering fixes. The window one's a big help for regular controls, but the ListView double buffering does nothing for me on Windows 7 :( Fairly sure I know why, but too lazy to try and fix that now. Also fixes the mMenu thing.
86 lines
3.6 KiB
C++
86 lines
3.6 KiB
C++
auto Icarus::superFamicomManifest(string location) -> string {
|
|
vector<uint8> buffer;
|
|
auto files = directory::files(location, "*.rom");
|
|
concatenate(buffer, {location, "program.rom"});
|
|
concatenate(buffer, {location, "data.rom" });
|
|
for(auto& file : files.match("slot-*.rom" )) concatenate(buffer, {location, file});
|
|
for(auto& file : files.match("*.boot.rom" )) concatenate(buffer, {location, file});
|
|
for(auto& file : files.match("*.program.rom")) concatenate(buffer, {location, file});
|
|
for(auto& file : files.match("*.data.rom" )) concatenate(buffer, {location, file});
|
|
return superFamicomManifest(buffer, location);
|
|
}
|
|
|
|
auto Icarus::superFamicomManifest(vector<uint8>& buffer, string location, bool* firmwareAppended) -> string {
|
|
string markup;
|
|
string digest = Hash::SHA256(buffer.data(), buffer.size()).digest();
|
|
|
|
if(settings["icarus/UseDatabase"].boolean() && !markup) {
|
|
for(auto node : database.superFamicom) {
|
|
if(node["sha256"].text() == digest) {
|
|
markup.append(node.text(), "\n sha256: ", digest, "\n");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(settings["icarus/UseHeuristics"].boolean() && !markup) {
|
|
bool hasMSU1 = file::exists({location, "msu1.rom"});
|
|
SuperFamicomCartridge cartridge{buffer.data(), buffer.size(), hasMSU1};
|
|
if(markup = cartridge.markup) {
|
|
if(firmwareAppended) *firmwareAppended = cartridge.firmware_appended;
|
|
markup.append("\n");
|
|
markup.append("information\n");
|
|
markup.append(" region: ", cartridge.region == SuperFamicomCartridge::Region::NTSC ? "NTSC" : "PAL", "\n");
|
|
markup.append(" title: ", prefixname(location), "\n");
|
|
markup.append(" sha256: ", digest, "\n");
|
|
markup.append(" note: ", "heuristically generated by icarus\n");
|
|
}
|
|
}
|
|
|
|
return markup;
|
|
}
|
|
|
|
auto Icarus::superFamicomManifestScan(vector<Markup::Node>& roms, Markup::Node node) -> void {
|
|
if(node["name"].text().endsWith(".rom")) roms.append(node);
|
|
for(auto leaf : node) superFamicomManifestScan(roms, leaf);
|
|
}
|
|
|
|
auto Icarus::superFamicomImport(vector<uint8>& buffer, string location) -> bool {
|
|
auto name = prefixname(location);
|
|
auto source = pathname(location);
|
|
string target{settings["Library/Location"].text(), "Super Famicom/", name, ".sfc/"};
|
|
//if(directory::exists(target)) return failure("game already exists");
|
|
|
|
bool firmwareAppended = true;
|
|
auto markup = superFamicomManifest(buffer, location, &firmwareAppended);
|
|
if(!markup) return failure("failed to parse ROM image");
|
|
|
|
auto document = BML::unserialize(markup);
|
|
vector<Markup::Node> roms;
|
|
superFamicomManifestScan(roms, document["board"]);
|
|
for(auto rom : roms) {
|
|
auto name = rom["name"].text();
|
|
auto size = rom["size"].natural();
|
|
if(name == "program.rom" || name == "data.rom" || firmwareAppended) continue;
|
|
if(file::size({source, name}) != size) return failure({"firmware (", name, ") missing or invalid"});
|
|
}
|
|
|
|
if(!directory::create(target)) return failure("library path unwritable");
|
|
|
|
if(settings["icarus/CreateManifests"].boolean()) file::write({target, "manifest.bml"}, markup);
|
|
uint offset = (buffer.size() & 0x7fff) == 512 ? 512 : 0; //skip header if present
|
|
for(auto rom : roms) {
|
|
auto name = rom["name"].text();
|
|
auto size = rom["size"].natural();
|
|
if(name == "program.rom" || name == "data.rom" || firmwareAppended) {
|
|
if(size > buffer.size() - offset) return failure("ROM image is missing data");
|
|
file::write({target, name}, buffer.data() + offset, size);
|
|
offset += size;
|
|
} else {
|
|
auto firmware = file::read({source, name});
|
|
file::write({target, name}, firmware);
|
|
}
|
|
}
|
|
return success();
|
|
}
|