1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-26 09:29:45 +00:00

Merge pull request #264 from TomHarte/SDLKiosk

SDL kiosk
This commit is contained in:
Thomas Harte 2017-11-07 22:44:48 -05:00 committed by GitHub
commit 09c855a659
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 1084 additions and 299 deletions

View File

@ -919,10 +919,30 @@ class ConcreteMachine:
}
// See header; provides the system ROMs.
void set_rom(ROMType type, std::vector<uint8_t> data) override final {
void set_rom(ROMType type, const std::vector<uint8_t> &data) override final {
roms_[static_cast<int>(type)] = data;
}
// Obtains the system ROMs.
bool set_rom_fetcher(const std::function<std::vector<std::unique_ptr<std::vector<uint8_t>>>(const std::string &machine, const std::vector<std::string> &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<ROMType>(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();

View File

@ -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<uint8_t> data) = 0;
virtual void set_rom(ROMType type, const std::vector<uint8_t> &data) = 0;
};
}

View File

@ -135,42 +135,27 @@ class TIA {
// objects
template<class T> 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> {
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<HorizontalRun> {
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

View File

@ -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<Outputs::CRT::CRT> get_crt() = 0;

View File

@ -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<uint8_t> &rom);
bool set_rom_fetcher(const std::function<std::vector<std::unique_ptr<std::vector<uint8_t>>>(const std::string &machine, const std::vector<std::string> &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<Storage::Disk::Disk> disk);
private:
Personality personality_;
};
}

View File

@ -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<uint8_t> &rom) {
assert(rom.size() == sizeof(rom_));
memcpy(rom_, rom.data(), std::min(sizeof(rom_), rom.size()));
bool Machine::set_rom_fetcher(const std::function<std::vector<std::unique_ptr<std::vector<uint8_t>>>(const std::string &machine, const std::vector<std::string> &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<Storage::Disk::Disk> disk) {

View File

@ -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<uint8_t> &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<std::vector<std::unique_ptr<std::vector<uint8_t>>>(const std::string &machine, const std::vector<std::string> &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<Commodore::Vic20::Vic6560>::OutputMode::NTSC);
mos6560_->set_clock_rate(1022727);
}
} else {
// PAL
set_clock_rate(1108404);
if(mos6560_) {
mos6560_->set_output_mode(MOS::MOS6560<Commodore::Vic20::Vic6560>::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<Commodore::Vic20::Vic6560>::OutputMode::PAL);
mos6560_->set_clock_rate(1108404);
}
break;
case NTSC:
set_clock_rate(1022727);
if(mos6560_) {
mos6560_->set_output_mode(MOS::MOS6560<Commodore::Vic20::Vic6560>::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<ConcreteMachine, false> m6502_;
uint8_t character_rom_[0x1000];
uint8_t basic_rom_[0x2000];
uint8_t kernel_rom_[0x2000];
std::vector<uint8_t> roms_[9];
std::vector<uint8_t> character_rom_;
std::vector<uint8_t> basic_rom_;
std::vector<uint8_t> 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<uint8_t> drive_rom_;
std::function<std::vector<std::unique_ptr<std::vector<uint8_t>>>(const std::string &machine, const std::vector<std::string> &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<std::unique_ptr<Inputs::Joystick>> 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();
}
}
};
}

View File

@ -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<uint8_t> to collapse length and data.
virtual void set_rom(ROMSlot slot, const std::vector<uint8_t> &data) = 0;
/// Sets the memory size of this Vic-20.
virtual void set_memory_size(MemorySize size) = 0;

View File

@ -39,11 +39,12 @@ class ConcreteMachine:
set_clock_rate(2000000);
}
void set_rom(ROMSlot slot, std::vector<uint8_t> data, bool is_writeable) override final {
void set_rom(ROMSlot slot, const std::vector<uint8_t> &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<size_t>(16384), data.size()));
}
// Obtains the system ROMs.
bool set_rom_fetcher(const std::function<std::vector<std::unique_ptr<std::vector<uint8_t>>>(const std::string &machine, const std::vector<std::string> &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<uint8_t>(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<uint8_t> dfs_, adfs_;
std::vector<uint8_t> dfs_, adfs1_, adfs2_;
// Paging
ROMSlot active_rom_ = ROMSlot::ROMSlot0;

View File

@ -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<uint8_t> data, bool is_writeable) = 0;
virtual void set_rom(ROMSlot slot, const std::vector<uint8_t> &data, bool is_writeable) = 0;
/// Enables or disables turbo-speed tape loading.
virtual void set_use_fast_tape_hack(bool activate) = 0;

View File

@ -203,6 +203,24 @@ class ConcreteMachine:
}
}
// Obtains the system ROMs.
bool set_rom_fetcher(const std::function<std::vector<std::unique_ptr<std::vector<uint8_t>>>(const std::string &machine, const std::vector<std::string> &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<ROM>(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);

View File

@ -19,7 +19,7 @@
namespace Oric {
enum ROM {
BASIC10, BASIC11, Microdisc, Colour
BASIC10 = 0, BASIC11, Microdisc, Colour
};
/*!

27
Machines/ROMMachine.hpp Normal file
View File

@ -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 <functional>
#include <memory>
#include <vector>
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<std::vector<std::unique_ptr<std::vector<uint8_t>>>(const std::string &machine, const std::vector<std::string> &names)> &rom_with_name) { return true; }
};
}
#endif /* ROMMachine_h */

View File

@ -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<typename T> class TypedDynamicMachine: public ::Machine::DynamicMachine {
public:
TypedDynamicMachine(T *machine) : machine_(machine) {}
ConfigurationTarget::Machine *configuration_target() {
return dynamic_cast<ConfigurationTarget::Machine *>(machine_.get());
}
CRTMachine::Machine *crt_machine() {
return dynamic_cast<CRTMachine::Machine *>(machine_.get());
}
JoystickMachine::Machine *joystick_machine() {
return dynamic_cast<JoystickMachine::Machine *>(machine_.get());
}
KeyboardMachine::Machine *keyboard_machine() {
return dynamic_cast<KeyboardMachine::Machine *>(machine_.get());
}
private:
std::unique_ptr<T> machine_;
};
}
::Machine::DynamicMachine *::Machine::MachineForTarget(const StaticAnalyser::Target &target) {
switch(target.machine) {
case StaticAnalyser::Target::AmstradCPC: return new TypedDynamicMachine<AmstradCPC::Machine>(AmstradCPC::Machine::AmstradCPC());
case StaticAnalyser::Target::Atari2600: return new TypedDynamicMachine<Atari2600::Machine>(Atari2600::Machine::Atari2600());
case StaticAnalyser::Target::Electron: return new TypedDynamicMachine<Electron::Machine>(Electron::Machine::Electron());
case StaticAnalyser::Target::Oric: return new TypedDynamicMachine<Oric::Machine>(Oric::Machine::Oric());
case StaticAnalyser::Target::Vic20: return new TypedDynamicMachine<Commodore::Vic20::Machine>(Commodore::Vic20::Machine::Vic20());
case StaticAnalyser::Target::ZX8081: return new TypedDynamicMachine<ZX8081::Machine>(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";
}
}

View File

@ -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 <string>
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 */

View File

@ -290,13 +290,30 @@ template<bool is_zx81> class ConcreteMachine:
Utility::TypeRecipient::set_typer_for_string(string, std::move(mapper));
}
void set_rom(ROMType type, std::vector<uint8_t> data) override final {
void set_rom(ROMType type, const std::vector<uint8_t> &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<std::vector<std::unique_ptr<std::vector<uint8_t>>>(const std::string &machine, const std::vector<std::string> &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<ROMType>(index), *data);
}
return true;
}
#pragma mark - Keyboard
void set_key_state(uint16_t key, bool isPressed) override final {

View File

@ -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<uint8_t> data) = 0;
virtual void set_rom(ROMType type, const std::vector<uint8_t> &data) = 0;
virtual void set_use_fast_tape_hack(bool activate) = 0;
virtual void set_tape_is_playing(bool is_playing) = 0;

View File

@ -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 = "<group>"; };
4B046DC31CFE651500E9E45E /* CRTMachine.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CRTMachine.hpp; sourceTree = "<group>"; };
4B049CDC1DA3C82F00322067 /* BCDTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BCDTest.swift; sourceTree = "<group>"; };
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 = "<group>"; };
4B055ABE1FAE98000060FFFF /* MachineForTarget.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MachineForTarget.cpp; sourceTree = "<group>"; };
4B055ABF1FAE98000060FFFF /* MachineForTarget.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MachineForTarget.hpp; sourceTree = "<group>"; };
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 = "<group>"; };
4B08A2761EE39306008B7065 /* TestMachine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestMachine.h; sourceTree = "<group>"; };
4B08A2771EE39306008B7065 /* TestMachine.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TestMachine.mm; sourceTree = "<group>"; };
@ -1078,6 +1210,7 @@
4BD5F1931D13528900631CD1 /* CSBestEffortUpdater.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSBestEffortUpdater.h; path = Updater/CSBestEffortUpdater.h; sourceTree = "<group>"; };
4BD5F1941D13528900631CD1 /* CSBestEffortUpdater.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = CSBestEffortUpdater.mm; path = Updater/CSBestEffortUpdater.mm; sourceTree = "<group>"; };
4BD9137D1F311BC5009BCF85 /* i8255.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = i8255.hpp; path = 8255/i8255.hpp; sourceTree = "<group>"; };
4BDCC5F81FB27A5E001220C5 /* ROMMachine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ROMMachine.hpp; sourceTree = "<group>"; };
4BDDBA981EF3451200347E61 /* Z80MachineCycleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Z80MachineCycleTests.swift; sourceTree = "<group>"; };
4BE77A2C1D84ADFB00BC3827 /* File.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = File.cpp; path = ../../StaticAnalyser/Commodore/File.cpp; sourceTree = "<group>"; };
4BE77A2D1D84ADFB00BC3827 /* File.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = File.hpp; path = ../../StaticAnalyser/Commodore/File.hpp; sourceTree = "<group>"; };
@ -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 = "<group>";
};
4B055A7B1FAE84A50060FFFF /* SDL */ = {
isa = PBXGroup;
children = (
4B055A7C1FAE84A50060FFFF /* main.cpp */,
);
name = SDL;
path = ../SDL;
sourceTree = "<group>";
};
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 = "<group>";
@ -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 = (

View File

@ -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"

View File

@ -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<std::string> &names) -> std::vector<std::unique_ptr<std::vector<uint8_t>>> {
NSString *subDirectory = [@"ROMImages/" stringByAppendingString:[NSString stringWithUTF8String:machine.c_str()]];
std::vector<std::unique_ptr<std::vector<uint8_t>>> 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<std::vector<uint8_t>> data(new std::vector<uint8_t>);
*data = fileData.stdVector8;
results.emplace_back(std::move(data));
}
}
return results;
});
}
return self;
}

View File

@ -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::Machine> _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

View File

@ -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::Machine> _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

View File

@ -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::Machine> _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 {

View File

@ -11,11 +11,11 @@
typedef NS_ENUM(NSInteger, CSVic20Country)
{
CSVic20CountryAmerican,
CSVic20CountryDanish,
CSVic20CountryEuropean,
CSVic20CountryJapanese,
CSVic20CountrySwedish,
CSVic20CountryAmerican
CSVic20CountrySwedish
};
typedef NS_ENUM(NSInteger, CSVic20MemorySize)

View File

@ -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]];
}
}

View File

@ -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::Machine> _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

276
OSBindings/SDL/main.cpp Normal file
View File

@ -0,0 +1,276 @@
//
// main.cpp
// Clock Signal
//
// Created by Thomas Harte on 04/11/2017.
// Copyright © 2017 Thomas Harte. All rights reserved.
//
#include <iostream>
#include <memory>
#include <cstdio>
#include <SDL2/SDL.h>
#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<int16_t> &buffer) {
if(SDL_GetQueuedAudioSize(audio_device) < AudioBufferSize*3)
SDL_QueueAudio(audio_device, reinterpret_cast<const void *>(buffer.data()), static_cast<Uint32>(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<StaticAnalyser::Target> 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<std::string> &names) -> std::vector<std::unique_ptr<std::vector<uint8_t>>> {
std::vector<std::unique_ptr<std::vector<uint8_t>>> 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<std::vector<uint8_t>> data(new std::vector<uint8_t>);
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<unsigned int>(width), static_cast<unsigned int>(height), false);
SDL_GL_SwapWindow(window);
}
// Clean up.
SDL_DestroyWindow( window );
SDL_Quit();
return 0;
}

View File

@ -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_;