diff --git a/Machines/AmstradCPC/AmstradCPC.cpp b/Machines/AmstradCPC/AmstradCPC.cpp index 9698aa3b1..d0599552d 100644 --- a/Machines/AmstradCPC/AmstradCPC.cpp +++ b/Machines/AmstradCPC/AmstradCPC.cpp @@ -781,7 +781,7 @@ template class ConcreteMachine: ay_.ay().set_port_handler(&key_state_); // construct the list of necessary ROMs - std::vector required_roms = {"amsdos.rom"}; + std::vector required_roms = { {"amsdos.rom"} }; std::string model_number; switch(target.model) { default: diff --git a/Machines/Apple/AppleII/AppleII.cpp b/Machines/Apple/AppleII/AppleII.cpp index f36e93103..a04c82318 100644 --- a/Machines/Apple/AppleII/AppleII.cpp +++ b/Machines/Apple/AppleII/AppleII.cpp @@ -347,26 +347,26 @@ template class ConcreteMachine: // Pick the required ROMs. using Target = Analyser::Static::AppleII::Target; - std::vector rom_names; + std::vector rom_names; size_t rom_size = 12*1024; switch(target.model) { default: - rom_names.push_back("apple2-character.rom"); - rom_names.push_back("apple2o.rom"); + rom_names.emplace_back("apple2-character.rom"); + rom_names.emplace_back("apple2o.rom"); break; case Target::Model::IIplus: - rom_names.push_back("apple2-character.rom"); - rom_names.push_back("apple2.rom"); + rom_names.emplace_back("apple2-character.rom"); + rom_names.emplace_back("apple2.rom"); break; case Target::Model::IIe: rom_size += 3840; - rom_names.push_back("apple2eu-character.rom"); - rom_names.push_back("apple2eu.rom"); + rom_names.emplace_back("apple2eu-character.rom"); + rom_names.emplace_back("apple2eu.rom"); break; case Target::Model::EnhancedIIe: rom_size += 3840; - rom_names.push_back("apple2e-character.rom"); - rom_names.push_back("apple2e.rom"); + rom_names.emplace_back("apple2e-character.rom"); + rom_names.emplace_back("apple2e.rom"); break; } const auto roms = rom_fetcher("AppleII", rom_names); diff --git a/Machines/Apple/AppleII/DiskIICard.cpp b/Machines/Apple/AppleII/DiskIICard.cpp index 2235cff6a..869770bfc 100644 --- a/Machines/Apple/AppleII/DiskIICard.cpp +++ b/Machines/Apple/AppleII/DiskIICard.cpp @@ -14,8 +14,8 @@ DiskIICard::DiskIICard(const ROMMachine::ROMFetcher &rom_fetcher, bool is_16_sec const auto roms = rom_fetcher( "DiskII", { - is_16_sector ? "boot-16.rom" : "boot-13.rom", - is_16_sector ? "state-machine-16.rom" : "state-machine-13.rom" + ROMMachine::ROM(is_16_sector ? "boot-16.rom" : "boot-13.rom"), + ROMMachine::ROM(is_16_sector ? "state-machine-16.rom" : "state-machine-13.rom") }); boot_ = std::move(*roms[0]); diskii_.set_state_machine(*roms[1]); diff --git a/Machines/ColecoVision/ColecoVision.cpp b/Machines/ColecoVision/ColecoVision.cpp index 722a33c9b..f0a409c9e 100644 --- a/Machines/ColecoVision/ColecoVision.cpp +++ b/Machines/ColecoVision/ColecoVision.cpp @@ -132,7 +132,7 @@ class ConcreteMachine: const auto roms = rom_fetcher( "ColecoVision", - { "coleco.rom" }); + { ROMMachine::ROM("coleco.rom") }); if(!roms[0]) { throw ROMMachine::Error::MissingROMs; diff --git a/Machines/Commodore/Vic-20/Vic20.cpp b/Machines/Commodore/Vic-20/Vic20.cpp index 1d82bc909..342d3cdb9 100644 --- a/Machines/Commodore/Vic-20/Vic20.cpp +++ b/Machines/Commodore/Vic-20/Vic20.cpp @@ -323,27 +323,27 @@ class ConcreteMachine: // install a joystick joysticks_.emplace_back(new Joystick(*user_port_via_port_handler_, *keyboard_via_port_handler_)); - std::vector rom_names = { "basic.bin" }; + std::vector rom_names = { ROMMachine::ROM("basic.bin") }; switch(target.region) { default: - rom_names.push_back("characters-english.bin"); - rom_names.push_back("kernel-pal.bin"); + rom_names.emplace_back("characters-english.bin"); + rom_names.emplace_back("kernel-pal.bin"); break; case Analyser::Static::Commodore::Target::Region::American: - rom_names.push_back("characters-english.bin"); - rom_names.push_back("kernel-ntsc.bin"); + rom_names.emplace_back("characters-english.bin"); + rom_names.emplace_back("kernel-ntsc.bin"); break; case Analyser::Static::Commodore::Target::Region::Danish: - rom_names.push_back("characters-danish.bin"); - rom_names.push_back("kernel-danish.bin"); + rom_names.emplace_back("characters-danish.bin"); + rom_names.emplace_back("kernel-danish.bin"); break; case Analyser::Static::Commodore::Target::Region::Japanese: - rom_names.push_back("characters-japanese.bin"); - rom_names.push_back("kernel-japanese.bin"); + rom_names.emplace_back("characters-japanese.bin"); + rom_names.emplace_back("kernel-japanese.bin"); break; case Analyser::Static::Commodore::Target::Region::Swedish: - rom_names.push_back("characters-swedish.bin"); - rom_names.push_back("kernel-japanese.bin"); + rom_names.emplace_back("characters-swedish.bin"); + rom_names.emplace_back("kernel-japanese.bin"); break; } diff --git a/Machines/Electron/Electron.cpp b/Machines/Electron/Electron.cpp index 383793397..5aeb80411 100644 --- a/Machines/Electron/Electron.cpp +++ b/Machines/Electron/Electron.cpp @@ -64,14 +64,14 @@ class ConcreteMachine: speaker_.set_input_rate(2000000 / SoundGenerator::clock_rate_divider); speaker_.set_high_frequency_cutoff(7000); - std::vector rom_names = {"basic.rom", "os.rom"}; + std::vector rom_names = { {"basic.rom"}, {"os.rom"} }; if(target.has_adfs) { - rom_names.push_back("ADFS-E00_1.rom"); - rom_names.push_back("ADFS-E00_2.rom"); + rom_names.emplace_back("ADFS-E00_1.rom"); + rom_names.emplace_back("ADFS-E00_2.rom"); } const size_t dfs_rom_position = rom_names.size(); if(target.has_dfs) { - rom_names.push_back("DFS-1770-2.20.rom"); + rom_names.emplace_back("DFS-1770-2.20.rom"); } const auto roms = rom_fetcher("Electron", rom_names); diff --git a/Machines/MSX/MSX.cpp b/Machines/MSX/MSX.cpp index b2e57dcdb..7754719cf 100644 --- a/Machines/MSX/MSX.cpp +++ b/Machines/MSX/MSX.cpp @@ -173,7 +173,7 @@ class ConcreteMachine: mixer_.set_relative_volumes({0.5f, 0.1f, 0.4f}); // Install the proper TV standard and select an ideal BIOS name. - std::vector rom_names = {"msx.rom"}; + std::vector rom_names = { {"msx.rom"} }; bool is_ntsc = true; uint8_t character_generator = 1; /* 0 = Japan, 1 = USA, etc, 2 = USSR */ @@ -182,7 +182,7 @@ class ConcreteMachine: switch(target.region) { case Target::Region::Japan: - rom_names.push_back("msx-japanese.rom"); + rom_names.emplace_back("msx-japanese.rom"); vdp_.set_tv_standard(TI::TMS::TVStandard::NTSC); is_ntsc = true; @@ -190,7 +190,7 @@ class ConcreteMachine: date_format = 0; break; case Target::Region::USA: - rom_names.push_back("msx-american.rom"); + rom_names.emplace_back("msx-american.rom"); vdp_.set_tv_standard(TI::TMS::TVStandard::NTSC); is_ntsc = true; @@ -198,7 +198,7 @@ class ConcreteMachine: date_format = 1; break; case Target::Region::Europe: - rom_names.push_back("msx-european.rom"); + rom_names.emplace_back("msx-european.rom"); vdp_.set_tv_standard(TI::TMS::TVStandard::PAL); is_ntsc = false; @@ -212,7 +212,7 @@ class ConcreteMachine: size_t disk_index = 0; if(target.has_disk_drive) { disk_index = rom_names.size(); - rom_names.push_back("disk.rom"); + rom_names.emplace_back("disk.rom"); } const auto roms = rom_fetcher("MSX", rom_names); diff --git a/Machines/MasterSystem/MasterSystem.cpp b/Machines/MasterSystem/MasterSystem.cpp index 7400c6dae..2ef9072e4 100644 --- a/Machines/MasterSystem/MasterSystem.cpp +++ b/Machines/MasterSystem/MasterSystem.cpp @@ -132,7 +132,7 @@ class ConcreteMachine: // Load the BIOS if relevant. if(has_bios()) { - const auto roms = rom_fetcher("MasterSystem", {"bios.sms"}); + const auto roms = rom_fetcher("MasterSystem", { ROMMachine::ROM("bios.sms") }); if(!roms[0]) { // No BIOS found; attempt to boot as though it has already disabled itself. memory_control_ |= 0x08; diff --git a/Machines/Oric/Oric.cpp b/Machines/Oric/Oric.cpp index 58ebdd907..5382dc710 100644 --- a/Machines/Oric/Oric.cpp +++ b/Machines/Oric/Oric.cpp @@ -228,16 +228,16 @@ template class Co diskii_.set_clocking_hint_observer(this); } - std::vector rom_names = {"colour.rom"}; + std::vector rom_names = { {"colour.rom"} }; switch(target.rom) { - case Analyser::Static::Oric::Target::ROM::BASIC10: rom_names.push_back("basic10.rom"); break; - case Analyser::Static::Oric::Target::ROM::BASIC11: rom_names.push_back("basic11.rom"); break; - case Analyser::Static::Oric::Target::ROM::Pravetz: rom_names.push_back("pravetz.rom"); break; + case Analyser::Static::Oric::Target::ROM::BASIC10: rom_names.emplace_back("basic10.rom"); break; + case Analyser::Static::Oric::Target::ROM::BASIC11: rom_names.emplace_back("basic11.rom"); break; + case Analyser::Static::Oric::Target::ROM::Pravetz: rom_names.emplace_back("pravetz.rom"); break; } switch(disk_interface) { default: break; - case Analyser::Static::Oric::Target::DiskInterface::Microdisc: rom_names.push_back("microdisc.rom"); break; - case Analyser::Static::Oric::Target::DiskInterface::Pravetz: rom_names.push_back("8dos.rom"); break; + case Analyser::Static::Oric::Target::DiskInterface::Microdisc: rom_names.emplace_back("microdisc.rom"); break; + case Analyser::Static::Oric::Target::DiskInterface::Pravetz: rom_names.emplace_back("8dos.rom"); break; } const auto roms = rom_fetcher("Oric", rom_names); @@ -261,7 +261,7 @@ template class Co pravetz_rom_ = std::move(*roms[2]); pravetz_rom_.resize(512); - auto state_machine_rom = rom_fetcher("DiskII", {"state-machine-16.rom"}); + auto state_machine_rom = rom_fetcher("DiskII", { ROMMachine::ROM("state-machine-16.rom") }); if(!state_machine_rom[0]) { throw ROMMachine::Error::MissingROMs; } diff --git a/Machines/ROMMachine.hpp b/Machines/ROMMachine.hpp index a42942563..cd187bfe6 100644 --- a/Machines/ROMMachine.hpp +++ b/Machines/ROMMachine.hpp @@ -16,6 +16,32 @@ namespace ROMMachine { +/*! + Describes a ROM image; this term is used in this emulator strictly in the sense of firmware — + system software that is an inherent part of a machine. +*/ +struct ROM { + /// A descriptive name for this ROM, e.g. "Electron MOS 1.0". + std::string descriptive_name; + /// An idiomatic file name for this ROM, e.g. "os10.rom". + std::string file_name; + /// The expected size of this ROM in bytes, e.g. 32768. + size_t size = 0; + /// CRC32s for all known acceptable copies of this ROM; intended to allow a host platform + /// to test user-provided ROMs of unknown provenance. **Not** intended to be used + /// to exclude ROMs where the user's intent is otherwise clear. + std::vector crc32s; + + /// This is a temporary constructor provided for transitional purposes. + ROM(std::string file_name) : + file_name(file_name) {} + + ROM(std::string descriptive_name, std::string file_name, size_t size, uint32_t crc32) : + descriptive_name(descriptive_name), file_name(file_name), size(size), crc32s({crc32}) {} + ROM(std::string descriptive_name, std::string file_name, size_t size, std::vector &crc32s) : + descriptive_name(descriptive_name), file_name(file_name), size(size), crc32s(std::move(crc32s)) {} +}; + /*! Defines the signature for a function that must be supplied by the host environment in order to give machines a route for fetching any system ROMs they might need. @@ -24,7 +50,7 @@ namespace ROMMachine { to be present. The recevier should return a vector of unique_ptrs that either contain the contents of the ROM from @c names that corresponds by index, or else are the nullptr */ -typedef std::function>>(const std::string &machine, const std::vector &names)> ROMFetcher; +typedef std::function>>(const std::string &machine, const std::vector &roms)> ROMFetcher; enum class Error { MissingROMs diff --git a/Machines/ZX8081/ZX8081.cpp b/Machines/ZX8081/ZX8081.cpp index ab9818006..5121fc59e 100644 --- a/Machines/ZX8081/ZX8081.cpp +++ b/Machines/ZX8081/ZX8081.cpp @@ -76,7 +76,7 @@ template class ConcreteMachine: clear_all_keys(); const bool use_zx81_rom = target.is_ZX81 || target.ZX80_uses_ZX81_ROM; - const auto roms = rom_fetcher("ZX8081", { use_zx81_rom ? "zx81.rom" : "zx80.rom" }); + const auto roms = rom_fetcher("ZX8081", { ROMMachine::ROM(use_zx81_rom ? "zx81.rom" : "zx80.rom") } ); if(!roms[0]) throw ROMMachine::Error::MissingROMs; rom_ = std::move(*roms[0]); diff --git a/OSBindings/Mac/Clock Signal/Machine/CSROMFetcher.mm b/OSBindings/Mac/Clock Signal/Machine/CSROMFetcher.mm index 0ab615bbf..44e7ebe62 100644 --- a/OSBindings/Mac/Clock Signal/Machine/CSROMFetcher.mm +++ b/OSBindings/Mac/Clock Signal/Machine/CSROMFetcher.mm @@ -15,11 +15,14 @@ #include ROMMachine::ROMFetcher CSROMFetcher() { - return [] (const std::string &machine, const std::vector &names) -> std::vector>> { - NSString *subDirectory = [@"ROMImages/" stringByAppendingString:[NSString stringWithUTF8String:machine.c_str()]]; + return [] (const std::string &machine, const std::vector &roms) -> std::vector>> { + NSString *subdirectory = [@"ROMImages/" stringByAppendingString:[NSString stringWithUTF8String:machine.c_str()]]; std::vector>> results; - for(const auto &name: names) { - NSData *fileData = [[NSBundle mainBundle] dataForResource:[NSString stringWithUTF8String:name.c_str()] withExtension:nil subdirectory:subDirectory]; + for(const auto &rom: roms) { + NSData *fileData = [[NSBundle mainBundle] + dataForResource:[NSString stringWithUTF8String:rom.file_name.c_str()] + withExtension:nil + subdirectory:subdirectory]; if(!fileData) results.emplace_back(nullptr); diff --git a/OSBindings/SDL/main.cpp b/OSBindings/SDL/main.cpp index 31721e5d7..23a49836e 100644 --- a/OSBindings/SDL/main.cpp +++ b/OSBindings/SDL/main.cpp @@ -365,11 +365,11 @@ int main(int argc, char *argv[]) { // /usr/local/share/CLK/[system]; // /usr/share/CLK/[system]; or // [user-supplied path]/[system] - std::vector rom_names; + std::vector requested_roms; std::string machine_name; - ROMMachine::ROMFetcher rom_fetcher = [&rom_names, &machine_name, &arguments] - (const std::string &machine, const std::vector &names) -> std::vector>> { - rom_names.insert(rom_names.end(), names.begin(), names.end()); + ROMMachine::ROMFetcher rom_fetcher = [&requested_roms, &machine_name, &arguments] + (const std::string &machine, const std::vector &roms) -> std::vector>> { + requested_roms.insert(requested_roms.end(), roms.begin(), roms.end()); machine_name = machine; std::vector paths = { @@ -386,10 +386,10 @@ int main(int argc, char *argv[]) { } std::vector>> results; - for(const auto &name: names) { + for(const auto &rom: roms) { FILE *file = nullptr; for(const auto &path: paths) { - std::string local_path = path + machine + "/" + name; + std::string local_path = path + machine + "/" + rom.file_name; file = std::fopen(local_path.c_str(), "rb"); if(file) break; } @@ -425,8 +425,8 @@ int main(int argc, char *argv[]) { case ::Machine::Error::MissingROM: std::cerr << "Could not find system ROMs; please install to /usr/local/share/CLK/ or /usr/share/CLK/, or provide a --rompath." << std::endl; std::cerr << "One or more of the following was needed but not found:" << std::endl; - for(const auto &name: rom_names) { - std::cerr << machine_name << '/' << name << std::endl; + for(const auto &rom: requested_roms) { + std::cerr << machine_name << '/' << rom.file_name << std::endl; } break; }