From ddcdd07dd08ed2ddb2041c6d7edc8796fe2efb7c Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Tue, 7 Nov 2017 21:19:51 -0500 Subject: [PATCH] Modifies the Vic-20 and C1540 to bring them into the realm of self-ROM fetching. Hence enables Vic-20 support within kiosk mode as currently drafted. --- Machines/AmstradCPC/AmstradCPC.cpp | 22 +- Machines/AmstradCPC/AmstradCPC.hpp | 2 +- Machines/CRTMachine.hpp | 8 +- Machines/Commodore/1540/C1540.hpp | 16 +- .../Commodore/1540/Implementation/C1540.cpp | 16 +- Machines/Commodore/Vic-20/Vic20.cpp | 188 +++++++++++------- Machines/Commodore/Vic-20/Vic20.hpp | 12 +- Machines/Electron/Electron.cpp | 20 +- Machines/Electron/Electron.hpp | 2 +- Machines/Oric/Oric.cpp | 16 +- Machines/ROMMachine.hpp | 27 +++ Machines/ZX8081/ZX8081.cpp | 16 +- Machines/ZX8081/ZX8081.hpp | 2 +- .../Clock Signal.xcodeproj/project.pbxproj | 2 + OSBindings/SDL/main.cpp | 42 ++-- 15 files changed, 252 insertions(+), 139 deletions(-) create mode 100644 Machines/ROMMachine.hpp diff --git a/Machines/AmstradCPC/AmstradCPC.cpp b/Machines/AmstradCPC/AmstradCPC.cpp index fbe4bf05f..38e1b1b06 100644 --- a/Machines/AmstradCPC/AmstradCPC.cpp +++ b/Machines/AmstradCPC/AmstradCPC.cpp @@ -919,21 +919,23 @@ class ConcreteMachine: } // See header; provides the system ROMs. - void set_rom(ROMType type, std::vector data) override final { + void set_rom(ROMType type, const std::vector &data) override final { roms_[static_cast(type)] = data; } // Obtains the system ROMs. - bool install_roms(const std::function>(const std::string &machine, const std::string &name)> &rom_with_name) override { - const char *os_files[] = { - "os464.rom", "basic464.rom", - "os664.rom", "basic664.rom", - "os6128.rom", "basic6128.rom", - "amsdos.rom" - }; + bool set_rom_fetcher(const std::function>>(const std::string &machine, const std::vector &names)> &roms_with_names) override { + auto roms = roms_with_names( + "AmstradCPC", + { + "os464.rom", "basic464.rom", + "os664.rom", "basic664.rom", + "os6128.rom", "basic6128.rom", + "amsdos.rom" + }); - for(size_t index = 0; index < sizeof(os_files) / sizeof(*os_files); ++index) { - auto data = rom_with_name("AmstradCPC", os_files[index]); + for(size_t index = 0; index < roms.size(); ++index) { + auto &data = roms[index]; if(!data) return false; set_rom(static_cast(index), *data); } diff --git a/Machines/AmstradCPC/AmstradCPC.hpp b/Machines/AmstradCPC/AmstradCPC.hpp index c070b3bb9..27c48c6df 100644 --- a/Machines/AmstradCPC/AmstradCPC.hpp +++ b/Machines/AmstradCPC/AmstradCPC.hpp @@ -39,7 +39,7 @@ class Machine: static Machine *AmstradCPC(); /// Sets the contents of rom @c type to @c data. Assumed to be a setup step; has no effect once a machine is running. - virtual void set_rom(ROMType type, std::vector data) = 0; + virtual void set_rom(ROMType type, const std::vector &data) = 0; }; } diff --git a/Machines/CRTMachine.hpp b/Machines/CRTMachine.hpp index 6c5fb346c..f6fbd9c30 100644 --- a/Machines/CRTMachine.hpp +++ b/Machines/CRTMachine.hpp @@ -12,6 +12,7 @@ #include "../Outputs/CRT/CRT.hpp" #include "../Outputs/Speaker.hpp" #include "../ClockReceiver/ClockReceiver.hpp" +#include "ROMMachine.hpp" namespace CRTMachine { @@ -20,7 +21,7 @@ namespace CRTMachine { that optionally provide a speaker, and that nominate a clock rate and can announce to a delegate should that clock rate change. */ -class Machine { +class Machine: public ROMMachine::Machine { public: Machine() : clock_is_unlimited_(false), delegate_(nullptr) {} @@ -36,11 +37,6 @@ class Machine { */ virtual void close_output() = 0; - /*! - Provides the machine with a way to obtain such ROMs as it needs. - */ - virtual bool install_roms(const std::function>(const std::string &machine, const std::string &name)> &rom_with_name) { return true; } - /// @returns The CRT this machine is drawing to. Should not be @c nullptr. virtual std::shared_ptr get_crt() = 0; diff --git a/Machines/Commodore/1540/C1540.hpp b/Machines/Commodore/1540/C1540.hpp index 4c3954672..5d3c5564c 100644 --- a/Machines/Commodore/1540/C1540.hpp +++ b/Machines/Commodore/1540/C1540.hpp @@ -10,6 +10,7 @@ #define Commodore1540_hpp #include "../SerialBus.hpp" +#include "../../ROMMachine.hpp" #include "../../../Storage/Disk/Disk.hpp" #include "Implementation/C1540Base.hpp" @@ -19,12 +20,18 @@ namespace C1540 { /*! Provides an emulation of the C1540. */ -class Machine: public MachineBase { +class Machine: public MachineBase, public ROMMachine::Machine { public: + enum Personality { + C1540, + C1541 + }; + Machine(Personality p); + /*! - Sets the ROM image to use for this drive; it is asserted that the buffer provided is 16 kb in size. + Sets the source for this drive's ROM image. */ - void set_rom(const std::vector &rom); + bool set_rom_fetcher(const std::function>>(const std::string &machine, const std::vector &names)> &roms_with_names); /*! Sets the serial bus to which this drive should attach itself. @@ -36,6 +43,9 @@ class Machine: public MachineBase { /// Inserts @c disk into the drive. void set_disk(std::shared_ptr disk); + + private: + Personality personality_; }; } diff --git a/Machines/Commodore/1540/Implementation/C1540.cpp b/Machines/Commodore/1540/Implementation/C1540.cpp index ac2a98e76..316c0ab0d 100644 --- a/Machines/Commodore/1540/Implementation/C1540.cpp +++ b/Machines/Commodore/1540/Implementation/C1540.cpp @@ -40,6 +40,8 @@ MachineBase::MachineBase() : set_drive(drive_); } +Machine::Machine(Commodore::C1540::Machine::Personality personality) : personality_(personality) {} + void Machine::set_serial_bus(std::shared_ptr<::Commodore::Serial::Bus> serial_bus) { Commodore::Serial::AttachPortAndBus(serial_port_, serial_bus); } @@ -80,9 +82,17 @@ Cycles MachineBase::perform_bus_operation(CPU::MOS6502::BusOperation operation, return Cycles(1); } -void Machine::set_rom(const std::vector &rom) { - assert(rom.size() == sizeof(rom_)); - memcpy(rom_, rom.data(), std::min(sizeof(rom_), rom.size())); +bool Machine::set_rom_fetcher(const std::function>>(const std::string &machine, const std::vector &names)> &roms_with_names) { + std::string rom_name; + switch(personality_) { + case Personality::C1540: rom_name = "1540.bin"; break; + case Personality::C1541: rom_name = "1541.bin"; break; + } + + auto roms = roms_with_names("Commodore1540", {rom_name}); + if(!roms[0]) return false; + memcpy(rom_, roms[0]->data(), std::min(sizeof(rom_), roms[0]->size())); + return true; } void Machine::set_disk(std::shared_ptr disk) { diff --git a/Machines/Commodore/Vic-20/Vic20.cpp b/Machines/Commodore/Vic-20/Vic20.cpp index 7b10b4eb1..98de4c8b5 100644 --- a/Machines/Commodore/Vic-20/Vic20.cpp +++ b/Machines/Commodore/Vic-20/Vic20.cpp @@ -37,6 +37,18 @@ enum JoystickInput { Fire = 0x20 }; +enum ROM { + CharactersDanish = 0, + CharactersEnglish, + CharactersJapanese, + CharactersSwedish, + KernelDanish, + KernelJapanese, + KernelNTSC, + KernelPAL, + KernelSwedish +}; + /*! Models the user-port VIA, which is the Vic's connection point for controlling its tape recorder — sensing the presence or absence of a tape and controlling the tape motor — and reading the current @@ -280,12 +292,6 @@ class ConcreteMachine: keyboard_via_port_handler_->set_interrupt_delegate(this); tape_->set_delegate(this); - // establish the memory maps - set_memory_size(MemorySize::Default); - - // set the NTSC clock rate - set_region(NTSC); - // install a joystick joysticks_.emplace_back(new Joystick(*user_port_via_port_handler_, *keyboard_via_port_handler_)); } @@ -294,24 +300,32 @@ class ConcreteMachine: delete[] rom_; } - void set_rom(ROMSlot slot, size_t length, const uint8_t *data) override final { - uint8_t *target = nullptr; - size_t max_length = 0x2000; - switch(slot) { - case Kernel: target = kernel_rom_; break; - case Characters: target = character_rom_; max_length = 0x1000; break; - case BASIC: target = basic_rom_; break; - case Drive: - drive_rom_.resize(length); - memcpy(drive_rom_.data(), data, length); - install_disk_rom(); - return; - } + void set_rom(ROMSlot slot, const std::vector &data) override final { + } - if(target) { - size_t length_to_copy = std::min(max_length, length); - memcpy(target, data, length_to_copy); + // Obtains the system ROMs. + bool set_rom_fetcher(const std::function>>(const std::string &machine, const std::vector &names)> &roms_with_names) override { + auto roms = roms_with_names( + "Vic20", + { + "characters-danish.bin", + "characters-english.bin", + "characters-japanese.bin", + "characters-swedish.bin", + "kernel-danish.bin", + "kernel-japanese.bin", + "kernel-ntsc.bin", + "kernel-pal.bin", + "kernel-swedish.bin", + "basic.bin" + }); + + for(size_t index = 0; index < roms.size(); ++index) { + auto &data = roms[index]; + if(!data) return false; + if(index < 9) roms_[index] = *data; else basic_rom_ = *data; } + return true; } void configure_as_target(const StaticAnalyser::Target &target) override final { @@ -333,13 +347,13 @@ class ConcreteMachine: if(target.media.disks.size()) { // construct the 1540 - c1540_.reset(new ::Commodore::C1540::Machine); + c1540_.reset(new ::Commodore::C1540::Machine(Commodore::C1540::Machine::C1540)); // attach it to the serial bus c1540_->set_serial_bus(serial_bus_); - // install the ROM if it was previously set - install_disk_rom(); + // give it a means to obtain its ROM + c1540_->set_rom_fetcher(rom_fetcher_); } insert_media(target.media); @@ -383,10 +397,38 @@ class ConcreteMachine: } void set_memory_size(MemorySize size) override final { + memory_size_ = size; + needs_configuration_ = true; + } + + void set_region(Region region) override final { + region_ = region; + needs_configuration_ = true; + } + + void configure_memory() { + // Determine PAL/NTSC + if(region_ == American || region_ == Japanese) { + // NTSC + set_clock_rate(1022727); + if(mos6560_) { + mos6560_->set_output_mode(MOS::MOS6560::OutputMode::NTSC); + mos6560_->set_clock_rate(1022727); + } + } else { + // PAL + set_clock_rate(1108404); + if(mos6560_) { + mos6560_->set_output_mode(MOS::MOS6560::OutputMode::PAL); + mos6560_->set_clock_rate(1108404); + } + } + memset(processor_read_memory_map_, 0, sizeof(processor_read_memory_map_)); memset(processor_write_memory_map_, 0, sizeof(processor_write_memory_map_)); + memset(mos6560_->video_memory_map, 0, sizeof(mos6560_->video_memory_map)); - switch(size) { + switch(memory_size_) { default: break; case ThreeKB: write_to_map(processor_read_memory_map_, expansion_ram_, 0x0000, 0x1000); @@ -402,40 +444,52 @@ class ConcreteMachine: write_to_map(processor_read_memory_map_, user_basic_memory_, 0x0000, sizeof(user_basic_memory_)); write_to_map(processor_read_memory_map_, screen_memory_, 0x1000, sizeof(screen_memory_)); write_to_map(processor_read_memory_map_, colour_memory_, 0x9400, sizeof(colour_memory_)); - write_to_map(processor_read_memory_map_, character_rom_, 0x8000, sizeof(character_rom_)); - write_to_map(processor_read_memory_map_, basic_rom_, 0xc000, sizeof(basic_rom_)); - write_to_map(processor_read_memory_map_, kernel_rom_, 0xe000, sizeof(kernel_rom_)); - + write_to_map(processor_write_memory_map_, user_basic_memory_, 0x0000, sizeof(user_basic_memory_)); write_to_map(processor_write_memory_map_, screen_memory_, 0x1000, sizeof(screen_memory_)); write_to_map(processor_write_memory_map_, colour_memory_, 0x9400, sizeof(colour_memory_)); + write_to_map(mos6560_->video_memory_map, user_basic_memory_, 0x2000, sizeof(user_basic_memory_)); + write_to_map(mos6560_->video_memory_map, screen_memory_, 0x3000, sizeof(screen_memory_)); + mos6560_->colour_memory = colour_memory_; + + write_to_map(processor_read_memory_map_, basic_rom_.data(), 0xc000, basic_rom_.size()); + + ROM character_rom; + ROM kernel_rom; + switch(region_) { + case American: + character_rom = CharactersEnglish; + kernel_rom = KernelNTSC; + break; + case Danish: + character_rom = CharactersDanish; + kernel_rom = KernelDanish; + break; + case Japanese: + character_rom = CharactersJapanese; + kernel_rom = KernelJapanese; + break; + case European: + character_rom = CharactersEnglish; + kernel_rom = KernelPAL; + break; + case Swedish: + character_rom = CharactersSwedish; + kernel_rom = KernelSwedish; + break; + } + + write_to_map(processor_read_memory_map_, roms_[character_rom].data(), 0x8000, roms_[character_rom].size()); + write_to_map(mos6560_->video_memory_map, roms_[character_rom].data(), 0x0000, roms_[character_rom].size()); + write_to_map(processor_read_memory_map_, roms_[kernel_rom].data(), 0xe000, roms_[kernel_rom].size()); + // install the inserted ROM if there is one if(rom_) { write_to_map(processor_read_memory_map_, rom_, rom_address_, rom_length_); } } - void set_region(Region region) override final { - region_ = region; - switch(region) { - case PAL: - set_clock_rate(1108404); - if(mos6560_) { - mos6560_->set_output_mode(MOS::MOS6560::OutputMode::PAL); - mos6560_->set_clock_rate(1108404); - } - break; - case NTSC: - set_clock_rate(1022727); - if(mos6560_) { - mos6560_->set_output_mode(MOS::MOS6560::OutputMode::NTSC); - mos6560_->set_clock_rate(1022727); - } - break; - } - } - void set_use_fast_tape_hack(bool activate) override final { use_fast_tape_hack_ = activate; } @@ -542,19 +596,16 @@ class ConcreteMachine: } void run_for(const Cycles cycles) override final { + if(needs_configuration_) { + needs_configuration_ = false; + configure_memory(); + } m6502_.run_for(cycles); } void setup_output(float aspect_ratio) override final { mos6560_.reset(new Vic6560()); mos6560_->get_speaker()->set_high_frequency_cut_off(1600); // There is a 1.6Khz low-pass filter in the Vic-20. - set_region(region_); - - memset(mos6560_->video_memory_map, 0, sizeof(mos6560_->video_memory_map)); - write_to_map(mos6560_->video_memory_map, character_rom_, 0x0000, sizeof(character_rom_)); - write_to_map(mos6560_->video_memory_map, user_basic_memory_, 0x2000, sizeof(user_basic_memory_)); - write_to_map(mos6560_->video_memory_map, screen_memory_, 0x3000, sizeof(screen_memory_)); - mos6560_->colour_memory = colour_memory_; } void close_output() override final { @@ -590,9 +641,11 @@ class ConcreteMachine: private: CPU::MOS6502::Processor m6502_; - uint8_t character_rom_[0x1000]; - uint8_t basic_rom_[0x2000]; - uint8_t kernel_rom_[0x2000]; + std::vector roms_[9]; + + std::vector character_rom_; + std::vector basic_rom_; + std::vector kernel_rom_; uint8_t expansion_ram_[0x8000]; uint8_t *rom_; @@ -601,7 +654,8 @@ class ConcreteMachine: uint8_t user_basic_memory_[0x0400]; uint8_t screen_memory_[0x1000]; uint8_t colour_memory_[0x0400]; - std::vector drive_rom_; + + std::function>>(const std::string &machine, const std::vector &names)> rom_fetcher_; uint8_t *processor_read_memory_map_[64]; uint8_t *processor_write_memory_map_[64]; @@ -615,7 +669,10 @@ class ConcreteMachine: } } - Region region_; + Region region_ = European; + MemorySize memory_size_ = MemorySize::Default; + bool needs_configuration_ = true; + Commodore::Vic20::KeyboardMapper keyboard_mapper_; std::vector> joysticks_; @@ -635,13 +692,6 @@ class ConcreteMachine: // Disk std::shared_ptr<::Commodore::C1540::Machine> c1540_; - void install_disk_rom() { - if(!drive_rom_.empty() && c1540_) { - c1540_->set_rom(drive_rom_); - c1540_->run_for(Cycles(2000000)); - drive_rom_.clear(); - } - } }; } diff --git a/Machines/Commodore/Vic-20/Vic20.hpp b/Machines/Commodore/Vic-20/Vic20.hpp index aac1025d5..e99c34c73 100644 --- a/Machines/Commodore/Vic-20/Vic20.hpp +++ b/Machines/Commodore/Vic-20/Vic20.hpp @@ -20,7 +20,7 @@ namespace Commodore { namespace Vic20 { enum ROMSlot { - Kernel, + Kernel = 0, BASIC, Characters, Drive @@ -33,8 +33,11 @@ enum MemorySize { }; enum Region { - NTSC, - PAL + American, + Danish, + Japanese, + European, + Swedish }; class Machine: @@ -49,8 +52,7 @@ class Machine: static Machine *Vic20(); /// Sets the contents of the rom in @c slot to the buffer @c data of length @c length. - virtual void set_rom(ROMSlot slot, size_t length, const uint8_t *data) = 0; - // TODO: take a std::vector to collapse length and data. + virtual void set_rom(ROMSlot slot, const std::vector &data) = 0; /// Sets the memory size of this Vic-20. virtual void set_memory_size(MemorySize size) = 0; diff --git a/Machines/Electron/Electron.cpp b/Machines/Electron/Electron.cpp index 647ed2ed6..da2624f51 100644 --- a/Machines/Electron/Electron.cpp +++ b/Machines/Electron/Electron.cpp @@ -39,7 +39,7 @@ class ConcreteMachine: set_clock_rate(2000000); } - void set_rom(ROMSlot slot, std::vector data, bool is_writeable) override final { + void set_rom(ROMSlot slot, const std::vector &data, bool is_writeable) override final { uint8_t *target = nullptr; switch(slot) { case ROMSlotDFS: dfs_ = data; return; @@ -57,20 +57,22 @@ class ConcreteMachine: } // Obtains the system ROMs. - bool install_roms(const std::function>(const std::string &machine, const std::string &name)> &rom_with_name) override { + bool set_rom_fetcher(const std::function>>(const std::string &machine, const std::vector &names)> &roms_with_names) override { + auto roms = roms_with_names( + "Electron", + { + "DFS-1770-2.20.rom", + "ADFS-E00_1.rom", "ADFS-E00_2.rom", + "basic.rom", "os.rom" + }); ROMSlot slots[] = { ROMSlotDFS, ROMSlotADFS1, ROMSlotADFS2, ROMSlotBASIC, ROMSlotOS }; - const char *os_files[] = { - "DFS-1770-2.20.rom", - "ADFS-E00_1.rom", "ADFS-E00_2.rom", - "basic.rom", "os.rom" - }; - for(size_t index = 0; index < sizeof(os_files) / sizeof(*os_files); ++index) { - auto data = rom_with_name("Electron", os_files[index]); + for(size_t index = 0; index < roms.size(); ++index) { + auto &data = roms[index]; if(!data) return false; set_rom(slots[index], *data, false); } diff --git a/Machines/Electron/Electron.hpp b/Machines/Electron/Electron.hpp index cc76e219e..80fd0fa4c 100644 --- a/Machines/Electron/Electron.hpp +++ b/Machines/Electron/Electron.hpp @@ -52,7 +52,7 @@ class Machine: Sets the contents of @c slot to @c data. If @c is_writeable is @c true then writing to the slot is enabled — it acts as if it were sideways RAM. Otherwise the slot is modelled as containing ROM. */ - virtual void set_rom(ROMSlot slot, std::vector data, bool is_writeable) = 0; + virtual void set_rom(ROMSlot slot, const std::vector &data, bool is_writeable) = 0; /// Enables or disables turbo-speed tape loading. virtual void set_use_fast_tape_hack(bool activate) = 0; diff --git a/Machines/Oric/Oric.cpp b/Machines/Oric/Oric.cpp index f5cacc1ad..c2b53c71f 100644 --- a/Machines/Oric/Oric.cpp +++ b/Machines/Oric/Oric.cpp @@ -204,14 +204,16 @@ class ConcreteMachine: } // Obtains the system ROMs. - bool install_roms(const std::function>(const std::string &machine, const std::string &name)> &rom_with_name) override { - const char *os_files[] = { - "basic10.rom", "basic11.rom", - "microdisc.rom", "colour.rom" - }; + bool set_rom_fetcher(const std::function>>(const std::string &machine, const std::vector &names)> &roms_with_names) override { + auto roms = roms_with_names( + "Oric", + { + "basic10.rom", "basic11.rom", + "microdisc.rom", "colour.rom" + }); - for(size_t index = 0; index < sizeof(os_files) / sizeof(*os_files); ++index) { - auto data = rom_with_name("Oric", os_files[index]); + for(size_t index = 0; index < roms.size(); ++index) { + auto &data = roms[index]; if(!data) return false; set_rom(static_cast(index), *data); } diff --git a/Machines/ROMMachine.hpp b/Machines/ROMMachine.hpp new file mode 100644 index 000000000..d95ae7042 --- /dev/null +++ b/Machines/ROMMachine.hpp @@ -0,0 +1,27 @@ +// +// ROMMachine.hpp +// Clock Signal +// +// Created by Thomas Harte on 07/11/2017. +// Copyright © 2017 Thomas Harte. All rights reserved. +// + +#ifndef ROMMachine_hpp +#define ROMMachine_hpp + +#include +#include +#include + +namespace ROMMachine { + +struct Machine { + /*! + Provides the machine with a way to obtain such ROMs as it needs. + */ + virtual bool set_rom_fetcher(const std::function>>(const std::string &machine, const std::vector &names)> &rom_with_name) { return true; } +}; + +} + +#endif /* ROMMachine_h */ diff --git a/Machines/ZX8081/ZX8081.cpp b/Machines/ZX8081/ZX8081.cpp index d9186cc73..e587f4561 100644 --- a/Machines/ZX8081/ZX8081.cpp +++ b/Machines/ZX8081/ZX8081.cpp @@ -290,7 +290,7 @@ template class ConcreteMachine: Utility::TypeRecipient::set_typer_for_string(string, std::move(mapper)); } - void set_rom(ROMType type, std::vector data) override final { + void set_rom(ROMType type, const std::vector &data) override final { switch(type) { case ZX80: zx80_rom_ = data; break; case ZX81: zx81_rom_ = data; break; @@ -298,13 +298,15 @@ template class ConcreteMachine: } // Obtains the system ROMs. - bool install_roms(const std::function>(const std::string &machine, const std::string &name)> &rom_with_name) override { - const char *os_files[] = { - "zx80.rom", "zx81.rom", - }; + bool set_rom_fetcher(const std::function>>(const std::string &machine, const std::vector &names)> &roms_with_names) override { + auto roms = roms_with_names( + "ZX8081", + { + "zx80.rom", "zx81.rom", + }); - for(size_t index = 0; index < sizeof(os_files) / sizeof(*os_files); ++index) { - auto data = rom_with_name("ZX8081", os_files[index]); + for(size_t index = 0; index < roms.size(); ++index) { + auto &data = roms[index]; if(!data) return false; set_rom(static_cast(index), *data); } diff --git a/Machines/ZX8081/ZX8081.hpp b/Machines/ZX8081/ZX8081.hpp index 8e119823d..ce797fbf8 100644 --- a/Machines/ZX8081/ZX8081.hpp +++ b/Machines/ZX8081/ZX8081.hpp @@ -30,7 +30,7 @@ class Machine: static Machine *ZX8081(const StaticAnalyser::Target &target_hint); virtual ~Machine(); - virtual void set_rom(ROMType type, std::vector data) = 0; + virtual void set_rom(ROMType type, const std::vector &data) = 0; virtual void set_use_fast_tape_hack(bool activate) = 0; virtual void set_tape_is_playing(bool is_playing) = 0; diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index dbf307ba2..e8c6029ad 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -1210,6 +1210,7 @@ 4BD5F1931D13528900631CD1 /* CSBestEffortUpdater.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSBestEffortUpdater.h; path = Updater/CSBestEffortUpdater.h; sourceTree = ""; }; 4BD5F1941D13528900631CD1 /* CSBestEffortUpdater.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = CSBestEffortUpdater.mm; path = Updater/CSBestEffortUpdater.mm; sourceTree = ""; }; 4BD9137D1F311BC5009BCF85 /* i8255.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = i8255.hpp; path = 8255/i8255.hpp; sourceTree = ""; }; + 4BDCC5F81FB27A5E001220C5 /* ROMMachine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ROMMachine.hpp; sourceTree = ""; }; 4BDDBA981EF3451200347E61 /* Z80MachineCycleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Z80MachineCycleTests.swift; sourceTree = ""; }; 4BE77A2C1D84ADFB00BC3827 /* File.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = File.cpp; path = ../../StaticAnalyser/Commodore/File.cpp; sourceTree = ""; }; 4BE77A2D1D84ADFB00BC3827 /* File.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = File.hpp; path = ../../StaticAnalyser/Commodore/File.hpp; sourceTree = ""; }; @@ -2352,6 +2353,7 @@ isa = PBXGroup; children = ( 4B54C0BB1F8D8E790050900F /* KeyboardMachine.cpp */, + 4BDCC5F81FB27A5E001220C5 /* ROMMachine.hpp */, 4BA9C3CF1D8164A9002DDB61 /* ConfigurationTarget.hpp */, 4B046DC31CFE651500E9E45E /* CRTMachine.hpp */, 4B7041271F92C26900735E45 /* JoystickMachine.hpp */, diff --git a/OSBindings/SDL/main.cpp b/OSBindings/SDL/main.cpp index c414a2234..9a1fb34fb 100644 --- a/OSBindings/SDL/main.cpp +++ b/OSBindings/SDL/main.cpp @@ -179,25 +179,33 @@ int main(int argc, char *argv[]) { // // /usr/local/share/CLK/[system]; or // /usr/share/CLK/[system] - machine->crt_machine()->install_roms( [] (const std::string &machine, const std::string &name) -> std::unique_ptr> { - std::string local_path = "/usr/local/share/CLK/" + machine + "/" + name; - FILE *file = fopen(local_path.c_str(), "r"); - if(!file) { - std::string path = "/usr/share/CLK/" + machine + "/" + name; - file = fopen(path.c_str(), "r"); + machine->crt_machine()->set_rom_fetcher( [] (const std::string &machine, const std::vector &names) -> std::vector>> { + std::vector>> results; + for(auto &name: names) { + std::string local_path = "/usr/local/share/CLK/" + machine + "/" + name; + FILE *file = fopen(local_path.c_str(), "r"); + if(!file) { + std::string path = "/usr/share/CLK/" + machine + "/" + name; + file = fopen(path.c_str(), "r"); + } + + if(!file) { + results.emplace_back(nullptr); + continue; + } + + std::unique_ptr> data(new std::vector); + + fseek(file, 0, SEEK_END); + data->resize(ftell(file)); + fseek(file, 0, SEEK_SET); + fread(data->data(), 1, data->size(), file); + fclose(file); + + results.emplace_back(std::move(data)); } - if(!file) return nullptr; - - std::unique_ptr> data(new std::vector); - - fseek(file, 0, SEEK_END); - data->resize(ftell(file)); - fseek(file, 0, SEEK_SET); - fread(data->data(), 1, data->size(), file); - fclose(file); - - return data; + return results; }); machine->configuration_target()->configure_as_target(targets.front());