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()).category("Program").text()); if(ramType && ramSize) output.append(Memory{}.type(ramType).size(ramSize).category("Save").battery(ramType == "RAM").text()); if(hasRTC) output.append(Memory{}.type("RTC").size(0x10).category("Time").text()); return output; } }