diff --git a/Machines/AmstradCPC/AmstradCPC.cpp b/Machines/AmstradCPC/AmstradCPC.cpp index 01cc1c2d3..38e1b1b06 100644 --- a/Machines/AmstradCPC/AmstradCPC.cpp +++ b/Machines/AmstradCPC/AmstradCPC.cpp @@ -919,10 +919,30 @@ 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 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 < roms.size(); ++index) { + auto &data = roms[index]; + if(!data) return false; + set_rom(static_cast(index), *data); + } + + return true; + } + void set_component_is_sleeping(void *component, bool is_sleeping) override final { fdc_is_sleeping_ = fdc_.is_sleeping(); tape_player_is_sleeping_ = tape_player_.is_sleeping(); 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/Atari2600/TIA.hpp b/Machines/Atari2600/TIA.hpp index a3d114d6a..5426ea989 100644 --- a/Machines/Atari2600/TIA.hpp +++ b/Machines/Atari2600/TIA.hpp @@ -135,42 +135,27 @@ class TIA { // objects template struct Object { // the two programmer-set values - int position; - int motion; + int position = 0; + int motion = 0; // motion_step_ is the current motion counter value; motion_time_ is the next time it will fire - int motion_step; - int motion_time; + int motion_step = 0; + int motion_time = 0; // indicates whether this object is currently undergoing motion - bool is_moving; - - Object() : position(0), motion(0), motion_step(0), motion_time(0), is_moving(false) {}; + bool is_moving = false; }; // player state struct Player: public Object { - Player() : - adder(4), - copy_flags(0), - graphic{0, 0}, - reverse_mask(false), - graphic_index(0), - pixel_position(32), - pixel_counter(0), - latched_pixel4_time(-1), - copy_index_(0), - queue_read_pointer_(0), - queue_write_pointer_(0) {} + int adder = 4; + int copy_flags = 0; // a bit field, corresponding to the first few values of NUSIZ + uint8_t graphic[2] = {0, 0}; // the player graphic; 1 = new, 0 = current + int reverse_mask = false; // 7 for a reflected player, 0 for normal + int graphic_index = 0; - int adder; - int copy_flags; // a bit field, corresponding to the first few values of NUSIZ - uint8_t graphic[2]; // the player graphic; 1 = new, 0 = current - int reverse_mask; // 7 for a reflected player, 0 for normal - int graphic_index; - - int pixel_position, pixel_counter; - int latched_pixel4_time; + int pixel_position = 32, pixel_counter = 0; + int latched_pixel4_time = -1; const bool enqueues = true; inline void skip_pixels(const int count, int from_horizontal_counter) { @@ -219,15 +204,14 @@ class TIA { } private: - int copy_index_; + int copy_index_ = 0; struct QueuedPixels { - int start, end; - int pixel_position; - int adder; - int reverse_mask; - QueuedPixels() : start(0), end(0), pixel_position(0), adder(0), reverse_mask(false) {} + int start = 0, end = 0; + int pixel_position = 0; + int adder = 0; + int reverse_mask = false; } queue_[4]; - int queue_read_pointer_, queue_write_pointer_; + int queue_read_pointer_ = 0, queue_write_pointer_ = 0; inline void output_pixels(uint8_t *const target, const int count, const uint8_t collision_identity, int output_pixel_position, int output_adder, int output_reverse_mask) { if(output_pixel_position == 32 || !graphic[graphic_index]) return; @@ -244,8 +228,8 @@ class TIA { // common actor for things that appear as a horizontal run of pixels struct HorizontalRun: public Object { - int pixel_position; - int size; + int pixel_position = 0; + int size = 1; const bool enqueues = false; inline void skip_pixels(const int count, int from_horizontal_counter) { @@ -268,16 +252,13 @@ class TIA { void dequeue_pixels(uint8_t *const target, const uint8_t collision_identity, const int time_now) {} void enqueue_pixels(const int start, const int end, int from_horizontal_counter) {} - - HorizontalRun() : pixel_position(0), size(1) {} }; - // missile state struct Missile: public HorizontalRun { - bool enabled; - bool locked_to_player; - int copy_flags; + bool enabled = false; + bool locked_to_player = false; + int copy_flags = 0; inline void output_pixels(uint8_t *const target, const int count, const uint8_t collision_identity, int from_horizontal_counter) { if(!pixel_position) return; @@ -287,14 +268,12 @@ class TIA { skip_pixels(count, from_horizontal_counter); } } - - Missile() : enabled(false), copy_flags(0) {} } missile_[2]; // ball state struct Ball: public HorizontalRun { - bool enabled[2]; - int enabled_index; + bool enabled[2] = {false, false}; + int enabled_index = 0; const int copy_flags = 0; inline void output_pixels(uint8_t *const target, const int count, const uint8_t collision_identity, int from_horizontal_counter) { @@ -305,8 +284,6 @@ class TIA { skip_pixels(count, from_horizontal_counter); } } - - Ball() : enabled{false, false}, enabled_index(0) {} } ball_; // motion diff --git a/Machines/CRTMachine.hpp b/Machines/CRTMachine.hpp index 96f2ba7fd..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) {} @@ -35,7 +36,7 @@ class Machine { OpenGL context is bound. */ virtual void close_output() = 0; - + /// @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 edde9f14e..da2624f51 100644 --- a/Machines/Electron/Electron.cpp +++ b/Machines/Electron/Electron.cpp @@ -39,11 +39,12 @@ 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; - case ROMSlotADFS: adfs_ = data; return; + case ROMSlotADFS1: adfs1_ = data; return; + case ROMSlotADFS2: adfs2_ = data; return; case ROMSlotOS: target = os_; break; default: @@ -55,6 +56,30 @@ class ConcreteMachine: memcpy(target, &data[0], std::min(static_cast(16384), data.size())); } + // 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( + "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 + }; + + for(size_t index = 0; index < roms.size(); ++index) { + auto &data = roms[index]; + if(!data) return false; + set_rom(slots[index], *data, false); + } + + return true; + } + void set_key_state(uint16_t key, bool isPressed) override final { if(key == KeyBreak) { m6502_.set_reset_line(isPressed); @@ -91,8 +116,8 @@ class ConcreteMachine: set_rom(ROMSlot0, dfs_, true); } if(target.acorn.has_adfs) { - set_rom(ROMSlot4, adfs_, true); - set_rom(ROMSlot5, std::vector(adfs_.begin() + 16384, adfs_.end()), true); + set_rom(ROMSlot4, adfs1_, true); + set_rom(ROMSlot5, adfs2_, true); } } @@ -435,7 +460,7 @@ class ConcreteMachine: uint8_t roms_[16][16384]; bool rom_write_masks_[16] = {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}; uint8_t os_[16384], ram_[32768]; - std::vector dfs_, adfs_; + std::vector dfs_, adfs1_, adfs2_; // Paging ROMSlot active_rom_ = ROMSlot::ROMSlot0; diff --git a/Machines/Electron/Electron.hpp b/Machines/Electron/Electron.hpp index 724956157..80fd0fa4c 100644 --- a/Machines/Electron/Electron.hpp +++ b/Machines/Electron/Electron.hpp @@ -28,7 +28,8 @@ enum ROMSlot: uint8_t { ROMSlot12, ROMSlot13, ROMSlot14, ROMSlot15, - ROMSlotOS, ROMSlotDFS, ROMSlotADFS + ROMSlotOS, ROMSlotDFS, + ROMSlotADFS1, ROMSlotADFS2 }; /*! @@ -51,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 0e1ad22c7..c2b53c71f 100644 --- a/Machines/Oric/Oric.cpp +++ b/Machines/Oric/Oric.cpp @@ -203,6 +203,24 @@ class ConcreteMachine: } } + // 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( + "Oric", + { + "basic10.rom", "basic11.rom", + "microdisc.rom", "colour.rom" + }); + + for(size_t index = 0; index < roms.size(); ++index) { + auto &data = roms[index]; + if(!data) return false; + set_rom(static_cast(index), *data); + } + + return true; + } + void set_key_state(uint16_t key, bool is_pressed) override final { if(key == KeyNMI) { m6502_.set_nmi_line(is_pressed); diff --git a/Machines/Oric/Oric.hpp b/Machines/Oric/Oric.hpp index 9a69965a7..4e4a8c418 100644 --- a/Machines/Oric/Oric.hpp +++ b/Machines/Oric/Oric.hpp @@ -19,7 +19,7 @@ namespace Oric { enum ROM { - BASIC10, BASIC11, Microdisc, Colour + BASIC10 = 0, BASIC11, Microdisc, Colour }; /*! 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/Utility/MachineForTarget.cpp b/Machines/Utility/MachineForTarget.cpp new file mode 100644 index 000000000..3bd1ed25d --- /dev/null +++ b/Machines/Utility/MachineForTarget.cpp @@ -0,0 +1,66 @@ +// +// MachineForTarget.cpp +// Clock Signal +// +// Created by Thomas Harte on 04/11/2017. +// Copyright © 2017 Thomas Harte. All rights reserved. +// + +#include "MachineForTarget.hpp" + +#include "../AmstradCPC/AmstradCPC.hpp" +#include "../Atari2600/Atari2600.hpp" +#include "../Commodore/Vic-20/Vic20.hpp" +#include "../Electron/Electron.hpp" +#include "../Oric/Oric.hpp" +#include "../ZX8081/ZX8081.hpp" + +namespace { + +template class TypedDynamicMachine: public ::Machine::DynamicMachine { + public: + TypedDynamicMachine(T *machine) : machine_(machine) {} + + ConfigurationTarget::Machine *configuration_target() { + return dynamic_cast(machine_.get()); + } + + CRTMachine::Machine *crt_machine() { + return dynamic_cast(machine_.get()); + } + + JoystickMachine::Machine *joystick_machine() { + return dynamic_cast(machine_.get()); + } + + KeyboardMachine::Machine *keyboard_machine() { + return dynamic_cast(machine_.get()); + } + + private: + std::unique_ptr machine_; +}; + +} + +::Machine::DynamicMachine *::Machine::MachineForTarget(const StaticAnalyser::Target &target) { + switch(target.machine) { + case StaticAnalyser::Target::AmstradCPC: return new TypedDynamicMachine(AmstradCPC::Machine::AmstradCPC()); + case StaticAnalyser::Target::Atari2600: return new TypedDynamicMachine(Atari2600::Machine::Atari2600()); + case StaticAnalyser::Target::Electron: return new TypedDynamicMachine(Electron::Machine::Electron()); + case StaticAnalyser::Target::Oric: return new TypedDynamicMachine(Oric::Machine::Oric()); + case StaticAnalyser::Target::Vic20: return new TypedDynamicMachine(Commodore::Vic20::Machine::Vic20()); + case StaticAnalyser::Target::ZX8081: return new TypedDynamicMachine(ZX8081::Machine::ZX8081(target)); + } +} + +std::string Machine::NameForTarget(const StaticAnalyser::Target &target) { + switch(target.machine) { + case StaticAnalyser::Target::AmstradCPC: return "AmstradCPC"; + case StaticAnalyser::Target::Atari2600: return "Atari2600"; + case StaticAnalyser::Target::Electron: return "Electron"; + case StaticAnalyser::Target::Oric: return "Oric"; + case StaticAnalyser::Target::Vic20: return "Vic20"; + case StaticAnalyser::Target::ZX8081: return "ZX8081"; + } +} diff --git a/Machines/Utility/MachineForTarget.hpp b/Machines/Utility/MachineForTarget.hpp new file mode 100644 index 000000000..14adcecf7 --- /dev/null +++ b/Machines/Utility/MachineForTarget.hpp @@ -0,0 +1,50 @@ +// +// MachineForTarget.hpp +// Clock Signal +// +// Created by Thomas Harte on 04/11/2017. +// Copyright © 2017 Thomas Harte. All rights reserved. +// + +#ifndef MachineForTarget_hpp +#define MachineForTarget_hpp + +#include "../../StaticAnalyser/StaticAnalyser.hpp" + +#include "../ConfigurationTarget.hpp" +#include "../CRTMachine.hpp" +#include "../JoystickMachine.hpp" +#include "../KeyboardMachine.hpp" + +#include + +namespace Machine { + +/*! + Provides the structure for owning a machine and dynamically casting it as desired without knowledge of + the machine's parent class or, therefore, the need to establish a common one. +*/ +struct DynamicMachine { + virtual ConfigurationTarget::Machine *configuration_target() = 0; + virtual CRTMachine::Machine *crt_machine() = 0; + virtual JoystickMachine::Machine *joystick_machine() = 0; + virtual KeyboardMachine::Machine *keyboard_machine() = 0; +}; + +/*! + Allocates an instance of DynamicMachine holding a machine that can + receive the supplied target. The machine has been allocated on the heap. + It is the caller's responsibility to delete the class when finished. +*/ +DynamicMachine *MachineForTarget(const StaticAnalyser::Target &target); + +/*! + Returns a short string name for the machine identified by the target, + which is guaranteed not to have any spaces or other potentially + filesystem-bothering contents. +*/ +std::string NameForTarget(const StaticAnalyser::Target &target); + +} + +#endif /* MachineForTarget_hpp */ diff --git a/Machines/ZX8081/ZX8081.cpp b/Machines/ZX8081/ZX8081.cpp index dcedbdeeb..e587f4561 100644 --- a/Machines/ZX8081/ZX8081.cpp +++ b/Machines/ZX8081/ZX8081.cpp @@ -290,13 +290,30 @@ 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; } } + // 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( + "ZX8081", + { + "zx80.rom", "zx81.rom", + }); + + for(size_t index = 0; index < roms.size(); ++index) { + auto &data = roms[index]; + if(!data) return false; + set_rom(static_cast(index), *data); + } + + return true; + } + #pragma mark - Keyboard void set_key_state(uint16_t key, bool isPressed) override final { diff --git a/Machines/ZX8081/ZX8081.hpp b/Machines/ZX8081/ZX8081.hpp index 9750183e6..ce797fbf8 100644 --- a/Machines/ZX8081/ZX8081.hpp +++ b/Machines/ZX8081/ZX8081.hpp @@ -19,7 +19,7 @@ namespace ZX8081 { enum ROMType: uint8_t { - ZX80, ZX81 + ZX80 = 0, ZX81 }; class Machine: @@ -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 84ab437c3..e8c6029ad 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -9,6 +9,120 @@ /* Begin PBXBuildFile section */ 4B01A6881F22F0DB001FD6E3 /* Z80MemptrTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B01A6871F22F0DB001FD6E3 /* Z80MemptrTests.swift */; }; 4B049CDD1DA3C82F00322067 /* BCDTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B049CDC1DA3C82F00322067 /* BCDTest.swift */; }; + 4B055A7A1FAE78A00060FFFF /* SDL2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B055A771FAE78210060FFFF /* SDL2.framework */; }; + 4B055A7E1FAE84AA0060FFFF /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B055A7C1FAE84A50060FFFF /* main.cpp */; }; + 4B055A7F1FAE852F0060FFFF /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1354A1D6D2C300054B2EA /* StaticAnalyser.cpp */; }; + 4B055A801FAE85350060FFFF /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BA799931D8B656E0045123D /* StaticAnalyser.cpp */; }; + 4B055A811FAE853A0060FFFF /* Disk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF829641D8F732B001BAE39 /* Disk.cpp */; }; + 4B055A821FAE853D0060FFFF /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BD14B0F1D74627C0088EAD6 /* StaticAnalyser.cpp */; }; + 4B055A831FAE85410060FFFF /* Tape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B96F7201D75119A0058BB2D /* Tape.cpp */; }; + 4B055A841FAE85450060FFFF /* Disk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BA22B051D8817CE0008C640 /* Disk.cpp */; }; + 4B055A851FAE85480060FFFF /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BE77A2C1D84ADFB00BC3827 /* File.cpp */; }; + 4B055A861FAE854C0060FFFF /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC5E4901D7ED365008CF980 /* StaticAnalyser.cpp */; }; + 4B055A871FAE854F0060FFFF /* Tape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC830CF1D6E7C690000A26F /* Tape.cpp */; }; + 4B055A881FAE85530060FFFF /* Disassembler6502.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B5A12551DD55862007A2231 /* Disassembler6502.cpp */; }; + 4B055A891FAE85580060FFFF /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF1FA91DADD41B0039D2E7 /* StaticAnalyser.cpp */; }; + 4B055A8A1FAE855B0060FFFF /* Tape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8805FC1DD02552003085B1 /* Tape.cpp */; }; + 4B055A8B1FAE85670060FFFF /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1497891EE4AC5E00CE2596 /* StaticAnalyser.cpp */; }; + 4B055A8C1FAE85670060FFFF /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B38F3421F2EB3E900D9235D /* StaticAnalyser.cpp */; }; + 4B055A8D1FAE85920060FFFF /* AsyncTaskQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B3940E51DA83C8300427841 /* AsyncTaskQueue.cpp */; }; + 4B055A8E1FAE85920060FFFF /* BestEffortUpdater.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B80ACFE1F85CAC900176895 /* BestEffortUpdater.cpp */; }; + 4B055A8F1FAE85A90060FFFF /* FileHolder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B5FADB81DE3151600AEC565 /* FileHolder.cpp */; }; + 4B055A901FAE85A90060FFFF /* TimedEventLoop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB697C91D4B6D3E00248BDF /* TimedEventLoop.cpp */; }; + 4B055A911FAE85B50060FFFF /* Cartridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEE0A6A1D72496600532C7B /* Cartridge.cpp */; }; + 4B055A921FAE85B50060FFFF /* PRG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEE0A6D1D72496600532C7B /* PRG.cpp */; }; + 4B055A931FAE85B50060FFFF /* BinaryDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B37EE801D7345A6006A09A4 /* BinaryDump.cpp */; }; + 4B055A941FAE85B50060FFFF /* CommodoreROM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BCA6CC61D9DD9F000C2D7B2 /* CommodoreROM.cpp */; }; + 4B055A951FAE85BB0060FFFF /* BitReverse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1558BE1F844ECD006E9A97 /* BitReverse.cpp */; }; + 4B055A961FAE85BB0060FFFF /* Commodore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8805F51DCFF6C9003085B1 /* Commodore.cpp */; }; + 4B055A971FAE85BB0060FFFF /* ZX8081.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BA0F68C1EEA0E8400E9489E /* ZX8081.cpp */; }; + 4B055A981FAE85C50060FFFF /* Drive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B30512B1D989E2200B4FED8 /* Drive.cpp */; }; + 4B055A991FAE85CB0060FFFF /* DiskController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B45187A1F75E91900926311 /* DiskController.cpp */; }; + 4B055A9A1FAE85CB0060FFFF /* MFMDiskController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B45187C1F75E91900926311 /* MFMDiskController.cpp */; }; + 4B055A9B1FAE85DA0060FFFF /* AcornADF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B45188D1F75FD1B00926311 /* AcornADF.cpp */; }; + 4B055A9C1FAE85DA0060FFFF /* CPCDSK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B45188F1F75FD1B00926311 /* CPCDSK.cpp */; }; + 4B055A9D1FAE85DA0060FFFF /* D64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518911F75FD1B00926311 /* D64.cpp */; }; + 4B055A9E1FAE85DA0060FFFF /* G64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518931F75FD1B00926311 /* G64.cpp */; }; + 4B055A9F1FAE85DA0060FFFF /* HFE.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518951F75FD1B00926311 /* HFE.cpp */; }; + 4B055AA01FAE85DA0060FFFF /* MFMSectorDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B58601C1F806AB200AEE2E3 /* MFMSectorDump.cpp */; }; + 4B055AA11FAE85DA0060FFFF /* OricMFMDSK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518971F75FD1B00926311 /* OricMFMDSK.cpp */; }; + 4B055AA21FAE85DA0060FFFF /* SSD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518991F75FD1B00926311 /* SSD.cpp */; }; + 4B055AA31FAE85DF0060FFFF /* ImplicitSectors.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BFDD78B1F7F2DB4008579B9 /* ImplicitSectors.cpp */; }; + 4B055AA41FAE85E50060FFFF /* DigitalPhaseLockedLoop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B45187F1F75E91900926311 /* DigitalPhaseLockedLoop.cpp */; }; + 4B055AA51FAE85EF0060FFFF /* Encoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7136841F78724F008B8ED9 /* Encoder.cpp */; }; + 4B055AA61FAE85EF0060FFFF /* Parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B71368C1F788112008B8ED9 /* Parser.cpp */; }; + 4B055AA71FAE85EF0060FFFF /* SegmentParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B71368F1F789C93008B8ED9 /* SegmentParser.cpp */; }; + 4B055AA81FAE85EF0060FFFF /* Shifter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7136871F78725F008B8ED9 /* Shifter.cpp */; }; + 4B055AA91FAE85EF0060FFFF /* CommodoreGCR.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB697CC1D4BA44400248BDF /* CommodoreGCR.cpp */; }; + 4B055AAA1FAE85F50060FFFF /* CPM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B3FE75C1F3CF68B00448EE4 /* CPM.cpp */; }; + 4B055AAB1FAE85FD0060FFFF /* PCMPatchedTrack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518711F75E91800926311 /* PCMPatchedTrack.cpp */; }; + 4B055AAC1FAE85FD0060FFFF /* PCMSegment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518731F75E91800926311 /* PCMSegment.cpp */; }; + 4B055AAD1FAE85FD0060FFFF /* PCMTrack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518751F75E91800926311 /* PCMTrack.cpp */; }; + 4B055AAE1FAE85FD0060FFFF /* TrackSerialiser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBFFEE51F7B27F1005F3FEB /* TrackSerialiser.cpp */; }; + 4B055AAF1FAE85FD0060FFFF /* UnformattedTrack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518771F75E91800926311 /* UnformattedTrack.cpp */; }; + 4B055AB01FAE86070060FFFF /* PulseQueuedTape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B448E821F1C4C480009ABD6 /* PulseQueuedTape.cpp */; }; + 4B055AB11FAE86070060FFFF /* Tape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B69FB3B1C4D908A00B5F0AA /* Tape.cpp */; }; + 4B055AB21FAE860F0060FFFF /* CommodoreTAP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC91B811D1F160E00884B76 /* CommodoreTAP.cpp */; }; + 4B055AB31FAE860F0060FFFF /* CSW.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B3BF5AE1F146264005B6C36 /* CSW.cpp */; }; + 4B055AB41FAE860F0060FFFF /* OricTAP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B59199A1DAC6C46005BB85C /* OricTAP.cpp */; }; + 4B055AB51FAE860F0060FFFF /* TapePRG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2BFC5D1D613E0200BA3AA9 /* TapePRG.cpp */; }; + 4B055AB61FAE860F0060FFFF /* TapeUEF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B69FB421C4D941400B5F0AA /* TapeUEF.cpp */; }; + 4B055AB71FAE860F0060FFFF /* TZX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B448E7F1F1C45A00009ABD6 /* TZX.cpp */; }; + 4B055AB81FAE860F0060FFFF /* ZX80O81P.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1497861EE4A1DA00CE2596 /* ZX80O81P.cpp */; }; + 4B055AB91FAE86170060FFFF /* Acorn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8805EE1DCFC99C003085B1 /* Acorn.cpp */; }; + 4B055ABA1FAE86170060FFFF /* Commodore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8805F21DCFD22A003085B1 /* Commodore.cpp */; }; + 4B055ABB1FAE86170060FFFF /* Oric.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8805F91DCFF807003085B1 /* Oric.cpp */; }; + 4B055ABC1FAE86170060FFFF /* ZX8081.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBFBB6A1EE8401E00C01E7A /* ZX8081.cpp */; }; + 4B055ABD1FAE86530060FFFF /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B69FB451C4D950F00B5F0AA /* libz.tbd */; }; + 4B055AC11FAE98DC0060FFFF /* MachineForTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B055ABE1FAE98000060FFFF /* MachineForTarget.cpp */; }; + 4B055AC21FAE9AE30060FFFF /* KeyboardMachine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B54C0BB1F8D8E790050900F /* KeyboardMachine.cpp */; }; + 4B055AC31FAE9AE80060FFFF /* AmstradCPC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B38F3461F2EC11D00D9235D /* AmstradCPC.cpp */; }; + 4B055AC41FAE9AE80060FFFF /* Keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B54C0C11F8D91CD0050900F /* Keyboard.cpp */; }; + 4B055AC51FAE9AEE0060FFFF /* Atari2600.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2E2D971C3A06EC00138695 /* Atari2600.cpp */; }; + 4B055AC61FAE9AEE0060FFFF /* Speaker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEA52641DF3472B007E74F2 /* Speaker.cpp */; }; + 4B055AC71FAE9AEE0060FFFF /* TIA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BE7C9161E3D397100A5496D /* TIA.cpp */; }; + 4B055AC81FAE9AFB0060FFFF /* C1540.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8334941F5E25B60097E338 /* C1540.cpp */; }; + 4B055AC91FAE9AFB0060FFFF /* Keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B54C0C41F8D91D90050900F /* Keyboard.cpp */; }; + 4B055ACA1FAE9AFB0060FFFF /* Vic20.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DC81F1D2C2425003C5BF8 /* Vic20.cpp */; }; + 4B055ACB1FAE9AFB0060FFFF /* SerialBus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DC8291D2C27A4003C5BF8 /* SerialBus.cpp */; }; + 4B055ACC1FAE9B030060FFFF /* Electron.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2E2D9B1C3A070400138695 /* Electron.cpp */; }; + 4B055ACD1FAE9B030060FFFF /* Keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B54C0C61F8D91E50050900F /* Keyboard.cpp */; }; + 4B055ACE1FAE9B030060FFFF /* Plus3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B30512E1D98ACC600B4FED8 /* Plus3.cpp */; }; + 4B055ACF1FAE9B030060FFFF /* Speaker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEA52611DF339D7007E74F2 /* Speaker.cpp */; }; + 4B055AD01FAE9B030060FFFF /* Tape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEA525D1DF33323007E74F2 /* Tape.cpp */; }; + 4B055AD11FAE9B030060FFFF /* Video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7913CA1DFCD80E00175A82 /* Video.cpp */; }; + 4B055AD21FAE9B0B0060FFFF /* Keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B54C0BD1F8D8F450050900F /* Keyboard.cpp */; }; + 4B055AD31FAE9B0B0060FFFF /* Microdisc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B5FADBE1DE3BF2B00AEC565 /* Microdisc.cpp */; }; + 4B055AD41FAE9B0B0060FFFF /* Oric.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF1FA21DADC3DD0039D2E7 /* Oric.cpp */; }; + 4B055AD51FAE9B0B0060FFFF /* Video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2BFDB01DAEF5FF001A68B8 /* Video.cpp */; }; + 4B055AD61FAE9B130060FFFF /* MemoryFuzzer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2B3A481F9B8FA70062DABF /* MemoryFuzzer.cpp */; }; + 4B055AD71FAE9B180060FFFF /* Keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B54C0CA1F8D92580050900F /* Keyboard.cpp */; }; + 4B055AD81FAE9B180060FFFF /* Video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BD3A3091EE755C800B5B501 /* Video.cpp */; }; + 4B055AD91FAE9B180060FFFF /* ZX8081.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1497901EE4B5A800CE2596 /* ZX8081.cpp */; }; + 4B055ADA1FAE9B460060FFFF /* 1770.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BD468F51D8DF41D0084958B /* 1770.cpp */; }; + 4B055ADB1FAE9B460060FFFF /* 6560.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC9DF4D1D04691600F44158 /* 6560.cpp */; }; + 4B055ADC1FAE9B460060FFFF /* AY38910.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4A762E1DB1A3FA007AAE2E /* AY38910.cpp */; }; + 4B055ADD1FAE9B460060FFFF /* i8272.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBC951C1F368D83008F4C34 /* i8272.cpp */; }; + 4B055ADE1FAE9B4C0060FFFF /* 6522Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B83348B1F5DB99C0097E338 /* 6522Base.cpp */; }; + 4B055ADF1FAE9B4C0060FFFF /* IRQDelegatePortHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8334891F5DB94B0097E338 /* IRQDelegatePortHandler.cpp */; }; + 4B055AE01FAE9B660060FFFF /* CRT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0CCC421C62D0B3001CAC5F /* CRT.cpp */; }; + 4B055AE11FAE9B6F0060FFFF /* ArrayBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B5073051DDD3B9400C48FBD /* ArrayBuilder.cpp */; }; + 4B055AE21FAE9B6F0060FFFF /* CRTOpenGL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBF990A1C8FBA6F0075DAFB /* CRTOpenGL.cpp */; }; + 4B055AE31FAE9B6F0060FFFF /* TextureBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBF99081C8FBA6F0075DAFB /* TextureBuilder.cpp */; }; + 4B055AE41FAE9B6F0060FFFF /* TextureTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBF99121C8FBA6F0075DAFB /* TextureTarget.cpp */; }; + 4B055AE51FAE9B6F0060FFFF /* IntermediateShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBB142F1CD2CECE00BDB55C /* IntermediateShader.cpp */; }; + 4B055AE61FAE9B6F0060FFFF /* OutputShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B7501CD1956900F86E85 /* OutputShader.cpp */; }; + 4B055AE71FAE9B6F0060FFFF /* Shader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B74D1CD194CC00F86E85 /* Shader.cpp */; }; + 4B055AE81FAE9B7B0060FFFF /* FIRFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC76E671C98E31700E6EF73 /* FIRFilter.cpp */; }; + 4B055AE91FAE9B990060FFFF /* 6502Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B6A4C951F58F09E00E3F787 /* 6502Base.cpp */; }; + 4B055AEA1FAE9B990060FFFF /* 6502Storage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8334851F5DA3780097E338 /* 6502Storage.cpp */; }; + 4B055AEB1FAE9BA20060FFFF /* PartialMachineCycle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8334811F5D9FF70097E338 /* PartialMachineCycle.cpp */; }; + 4B055AEC1FAE9BA20060FFFF /* Z80Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B322E031F5A2E3C004EB04C /* Z80Base.cpp */; }; + 4B055AED1FAE9BA20060FFFF /* Z80Storage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8334831F5DA0360097E338 /* Z80Storage.cpp */; }; + 4B055AEE1FAE9BBF0060FFFF /* Keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B86E2591F8C628F006FAA45 /* Keyboard.cpp */; }; + 4B055AEF1FAE9BF00060FFFF /* Typer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2B3A471F9B8FA70062DABF /* Typer.cpp */; }; + 4B055AF11FAE9C160060FFFF /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BC76E6A1C98F43700E6EF73 /* Accelerate.framework */; }; + 4B055AF21FAE9C1C0060FFFF /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B055AF01FAE9C080060FFFF /* OpenGL.framework */; }; 4B08A2751EE35D56008B7065 /* Z80InterruptTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B08A2741EE35D56008B7065 /* Z80InterruptTests.swift */; }; 4B08A2781EE39306008B7065 /* TestMachine.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B08A2771EE39306008B7065 /* TestMachine.mm */; }; 4B0CCC451C62D0B3001CAC5F /* CRT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0CCC421C62D0B3001CAC5F /* CRT.cpp */; }; @@ -481,10 +595,28 @@ }; /* End PBXContainerItemProxy section */ +/* Begin PBXCopyFilesBuildPhase section */ + 4B055A681FAE763F0060FFFF /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ 4B01A6871F22F0DB001FD6E3 /* Z80MemptrTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Z80MemptrTests.swift; sourceTree = ""; }; 4B046DC31CFE651500E9E45E /* CRTMachine.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CRTMachine.hpp; sourceTree = ""; }; 4B049CDC1DA3C82F00322067 /* BCDTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BCDTest.swift; sourceTree = ""; }; + 4B055A6A1FAE763F0060FFFF /* Clock Signal Kiosk */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "Clock Signal Kiosk"; sourceTree = BUILT_PRODUCTS_DIR; }; + 4B055A771FAE78210060FFFF /* SDL2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL2.framework; path = ../../../../Library/Frameworks/SDL2.framework; sourceTree = SOURCE_ROOT; }; + 4B055A7C1FAE84A50060FFFF /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 4B055ABE1FAE98000060FFFF /* MachineForTarget.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MachineForTarget.cpp; sourceTree = ""; }; + 4B055ABF1FAE98000060FFFF /* MachineForTarget.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MachineForTarget.hpp; sourceTree = ""; }; + 4B055AF01FAE9C080060FFFF /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; }; 4B08A2741EE35D56008B7065 /* Z80InterruptTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Z80InterruptTests.swift; sourceTree = ""; }; 4B08A2761EE39306008B7065 /* TestMachine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestMachine.h; sourceTree = ""; }; 4B08A2771EE39306008B7065 /* TestMachine.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TestMachine.mm; sourceTree = ""; }; @@ -1078,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 = ""; }; @@ -1134,6 +1267,17 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 4B055A671FAE763F0060FFFF /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4B055AF21FAE9C1C0060FFFF /* OpenGL.framework in Frameworks */, + 4B055AF11FAE9C160060FFFF /* Accelerate.framework in Frameworks */, + 4B055ABD1FAE86530060FFFF /* libz.tbd in Frameworks */, + 4B055A7A1FAE78A00060FFFF /* SDL2.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 4BB73E9B1B587A5100552FC2 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -1160,6 +1304,24 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 4B055A761FAE78210060FFFF /* Frameworks */ = { + isa = PBXGroup; + children = ( + 4B055AF01FAE9C080060FFFF /* OpenGL.framework */, + 4B055A771FAE78210060FFFF /* SDL2.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 4B055A7B1FAE84A50060FFFF /* SDL */ = { + isa = PBXGroup; + children = ( + 4B055A7C1FAE84A50060FFFF /* main.cpp */, + ); + name = SDL; + path = ../SDL; + sourceTree = ""; + }; 4B0CCC411C62D0B3001CAC5F /* CRT */ = { isa = PBXGroup; children = ( @@ -1300,6 +1462,8 @@ 4B2B3A461F9B8FA70062DABF /* Utility */ = { isa = PBXGroup; children = ( + 4B055ABE1FAE98000060FFFF /* MachineForTarget.cpp */, + 4B055ABF1FAE98000060FFFF /* MachineForTarget.hpp */, 4B2B3A471F9B8FA70062DABF /* Typer.cpp */, 4B2B3A481F9B8FA70062DABF /* MemoryFuzzer.cpp */, 4B2B3A491F9B8FA70062DABF /* MemoryFuzzer.hpp */, @@ -2095,12 +2259,14 @@ 4BF660691F281573002CB053 /* ClockReceiver */, 4BC9DF4A1D04691600F44158 /* Components */, 4B3940E81DA83C8700427841 /* Concurrency */, + 4B055A761FAE78210060FFFF /* Frameworks */, 4B86E2581F8C628F006FAA45 /* Inputs */, 4BB73EDC1B587CA500552FC2 /* Machines */, 4BB697C81D4B559300248BDF /* NumberTheory */, 4B366DFD1B5C165F0026627B /* Outputs */, 4BB73EDD1B587CA500552FC2 /* Processors */, 4BB73E9F1B587A5100552FC2 /* Products */, + 4B055A7B1FAE84A50060FFFF /* SDL */, 4B2409591C45DF85004DA684 /* SignalProcessing */, 4BF1354D1D6D2C360054B2EA /* StaticAnalyser */, 4B69FB391C4D908A00B5F0AA /* Storage */, @@ -2116,6 +2282,7 @@ 4BB73E9E1B587A5100552FC2 /* Clock Signal.app */, 4BB73EB21B587A5100552FC2 /* Clock SignalTests.xctest */, 4BB73EBD1B587A5100552FC2 /* Clock SignalUITests.xctest */, + 4B055A6A1FAE763F0060FFFF /* Clock Signal Kiosk */, ); name = Products; sourceTree = ""; @@ -2186,6 +2353,7 @@ isa = PBXGroup; children = ( 4B54C0BB1F8D8E790050900F /* KeyboardMachine.cpp */, + 4BDCC5F81FB27A5E001220C5 /* ROMMachine.hpp */, 4BA9C3CF1D8164A9002DDB61 /* ConfigurationTarget.hpp */, 4B046DC31CFE651500E9E45E /* CRTMachine.hpp */, 4B7041271F92C26900735E45 /* JoystickMachine.hpp */, @@ -2496,6 +2664,23 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ + 4B055A691FAE763F0060FFFF /* Clock Signal Kiosk */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4B055A701FAE763F0060FFFF /* Build configuration list for PBXNativeTarget "Clock Signal Kiosk" */; + buildPhases = ( + 4B055A661FAE763F0060FFFF /* Sources */, + 4B055A671FAE763F0060FFFF /* Frameworks */, + 4B055A681FAE763F0060FFFF /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Clock Signal Kiosk"; + productName = "Clock Signal Kiosk"; + productReference = 4B055A6A1FAE763F0060FFFF /* Clock Signal Kiosk */; + productType = "com.apple.product-type.tool"; + }; 4BB73E9D1B587A5100552FC2 /* Clock Signal */ = { isa = PBXNativeTarget; buildConfigurationList = 4BB73EC61B587A5100552FC2 /* Build configuration list for PBXNativeTarget "Clock Signal" */; @@ -2559,6 +2744,10 @@ LastUpgradeCheck = 0900; ORGANIZATIONNAME = "Thomas Harte"; TargetAttributes = { + 4B055A691FAE763F0060FFFF = { + CreatedOnToolsVersion = 9.1; + ProvisioningStyle = Automatic; + }; 4BB73E9D1B587A5100552FC2 = { CreatedOnToolsVersion = 7.0; LastSwiftMigration = 0900; @@ -2596,6 +2785,7 @@ 4BB73E9D1B587A5100552FC2 /* Clock Signal */, 4BB73EB11B587A5100552FC2 /* Clock SignalTests */, 4BB73EBC1B587A5100552FC2 /* Clock SignalUITests */, + 4B055A691FAE763F0060FFFF /* Clock Signal Kiosk */, ); }; /* End PBXProject section */ @@ -2913,6 +3103,123 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 4B055A661FAE763F0060FFFF /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4B055AAA1FAE85F50060FFFF /* CPM.cpp in Sources */, + 4B055A9A1FAE85CB0060FFFF /* MFMDiskController.cpp in Sources */, + 4B055ACB1FAE9AFB0060FFFF /* SerialBus.cpp in Sources */, + 4B055AA41FAE85E50060FFFF /* DigitalPhaseLockedLoop.cpp in Sources */, + 4B055AE61FAE9B6F0060FFFF /* OutputShader.cpp in Sources */, + 4B055A9B1FAE85DA0060FFFF /* AcornADF.cpp in Sources */, + 4B055AD51FAE9B0B0060FFFF /* Video.cpp in Sources */, + 4B055A811FAE853A0060FFFF /* Disk.cpp in Sources */, + 4B055AE11FAE9B6F0060FFFF /* ArrayBuilder.cpp in Sources */, + 4B055AA51FAE85EF0060FFFF /* Encoder.cpp in Sources */, + 4B055AEA1FAE9B990060FFFF /* 6502Storage.cpp in Sources */, + 4B055A8A1FAE855B0060FFFF /* Tape.cpp in Sources */, + 4B055AA71FAE85EF0060FFFF /* SegmentParser.cpp in Sources */, + 4B055AC11FAE98DC0060FFFF /* MachineForTarget.cpp in Sources */, + 4B055AD81FAE9B180060FFFF /* Video.cpp in Sources */, + 4B055AE51FAE9B6F0060FFFF /* IntermediateShader.cpp in Sources */, + 4B055A851FAE85480060FFFF /* File.cpp in Sources */, + 4B055AD31FAE9B0B0060FFFF /* Microdisc.cpp in Sources */, + 4B055AB41FAE860F0060FFFF /* OricTAP.cpp in Sources */, + 4B055AB71FAE860F0060FFFF /* TZX.cpp in Sources */, + 4B055A8C1FAE85670060FFFF /* StaticAnalyser.cpp in Sources */, + 4B055ADA1FAE9B460060FFFF /* 1770.cpp in Sources */, + 4B055ADC1FAE9B460060FFFF /* AY38910.cpp in Sources */, + 4B055AD71FAE9B180060FFFF /* Keyboard.cpp in Sources */, + 4B055AB61FAE860F0060FFFF /* TapeUEF.cpp in Sources */, + 4B055A9D1FAE85DA0060FFFF /* D64.cpp in Sources */, + 4B055ABB1FAE86170060FFFF /* Oric.cpp in Sources */, + 4B055AE81FAE9B7B0060FFFF /* FIRFilter.cpp in Sources */, + 4B055A901FAE85A90060FFFF /* TimedEventLoop.cpp in Sources */, + 4B055AAB1FAE85FD0060FFFF /* PCMPatchedTrack.cpp in Sources */, + 4B055AC71FAE9AEE0060FFFF /* TIA.cpp in Sources */, + 4B055AD21FAE9B0B0060FFFF /* Keyboard.cpp in Sources */, + 4B055AA31FAE85DF0060FFFF /* ImplicitSectors.cpp in Sources */, + 4B055AAE1FAE85FD0060FFFF /* TrackSerialiser.cpp in Sources */, + 4B055A981FAE85C50060FFFF /* Drive.cpp in Sources */, + 4B055AE21FAE9B6F0060FFFF /* CRTOpenGL.cpp in Sources */, + 4B055AC31FAE9AE80060FFFF /* AmstradCPC.cpp in Sources */, + 4B055A9E1FAE85DA0060FFFF /* G64.cpp in Sources */, + 4B055AB81FAE860F0060FFFF /* ZX80O81P.cpp in Sources */, + 4B055A8E1FAE85920060FFFF /* BestEffortUpdater.cpp in Sources */, + 4B055AB01FAE86070060FFFF /* PulseQueuedTape.cpp in Sources */, + 4B055A801FAE85350060FFFF /* StaticAnalyser.cpp in Sources */, + 4B055AAC1FAE85FD0060FFFF /* PCMSegment.cpp in Sources */, + 4B055AB31FAE860F0060FFFF /* CSW.cpp in Sources */, + 4B055ACF1FAE9B030060FFFF /* Speaker.cpp in Sources */, + 4B055AEE1FAE9BBF0060FFFF /* Keyboard.cpp in Sources */, + 4B055A881FAE85530060FFFF /* Disassembler6502.cpp in Sources */, + 4B055AED1FAE9BA20060FFFF /* Z80Storage.cpp in Sources */, + 4B055AD11FAE9B030060FFFF /* Video.cpp in Sources */, + 4B055AA21FAE85DA0060FFFF /* SSD.cpp in Sources */, + 4B055ADD1FAE9B460060FFFF /* i8272.cpp in Sources */, + 4B055AC51FAE9AEE0060FFFF /* Atari2600.cpp in Sources */, + 4B055A9C1FAE85DA0060FFFF /* CPCDSK.cpp in Sources */, + 4B055AE41FAE9B6F0060FFFF /* TextureTarget.cpp in Sources */, + 4B055ABA1FAE86170060FFFF /* Commodore.cpp in Sources */, + 4B055AA61FAE85EF0060FFFF /* Parser.cpp in Sources */, + 4B055AE91FAE9B990060FFFF /* 6502Base.cpp in Sources */, + 4B055A861FAE854C0060FFFF /* StaticAnalyser.cpp in Sources */, + 4B055AEF1FAE9BF00060FFFF /* Typer.cpp in Sources */, + 4B055ACA1FAE9AFB0060FFFF /* Vic20.cpp in Sources */, + 4B055ABC1FAE86170060FFFF /* ZX8081.cpp in Sources */, + 4B055AC91FAE9AFB0060FFFF /* Keyboard.cpp in Sources */, + 4B055A991FAE85CB0060FFFF /* DiskController.cpp in Sources */, + 4B055ACC1FAE9B030060FFFF /* Electron.cpp in Sources */, + 4B055AB11FAE86070060FFFF /* Tape.cpp in Sources */, + 4B055AA91FAE85EF0060FFFF /* CommodoreGCR.cpp in Sources */, + 4B055A7F1FAE852F0060FFFF /* StaticAnalyser.cpp in Sources */, + 4B055ADB1FAE9B460060FFFF /* 6560.cpp in Sources */, + 4B055AA01FAE85DA0060FFFF /* MFMSectorDump.cpp in Sources */, + 4B055AA11FAE85DA0060FFFF /* OricMFMDSK.cpp in Sources */, + 4B055A951FAE85BB0060FFFF /* BitReverse.cpp in Sources */, + 4B055A891FAE85580060FFFF /* StaticAnalyser.cpp in Sources */, + 4B055ACE1FAE9B030060FFFF /* Plus3.cpp in Sources */, + 4B055A8D1FAE85920060FFFF /* AsyncTaskQueue.cpp in Sources */, + 4B055AC41FAE9AE80060FFFF /* Keyboard.cpp in Sources */, + 4B055A941FAE85B50060FFFF /* CommodoreROM.cpp in Sources */, + 4B055A971FAE85BB0060FFFF /* ZX8081.cpp in Sources */, + 4B055AAD1FAE85FD0060FFFF /* PCMTrack.cpp in Sources */, + 4B055A841FAE85450060FFFF /* Disk.cpp in Sources */, + 4B055A831FAE85410060FFFF /* Tape.cpp in Sources */, + 4B055AC61FAE9AEE0060FFFF /* Speaker.cpp in Sources */, + 4B055AA81FAE85EF0060FFFF /* Shifter.cpp in Sources */, + 4B055AC81FAE9AFB0060FFFF /* C1540.cpp in Sources */, + 4B055A8F1FAE85A90060FFFF /* FileHolder.cpp in Sources */, + 4B055A911FAE85B50060FFFF /* Cartridge.cpp in Sources */, + 4B055ACD1FAE9B030060FFFF /* Keyboard.cpp in Sources */, + 4B055A8B1FAE85670060FFFF /* StaticAnalyser.cpp in Sources */, + 4B055AB21FAE860F0060FFFF /* CommodoreTAP.cpp in Sources */, + 4B055ADF1FAE9B4C0060FFFF /* IRQDelegatePortHandler.cpp in Sources */, + 4B055AB51FAE860F0060FFFF /* TapePRG.cpp in Sources */, + 4B055AE01FAE9B660060FFFF /* CRT.cpp in Sources */, + 4B055AD01FAE9B030060FFFF /* Tape.cpp in Sources */, + 4B055A961FAE85BB0060FFFF /* Commodore.cpp in Sources */, + 4B055ADE1FAE9B4C0060FFFF /* 6522Base.cpp in Sources */, + 4B055AD41FAE9B0B0060FFFF /* Oric.cpp in Sources */, + 4B055A821FAE853D0060FFFF /* StaticAnalyser.cpp in Sources */, + 4B055A921FAE85B50060FFFF /* PRG.cpp in Sources */, + 4B055AAF1FAE85FD0060FFFF /* UnformattedTrack.cpp in Sources */, + 4B055A7E1FAE84AA0060FFFF /* main.cpp in Sources */, + 4B055A9F1FAE85DA0060FFFF /* HFE.cpp in Sources */, + 4B055AE71FAE9B6F0060FFFF /* Shader.cpp in Sources */, + 4B055AEC1FAE9BA20060FFFF /* Z80Base.cpp in Sources */, + 4B055AE31FAE9B6F0060FFFF /* TextureBuilder.cpp in Sources */, + 4B055AB91FAE86170060FFFF /* Acorn.cpp in Sources */, + 4B055A931FAE85B50060FFFF /* BinaryDump.cpp in Sources */, + 4B055AD61FAE9B130060FFFF /* MemoryFuzzer.cpp in Sources */, + 4B055AC21FAE9AE30060FFFF /* KeyboardMachine.cpp in Sources */, + 4B055AD91FAE9B180060FFFF /* ZX8081.cpp in Sources */, + 4B055AEB1FAE9BA20060FFFF /* PartialMachineCycle.cpp in Sources */, + 4B055A871FAE854F0060FFFF /* Tape.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 4BB73E9A1B587A5100552FC2 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -3182,6 +3489,44 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ + 4B055A6E1FAE763F0060FFFF /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(USER_LIBRARY_DIR)/Frameworks", + ); + GCC_C_LANGUAGE_STANDARD = gnu11; + MACOSX_DEPLOYMENT_TARGET = 10.12; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 4B055A6F1FAE763F0060FFFF /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(USER_LIBRARY_DIR)/Frameworks", + ); + GCC_C_LANGUAGE_STANDARD = gnu11; + MACOSX_DEPLOYMENT_TARGET = 10.12; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; 4BB73EC41B587A5100552FC2 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -3294,6 +3639,10 @@ CLANG_WARN__EXIT_TIME_DESTRUCTORS = YES; CODE_SIGN_ENTITLEMENTS = "Clock Signal/Clock Signal.entitlements"; COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(USER_LIBRARY_DIR)/Frameworks", + ); GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; GCC_WARN_ABOUT_MISSING_NEWLINE = YES; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; @@ -3324,6 +3673,10 @@ CLANG_WARN__EXIT_TIME_DESTRUCTORS = YES; CODE_SIGN_ENTITLEMENTS = "Clock Signal/Clock Signal.entitlements"; COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(USER_LIBRARY_DIR)/Frameworks", + ); GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; GCC_WARN_ABOUT_MISSING_NEWLINE = YES; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; @@ -3408,6 +3761,15 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 4B055A701FAE763F0060FFFF /* Build configuration list for PBXNativeTarget "Clock Signal Kiosk" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4B055A6E1FAE763F0060FFFF /* Debug */, + 4B055A6F1FAE763F0060FFFF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 4BB73E991B587A5100552FC2 /* Build configuration list for PBXProject "Clock Signal" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme b/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme index 952d0cbdc..b254c3119 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme +++ b/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme @@ -72,7 +72,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - enableUBSanitizer = "YES" + disableMainThreadChecker = "YES" language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" diff --git a/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm b/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm index 6c7746ac0..c1a3049f2 100644 --- a/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm +++ b/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm @@ -16,6 +16,9 @@ #include "JoystickMachine.hpp" #include "KeyboardMachine.hpp" +#import "NSBundle+DataResource.h" +#import "NSData+StdVector.h" + @interface CSMachine() - (void)speaker:(Outputs::Speaker *)speaker didCompleteSamples:(const int16_t *)samples length:(int)length; - (void)machineDidChangeClockRate; @@ -69,6 +72,23 @@ struct MachineDelegate: CRTMachine::Machine::Delegate, public LockProtectedDeleg _speakerDelegate.machineAccessLock = _delegateMachineAccessLock; _machine->set_delegate(&_machineDelegate); + _machine->set_rom_fetcher( [] (const std::string &machine, const std::vector &names) -> std::vector>> { + NSString *subDirectory = [@"ROMImages/" stringByAppendingString:[NSString stringWithUTF8String:machine.c_str()]]; + std::vector>> results; + for(auto &name: names) { + NSData *fileData = [[NSBundle mainBundle] dataForResource:[NSString stringWithUTF8String:name.c_str()] withExtension:nil subdirectory:subDirectory]; + + if(!fileData) + results.emplace_back(nullptr); + else { + std::unique_ptr> data(new std::vector); + *data = fileData.stdVector8; + results.emplace_back(std::move(data)); + } + } + + return results; + }); } return self; } diff --git a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSAmstradCPC.mm b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSAmstradCPC.mm index f129bdecb..c3442c2c8 100644 --- a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSAmstradCPC.mm +++ b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSAmstradCPC.mm @@ -10,10 +10,6 @@ #include "AmstradCPC.hpp" -#import "CSMachine+Subclassing.h" -#import "NSData+StdVector.h" -#import "NSBundle+DataResource.h" - @implementation CSAmstradCPC { std::unique_ptr _amstradCPC; } @@ -24,35 +20,10 @@ self = [super initWithMachine:machine]; if(self) { _amstradCPC.reset(machine); - - NSDictionary *roms = @{ - @(AmstradCPC::ROMType::OS464) : @"os464", - @(AmstradCPC::ROMType::OS664) : @"os664", - @(AmstradCPC::ROMType::OS6128) : @"os6128", - @(AmstradCPC::ROMType::BASIC464) : @"basic464", - @(AmstradCPC::ROMType::BASIC664) : @"basic664", - @(AmstradCPC::ROMType::BASIC6128) : @"basic6128", - @(AmstradCPC::ROMType::AMSDOS) : @"amsdos", - }; - - for(NSNumber *key in roms.allKeys) { - AmstradCPC::ROMType type = (AmstradCPC::ROMType)key.integerValue; - NSString *name = roms[key]; - NSData *data = [self rom:name]; - if(data) { - _amstradCPC->set_rom(type, data.stdVector8); - } else { - NSLog(@"Amstrad CPC ROM missing: %@", name); - } - } } return self; } -- (NSData *)rom:(NSString *)name { - return [[NSBundle mainBundle] dataForResource:name withExtension:@"rom" subdirectory:@"ROMImages/AmstradCPC"]; -} - - (NSString *)userDefaultsPrefix { return @"amstradCPC"; } @end diff --git a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSElectron.mm b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSElectron.mm index 8a9611ed3..1f0aa2ba0 100644 --- a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSElectron.mm +++ b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSElectron.mm @@ -9,11 +9,7 @@ #import "CSElectron.h" #include "Electron.hpp" -#include "StaticAnalyser.hpp" -#import "CSMachine+Subclassing.h" -#import "NSData+StdVector.h" -#import "NSBundle+DataResource.h" @implementation CSElectron { std::unique_ptr _electron; @@ -25,38 +21,12 @@ self = [super initWithMachine:machine]; if(self) { _electron.reset(machine); - - [self setOSROM:[self rom:@"os"]]; - [self setBASICROM:[self rom:@"basic"]]; - [self setDFSROM:[self rom:@"DFS-1770-2.20"]]; - - NSMutableData *adfs = [[self rom:@"ADFS-E00_1"] mutableCopy]; - [adfs appendData:[self rom:@"ADFS-E00_2"]]; - [self setADFSROM:adfs]; } return self; } -- (NSData *)rom:(NSString *)name { - return [[NSBundle mainBundle] dataForResource:name withExtension:@"rom" subdirectory:@"ROMImages/Electron"]; -} - #pragma mark - ROM setting -- (void)setOSROM:(nonnull NSData *)rom { [self setROM:rom slot:Electron::ROMSlotOS]; } -- (void)setBASICROM:(nonnull NSData *)rom { [self setROM:rom slot:Electron::ROMSlotBASIC]; } -- (void)setADFSROM:(nonnull NSData *)rom { [self setROM:rom slot:Electron::ROMSlotADFS]; } -- (void)setDFSROM:(nonnull NSData *)rom { [self setROM:rom slot:Electron::ROMSlotDFS]; } - -- (void)setROM:(nonnull NSData *)rom slot:(int)slot { - if(rom) - { - @synchronized(self) { - _electron->set_rom((Electron::ROMSlot)slot, rom.stdVector8, false); - } - } -} - - (NSString *)userDefaultsPrefix { return @"electron"; } #pragma mark - Options diff --git a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSOric.mm b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSOric.mm index 2e9a5daf0..5c5a396f0 100644 --- a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSOric.mm +++ b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSOric.mm @@ -9,11 +9,6 @@ #import "CSOric.h" #include "Oric.hpp" -#include "StaticAnalyser.hpp" - -#import "CSMachine+Subclassing.h" -#import "NSData+StdVector.h" -#import "NSBundle+DataResource.h" @implementation CSOric { std::unique_ptr _oric; @@ -25,24 +20,10 @@ self = [super initWithMachine:machine]; if(self) { _oric.reset(machine); - - NSData *basic10 = [self rom:@"basic10"]; - NSData *basic11 = [self rom:@"basic11"]; - NSData *colour = [self rom:@"colour"]; - NSData *microdisc = [self rom:@"microdisc"]; - - if(basic10) _oric->set_rom(Oric::BASIC10, basic10.stdVector8); - if(basic11) _oric->set_rom(Oric::BASIC11, basic11.stdVector8); - if(colour) _oric->set_rom(Oric::Colour, colour.stdVector8); - if(microdisc) _oric->set_rom(Oric::Microdisc, microdisc.stdVector8); } return self; } -- (NSData *)rom:(NSString *)name { - return [[NSBundle mainBundle] dataForResource:name withExtension:@"rom" subdirectory:@"ROMImages/Oric"]; -} - #pragma mark - Options - (void)setUseFastLoadingHack:(BOOL)useFastLoadingHack { diff --git a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.h b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.h index 8a4af6136..0a71e6e3f 100644 --- a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.h +++ b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.h @@ -11,11 +11,11 @@ typedef NS_ENUM(NSInteger, CSVic20Country) { + CSVic20CountryAmerican, CSVic20CountryDanish, CSVic20CountryEuropean, CSVic20CountryJapanese, - CSVic20CountrySwedish, - CSVic20CountryAmerican + CSVic20CountrySwedish }; typedef NS_ENUM(NSInteger, CSVic20MemorySize) diff --git a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm index fbfbbe20c..0e4977b9b 100644 --- a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm +++ b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm @@ -9,12 +9,6 @@ #import "CSVic20.h" #include "Vic20.hpp" -#include "CommodoreTAP.hpp" -#include "G64.hpp" -#include "D64.hpp" - -#import "CSmachine+Subclassing.h" -#import "NSBundle+DataResource.h" using namespace Commodore::Vic20; @@ -31,41 +25,11 @@ using namespace Commodore::Vic20; self = [super initWithMachine:machine]; if(self) { _vic20.reset(machine); - [self setDriveROM:[[NSBundle mainBundle] dataForResource:@"1540" withExtension:@"bin" subdirectory:@"ROMImages/Commodore1540"]]; - [self setBASICROM:[self rom:@"basic"]]; [self setCountry:CSVic20CountryEuropean]; } return self; } -- (NSData *)rom:(NSString *)name { - return [[NSBundle mainBundle] dataForResource:name withExtension:@"bin" subdirectory:@"ROMImages/Vic20"]; -} - -#pragma mark - ROM setting - -- (void)setROM:(nonnull NSData *)rom slot:(ROMSlot)slot { - @synchronized(self) { - _vic20->set_rom(slot, rom.length, (const uint8_t *)rom.bytes); - } -} - -- (void)setKernelROM:(nonnull NSData *)rom { - [self setROM:rom slot:Kernel]; -} - -- (void)setBASICROM:(nonnull NSData *)rom { - [self setROM:rom slot:BASIC]; -} - -- (void)setCharactersROM:(nonnull NSData *)rom { - [self setROM:rom slot:Characters]; -} - -- (void)setDriveROM:(nonnull NSData *)rom { - [self setROM:rom slot:Drive]; -} - #pragma mark - Keyboard map /*- (void)setKey:(uint16_t)key isPressed:(BOOL)isPressed { @@ -89,40 +53,17 @@ using namespace Commodore::Vic20; - (void)setCountry:(CSVic20Country)country { _country = country; - NSString *charactersROM, *kernelROM; Commodore::Vic20::Region region; switch(country) { - case CSVic20CountryDanish: - region = Commodore::Vic20::Region::PAL; - charactersROM = @"characters-danish"; - kernelROM = @"kernel-danish"; - break; - case CSVic20CountryEuropean: - region = Commodore::Vic20::Region::PAL; - charactersROM = @"characters-english"; - kernelROM = @"kernel-pal"; - break; - case CSVic20CountryJapanese: - region = Commodore::Vic20::Region::NTSC; - charactersROM = @"characters-japanese"; - kernelROM = @"kernel-japanese"; - break; - case CSVic20CountrySwedish: - region = Commodore::Vic20::Region::PAL; - charactersROM = @"characters-swedish"; - kernelROM = @"kernel-swedish"; - break; - case CSVic20CountryAmerican: - region = Commodore::Vic20::Region::NTSC; - charactersROM = @"characters-english"; - kernelROM = @"kernel-ntsc"; - break; + case CSVic20CountryDanish: region = Commodore::Vic20::Danish; break; + case CSVic20CountryEuropean: region = Commodore::Vic20::European; break; + case CSVic20CountryJapanese: region = Commodore::Vic20::Japanese; break; + case CSVic20CountrySwedish: region = Commodore::Vic20::Swedish; break; + case CSVic20CountryAmerican: region = Commodore::Vic20::American; break; } @synchronized(self) { _vic20->set_region(region); - [self setCharactersROM:[self rom:charactersROM]]; - [self setKernelROM:[self rom:kernelROM]]; } } diff --git a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSZX8081.mm b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSZX8081.mm index fb5d07578..800c1b6f7 100644 --- a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSZX8081.mm +++ b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSZX8081.mm @@ -10,10 +10,6 @@ #include "ZX8081.hpp" -#import "CSMachine+Subclassing.h" -#import "NSData+StdVector.h" -#import "NSBundle+DataResource.h" - @implementation CSZX8081 { std::unique_ptr _zx8081; } @@ -24,16 +20,10 @@ self = [super initWithMachine:machine]; if(self) { _zx8081.reset(machine); - _zx8081->set_rom(ZX8081::ROMType::ZX80, [self rom:@"zx80"].stdVector8); - _zx8081->set_rom(ZX8081::ROMType::ZX81, [self rom:@"zx81"].stdVector8); } return self; } -- (NSData *)rom:(NSString *)name { - return [[NSBundle mainBundle] dataForResource:name withExtension:@"rom" subdirectory:@"ROMImages/ZX8081"]; -} - - (NSString *)userDefaultsPrefix { return @"zx8081"; } #pragma mark - Options diff --git a/OSBindings/SDL/main.cpp b/OSBindings/SDL/main.cpp new file mode 100644 index 000000000..2363da84b --- /dev/null +++ b/OSBindings/SDL/main.cpp @@ -0,0 +1,276 @@ +// +// main.cpp +// Clock Signal +// +// Created by Thomas Harte on 04/11/2017. +// Copyright © 2017 Thomas Harte. All rights reserved. +// + +#include +#include +#include + +#include + +#include "../../StaticAnalyser/StaticAnalyser.hpp" +#include "../../Machines/Utility/MachineForTarget.hpp" + +#include "../../Machines/ConfigurationTarget.hpp" +#include "../../Machines/CRTMachine.hpp" + +#include "../../Concurrency/BestEffortUpdater.hpp" + +namespace { + +struct CRTMachineDelegate: public CRTMachine::Machine::Delegate { + void machine_did_change_clock_rate(CRTMachine::Machine *machine) { + best_effort_updater->set_clock_rate(machine->get_clock_rate()); + } + + void machine_did_change_clock_is_unlimited(CRTMachine::Machine *machine) { + } + + Concurrency::BestEffortUpdater *best_effort_updater; +}; + +struct BestEffortUpdaterDelegate: public Concurrency::BestEffortUpdater::Delegate { + void update(Concurrency::BestEffortUpdater *updater, int cycles, bool did_skip_previous_update) { + machine->crt_machine()->run_for(Cycles(cycles)); + } + + Machine::DynamicMachine *machine; +}; + +// This is set to a relatively large number for now. +const int AudioBufferSize = 1024; + +struct SpeakerDelegate: public Outputs::Speaker::Delegate { + void speaker_did_complete_samples(Outputs::Speaker *speaker, const std::vector &buffer) { + if(SDL_GetQueuedAudioSize(audio_device) < AudioBufferSize*3) + SDL_QueueAudio(audio_device, reinterpret_cast(buffer.data()), static_cast(buffer.size() * sizeof(uint16_t))); + updater->update(); + } + + SDL_AudioDeviceID audio_device; + Concurrency::BestEffortUpdater *updater; +}; + +bool KeyboardKeyForSDLScancode(SDL_Keycode scancode, Inputs::Keyboard::Key &key) { +#define BIND(x, y) case SDL_SCANCODE_##x: key = Inputs::Keyboard::Key::y; break; + switch(scancode) { + default: return false; + + BIND(F1, F1) BIND(F2, F2) BIND(F3, F3) BIND(F4, F4) BIND(F5, F5) BIND(F6, F6) + BIND(F7, F7) BIND(F8, F8) BIND(F9, F9) BIND(F10, F10) BIND(F11, F11) BIND(F12, F12) + + BIND(1, k1) BIND(2, k2) BIND(3, k3) BIND(4, k4) BIND(5, k5) + BIND(6, k6) BIND(7, k7) BIND(8, k8) BIND(9, k9) BIND(0, k0) + + BIND(Q, Q) BIND(W, W) BIND(E, E) BIND(R, R) BIND(T, T) + BIND(Y, Y) BIND(U, U) BIND(I, I) BIND(O, O) BIND(P, P) + BIND(A, A) BIND(S, S) BIND(D, D) BIND(F, F) BIND(G, G) + BIND(H, H) BIND(J, J) BIND(K, K) BIND(L, L) + BIND(Z, Z) BIND(X, X) BIND(C, C) BIND(V, V) + BIND(B, B) BIND(N, N) BIND(M, M) + + BIND(KP_7, KeyPad7) BIND(KP_8, KeyPad8) BIND(KP_9, KeyPad9) + BIND(KP_4, KeyPad4) BIND(KP_5, KeyPad5) BIND(KP_6, KeyPad6) + BIND(KP_1, KeyPad1) BIND(KP_2, KeyPad2) BIND(KP_3, KeyPad3) + BIND(KP_0, KeyPad0) + + BIND(ESCAPE, Escape) + + BIND(PRINTSCREEN, PrintScreen) BIND(SCROLLLOCK, ScrollLock) BIND(PAUSE, Pause) + + BIND(GRAVE, BackTick) BIND(MINUS, Hyphen) BIND(EQUALS, Equals) BIND(BACKSPACE, BackSpace) + + BIND(TAB, Tab) + BIND(LEFTBRACKET, OpenSquareBracket) BIND(RIGHTBRACKET, CloseSquareBracket) + BIND(BACKSLASH, BackSlash) + + BIND(CAPSLOCK, CapsLock) BIND(SEMICOLON, Semicolon) + BIND(APOSTROPHE, Quote) BIND(RETURN, Enter) + + BIND(LSHIFT, LeftShift) BIND(COMMA, Comma) BIND(PERIOD, FullStop) + BIND(SLASH, ForwardSlash) BIND(RSHIFT, RightShift) + + BIND(LCTRL, LeftControl) BIND(LALT, LeftOption) BIND(LGUI, LeftMeta) + BIND(SPACE, Space) + BIND(RCTRL, RightControl) BIND(RALT, RightOption) BIND(RGUI, RightMeta) + + BIND(LEFT, Left) BIND(RIGHT, Right) BIND(UP, Up) BIND(DOWN, Down) + + BIND(INSERT, Insert) BIND(HOME, Home) BIND(PAGEUP, PageUp) + BIND(DELETE, Delete) BIND(END, End) BIND(PAGEDOWN, PageDown) + + BIND(NUMLOCKCLEAR, NumLock) BIND(KP_DIVIDE, KeyPadSlash) BIND(KP_MULTIPLY, KeyPadAsterisk) + BIND(KP_PLUS, KeyPadPlus) BIND(KP_MINUS, KeyPadMinus) BIND(KP_ENTER, KeyPadEnter) + BIND(KP_DECIMAL, KeyPadDecimalPoint) + BIND(KP_EQUALS, KeyPadEquals) + BIND(HELP, Help) + + // SDL doesn't seem to have scancodes for hash or keypad delete? + } +#undef BIND + return true; +} + +} + +int main(int argc, char *argv[]) { + SDL_Window *window = nullptr; + + // Perform a sanity check on arguments. + if(argc < 2) { + std::cerr << "Usage: " << argv[0] << " [file]" << std::endl; + return -1; + } + + // Determine the machine for the supplied file. + std::list targets = StaticAnalyser::GetTargets(argv[1]); + if(targets.empty()) { + std::cerr << "Cannot open " << argv[1] << std::endl; + return -1; + } + + Concurrency::BestEffortUpdater updater; + BestEffortUpdaterDelegate best_effort_updater_delegate; + CRTMachineDelegate crt_delegate; + SpeakerDelegate speaker_delegate; + + // Create and configure a machine. + std::unique_ptr<::Machine::DynamicMachine> machine(::Machine::MachineForTarget(targets.front())); + + updater.set_clock_rate(machine->crt_machine()->get_clock_rate()); + crt_delegate.best_effort_updater = &updater; + best_effort_updater_delegate.machine = machine.get(); + speaker_delegate.updater = &updater; + + machine->crt_machine()->set_delegate(&crt_delegate); + updater.set_delegate(&best_effort_updater_delegate); + + // Attempt to set up video and audio. + if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) { + std::cerr << "SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl; + return -1; + } + + // Ask for no depth buffer, a core profile and vsync-aligned rendering. + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetSwapInterval(1); + + window = SDL_CreateWindow( "Clock Signal", + SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, + 400, 300, + SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); + + if(!window) + { + std::cerr << "Could not create window" << std::endl; + return -1; + } + + SDL_GLContext gl_context = SDL_GL_CreateContext(window); + SDL_GL_MakeCurrent(window, gl_context); + + // For vanilla SDL purposes, assume system ROMs can be found in one of: + // + // /usr/local/share/CLK/[system]; or + // /usr/share/CLK/[system] + bool roms_loaded = 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)); + } + + return results; + }); + + if(!roms_loaded) { + std::cerr << "Could not find system ROMs; please install to /usr/local/share/CLK/ or /usr/share/CLK/" << std::endl; + return -1; + } + + machine->configuration_target()->configure_as_target(targets.front()); + + // Setup output, assuming a CRT machine for now, and prepare a best-effort updater. + machine->crt_machine()->setup_output(4.0 / 3.0); + machine->crt_machine()->get_crt()->set_output_gamma(2.2f); + + // For now, lie about audio output intentions. + auto speaker = machine->crt_machine()->get_speaker(); + if(speaker) { + // Create an audio pipe. + SDL_AudioSpec desired_audio_spec; + SDL_AudioSpec obtained_audio_spec; + + SDL_zero(desired_audio_spec); + desired_audio_spec.freq = 48000; // TODO: how can I get SDL to reveal the output rate of this machine? + desired_audio_spec.format = AUDIO_S16; + desired_audio_spec.channels = 1; + desired_audio_spec.samples = AudioBufferSize; + + speaker_delegate.audio_device = SDL_OpenAudioDevice(nullptr, 0, &desired_audio_spec, &obtained_audio_spec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); + + speaker->set_output_rate(obtained_audio_spec.freq, obtained_audio_spec.samples); + speaker->set_delegate(&speaker_delegate); + SDL_PauseAudioDevice(speaker_delegate.audio_device, 0); + } + + // Run the main event loop until the OS tells us to quit. + bool should_quit = false; + while(!should_quit) { + // Process all pending events. + SDL_Event event; + while(SDL_PollEvent(&event)) { + switch(event.type) { + case SDL_QUIT: should_quit = true; break; + + case SDL_KEYDOWN: + case SDL_KEYUP: + KeyboardMachine::Machine *keyboard_machine = machine->keyboard_machine(); + if(!keyboard_machine) break; + + Inputs::Keyboard::Key key = Inputs::Keyboard::Key::Space; + if(!KeyboardKeyForSDLScancode(event.key.keysym.scancode, key)) break; + keyboard_machine->get_keyboard().set_key_pressed(key, event.type == SDL_KEYDOWN); + break; + } + } + + // Display a new frame and wait for vsync. + updater.update(); + int width, height; + SDL_GetWindowSize(window, &width, &height); + machine->crt_machine()->get_crt()->draw_frame(static_cast(width), static_cast(height), false); + SDL_GL_SwapWindow(window); + } + + // Clean up. + SDL_DestroyWindow( window ); + SDL_Quit(); + + return 0; +} diff --git a/Outputs/Speaker.hpp b/Outputs/Speaker.hpp index 9eb18ce86..868fb5967 100644 --- a/Outputs/Speaker.hpp +++ b/Outputs/Speaker.hpp @@ -109,7 +109,7 @@ class Speaker { size_t buffer_in_progress_pointer_; size_t number_of_taps_, requested_number_of_taps_; bool coefficients_are_dirty_; - Delegate *delegate_; + Delegate *delegate_ = nullptr; float input_cycles_per_second_, output_cycles_per_second_;