mirror of https://github.com/bsnes-emu/bsnes.git
Update to v106r07 release.
byuu says: Changelog: - Super Game Boy: for the 50th time, higan won't segfault if you cancel the Game Boy cartridge load request - icarus: moved to new manifest syntax for all remaining systems - Game Boy: moved to new manifest syntax Errata: - Game Boy: save RAM does not appear to be working for some reason - Famicom: higan won't even start to run this system; it just acts like a cartridge was never loaded ... - cores outside of the Super Famicom and Game Boy/Color will not run due to icarus/higan manifest syntax differences
This commit is contained in:
parent
61091167b8
commit
c49d3b2006
|
@ -12,7 +12,7 @@ using namespace nall;
|
|||
|
||||
namespace Emulator {
|
||||
static const string Name = "higan";
|
||||
static const string Version = "106.06";
|
||||
static const string Version = "106.07";
|
||||
static const string Author = "byuu";
|
||||
static const string License = "GPLv3";
|
||||
static const string Website = "https://byuu.org/";
|
||||
|
|
|
@ -19,6 +19,12 @@ Cartridge cartridge;
|
|||
|
||||
auto Cartridge::load() -> bool {
|
||||
information = {};
|
||||
rom = {};
|
||||
ram = {};
|
||||
rtc = {};
|
||||
mapper = &mbc0;
|
||||
accelerometer = false;
|
||||
rumble = false;
|
||||
|
||||
if(Model::GameBoy()) {
|
||||
if(auto loaded = platform->load(ID::GameBoy, "Game Boy", "gb")) {
|
||||
|
@ -43,10 +49,9 @@ auto Cartridge::load() -> bool {
|
|||
} else return false;
|
||||
|
||||
auto document = BML::unserialize(information.manifest);
|
||||
auto board = document["board"];
|
||||
information.title = document["information/title"].text();
|
||||
information.title = document["game/label"].text();
|
||||
|
||||
auto mapperID = document["board/mapper"].text();
|
||||
auto mapperID = document["game/board"].text();
|
||||
if(mapperID == "MBC0" ) mapper = &mbc0;
|
||||
if(mapperID == "MBC1" ) mapper = &mbc1;
|
||||
if(mapperID == "MBC1M") mapper = &mbc1m;
|
||||
|
@ -59,32 +64,37 @@ auto Cartridge::load() -> bool {
|
|||
if(mapperID == "HuC1" ) mapper = &huc1;
|
||||
if(mapperID == "HuC3" ) mapper = &huc3;
|
||||
if(mapperID == "TAMA" ) mapper = &tama;
|
||||
if(!mapper) mapper = &mbc0;
|
||||
|
||||
accelerometer = (bool)document["board/accelerometer"];
|
||||
rumble = (bool)document["board/rumble"];
|
||||
accelerometer = (bool)document["game/board/accelerometer"];
|
||||
rumble = (bool)document["game/board/rumble"];
|
||||
|
||||
rom.size = max(0x4000, document["board/rom/size"].natural());
|
||||
rom.data = (uint8*)memory::allocate(rom.size, 0xff);
|
||||
if(auto name = document["board/rom/name"].text()) {
|
||||
if(auto fp = platform->open(pathID(), name, File::Read, File::Required)) {
|
||||
fp->read(rom.data, min(rom.size, fp->size()));
|
||||
if(auto node = document["game/memory[type=ROM]"]) {
|
||||
rom.size = max(0x4000, node["size"].natural());
|
||||
rom.data = (uint8*)memory::allocate(rom.size, 0xff);
|
||||
if(auto name = node["name"].text()) {
|
||||
if(auto fp = platform->open(pathID(), name, File::Read, File::Required)) {
|
||||
fp->read(rom.data, min(rom.size, fp->size()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ram.size = document["board/ram/size"].natural();
|
||||
ram.data = (uint8*)memory::allocate(ram.size, 0xff);
|
||||
if(auto name = document["board/ram/name"].text()) {
|
||||
if(auto fp = platform->open(pathID(), name, File::Read, File::Optional)) {
|
||||
fp->read(ram.data, min(ram.size, fp->size()));
|
||||
if(auto node = document["game/memory[type=NVRAM]"]) {
|
||||
ram.size = node["size"].natural();
|
||||
ram.data = (uint8*)memory::allocate(ram.size, 0xff);
|
||||
if(auto name = node["name"].text()) {
|
||||
if(auto fp = platform->open(pathID(), name, File::Read, File::Optional)) {
|
||||
fp->read(ram.data, min(ram.size, fp->size()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rtc.size = document["board/rtc/size"].natural();
|
||||
rtc.data = (uint8*)memory::allocate(rtc.size, 0xff);
|
||||
if(auto name = document["board/rtc/name"].text()) {
|
||||
if(auto fp = platform->open(pathID(), name, File::Read, File::Optional)) {
|
||||
fp->read(rtc.data, min(rtc.size, fp->size()));
|
||||
if(auto node = document["game/memory[type=RTC]"]) {
|
||||
rtc.size = node["size"].natural();
|
||||
rtc.data = (uint8*)memory::allocate(rtc.size, 0xff);
|
||||
if(auto name = node["name"].text()) {
|
||||
if(auto fp = platform->open(pathID(), name, File::Read, File::Optional)) {
|
||||
fp->read(rtc.data, min(rtc.size, fp->size()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,15 +105,19 @@ auto Cartridge::load() -> bool {
|
|||
auto Cartridge::save() -> void {
|
||||
auto document = BML::unserialize(information.manifest);
|
||||
|
||||
if(auto name = document["board/ram/name"].text()) {
|
||||
if(auto fp = platform->open(pathID(), name, File::Write)) {
|
||||
fp->write(ram.data, ram.size);
|
||||
if(auto node = document["game/memory[type=NVRAM]"]) {
|
||||
if(auto name = node["name"].text()) {
|
||||
if(auto fp = platform->open(pathID(), name, File::Write)) {
|
||||
fp->write(ram.data, ram.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(auto name = document["board/rtc/name"].text()) {
|
||||
if(auto fp = platform->open(pathID(), name, File::Write)) {
|
||||
fp->write(rtc.data, rtc.size);
|
||||
if(auto node = document["game/memory[type=RTC]"]) {
|
||||
if(auto name = node["name"].text()) {
|
||||
if(auto fp = platform->open(pathID(), name, File::Write)) {
|
||||
fp->write(rtc.data, rtc.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,10 +22,15 @@ auto Cartridge::loadBoard(Markup::Node node) -> Markup::Node {
|
|||
}
|
||||
if(!matched) continue;
|
||||
|
||||
if(region.endsWith("-USA")
|
||||
|| region.endsWith("-CAN")
|
||||
|| region.endsWith("-JPN")
|
||||
|| region.endsWith("-KOR")
|
||||
if(region.endsWith("BRA")
|
||||
|| region.endsWith("CAN")
|
||||
|| region.endsWith("HKG")
|
||||
|| region.endsWith("JPN")
|
||||
|| region.endsWith("KOR")
|
||||
|| region.endsWith("LTN")
|
||||
|| region.endsWith("ROC")
|
||||
|| region.endsWith("USA")
|
||||
|| region.beginsWith("SHVC-")
|
||||
|| region == "NTSC") {
|
||||
output.append("region=ntsc\n");
|
||||
} else {
|
||||
|
@ -62,7 +67,6 @@ auto Cartridge::loadBoard(Markup::Node node) -> Markup::Node {
|
|||
}
|
||||
}
|
||||
|
||||
print(output, "\n");
|
||||
return BML::unserialize(output);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
database
|
||||
revision: 2018-02-14
|
||||
revision: 2018-02-16
|
||||
|
||||
//BS Memory (JPN)
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
database
|
||||
revision: 2018-02-14
|
||||
revision: 2018-02-16
|
||||
|
||||
//Sufami Turbo (JPN)
|
||||
|
||||
|
|
|
@ -1,5 +1,34 @@
|
|||
database
|
||||
revision: 2018-02-14
|
||||
revision: 2018-02-16
|
||||
|
||||
//Prototypes (JPN)
|
||||
|
||||
database
|
||||
revision: 2018-02-16
|
||||
|
||||
game
|
||||
sha256: 182cd72c2ef57119b56bef1f7c18660498422a912f1bb652771d465cd183b04e
|
||||
region: JPN
|
||||
revision: 1.0
|
||||
board: SHVC-4PV5B-01
|
||||
name: From TV Animation - Slam Dunk - Shuueisha Limited
|
||||
label: From TV Animation - Slam Dunk - 集英社Limited
|
||||
memory
|
||||
type: EPROM
|
||||
size: 0x180000
|
||||
name: program.rom
|
||||
|
||||
game
|
||||
sha256: bcba4ca39f0279f7a52657bccbffa84564eaea455e2565597b93942ec245fdb1
|
||||
region: JPN
|
||||
revision: 1.0
|
||||
board: SHVC-2P3B-01
|
||||
name: Kunio-kun no Dodgeball da yo - Zen'in Shuugou! - Tournament Special
|
||||
label: くにおくんのドッジボールだよ 全員集合! トーナメントスペシャル
|
||||
memory
|
||||
type: EPROM
|
||||
size: 0x80000
|
||||
name: program.rom
|
||||
|
||||
//Super Comboy (KOR)
|
||||
|
||||
|
@ -82,7 +111,55 @@ game
|
|||
//Super Famicom (JPN)
|
||||
|
||||
database
|
||||
revision: 2018-02-14
|
||||
revision: 2018-02-16
|
||||
|
||||
game
|
||||
sha256: 6f6bacdd73aef29ff6a015c25db4a5cd8ba31142b2cc3fe56261d23bbf8329ea
|
||||
region: SHVC-AAZJ-JPN
|
||||
revision: SHVC-AAZJ-0
|
||||
board: SHVC-1J5M-01
|
||||
name: Angelique - Premium Box
|
||||
label: アンジェリーク プレミアムBox
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x200000
|
||||
name: program.rom
|
||||
memory
|
||||
type: NVRAM
|
||||
size: 0x8000
|
||||
name: save.ram
|
||||
|
||||
game
|
||||
sha256: 1f7619ea0d02f16e2b2dcbb36013bb3405eb791885f23884b583eb63768614c4
|
||||
region: SHVC-AQLJ-JPN
|
||||
revision: SHVC-AQLJ-0
|
||||
board: SHVC-1J5M-01
|
||||
name: Angelique - Voice Fantasy
|
||||
label: アンジェリーク ヴォイス・ファンタジー
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x300000
|
||||
name: program.rom
|
||||
memory
|
||||
type: NVRAM
|
||||
size: 0x8000
|
||||
name: save.ram
|
||||
|
||||
game
|
||||
sha256: ecd772c4a21101d079a795e47abbe00052bef69cc1c854a328f0077016c53311
|
||||
region: SHVC-AH9J-JPN
|
||||
revision: SHVC-AH9J-0
|
||||
board: SHVC-1J3M-20
|
||||
name: Bomberman B-Daman
|
||||
label: ボンバーマン ビーダマン
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x100000
|
||||
name: program.rom
|
||||
memory
|
||||
type: NVRAM
|
||||
size: 0x2000
|
||||
name: save.ram
|
||||
|
||||
game
|
||||
sha256: 3ce321496edc5d77038de2034eb3fb354d7724afd0bc7fd0319f3eb5d57b984d
|
||||
|
@ -104,6 +181,22 @@ game
|
|||
size: 0x80000
|
||||
name: download.ram
|
||||
|
||||
game
|
||||
sha256: c195641a1b472590cb3d0be0c48d682b9fee94d7b700dd7bd3297bb995b49307
|
||||
region: SHVC-B5
|
||||
revision: SHVC-B5-0
|
||||
board: SHVC-1J3B-01
|
||||
name: Conveni Wars - Barcode Battler Senki - Super Senshi Shutsugeki seyo!
|
||||
label: Conveni Wars Barcode Battler 戦記 スーパー戦士 出撃せよ!
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x80000
|
||||
name: program.rom
|
||||
memory
|
||||
type: NVRAM
|
||||
size: 0x2000
|
||||
name: save.ram
|
||||
|
||||
game
|
||||
sha256: 38a855229eab468c3ede7573db73082c66b157adfc7af787ccac50559b747f5f
|
||||
region: SHVC-ZDBJ-JPN
|
||||
|
@ -120,6 +213,54 @@ game
|
|||
size: 0x8000
|
||||
name: save.ram
|
||||
|
||||
game
|
||||
sha256: dcb14c95f058a32f40cc329793f5d95fd6cf1755cffe02c0594d1c583a06d356
|
||||
region: SHVC-AEMJ-JPN
|
||||
revision: SHVC-AEMJ-0
|
||||
board: SHVC-1J3M-20
|
||||
name: Emit Vol. 1 - Toki no Maigo
|
||||
label: エミット Vol. 1 時の迷子
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x300000
|
||||
name: program.rom
|
||||
memory
|
||||
type: NVRAM
|
||||
size: 0x2000
|
||||
name: save.ram
|
||||
|
||||
game
|
||||
sha256: dc1ecf27d9ce4fdf674c9405339016f5a812f7c4687e588cc6404e2b3b92541a
|
||||
region: SHVC-AEIJ-JPN
|
||||
revision: SHVC-AEIJ-0
|
||||
board: SHVC-1J3M-20
|
||||
name: Emit Vol. 2 - Inochigake no Tabi
|
||||
label: エミット Vol. 2 命がけの旅
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x300000
|
||||
name: program.rom
|
||||
memory
|
||||
type: NVRAM
|
||||
size: 0x2000
|
||||
name: save.ram
|
||||
|
||||
game
|
||||
sha256: f49417cb8759a30e12439e846f7d581afd1519c625e6a0522876666098521fcc
|
||||
region: SHVC-AETJ-JPN
|
||||
revision: SHVC-AETJ-0
|
||||
board: SHVC-1J3M-20
|
||||
name: Emit Vol. 3 - Watashi ni Sayonara o
|
||||
label: エミット Vol. 3 私にさよならを
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x300000
|
||||
name: program.rom
|
||||
memory
|
||||
type: NVRAM
|
||||
size: 0x2000
|
||||
name: save.ram
|
||||
|
||||
game
|
||||
sha256: 74aa3a26b66f34819fbbdcdb2475cf9161cc2590fb1ec89fb24940ef10e44332
|
||||
region: SHVC-F4
|
||||
|
@ -136,6 +277,22 @@ game
|
|||
size: 0x2000
|
||||
name: save.ram
|
||||
|
||||
game
|
||||
sha256: db337a2e8cf6de653d092ba3489cabc658f91c63ec8a9db4e1866400aadf913f
|
||||
region: SHVC-AGHJ-JPN
|
||||
revision: SHVC-AGHJ-0
|
||||
board: SHVC-2J3M-20
|
||||
name: Get in the Hole
|
||||
label: ゲットインザホール
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x180000
|
||||
name: program.rom
|
||||
memory
|
||||
type: NVRAM
|
||||
size: 0x2000
|
||||
name: save.ram
|
||||
|
||||
game
|
||||
sha256: 4dfba33201de6b5dec952d0f327aeb44ed784c025a72c982356dd41b52efc219
|
||||
region: SHVC-ZBPJ-JPN
|
||||
|
@ -172,6 +329,66 @@ game
|
|||
size: 0x2000
|
||||
name: save.ram
|
||||
|
||||
game
|
||||
sha256: fe44f9d0db9f04f704764577b94e5bf2e18bc7a1c4ff1e6bdaca06d49ed6813c
|
||||
region: SHVC-LK
|
||||
revision: SHVC-LK-0
|
||||
board: SHVC-1A0N-20
|
||||
name: Lethal Enforcers
|
||||
label: リーサルエンフォーサーズ
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x200000
|
||||
name: program.rom
|
||||
|
||||
game
|
||||
sha256: c51c5930b344f553415d54c3c964c050e1eb6355b10f5966deabb686e70e1750
|
||||
region: SHVC-WE
|
||||
revision: SHVC-WE-0
|
||||
board: SHVC-YA0N-01
|
||||
name: Mario & Wario
|
||||
label: マリオとワリオ
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x100000
|
||||
name: program.rom
|
||||
|
||||
game
|
||||
sha256: e842cac1a4301be196f1e137fbd1a16866d5c913f24dbca313f4dd8bd7472f45
|
||||
region: SHVC-MP
|
||||
revision: SHVC-MP-0
|
||||
board: SHVC-1A5B-04
|
||||
name: Mario Paint
|
||||
label: マリオペイント
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x100000
|
||||
name: program.rom
|
||||
memory
|
||||
type: NVRAM
|
||||
size: 0x8000
|
||||
name: save.ram
|
||||
|
||||
game
|
||||
sha256: 2298d92acdfecc7270a6c9a57a6ddc55d7fa841fe9c0e7c0d64e33682fffa429
|
||||
region: SHVC-A4WJ-JPN
|
||||
revision: SHVC-A4WJ-0
|
||||
board: SHVC-1L5B-20
|
||||
name: Mini Yonku Shining Scorpion - Let's & Go!!
|
||||
label: ミニ四駆シャイニングスコーピオン レッツ&ゴー!!
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x400000
|
||||
name: program.rom
|
||||
memory
|
||||
type: NVRAM
|
||||
size: 0x8000
|
||||
name: save.ram
|
||||
memory
|
||||
type: RAM
|
||||
size: 0x800
|
||||
name: internal.ram
|
||||
|
||||
game
|
||||
sha256: d712adecbde70a74c4a580fe90a45d0d19f2641d1b4e091d507bddeec9601de1
|
||||
region: SHVC-ZMCJ-JPN
|
||||
|
@ -268,6 +485,34 @@ game
|
|||
size: 0x40000
|
||||
name: program.rom
|
||||
|
||||
game
|
||||
sha256: 442397be57b3740ca236cfb37633b95f88a2c80dafc94b56a805229793563ce1
|
||||
region: SHVC-9B
|
||||
revision: SHVC-9B-0
|
||||
board: SHVC-1J0N-10
|
||||
name: Super Bomberman 2 - Taikenban
|
||||
label: スーパーボンバーマン2 体験版
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x100000
|
||||
name: program.rom
|
||||
|
||||
game
|
||||
sha256: 5f8e6894f71c62bc5e70485715dbd2e2d8f3c0383ec54211dc5fe180098d0e3f
|
||||
region: SHVC-AK8J-JPN
|
||||
revision: SHVC-AK8J-0
|
||||
board: SHVC-1J3M-20
|
||||
name: Super Bomberman 5 - CoroCoro Comic
|
||||
label: スーパーボンバーマン5 コロコロコミック
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x200000
|
||||
name: program.rom
|
||||
memory
|
||||
type: NVRAM
|
||||
size: 0x2000
|
||||
name: save.ram
|
||||
|
||||
game
|
||||
sha256: 4d7fc331a811b8dc630b469262fd6f45e289243cef83101f32038158967d1b28
|
||||
region: SHVC-SGB
|
||||
|
@ -348,6 +593,66 @@ game
|
|||
size: 0x2000
|
||||
name: save.ram
|
||||
|
||||
game
|
||||
sha256: ecd462c64516169cc83dd266af354fe676fcf53811863a361d78cc918619da0d
|
||||
region: SHVC-XL
|
||||
revision: SHVC-XL-1
|
||||
board: SHVC-1A5M-20
|
||||
name: Super Sangokushi II
|
||||
label: スーパー三国志II 復刻版
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x100000
|
||||
name: program.rom
|
||||
memory
|
||||
type: NVRAM
|
||||
size: 0x8000
|
||||
name: save.ram
|
||||
|
||||
game
|
||||
sha256: fde83367c1caf6edfb41a0c609bacc90084e9808b32ba52b13d204eb59535ab5
|
||||
region: SHVC-LR
|
||||
revision: SHVC-LR-0
|
||||
board: SHVC-1A0N-20
|
||||
name: Super Scope 6
|
||||
label: スーパースコープ6
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x100000
|
||||
name: program.rom
|
||||
|
||||
game
|
||||
sha256: 8dda3b0888a32005041f2feb9be4e14807d40291f951a4612461cf41dac9cb78
|
||||
region: SHVC-T2
|
||||
revision: SHVC-T2-0
|
||||
board: SHVC-1A1B-06
|
||||
name: Super Tetris 2 + Bombliss
|
||||
label: Super Tetris 2 + Bombliss
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x100000
|
||||
name: program.rom
|
||||
memory
|
||||
type: NVRAM
|
||||
size: 0x800
|
||||
name: save.ram
|
||||
|
||||
game
|
||||
sha256: b66da2a23f249e525b1dd444596a3f10559cb3c30fa3c0bca83ed8f4405fcfcf
|
||||
region: SHVC-ANZJ-JPN
|
||||
revision: SHVC-ANZJ-0
|
||||
board: SHVC-1J3M-20
|
||||
name: Undake 30 - Same Game Daisakusen - Mario Version
|
||||
label: Undake 30 鮫亀大作戦 マリオバージョン
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x60000
|
||||
name: program.rom
|
||||
memory
|
||||
type: NVRAM
|
||||
size: 0x2000
|
||||
name: save.ram
|
||||
|
||||
//Super Famicom (ROC)
|
||||
|
||||
database
|
||||
|
|
|
@ -5,10 +5,9 @@ auto Icarus::bsMemoryManifest(string location) -> string {
|
|||
}
|
||||
|
||||
auto Icarus::bsMemoryManifest(vector<uint8_t>& buffer, string location) -> string {
|
||||
auto digest = Hash::SHA256(buffer).digest();
|
||||
|
||||
if(settings["icarus/UseDatabase"].boolean()) {
|
||||
for(auto game : database.bsMemory.find("game")) {
|
||||
auto digest = Hash::SHA256(buffer).digest();
|
||||
for(auto game : Database::BSMemory.find("game")) {
|
||||
if(game["sha256"].text() == digest) return BML::serialize(game);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
Icarus::Icarus() {
|
||||
database.famicom = BML::unserialize(string::read(locate("Database/Famicom.bml")));
|
||||
database.superFamicom = BML::unserialize(string::read(locate("Database/Super Famicom.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.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.bsMemory = BML::unserialize(string::read(locate("Database/BS Memory.bml")));
|
||||
database.sufamiTurbo = BML::unserialize(string::read(locate("Database/Sufami Turbo.bml")));
|
||||
Database::Famicom = BML::unserialize(string::read(locate("Database/Famicom.bml")));
|
||||
Database::SuperFamicom = BML::unserialize(string::read(locate("Database/Super Famicom.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::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::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 {
|
||||
|
@ -35,7 +35,7 @@ auto Icarus::failure(string message) -> string {
|
|||
|
||||
auto Icarus::manifest(string location) -> string {
|
||||
location.transform("\\", "/").trimRight("/").append("/");
|
||||
if(!directory::exists(location)) return "";
|
||||
if(!directory::exists(location)) return {};
|
||||
|
||||
auto type = Location::suffix(location).downcase();
|
||||
if(type == ".fc") return famicomManifest(location);
|
||||
|
@ -53,7 +53,7 @@ auto Icarus::manifest(string location) -> string {
|
|||
if(type == ".bs") return bsMemoryManifest(location);
|
||||
if(type == ".st") return sufamiTurboManifest(location);
|
||||
|
||||
return "";
|
||||
return {};
|
||||
}
|
||||
|
||||
auto Icarus::import(string location) -> string {
|
||||
|
|
|
@ -38,7 +38,7 @@ struct Icarus {
|
|||
|
||||
//famicom.cpp
|
||||
auto famicomManifest(string location) -> string;
|
||||
auto famicomManifest(vector<uint8_t>& buffer, string location, uint* prgrom = nullptr, uint* chrrom = nullptr) -> string;
|
||||
auto famicomManifest(vector<uint8_t>& buffer, string location) -> string;
|
||||
auto famicomImport(vector<uint8_t>& buffer, string location) -> string;
|
||||
|
||||
//super-famicom.cpp
|
||||
|
@ -109,21 +109,21 @@ struct Icarus {
|
|||
private:
|
||||
string errorMessage;
|
||||
string_vector missingFiles;
|
||||
|
||||
struct {
|
||||
Markup::Node famicom;
|
||||
Markup::Node superFamicom;
|
||||
Markup::Node masterSystem;
|
||||
Markup::Node megaDrive;
|
||||
Markup::Node pcEngine;
|
||||
Markup::Node superGrafx;
|
||||
Markup::Node gameBoy;
|
||||
Markup::Node gameBoyColor;
|
||||
Markup::Node gameBoyAdvance;
|
||||
Markup::Node gameGear;
|
||||
Markup::Node wonderSwan;
|
||||
Markup::Node wonderSwanColor;
|
||||
Markup::Node bsMemory;
|
||||
Markup::Node sufamiTurbo;
|
||||
} database;
|
||||
};
|
||||
|
||||
namespace Database {
|
||||
Markup::Node Famicom;
|
||||
Markup::Node SuperFamicom;
|
||||
Markup::Node MasterSystem;
|
||||
Markup::Node MegaDrive;
|
||||
Markup::Node PCEngine;
|
||||
Markup::Node SuperGrafx;
|
||||
Markup::Node GameBoy;
|
||||
Markup::Node GameBoyColor;
|
||||
Markup::Node GameBoyAdvance;
|
||||
Markup::Node GameGear;
|
||||
Markup::Node WonderSwan;
|
||||
Markup::Node WonderSwanColor;
|
||||
Markup::Node BSMemory;
|
||||
Markup::Node SufamiTurbo;
|
||||
};
|
||||
|
|
|
@ -6,35 +6,20 @@ auto Icarus::famicomManifest(string location) -> string {
|
|||
return famicomManifest(buffer, location);
|
||||
}
|
||||
|
||||
auto Icarus::famicomManifest(vector<uint8_t>& buffer, string location, uint* prgrom, uint* chrrom) -> string {
|
||||
string markup;
|
||||
string digest = Hash::SHA256(buffer.data(), buffer.size()).digest();
|
||||
|
||||
if(settings["icarus/UseDatabase"].boolean() && !markup) {
|
||||
for(auto node : database.famicom) {
|
||||
if(node["sha256"].text() == digest) {
|
||||
markup.append(node.text(), "\n sha256: ", digest, "\n");
|
||||
break;
|
||||
}
|
||||
auto Icarus::famicomManifest(vector<uint8_t>& 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() && !markup) {
|
||||
FamicomCartridge 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");
|
||||
}
|
||||
if(settings["icarus/UseHeuristics"].boolean()) {
|
||||
Heuristics::Famicom game{buffer, location};
|
||||
if(auto manifest = game.manifest()) return manifest;
|
||||
}
|
||||
|
||||
auto document = BML::unserialize(markup);
|
||||
if(prgrom) *prgrom = document["board/prg/rom/size"].natural(); //0 if node does not exist
|
||||
if(chrrom) *chrrom = document["board/chr/rom/size"].natural(); //0 if node does not exist
|
||||
|
||||
return markup;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto Icarus::famicomImport(vector<uint8_t>& buffer, string location) -> string {
|
||||
|
@ -42,20 +27,22 @@ auto Icarus::famicomImport(vector<uint8_t>& buffer, string location) -> string {
|
|||
auto source = Location::path(location);
|
||||
string target{settings["Library/Location"].text(), "Famicom/", name, ".fc/"};
|
||||
|
||||
uint prgrom = 0;
|
||||
uint chrrom = 0;
|
||||
auto markup = famicomManifest(buffer, location, &prgrom, &chrrom);
|
||||
if(!markup) return failure("failed to parse ROM image");
|
||||
auto manifest = famicomManifest(buffer, location);
|
||||
if(!manifest) return failure("failed to parse ROM image");
|
||||
|
||||
auto document = BML::unserialize(manifest);
|
||||
uint prgrom = document["game/memory[name=program.rom]"]["size"].natural();
|
||||
uint chrrom = document["game/memory[name=character.rom]"]["size"].natural();
|
||||
|
||||
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, "ines.rom"}, buffer.data(), 16);
|
||||
write({target, "program.rom"}, buffer.data() + 16, prgrom);
|
||||
if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest);
|
||||
write({target, "ines.rom"}, &buffer[0], 16);
|
||||
write({target, "program.rom"}, &buffer[16], prgrom);
|
||||
if(!chrrom) return success(target);
|
||||
write({target, "character.rom"}, buffer.data() + 16 + prgrom, chrrom);
|
||||
write({target, "character.rom"}, &buffer[16 + prgrom], chrrom);
|
||||
return success(target);
|
||||
}
|
||||
|
|
|
@ -5,30 +5,19 @@ auto Icarus::gameBoyAdvanceManifest(string location) -> string {
|
|||
}
|
||||
|
||||
auto Icarus::gameBoyAdvanceManifest(vector<uint8_t>& 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/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() && !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");
|
||||
}
|
||||
if(settings["icarus/UseHeuristics"].boolean()) {
|
||||
Heuristics::GameBoyAdvance game{buffer, location};
|
||||
if(auto manifest = game.manifest()) return manifest;
|
||||
}
|
||||
|
||||
return markup;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto Icarus::gameBoyAdvanceImport(vector<uint8_t>& buffer, string location) -> string {
|
||||
|
@ -36,15 +25,15 @@ auto Icarus::gameBoyAdvanceImport(vector<uint8_t>& buffer, string location) -> s
|
|||
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");
|
||||
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"}, markup);
|
||||
if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest);
|
||||
write({target, "program.rom"}, buffer);
|
||||
return success(target);
|
||||
}
|
||||
|
|
|
@ -5,30 +5,20 @@ auto Icarus::gameBoyColorManifest(string location) -> string {
|
|||
}
|
||||
|
||||
auto Icarus::gameBoyColorManifest(vector<uint8_t>& buffer, string location) -> string {
|
||||
string markup;
|
||||
string digest = Hash::SHA256(buffer.data(), buffer.size()).digest();
|
||||
auto digest = Hash::SHA256(buffer).digest();
|
||||
|
||||
if(settings["icarus/UseDatabase"].boolean() && !markup) {
|
||||
for(auto node : database.gameBoyColor) {
|
||||
if(node["sha256"].text() == digest) {
|
||||
markup.append(node.text(), "\n sha256: ", digest, "\n");
|
||||
break;
|
||||
}
|
||||
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() && !markup) {
|
||||
GameBoyCartridge 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");
|
||||
}
|
||||
if(settings["icarus/UseHeuristics"].boolean()) {
|
||||
Heuristics::GameBoy game{buffer, location};
|
||||
if(auto manifest = game.manifest()) return manifest;
|
||||
}
|
||||
|
||||
return markup;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto Icarus::gameBoyColorImport(vector<uint8_t>& buffer, string location) -> string {
|
||||
|
@ -36,15 +26,15 @@ auto Icarus::gameBoyColorImport(vector<uint8_t>& buffer, string location) -> str
|
|||
auto source = Location::path(location);
|
||||
string target{settings["Library/Location"].text(), "Game Boy Color/", name, ".gbc/"};
|
||||
|
||||
auto markup = gameBoyColorManifest(buffer, location);
|
||||
if(!markup) return failure("failed to parse ROM image");
|
||||
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"}, markup);
|
||||
if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest);
|
||||
write({target, "program.rom"}, buffer);
|
||||
return success(target);
|
||||
}
|
||||
|
|
|
@ -5,30 +5,20 @@ auto Icarus::gameBoyManifest(string location) -> string {
|
|||
}
|
||||
|
||||
auto Icarus::gameBoyManifest(vector<uint8_t>& buffer, string location) -> string {
|
||||
string markup;
|
||||
string digest = Hash::SHA256(buffer.data(), buffer.size()).digest();
|
||||
auto digest = Hash::SHA256(buffer).digest();
|
||||
|
||||
if(settings["icarus/UseDatabase"].boolean() && !markup) {
|
||||
for(auto node : database.gameBoy) {
|
||||
if(node["sha256"].text() == digest) {
|
||||
markup.append(node.text(), "\n sha256: ", digest, "\n");
|
||||
break;
|
||||
}
|
||||
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() && !markup) {
|
||||
GameBoyCartridge 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");
|
||||
}
|
||||
if(settings["icarus/UseHeuristics"].boolean()) {
|
||||
Heuristics::GameBoy game{buffer, location};
|
||||
if(auto manifest = game.manifest()) return manifest;
|
||||
}
|
||||
|
||||
return markup;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto Icarus::gameBoyImport(vector<uint8_t>& buffer, string location) -> string {
|
||||
|
@ -36,15 +26,15 @@ auto Icarus::gameBoyImport(vector<uint8_t>& buffer, string location) -> string {
|
|||
auto source = Location::path(location);
|
||||
string target{settings["Library/Location"].text(), "Game Boy/", name, ".gb/"};
|
||||
|
||||
auto markup = gameBoyManifest(buffer, location);
|
||||
if(!markup) return failure("failed to parse ROM image");
|
||||
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"}, markup);
|
||||
if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest);
|
||||
write({target, "program.rom"}, buffer);
|
||||
return success(target);
|
||||
}
|
||||
|
|
|
@ -5,24 +5,19 @@ auto Icarus::gameGearManifest(string location) -> string {
|
|||
}
|
||||
|
||||
auto Icarus::gameGearManifest(vector<uint8_t>& buffer, string location) -> string {
|
||||
string manifest;
|
||||
|
||||
if(settings["icarus/UseDatabase"].boolean() && !manifest) {
|
||||
string digest = Hash::SHA256(buffer.data(), buffer.size()).digest();
|
||||
for(auto node : database.gameGear) {
|
||||
if(node["sha256"].text() == digest) {
|
||||
manifest.append(node.text(), "\n sha256: ", digest, "\n");
|
||||
break;
|
||||
}
|
||||
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() && !manifest) {
|
||||
GameGearCartridge cartridge{location, buffer.data(), buffer.size()};
|
||||
manifest = cartridge.manifest;
|
||||
if(settings["icarus/UseHeuristics"].boolean()) {
|
||||
Heuristics::GameGear game{buffer, location};
|
||||
if(auto manifest = game.manifest()) return manifest;
|
||||
}
|
||||
|
||||
return manifest;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto Icarus::gameGearImport(vector<uint8_t>& buffer, string location) -> string {
|
||||
|
|
|
@ -5,24 +5,19 @@ auto Icarus::masterSystemManifest(string location) -> string {
|
|||
}
|
||||
|
||||
auto Icarus::masterSystemManifest(vector<uint8_t>& buffer, string location) -> string {
|
||||
string manifest;
|
||||
|
||||
if(settings["icarus/UseDatabase"].boolean() && !manifest) {
|
||||
string digest = Hash::SHA256(buffer.data(), buffer.size()).digest();
|
||||
for(auto node : database.masterSystem) {
|
||||
if(node["sha256"].text() == digest) {
|
||||
manifest.append(node.text(), "\n sha256: ", digest, "\n");
|
||||
break;
|
||||
}
|
||||
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() && !manifest) {
|
||||
MasterSystemCartridge cartridge{location, buffer.data(), buffer.size()};
|
||||
manifest = cartridge.manifest;
|
||||
if(settings["icarus/UseHeuristics"].boolean()) {
|
||||
Heuristics::MasterSystem game{buffer, location};
|
||||
if(auto manifest = game.manifest()) return manifest;
|
||||
}
|
||||
|
||||
return manifest;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto Icarus::masterSystemImport(vector<uint8_t>& buffer, string location) -> string {
|
||||
|
|
|
@ -5,24 +5,19 @@ auto Icarus::megaDriveManifest(string location) -> string {
|
|||
}
|
||||
|
||||
auto Icarus::megaDriveManifest(vector<uint8_t>& buffer, string location) -> string {
|
||||
string manifest;
|
||||
|
||||
if(settings["icarus/UseDatabase"].boolean() && !manifest) {
|
||||
string digest = Hash::SHA256(buffer.data(), buffer.size()).digest();
|
||||
for(auto node : database.megaDrive) {
|
||||
if(node["sha256"].text() == digest) {
|
||||
manifest.append(node.text(), "\n sha256: ", digest, "\n");
|
||||
break;
|
||||
}
|
||||
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() && !manifest) {
|
||||
MegaDriveCartridge cartridge{location, buffer.data(), buffer.size()};
|
||||
manifest = cartridge.manifest;
|
||||
if(settings["icarus/UseHeuristics"].boolean()) {
|
||||
Heuristics::MegaDrive game{buffer, location};
|
||||
if(auto manifest = game.manifest()) return manifest;
|
||||
}
|
||||
|
||||
return manifest;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto Icarus::megaDriveImport(vector<uint8_t>& buffer, string location) -> string {
|
||||
|
|
|
@ -5,24 +5,19 @@ auto Icarus::pcEngineManifest(string location) -> string {
|
|||
}
|
||||
|
||||
auto Icarus::pcEngineManifest(vector<uint8_t>& buffer, string location) -> string {
|
||||
string manifest;
|
||||
|
||||
if(settings["icarus/UseDatabase"].boolean() && !manifest) {
|
||||
string digest = Hash::SHA256(buffer.data(), buffer.size()).digest();
|
||||
for(auto node : database.pcEngine) {
|
||||
if(node["sha256"].text() == digest) {
|
||||
manifest.append(node.text(), "\n sha256: ", digest, "\n");
|
||||
break;
|
||||
}
|
||||
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() && !manifest) {
|
||||
PCEngineCartridge cartridge{location, buffer.data(), buffer.size()};
|
||||
manifest = cartridge.manifest;
|
||||
if(settings["icarus/UseHeuristics"].boolean()) {
|
||||
Heuristics::PCEngine game{buffer, location};
|
||||
if(auto manifest = game.manifest()) return manifest;
|
||||
}
|
||||
|
||||
return manifest;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto Icarus::pcEngineImport(vector<uint8_t>& buffer, string location) -> string {
|
||||
|
|
|
@ -5,10 +5,9 @@ auto Icarus::sufamiTurboManifest(string location) -> string {
|
|||
}
|
||||
|
||||
auto Icarus::sufamiTurboManifest(vector<uint8_t>& buffer, string location) -> string {
|
||||
auto digest = Hash::SHA256(buffer).digest();
|
||||
|
||||
if(settings["icarus/UseDatabase"].boolean()) {
|
||||
for(auto game : database.sufamiTurbo.find("game")) {
|
||||
auto digest = Hash::SHA256(buffer).digest();
|
||||
for(auto game : Database::SufamiTurbo.find("game")) {
|
||||
if(game["sha256"].text() == digest) return BML::serialize(game);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,10 +10,9 @@ auto Icarus::superFamicomManifest(string location) -> string {
|
|||
}
|
||||
|
||||
auto Icarus::superFamicomManifest(vector<uint8_t>& buffer, string location) -> string {
|
||||
auto digest = Hash::SHA256(buffer).digest();
|
||||
|
||||
if(settings["icarus/UseDatabase"].boolean()) {
|
||||
for(auto game : database.superFamicom.find("game")) {
|
||||
auto digest = Hash::SHA256(buffer).digest();
|
||||
for(auto game : Database::SuperFamicom.find("game")) {
|
||||
if(game["sha256"].text() == digest) return BML::serialize(game);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,24 +5,19 @@ auto Icarus::superGrafxManifest(string location) -> string {
|
|||
}
|
||||
|
||||
auto Icarus::superGrafxManifest(vector<uint8_t>& buffer, string location) -> string {
|
||||
string manifest;
|
||||
|
||||
if(settings["icarus/UseDatabase"].boolean() && !manifest) {
|
||||
string digest = Hash::SHA256(buffer.data(), buffer.size()).digest();
|
||||
for(auto node : database.superGrafx) {
|
||||
if(node["sha256"].text() == digest) {
|
||||
manifest.append(node.text(), "\n sha256: ", digest, "\n");
|
||||
break;
|
||||
}
|
||||
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() && !manifest) {
|
||||
SuperGrafxCartridge cartridge{location, buffer.data(), buffer.size()};
|
||||
manifest = cartridge.manifest;
|
||||
if(settings["icarus/UseHeuristics"].boolean()) {
|
||||
Heuristics::SuperGrafx game{buffer, location};
|
||||
if(auto manifest = game.manifest()) return manifest;
|
||||
}
|
||||
|
||||
return manifest;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto Icarus::superGrafxImport(vector<uint8_t>& buffer, string location) -> string {
|
||||
|
|
|
@ -5,24 +5,19 @@ auto Icarus::wonderSwanColorManifest(string location) -> string {
|
|||
}
|
||||
|
||||
auto Icarus::wonderSwanColorManifest(vector<uint8_t>& buffer, string location) -> string {
|
||||
string manifest;
|
||||
|
||||
if(settings["icarus/UseDatabase"].boolean() && !manifest) {
|
||||
string digest = Hash::SHA256(buffer.data(), buffer.size()).digest();
|
||||
for(auto node : database.wonderSwanColor) {
|
||||
if(node["sha256"].text() == digest) {
|
||||
manifest.append(node.text(), "\n sha256: ", digest, "\n");
|
||||
break;
|
||||
}
|
||||
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() && !manifest) {
|
||||
WonderSwanCartridge cartridge{location, buffer.data(), buffer.size()};
|
||||
manifest = cartridge.manifest;
|
||||
if(settings["icarus/UseHeuristics"].boolean()) {
|
||||
Heuristics::WonderSwan game{buffer, location};
|
||||
if(auto manifest = game.manifest()) return manifest;
|
||||
}
|
||||
|
||||
return manifest;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto Icarus::wonderSwanColorImport(vector<uint8_t>& buffer, string location) -> string {
|
||||
|
|
|
@ -5,24 +5,19 @@ auto Icarus::wonderSwanManifest(string location) -> string {
|
|||
}
|
||||
|
||||
auto Icarus::wonderSwanManifest(vector<uint8_t>& buffer, string location) -> string {
|
||||
string manifest;
|
||||
|
||||
if(settings["icarus/UseDatabase"].boolean() && !manifest) {
|
||||
string digest = Hash::SHA256(buffer.data(), buffer.size()).digest();
|
||||
for(auto node : database.wonderSwan) {
|
||||
if(node["sha256"].text() == digest) {
|
||||
manifest.append(node.text(), "\n sha256: ", digest, "\n");
|
||||
break;
|
||||
}
|
||||
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() && !manifest) {
|
||||
WonderSwanCartridge cartridge{location, buffer.data(), buffer.size()};
|
||||
manifest = cartridge.manifest;
|
||||
if(settings["icarus/UseHeuristics"].boolean()) {
|
||||
Heuristics::WonderSwan game{buffer, location};
|
||||
if(auto manifest = game.manifest()) return manifest;
|
||||
}
|
||||
|
||||
return manifest;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto Icarus::wonderSwanImport(vector<uint8_t>& buffer, string location) -> string {
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
namespace Heuristics {
|
||||
|
||||
struct BSMemory {
|
||||
struct BSMemory : Heuristics {
|
||||
BSMemory(vector<uint8_t>& data, string location);
|
||||
explicit operator bool() const;
|
||||
|
||||
auto manifest() const -> string;
|
||||
|
||||
private:
|
||||
|
@ -19,17 +18,14 @@ BSMemory::operator bool() const {
|
|||
}
|
||||
|
||||
auto BSMemory::manifest() const -> string {
|
||||
if(!operator bool()) return "";
|
||||
if(!operator bool()) return {};
|
||||
|
||||
string output;
|
||||
output.append("game\n");
|
||||
output.append(" sha256: ", Hash::SHA256(data).digest(), "\n");
|
||||
output.append(" name: ", Location::prefix(location), "\n");
|
||||
output.append(" label: ", Location::prefix(location), "\n");
|
||||
output.append(" memory\n");
|
||||
output.append(" type: NAND\n");
|
||||
output.append(" size: 0x", hex(data.size()), "\n");
|
||||
output.append(" name: program.rom\n");
|
||||
output.append(memory("NAND", data.size(), "program.rom"));
|
||||
return output;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,161 +1,173 @@
|
|||
struct FamicomCartridge {
|
||||
FamicomCartridge(const uint8_t* data, uint size);
|
||||
namespace Heuristics {
|
||||
|
||||
string markup;
|
||||
struct Famicom : Heuristics {
|
||||
Famicom(vector<uint8_t>& data, string location);
|
||||
explicit operator bool() const;
|
||||
auto manifest() const -> string;
|
||||
|
||||
//private:
|
||||
uint mapper;
|
||||
uint mirror;
|
||||
uint prgrom;
|
||||
uint prgram;
|
||||
uint chrrom;
|
||||
uint chrram;
|
||||
private:
|
||||
vector<uint8_t>& data;
|
||||
string location;
|
||||
};
|
||||
|
||||
FamicomCartridge::FamicomCartridge(const uint8_t* data, uint size) {
|
||||
if(size < 16) return;
|
||||
if(data[0] != 'N') return;
|
||||
if(data[1] != 'E') return;
|
||||
if(data[2] != 'S') return;
|
||||
if(data[3] != 26) return;
|
||||
Famicom::Famicom(vector<uint8_t>& data, string location) : data(data), location(location) {
|
||||
}
|
||||
|
||||
mapper = ((data[7] >> 4) << 4) | (data[6] >> 4);
|
||||
mirror = ((data[6] & 0x08) >> 2) | (data[6] & 0x01);
|
||||
prgrom = data[4] * 0x4000;
|
||||
chrrom = data[5] * 0x2000;
|
||||
prgram = 0u;
|
||||
chrram = chrrom == 0u ? 8192u : 0u;
|
||||
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;
|
||||
}
|
||||
|
||||
markup.append("board ");
|
||||
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(" name: ", Location::prefix(location), "\n");
|
||||
output.append(" label: ", Location::prefix(location), "\n");
|
||||
|
||||
switch(mapper) {
|
||||
default:
|
||||
markup.append("id:NES-NROM-256\n");
|
||||
markup.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
|
||||
output.append(" board: NES-NROM-256\n");
|
||||
output.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
|
||||
break;
|
||||
|
||||
case 1:
|
||||
markup.append("id:NES-SXROM\n");
|
||||
markup.append(" chip type=MMC1B2\n");
|
||||
output.append(" board: NES-SXROM\n");
|
||||
output.append(" chip type=MMC1B2\n");
|
||||
prgram = 8192;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
markup.append("id:NES-UOROM\n");
|
||||
markup.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
|
||||
output.append(" board: NES-UOROM\n");
|
||||
output.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
|
||||
break;
|
||||
|
||||
case 3:
|
||||
markup.append("id:NES-CNROM\n");
|
||||
markup.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
|
||||
output.append(" board: NES-CNROM\n");
|
||||
output.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
|
||||
break;
|
||||
|
||||
case 4:
|
||||
//MMC3
|
||||
markup.append("id:NES-TLROM\n");
|
||||
markup.append(" chip type=MMC3B\n");
|
||||
output.append(" board: NES-TLROM\n");
|
||||
output.append(" chip type=MMC3B\n");
|
||||
prgram = 8192;
|
||||
//MMC6
|
||||
//markup.append("id:NES-HKROM\n");
|
||||
//markup.append(" chip type=MMC6n");
|
||||
//output.append(" board: NES-HKROM\n");
|
||||
//output.append(" chip type=MMC6\n");
|
||||
//prgram = 1024;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
markup.append("id:NES-ELROM\n");
|
||||
markup.append(" chip type=MMC5\n");
|
||||
output.append(" board: NES-ELROM\n");
|
||||
output.append(" chip type=MMC5\n");
|
||||
prgram = 65536;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
markup.append("id:NES-AOROM\n");
|
||||
output.append(" board: NES-AOROM\n");
|
||||
break;
|
||||
|
||||
case 9:
|
||||
markup.append("id:NES-PNROM\n");
|
||||
markup.append(" chip type=MMC2\n");
|
||||
output.append(" board: NES-PNROM\n");
|
||||
output.append(" chip type=MMC2\n");
|
||||
prgram = 8192;
|
||||
break;
|
||||
|
||||
case 10:
|
||||
markup.append("id:NES-FKROM\n");
|
||||
markup.append(" chip type=MMC4\n");
|
||||
output.append(" board: NES-FKROM\n");
|
||||
output.append(" chip type=MMC4\n");
|
||||
prgram = 8192;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
markup.append("id:BANDAI-FCG\n");
|
||||
markup.append(" chip type=LZ93D50\n");
|
||||
output.append(" board: BANDAI-FCG\n");
|
||||
output.append(" chip type=LZ93D50\n");
|
||||
break;
|
||||
|
||||
case 21:
|
||||
case 23:
|
||||
case 25:
|
||||
//VRC4
|
||||
markup.append("id:KONAMI-VRC-4\n");
|
||||
markup.append(" chip type=VRC4\n");
|
||||
markup.append(" pinout a0=1 a1=0\n");
|
||||
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
|
||||
markup.append("id:KONAMI-VRC-2\n");
|
||||
markup.append(" chip type=VRC2\n");
|
||||
markup.append(" pinout a0=0 a1=1\n");
|
||||
output.append(" board: KONAMI-VRC-2\n");
|
||||
output.append(" chip type=VRC2\n");
|
||||
output.append(" pinout a0=0 a1=1\n");
|
||||
break;
|
||||
|
||||
case 24:
|
||||
markup.append("id:KONAMI-VRC-6\n");
|
||||
markup.append(" chip type=VRC6\n");
|
||||
output.append(" board: KONAMI-VRC-6\n");
|
||||
output.append(" chip type=VRC6\n");
|
||||
break;
|
||||
|
||||
case 26:
|
||||
markup.append("id:KONAMI-VRC-6\n");
|
||||
markup.append(" chip type=VRC6\n");
|
||||
output.append(" board: KONAMI-VRC-6\n");
|
||||
output.append(" chip type=VRC6\n");
|
||||
prgram = 8192;
|
||||
break;
|
||||
|
||||
case 34:
|
||||
markup.append("id:NES-BNROM\n");
|
||||
markup.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
|
||||
output.append(" board: NES-BNROM\n");
|
||||
output.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
|
||||
break;
|
||||
|
||||
case 66:
|
||||
markup.append("id:NES-GNROM\n");
|
||||
markup.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
|
||||
output.append(" board: NES-GNROM\n");
|
||||
output.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
|
||||
break;
|
||||
|
||||
case 69:
|
||||
markup.append("id:SUNSOFT-5B\n");
|
||||
markup.append(" chip type=5B\n");
|
||||
output.append(" board: SUNSOFT-5B\n");
|
||||
output.append(" chip type=5B\n");
|
||||
prgram = 8192;
|
||||
break;
|
||||
|
||||
case 73:
|
||||
markup.append("id:KONAMI-VRC-3\n");
|
||||
markup.append(" chip type=VRC3\n");
|
||||
markup.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
|
||||
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:
|
||||
markup.append("id:KONAMI-VRC-1\n");
|
||||
markup.append(" chip type=VRC1\n");
|
||||
output.append(" board: KONAMI-VRC-1\n");
|
||||
output.append(" chip type=VRC1\n");
|
||||
break;
|
||||
|
||||
case 85:
|
||||
markup.append("id:KONAMI-VRC-7\n");
|
||||
markup.append(" chip type=VRC7\n");
|
||||
output.append(" board: KONAMI-VRC-7\n");
|
||||
output.append(" chip type=VRC7\n");
|
||||
prgram = 8192;
|
||||
break;
|
||||
}
|
||||
|
||||
markup.append(" prg\n");
|
||||
if(prgrom) markup.append(" rom name=program.rom size=0x", hex(prgrom), "\n");
|
||||
if(prgram) markup.append(" ram name=save.ram size=0x", hex(prgram), "\n");
|
||||
if(prgrom) output.append(memory("ROM", prgrom, "program.rom"));
|
||||
if(prgram) output.append(memory("NVRAM", prgram, "save.ram"));
|
||||
|
||||
if(chrrom) output.append(memory("ROM", chrrom, "character.rom"));
|
||||
if(chrram) output.append(memory("RAM", chrram, "character.ram"));
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
markup.append(" chr\n");
|
||||
if(chrrom) markup.append(" rom name=character.rom size=0x", hex(chrrom), "\n");
|
||||
if(chrram) markup.append(" ram size=0x", hex(chrram), "\n");
|
||||
}
|
||||
|
|
|
@ -1,50 +1,66 @@
|
|||
struct GameBoyAdvanceCartridge {
|
||||
GameBoyAdvanceCartridge(const uint8_t* data, unsigned size);
|
||||
namespace Heuristics {
|
||||
|
||||
string markup;
|
||||
string identifiers;
|
||||
struct GameBoyAdvance : Heuristics {
|
||||
GameBoyAdvance(vector<uint8_t>& buffer, string location);
|
||||
explicit operator bool() const;
|
||||
auto manifest() const -> string;
|
||||
|
||||
private:
|
||||
vector<uint8_t>& data;
|
||||
string location;
|
||||
};
|
||||
|
||||
GameBoyAdvanceCartridge::GameBoyAdvanceCartridge(const uint8_t* data, unsigned size) {
|
||||
struct Identifier {
|
||||
string name;
|
||||
unsigned size;
|
||||
GameBoyAdvance::GameBoyAdvance(vector<uint8_t>& data, string location) : data(data), location(location) {
|
||||
}
|
||||
|
||||
GameBoyAdvance::operator bool() const {
|
||||
return (bool)data;
|
||||
}
|
||||
|
||||
auto GameBoyAdvance::manifest() const -> string {
|
||||
if(!operator bool()) return {};
|
||||
|
||||
string_vector identifiers = {
|
||||
"SRAM_V",
|
||||
"SRAM_F_V",
|
||||
"EEPROM_V",
|
||||
"FLASH_V",
|
||||
"FLASH512_V",
|
||||
"FLASH1M_V",
|
||||
};
|
||||
vector<Identifier> idlist;
|
||||
idlist.append({"SRAM_V", 6});
|
||||
idlist.append({"SRAM_F_V", 8});
|
||||
idlist.append({"EEPROM_V", 8});
|
||||
idlist.append({"FLASH_V", 7});
|
||||
idlist.append({"FLASH512_V", 10});
|
||||
idlist.append({"FLASH1M_V", 9});
|
||||
|
||||
string_vector list;
|
||||
for(auto& id : idlist) {
|
||||
for(signed n = 0; n < size - 16; n++) {
|
||||
if(!memcmp(data + n, (const char*)id.name, id.size)) {
|
||||
const char* p = (const char*)data + n + id.size;
|
||||
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];
|
||||
memcpy(text, data + n, id.size + 3);
|
||||
text[id.size + 3] = 0;
|
||||
memory::copy(text, &data[n], identifier.size() + 3);
|
||||
text[identifier.size() + 3] = 0;
|
||||
if(!list.find(text)) list.append(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
identifiers = list.merge(",");
|
||||
|
||||
markup.append("board\n");
|
||||
markup.append(" rom type=mrom name=program.rom size=0x", hex(size), "\n");
|
||||
if(0);
|
||||
else if(identifiers.beginsWith("SRAM_V" )) markup.append(" ram type=sram name=save.ram size=0x8000\n");
|
||||
else if(identifiers.beginsWith("SRAM_F_V" )) markup.append(" ram type=sram name=save.ram size=0x8000\n");
|
||||
else if(identifiers.beginsWith("EEPROM_V" )) markup.append(" ram type=eeprom name=save.ram size=0x0\n");
|
||||
else if(identifiers.beginsWith("FLASH_V" )) markup.append(" ram type=flash name=save.ram size=0x10000\n");
|
||||
else if(identifiers.beginsWith("FLASH512_V")) markup.append(" ram type=flash name=save.ram size=0x10000\n");
|
||||
else if(identifiers.beginsWith("FLASH1M_V" )) markup.append(" ram type=flash name=save.ram size=0x20000\n");
|
||||
//if(identifiers) markup.append(" #detected: ", identifiers, "\n");
|
||||
string output;
|
||||
output.append("game\n");
|
||||
output.append(" sha256: ", Hash::SHA256(data).digest(), "\n");
|
||||
output.append(" name: ", Location::prefix(location), "\n");
|
||||
output.append(" label: ", Location::prefix(location), "\n");
|
||||
output.append(memory("ROM", data.size(), "program.rom"));
|
||||
if(!list);
|
||||
else if(list.left().beginsWith("SRAM_V" )) output.append(memory("NVRAM", 0x8000, "save.ram"));
|
||||
else if(list.left().beginsWith("SRAM_F_V" )) output.append(memory("NVRAM", 0x8000, "save.ram"));
|
||||
else if(list.left().beginsWith("EEPROM_V" )) output.append(memory("EEPROM", 0x0, "save.ram"));
|
||||
else if(list.left().beginsWith("FLASH_V" )) output.append(memory("NAND", 0x10000, "save.ram"));
|
||||
else if(list.left().beginsWith("FLASH512_V")) output.append(memory("NAND", 0x10000, "save.ram"));
|
||||
else if(list.left().beginsWith("FLASH1M_V" )) output.append(memory("NAND", 0x20000, "save.ram"));
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,12 +1,38 @@
|
|||
struct GameBoyCartridge {
|
||||
GameBoyCartridge(uint8_t* data, uint size);
|
||||
namespace Heuristics {
|
||||
|
||||
string markup;
|
||||
struct GameBoy : Heuristics {
|
||||
GameBoy(vector<uint8_t>& data, string location);
|
||||
explicit operator bool() const;
|
||||
auto manifest() const -> string;
|
||||
|
||||
bool black = false; //cartridge works in DMG+CGB mode
|
||||
bool clear = false; //cartridge works in CGB mode only
|
||||
private:
|
||||
auto read(uint offset) const -> uint8_t { return data[headerAddress + offset]; }
|
||||
|
||||
vector<uint8_t>& data;
|
||||
string location;
|
||||
uint headerAddress = 0;
|
||||
};
|
||||
|
||||
GameBoy::GameBoy(vector<uint8_t>& data, string location) : data(data), location(location) {
|
||||
headerAddress = data.size() < 0x8000 ? data.size() : data.size() - 0x8000;
|
||||
if(read(0x0104) == 0xce && read(0x0105) == 0xed && read(0x0106) == 0x66 && read(0x0107) == 0x66
|
||||
&& read(0x0108) == 0xcc && read(0x0109) == 0x0d && read(0x0147) >= 0x0b && read(0x0147) <= 0x0d
|
||||
) { //MMM01 stores header at bottom of data[]
|
||||
} else { //all other mappers store header at top of data[]
|
||||
headerAddress = 0;
|
||||
}
|
||||
}
|
||||
|
||||
GameBoy::operator bool() const {
|
||||
return data.size() >= 0x4000;
|
||||
}
|
||||
|
||||
auto GameBoy::manifest() const -> string {
|
||||
if(!operator bool()) return {};
|
||||
|
||||
bool black = (read(0x0143) & 0xc0) == 0x80; //cartridge works in DMG+CGB mode
|
||||
bool clear = (read(0x0143) & 0xc0) == 0xc0; //cartridge works in CGB mode only
|
||||
|
||||
string mapper = "MBC0";
|
||||
bool flash = false;
|
||||
bool battery = false;
|
||||
bool ram = false;
|
||||
|
@ -18,27 +44,10 @@ struct GameBoyCartridge {
|
|||
uint romSize = 0;
|
||||
uint ramSize = 0;
|
||||
uint rtcSize = 0;
|
||||
};
|
||||
|
||||
GameBoyCartridge::GameBoyCartridge(uint8_t* data, uint size) {
|
||||
if(size < 0x4000) return;
|
||||
string mapper = "MBC0";
|
||||
|
||||
uint index = size < 0x8000 ? size : size - 0x8000;
|
||||
if(data[index + 0x0104] == 0xce && data[index + 0x0105] == 0xed
|
||||
&& data[index + 0x0106] == 0x66 && data[index + 0x0107] == 0x66
|
||||
&& data[index + 0x0108] == 0xcc && data[index + 0x0109] == 0x0d
|
||||
&& data[index + 0x0147] >= 0x0b && data[index + 0x0147] <= 0x0d
|
||||
) {
|
||||
//MMM01 stores header at bottom of data[]
|
||||
} else {
|
||||
//all other mappers store header at top of data[]
|
||||
index = 0;
|
||||
}
|
||||
|
||||
black = (data[index + 0x0143] & 0xc0) == 0x80;
|
||||
clear = (data[index + 0x0143] & 0xc0) == 0xc0;
|
||||
|
||||
switch(data[index + 0x0147]) {
|
||||
switch(read(0x0147)) {
|
||||
|
||||
case 0x00:
|
||||
mapper = "MBC0";
|
||||
|
@ -195,7 +204,7 @@ GameBoyCartridge::GameBoyCartridge(uint8_t* data, uint size) {
|
|||
|
||||
}
|
||||
|
||||
switch(data[index + 0x0148]) { default:
|
||||
switch(read(0x0148)) { default:
|
||||
case 0x00: romSize = 2 * 16 * 1024; break;
|
||||
case 0x01: romSize = 4 * 16 * 1024; break;
|
||||
case 0x02: romSize = 8 * 16 * 1024; break;
|
||||
|
@ -211,7 +220,7 @@ GameBoyCartridge::GameBoyCartridge(uint8_t* data, uint size) {
|
|||
|
||||
if(mapper == "MBC6" && flash) flashSize = 1024 * 1024;
|
||||
|
||||
switch(data[index + 0x0149]) { default:
|
||||
switch(read(0x0149)) { default:
|
||||
case 0x00: ramSize = 0 * 1024; break;
|
||||
case 0x01: ramSize = 2 * 1024; break;
|
||||
case 0x02: ramSize = 8 * 1024; break;
|
||||
|
@ -226,9 +235,19 @@ GameBoyCartridge::GameBoyCartridge(uint8_t* data, uint size) {
|
|||
if(mapper == "MBC3" && rtc) rtcSize = 13;
|
||||
if(mapper == "TAMA" && rtc) rtcSize = 21;
|
||||
|
||||
markup.append("board mapper=", mapper, accelerometer ? " accelerometer" : "", rumble ? " rumble" : "", "\n");
|
||||
markup.append(" rom name=program.rom size=0x", hex(romSize), "\n");
|
||||
if(flash && flashSize) markup.append(" flash name=download.rom size=0x", hex(flashSize), "\n");
|
||||
if(ram && ramSize) markup.append(" ram ", battery ? "name=save.ram " : "", "size=0x", hex(ramSize), "\n");
|
||||
if(rtc && rtcSize) markup.append(" rtc ", battery ? "name=rtc.ram " : "", "size=0x", hex(rtcSize), "\n");
|
||||
string output;
|
||||
output.append("game\n");
|
||||
output.append(" sha256: ", Hash::SHA256(data).digest(), "\n");
|
||||
output.append(" board: ", mapper, "\n");
|
||||
if(accelerometer) output.append(" accelerometer\n");
|
||||
if(rumble) output.append(" rumble\n");
|
||||
output.append(" name: ", Location::prefix(location), "\n");
|
||||
output.append(" label: ", Location::prefix(location), "\n");
|
||||
output.append(memory("ROM", data.size(), "program.rom"));
|
||||
if(flash && flashSize) output.append(memory("NAND", flashSize, "download.rom"));
|
||||
if(ram && ramSize) output.append(memory(battery ? "NVRAM" : "RAM", ramSize, "save.ram"));
|
||||
if(rtc && rtcSize) output.append(memory("RTC", rtcSize, "rtc.ram"));
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,20 +1,30 @@
|
|||
struct GameGearCartridge {
|
||||
GameGearCartridge(string location, uint8_t* data, uint size);
|
||||
namespace Heuristics {
|
||||
|
||||
string manifest;
|
||||
struct GameGear : Heuristics {
|
||||
GameGear(vector<uint8_t>& data, string location);
|
||||
explicit operator bool() const;
|
||||
auto manifest() const -> string;
|
||||
|
||||
//private:
|
||||
struct Information {
|
||||
} information;
|
||||
private:
|
||||
vector<uint8_t>& data;
|
||||
string location;
|
||||
};
|
||||
|
||||
GameGearCartridge::GameGearCartridge(string location, uint8_t* data, uint size) {
|
||||
manifest.append("board\n");
|
||||
manifest.append(" rom name=program.rom size=0x", hex(size), "\n");
|
||||
manifest.append("\n");
|
||||
manifest.append("information\n");
|
||||
manifest.append(" title: ", Location::prefix(location), "\n");
|
||||
manifest.append(" sha256: ", Hash::SHA256(data, size).digest(), "\n");
|
||||
manifest.append("\n");
|
||||
manifest.append("note: heuristically generated by icarus\n");
|
||||
GameGear::GameGear(vector<uint8_t>& 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(" name: ", Location::prefix(location), "\n");
|
||||
output.append(" label: ", Location::prefix(location), "\n");
|
||||
output.append(memory("ROM", data.size(), "program.rom"));
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
namespace Heuristics {
|
||||
|
||||
auto Heuristics::memory(string type, uint size, string name) const -> string {
|
||||
string output;
|
||||
output.append(" memory\n");
|
||||
output.append(" type: ", type, "\n");
|
||||
output.append(" size: 0x", hex(size), "\n");
|
||||
output.append(" name: ", name, "\n");
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
namespace Heuristics {
|
||||
|
||||
struct Heuristics {
|
||||
auto memory(string type, uint size, string name) const -> string;
|
||||
};
|
||||
|
||||
}
|
|
@ -1,21 +1,31 @@
|
|||
struct MasterSystemCartridge {
|
||||
MasterSystemCartridge(string location, uint8_t* data, uint size);
|
||||
namespace Heuristics {
|
||||
|
||||
string manifest;
|
||||
struct MasterSystem : Heuristics {
|
||||
MasterSystem(vector<uint8_t>& data, string location);
|
||||
explicit operator bool() const;
|
||||
auto manifest() const -> string;
|
||||
|
||||
//private:
|
||||
struct Information {
|
||||
} information;
|
||||
private:
|
||||
vector<uint8_t>& data;
|
||||
string location;
|
||||
};
|
||||
|
||||
MasterSystemCartridge::MasterSystemCartridge(string location, uint8_t* data, uint size) {
|
||||
manifest.append("board\n");
|
||||
manifest.append(" rom name=program.rom size=0x", hex(size), "\n");
|
||||
manifest.append(" ram name=save.ram size=0x8000\n");
|
||||
manifest.append("\n");
|
||||
manifest.append("information\n");
|
||||
manifest.append(" title: ", Location::prefix(location), "\n");
|
||||
manifest.append(" sha256: ", Hash::SHA256(data, size).digest(), "\n");
|
||||
manifest.append("\n");
|
||||
manifest.append("note: heuristically generated by icarus\n");
|
||||
MasterSystem::MasterSystem(vector<uint8_t>& 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(" name: ", Location::prefix(location), "\n");
|
||||
output.append(" label: ", Location::prefix(location), "\n");
|
||||
output.append(memory("ROM", data.size(), "program.rom"));
|
||||
output.append(memory("NVRAM", 0x8000, "save.ram"));
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,15 +1,24 @@
|
|||
struct MegaDriveCartridge {
|
||||
MegaDriveCartridge(string location, uint8_t* data, uint size);
|
||||
namespace Heuristics {
|
||||
|
||||
string manifest;
|
||||
struct MegaDrive : Heuristics {
|
||||
MegaDrive(vector<uint8_t>& data, string location);
|
||||
explicit operator bool() const;
|
||||
auto manifest() const -> string;
|
||||
|
||||
//private:
|
||||
struct Information {
|
||||
} information;
|
||||
private:
|
||||
vector<uint8_t>& data;
|
||||
string location;
|
||||
};
|
||||
|
||||
MegaDriveCartridge::MegaDriveCartridge(string location, uint8_t* data, uint size) {
|
||||
if(size < 0x200) return;
|
||||
MegaDrive::MegaDrive(vector<uint8_t>& 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";
|
||||
|
||||
|
@ -40,32 +49,38 @@ MegaDriveCartridge::MegaDriveCartridge(string location, uint8_t* data, uint size
|
|||
string_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(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(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(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");
|
||||
regions.append("NTSC-J");
|
||||
}
|
||||
|
||||
manifest.append("board region=", regions.left(), "\n");
|
||||
manifest.append(" rom name=program.rom size=0x", hex(size), "\n");
|
||||
if(ramSize && ramMode != "none")
|
||||
manifest.append(" ram name=save.ram size=0x", hex(ramSize), " offset=0x", hex(ramFrom), " mode=", ramMode, "\n");
|
||||
manifest.append("\n");
|
||||
manifest.append("information\n");
|
||||
manifest.append(" title: ", Location::prefix(location), "\n");
|
||||
manifest.append("\n");
|
||||
manifest.append("note: heuristically generated by icarus\n");
|
||||
string output;
|
||||
output.append("game\n");
|
||||
output.append(" sha256: ", Hash::SHA256(data).digest(), "\n");
|
||||
output.append(" name: ", Location::prefix(location), "\n");
|
||||
output.append(" label: ", Location::prefix(location), "\n");
|
||||
output.append(" region: ", regions.left(), "\n");
|
||||
output.append(memory("ROM", data.size(), "program.rom"));
|
||||
if(ramSize && ramMode != "none") {
|
||||
output.append(memory("NVRAM", ramSize, "save.ram"));
|
||||
output.append(" mode: ", ramMode, "\n");
|
||||
output.append(" offset: 0x", hex(ramFrom), "\n");
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,23 +1,35 @@
|
|||
struct PCEngineCartridge {
|
||||
PCEngineCartridge(string location, uint8_t* data, uint size);
|
||||
namespace Heuristics {
|
||||
|
||||
string manifest;
|
||||
struct PCEngine : Heuristics {
|
||||
PCEngine(vector<uint8_t>& data, string location);
|
||||
explicit operator bool() const;
|
||||
auto manifest() const -> string;
|
||||
|
||||
//private:
|
||||
struct Information {
|
||||
} information;
|
||||
private:
|
||||
vector<uint8_t>& data;
|
||||
string location;
|
||||
};
|
||||
|
||||
PCEngineCartridge::PCEngineCartridge(string location, uint8_t* data, uint size) {
|
||||
//skip header
|
||||
if((size & 0x1fff) == 512) data += 512, size -= 512;
|
||||
|
||||
manifest.append("board\n");
|
||||
manifest.append(" rom name=program.rom size=0x", hex(size), "\n");
|
||||
manifest.append("\n");
|
||||
manifest.append("information\n");
|
||||
manifest.append(" title: ", Location::prefix(location), "\n");
|
||||
manifest.append(" sha256: ", Hash::SHA256(data, size).digest(), "\n");
|
||||
manifest.append("\n");
|
||||
manifest.append("note: heuristically generated by icarus\n");
|
||||
PCEngine::PCEngine(vector<uint8_t>& 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(" name: ", Location::prefix(location), "\n");
|
||||
output.append(" label: ", Location::prefix(location), "\n");
|
||||
output.append(memory("ROM", data.size(), "program.rom"));
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
namespace Heuristics {
|
||||
|
||||
struct SufamiTurbo {
|
||||
struct SufamiTurbo : Heuristics {
|
||||
SufamiTurbo(vector<uint8_t>& data, string location);
|
||||
explicit operator bool() const;
|
||||
|
||||
|
@ -19,27 +19,18 @@ SufamiTurbo::operator bool() const {
|
|||
}
|
||||
|
||||
auto SufamiTurbo::manifest() const -> string {
|
||||
if(!operator bool()) return "";
|
||||
if(!operator bool()) return {};
|
||||
|
||||
uint romSize = data[0x36] * 0x20000; //128KB
|
||||
uint ramSize = data[0x37] * 0x800; // 2KB
|
||||
|
||||
string output;
|
||||
output.append("game\n");
|
||||
output.append(" name: ", Location::prefix(location), "\n");
|
||||
output.append(" label: ", Location::prefix(location), "\n");
|
||||
if(romSize) {
|
||||
output.append(" memory\n");
|
||||
output.append(" type: ROM\n");
|
||||
output.append(" size: 0x", hex(data.size()), "\n");
|
||||
output.append(" name: program.rom\n");
|
||||
}
|
||||
if(ramSize) {
|
||||
output.append(" memory\n");
|
||||
output.append(" type: NVRAM\n");
|
||||
output.append(" size: 0x", hex(ramSize), "\n");
|
||||
output.append(" name: save.ram\n");
|
||||
}
|
||||
output.append(" sha256: ", Hash::SHA256(data).digest(), "\n");
|
||||
output.append(" name: ", Location::prefix(location), "\n");
|
||||
output.append(" label: ", Location::prefix(location), "\n");
|
||||
output.append(memory("ROM", data.size(), "program.rom"));
|
||||
if(ramSize) output.append(memory("NVRAM", ramSize, "save.ram"));
|
||||
return output;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
namespace Heuristics {
|
||||
|
||||
struct SuperFamicom {
|
||||
struct SuperFamicom : Heuristics {
|
||||
SuperFamicom(vector<uint8_t>& data, string location);
|
||||
explicit operator bool() const;
|
||||
|
||||
|
@ -17,7 +17,6 @@ struct SuperFamicom {
|
|||
|
||||
private:
|
||||
auto size() const -> uint { return data.size(); }
|
||||
auto memory(string type, uint size, string name) const -> string;
|
||||
auto scoreHeader(uint address) -> uint;
|
||||
auto firmwareARM() const -> string;
|
||||
auto firmwareHITACHI() const -> string;
|
||||
|
@ -123,15 +122,6 @@ auto SuperFamicom::manifest() const -> string {
|
|||
return output;
|
||||
}
|
||||
|
||||
auto SuperFamicom::memory(string type, uint size, string name) const -> string {
|
||||
string output;
|
||||
output.append(" memory\n");
|
||||
output.append(" type: ", type, "\n");
|
||||
output.append(" size: 0x", hex(size), "\n");
|
||||
output.append(" name: ", name, "\n");
|
||||
return output;
|
||||
}
|
||||
|
||||
auto SuperFamicom::region() const -> string {
|
||||
string region;
|
||||
|
||||
|
|
|
@ -1,20 +1,30 @@
|
|||
struct SuperGrafxCartridge {
|
||||
SuperGrafxCartridge(string location, uint8_t* data, uint size);
|
||||
namespace Heuristics {
|
||||
|
||||
string manifest;
|
||||
struct SuperGrafx : Heuristics {
|
||||
SuperGrafx(vector<uint8_t>& data, string location);
|
||||
explicit operator bool() const;
|
||||
auto manifest() const -> string;
|
||||
|
||||
//private:
|
||||
struct Information {
|
||||
} information;
|
||||
private:
|
||||
vector<uint8_t>& data;
|
||||
string location;
|
||||
};
|
||||
|
||||
SuperGrafxCartridge::SuperGrafxCartridge(string location, uint8_t* data, uint size) {
|
||||
manifest.append("board\n");
|
||||
manifest.append(" rom name=program.rom size=0x", hex(size), "\n");
|
||||
manifest.append("\n");
|
||||
manifest.append("information\n");
|
||||
manifest.append(" title: ", Location::prefix(location), "\n");
|
||||
manifest.append(" sha256: ", Hash::SHA256(data, size).digest(), "\n");
|
||||
manifest.append("\n");
|
||||
manifest.append("note: heuristically generated by icarus\n");
|
||||
SuperGrafx::operator bool() const {
|
||||
return (bool)data;
|
||||
}
|
||||
|
||||
SuperGrafx::SuperGrafx(vector<uint8_t>& 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(" name: ", Location::prefix(location), "\n");
|
||||
output.append(" label: ", Location::prefix(location), "\n");
|
||||
output.append(memory("ROM", data.size(), "program.rom"));
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,53 +1,55 @@
|
|||
struct WonderSwanCartridge {
|
||||
WonderSwanCartridge(string location, uint8_t* data, uint size);
|
||||
namespace Heuristics {
|
||||
|
||||
string manifest;
|
||||
struct WonderSwan : Heuristics {
|
||||
WonderSwan(vector<uint8_t>& buffer, string location);
|
||||
explicit operator bool() const;
|
||||
auto manifest() const -> string;
|
||||
|
||||
//private:
|
||||
struct Information {
|
||||
bool color;
|
||||
|
||||
string ramType;
|
||||
uint ramSize;
|
||||
bool orientation; //0 = horizontal; 1 = vertical
|
||||
bool hasRTC;
|
||||
} information;
|
||||
private:
|
||||
vector<uint8_t>& data;
|
||||
string location;
|
||||
};
|
||||
|
||||
WonderSwanCartridge::WonderSwanCartridge(string location, uint8_t* data, uint size) {
|
||||
if(size < 0x10000) return;
|
||||
WonderSwan::WonderSwan(vector<uint8_t>& data, string location) : data(data), location(location) {
|
||||
}
|
||||
|
||||
auto metadata = data + size - 16;
|
||||
WonderSwan::operator bool() const {
|
||||
return data.size() >= 0x10000;
|
||||
}
|
||||
|
||||
information.color = metadata[7];
|
||||
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]) {
|
||||
default: information.ramType = ""; information.ramSize = 0; break;
|
||||
case 0x01: information.ramType = "sram"; information.ramSize = 8 * 1024; break;
|
||||
case 0x02: information.ramType = "sram"; information.ramSize = 32 * 1024; break;
|
||||
case 0x03: information.ramType = "sram"; information.ramSize = 128 * 1024; break;
|
||||
case 0x04: information.ramType = "sram"; information.ramSize = 256 * 1024; break;
|
||||
case 0x05: information.ramType = "sram"; information.ramSize = 512 * 1024; break;
|
||||
case 0x10: information.ramType = "eeprom"; information.ramSize = 128; break;
|
||||
case 0x20: information.ramType = "eeprom"; information.ramSize = 2048; break;
|
||||
case 0x50: information.ramType = "eeprom"; information.ramSize = 1024; break;
|
||||
case 0x01: ramType = "NVRAM"; ramSize = 8 * 1024; break;
|
||||
case 0x02: ramType = "NVRAM"; ramSize = 32 * 1024; break;
|
||||
case 0x03: ramType = "NVRAM"; ramSize = 128 * 1024; break;
|
||||
case 0x04: ramType = "NVRAM"; ramSize = 256 * 1024; break;
|
||||
case 0x05: ramType = "NVRAM"; 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;
|
||||
}
|
||||
|
||||
information.orientation = metadata[12] & 1;
|
||||
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(" name: ", Location::prefix(location), "\n");
|
||||
output.append(" label: ", Location::prefix(location), "\n");
|
||||
output.append(" orientation: ", !orientation ? "horizontal" : "vertical", "\n");
|
||||
output.append(memory("ROM", data.size(), "program.rom"));
|
||||
if(ramType && ramSize) output.append(memory(ramType, ramSize, "save.ram"));
|
||||
if(hasRTC) output.append(memory("NVRAM", 16, "rtc.ram"));
|
||||
return output;
|
||||
}
|
||||
|
||||
information.hasRTC = metadata[13] & 1;
|
||||
|
||||
manifest.append("board\n");
|
||||
manifest.append(" rom name=program.rom size=0x", hex(size), "\n");
|
||||
if(information.ramType && information.ramSize)
|
||||
manifest.append(" ram name=save.ram type=", information.ramType, " size=0x", hex(information.ramSize), "\n");
|
||||
if(information.hasRTC)
|
||||
manifest.append(" rtc name=rtc.ram size=16\n");
|
||||
manifest.append("\n");
|
||||
manifest.append("information\n");
|
||||
manifest.append(" title: ", Location::prefix(location), "\n");
|
||||
manifest.append(" orientation: ", !information.orientation ? "horizontal" : "vertical", "\n");
|
||||
manifest.append(" sha256: ", Hash::SHA256(data, size).digest(), "\n");
|
||||
manifest.append("\n");
|
||||
manifest.append("note: heuristically generated by icarus\n");
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@ auto locate(string name) -> string {
|
|||
#include "settings.cpp"
|
||||
Settings settings;
|
||||
|
||||
#include "heuristics/heuristics.hpp"
|
||||
#include "heuristics/heuristics.cpp"
|
||||
#include "heuristics/famicom.cpp"
|
||||
#include "heuristics/super-famicom.cpp"
|
||||
#include "heuristics/master-system.cpp"
|
||||
|
|
Loading…
Reference in New Issue