1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-25 18:30:21 +00:00

Merge pull request #800 from TomHarte/QtProject

UNREADY. Adds a provisional Qt target.
This commit is contained in:
Thomas Harte 2020-07-06 22:33:39 -04:00 committed by GitHub
commit 2230ac6c38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
177 changed files with 3702 additions and 495 deletions

View File

@ -24,13 +24,13 @@ namespace Activity {
class Observer { class Observer {
public: public:
/// Announces to the receiver that there is an LED of name @c name. /// Announces to the receiver that there is an LED of name @c name.
virtual void register_led(const std::string &name) {} virtual void register_led([[maybe_unused]] const std::string &name) {}
/// Announces to the receiver that there is a drive of name @c name. /// Announces to the receiver that there is a drive of name @c name.
virtual void register_drive(const std::string &name) {} virtual void register_drive([[maybe_unused]] const std::string &name) {}
/// Informs the receiver of the new state of the LED with name @c name. /// Informs the receiver of the new state of the LED with name @c name.
virtual void set_led_status(const std::string &name, bool lit) {} virtual void set_led_status([[maybe_unused]] const std::string &name, [[maybe_unused]] bool lit) {}
enum class DriveEvent { enum class DriveEvent {
StepNormal, StepNormal,
@ -39,10 +39,10 @@ class Observer {
}; };
/// Informs the receiver that the named event just occurred for the drive with name @c name. /// Informs the receiver that the named event just occurred for the drive with name @c name.
virtual void announce_drive_event(const std::string &name, DriveEvent event) {} virtual void announce_drive_event([[maybe_unused]] const std::string &name, [[maybe_unused]] DriveEvent event) {}
/// Informs the receiver of the motor-on status of the drive with name @c name. /// Informs the receiver of the motor-on status of the drive with name @c name.
virtual void set_drive_motor_status(const std::string &name, bool is_on) {} virtual void set_drive_motor_status([[maybe_unused]] const std::string &name, [[maybe_unused]] bool is_on) {}
}; };
} }

View File

@ -23,8 +23,8 @@ void MultiInterface<MachineType>::perform_parallel(const std::function<void(Mach
std::condition_variable condition; std::condition_variable condition;
std::mutex mutex; std::mutex mutex;
{ {
std::lock_guard<decltype(machines_mutex_)> machines_lock(machines_mutex_); std::lock_guard machines_lock(machines_mutex_);
std::lock_guard<std::mutex> lock(mutex); std::lock_guard lock(mutex);
outstanding_machines = machines_.size(); outstanding_machines = machines_.size();
for(std::size_t index = 0; index < machines_.size(); ++index) { for(std::size_t index = 0; index < machines_.size(); ++index) {
@ -32,20 +32,20 @@ void MultiInterface<MachineType>::perform_parallel(const std::function<void(Mach
queues_[index].enqueue([&mutex, &condition, machine, function, &outstanding_machines]() { queues_[index].enqueue([&mutex, &condition, machine, function, &outstanding_machines]() {
if(machine) function(machine); if(machine) function(machine);
std::lock_guard<std::mutex> lock(mutex); std::lock_guard lock(mutex);
outstanding_machines--; outstanding_machines--;
condition.notify_all(); condition.notify_all();
}); });
} }
} }
std::unique_lock<std::mutex> lock(mutex); std::unique_lock lock(mutex);
condition.wait(lock, [&outstanding_machines] { return !outstanding_machines; }); condition.wait(lock, [&outstanding_machines] { return !outstanding_machines; });
} }
template <typename MachineType> template <typename MachineType>
void MultiInterface<MachineType>::perform_serial(const std::function<void(MachineType *)> &function) { void MultiInterface<MachineType>::perform_serial(const std::function<void(MachineType *)> &function) {
std::lock_guard<decltype(machines_mutex_)> machines_lock(machines_mutex_); std::lock_guard machines_lock(machines_mutex_);
for(const auto &machine: machines_) { for(const auto &machine: machines_) {
const auto typed_machine = ::Machine::get<MachineType>(*machine.get()); const auto typed_machine = ::Machine::get<MachineType>(*machine.get());
if(typed_machine) function(typed_machine); if(typed_machine) function(typed_machine);
@ -56,13 +56,13 @@ void MultiInterface<MachineType>::perform_serial(const std::function<void(Machin
void MultiScanProducer::set_scan_target(Outputs::Display::ScanTarget *scan_target) { void MultiScanProducer::set_scan_target(Outputs::Display::ScanTarget *scan_target) {
scan_target_ = scan_target; scan_target_ = scan_target;
std::lock_guard<decltype(machines_mutex_)> machines_lock(machines_mutex_); std::lock_guard machines_lock(machines_mutex_);
const auto machine = machines_.front()->scan_producer(); const auto machine = machines_.front()->scan_producer();
if(machine) machine->set_scan_target(scan_target); if(machine) machine->set_scan_target(scan_target);
} }
Outputs::Display::ScanStatus MultiScanProducer::get_scan_status() const { Outputs::Display::ScanStatus MultiScanProducer::get_scan_status() const {
std::lock_guard<decltype(machines_mutex_)> machines_lock(machines_mutex_); std::lock_guard machines_lock(machines_mutex_);
const auto machine = machines_.front()->scan_producer(); const auto machine = machines_.front()->scan_producer();
if(machine) return machine->get_scan_status(); if(machine) return machine->get_scan_status();
return Outputs::Display::ScanStatus(); return Outputs::Display::ScanStatus();
@ -74,7 +74,7 @@ void MultiScanProducer::did_change_machine_order() {
perform_serial([](MachineTypes::ScanProducer *machine) { perform_serial([](MachineTypes::ScanProducer *machine) {
machine->set_scan_target(nullptr); machine->set_scan_target(nullptr);
}); });
std::lock_guard<decltype(machines_mutex_)> machines_lock(machines_mutex_); std::lock_guard machines_lock(machines_mutex_);
const auto machine = machines_.front()->scan_producer(); const auto machine = machines_.front()->scan_producer();
if(machine) machine->set_scan_target(scan_target_); if(machine) machine->set_scan_target(scan_target_);
} }

View File

@ -69,7 +69,7 @@ class MultiTimedMachine: public MultiInterface<MachineTypes::TimedMachine>, publ
void run_for(Time::Seconds duration) final; void run_for(Time::Seconds duration) final;
private: private:
void run_for(const Cycles cycles) final {} void run_for(const Cycles) final {}
Delegate *delegate_ = nullptr; Delegate *delegate_ = nullptr;
}; };

View File

@ -67,7 +67,7 @@ void MultiSpeaker::set_delegate(Outputs::Speaker::Speaker::Delegate *delegate) {
void MultiSpeaker::speaker_did_complete_samples(Speaker *speaker, const std::vector<int16_t> &buffer) { void MultiSpeaker::speaker_did_complete_samples(Speaker *speaker, const std::vector<int16_t> &buffer) {
if(!delegate_) return; if(!delegate_) return;
{ {
std::lock_guard<std::mutex> lock_guard(front_speaker_mutex_); std::lock_guard lock_guard(front_speaker_mutex_);
if(speaker != front_speaker_) return; if(speaker != front_speaker_) return;
} }
did_complete_samples(this, buffer, stereo_output_); did_complete_samples(this, buffer, stereo_output_);
@ -76,7 +76,7 @@ void MultiSpeaker::speaker_did_complete_samples(Speaker *speaker, const std::vec
void MultiSpeaker::speaker_did_change_input_clock(Speaker *speaker) { void MultiSpeaker::speaker_did_change_input_clock(Speaker *speaker) {
if(!delegate_) return; if(!delegate_) return;
{ {
std::lock_guard<std::mutex> lock_guard(front_speaker_mutex_); std::lock_guard lock_guard(front_speaker_mutex_);
if(speaker != front_speaker_) return; if(speaker != front_speaker_) return;
} }
delegate_->speaker_did_change_input_clock(this); delegate_->speaker_did_change_input_clock(this);
@ -84,7 +84,7 @@ void MultiSpeaker::speaker_did_change_input_clock(Speaker *speaker) {
void MultiSpeaker::set_new_front_machine(::Machine::DynamicMachine *machine) { void MultiSpeaker::set_new_front_machine(::Machine::DynamicMachine *machine) {
{ {
std::lock_guard<std::mutex> lock_guard(front_speaker_mutex_); std::lock_guard lock_guard(front_speaker_mutex_);
front_speaker_ = machine->audio_producer()->get_speaker(); front_speaker_ = machine->audio_producer()->get_speaker();
} }
if(delegate_) { if(delegate_) {

View File

@ -60,7 +60,7 @@ bool MultiMachine::would_collapse(const std::vector<std::unique_ptr<DynamicMachi
} }
void MultiMachine::did_run_machines(MultiTimedMachine *) { void MultiMachine::did_run_machines(MultiTimedMachine *) {
std::lock_guard<decltype(machines_mutex_)> machines_lock(machines_mutex_); std::lock_guard machines_lock(machines_mutex_);
#ifndef NDEBUG #ifndef NDEBUG
for(const auto &machine: machines_) { for(const auto &machine: machines_) {
auto timed_machine = machine->timed_machine(); auto timed_machine = machine->timed_machine();

View File

@ -57,7 +57,7 @@ static std::vector<std::shared_ptr<Storage::Cartridge::Cartridge>>
return acorn_cartridges; return acorn_cartridges;
} }
Analyser::Static::TargetList Analyser::Static::Acorn::GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms) { Analyser::Static::TargetList Analyser::Static::Acorn::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
auto target = std::make_unique<Target>(); auto target = std::make_unique<Target>();
target->confidence = 0.5; // TODO: a proper estimation target->confidence = 0.5; // TODO: a proper estimation
target->has_dfs = false; target->has_dfs = false;

View File

@ -179,7 +179,7 @@ static bool CheckBootSector(const std::shared_ptr<Storage::Disk::Disk> &disk, co
return false; return false;
} }
Analyser::Static::TargetList Analyser::Static::AmstradCPC::GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms) { Analyser::Static::TargetList Analyser::Static::AmstradCPC::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
TargetList destination; TargetList destination;
auto target = std::make_unique<Target>(); auto target = std::make_unique<Target>();
target->confidence = 0.5; target->confidence = 0.5;

View File

@ -9,7 +9,7 @@
#include "StaticAnalyser.hpp" #include "StaticAnalyser.hpp"
#include "Target.hpp" #include "Target.hpp"
Analyser::Static::TargetList Analyser::Static::AppleII::GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms) { Analyser::Static::TargetList Analyser::Static::AppleII::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
auto target = std::make_unique<Target>(); auto target = std::make_unique<Target>();
target->media = media; target->media = media;

View File

@ -88,7 +88,7 @@ static void DeterminePagingFor8kCartridge(Target &target, const Storage::Cartrid
else if(tigervision_access_count > atari_access_count) target.paging_model = Target::PagingModel::Tigervision; else if(tigervision_access_count > atari_access_count) target.paging_model = Target::PagingModel::Tigervision;
} }
static void DeterminePagingFor16kCartridge(Target &target, const Storage::Cartridge::Cartridge::Segment &segment, const Analyser::Static::MOS6502::Disassembly &disassembly) { static void DeterminePagingFor16kCartridge(Target &target, const Storage::Cartridge::Cartridge::Segment &, const Analyser::Static::MOS6502::Disassembly &disassembly) {
// Make an assumption that this is the Atari paging model. // Make an assumption that this is the Atari paging model.
target.paging_model = Target::PagingModel::Atari16k; target.paging_model = Target::PagingModel::Atari16k;
@ -108,7 +108,7 @@ static void DeterminePagingFor16kCartridge(Target &target, const Storage::Cartri
if(mnetwork_access_count > atari_access_count) target.paging_model = Target::PagingModel::MNetwork; if(mnetwork_access_count > atari_access_count) target.paging_model = Target::PagingModel::MNetwork;
} }
static void DeterminePagingFor64kCartridge(Target &target, const Storage::Cartridge::Cartridge::Segment &segment, const Analyser::Static::MOS6502::Disassembly &disassembly) { static void DeterminePagingFor64kCartridge(Target &target, const Storage::Cartridge::Cartridge::Segment &, const Analyser::Static::MOS6502::Disassembly &disassembly) {
// Make an assumption that this is a Tigervision if there is a write to 3F. // Make an assumption that this is a Tigervision if there is a write to 3F.
target.paging_model = target.paging_model =
(disassembly.external_stores.find(0x3f) != disassembly.external_stores.end()) ? (disassembly.external_stores.find(0x3f) != disassembly.external_stores.end()) ?
@ -177,7 +177,7 @@ static void DeterminePagingForCartridge(Target &target, const Storage::Cartridge
} }
} }
Analyser::Static::TargetList Analyser::Static::Atari2600::GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms) { Analyser::Static::TargetList Analyser::Static::Atari2600::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
// TODO: sanity checking; is this image really for an Atari 2600? // TODO: sanity checking; is this image really for an Atari 2600?
auto target = std::make_unique<Target>(); auto target = std::make_unique<Target>();
target->confidence = 0.5; target->confidence = 0.5;

View File

@ -9,7 +9,7 @@
#include "StaticAnalyser.hpp" #include "StaticAnalyser.hpp"
#include "Target.hpp" #include "Target.hpp"
Analyser::Static::TargetList Analyser::Static::AtariST::GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms) { Analyser::Static::TargetList Analyser::Static::AtariST::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
// This analyser can comprehend disks and mass-storage devices only. // This analyser can comprehend disks and mass-storage devices only.
if(media.disks.empty()) return {}; if(media.disks.empty()) return {};

View File

@ -52,7 +52,7 @@ static std::vector<std::shared_ptr<Storage::Cartridge::Cartridge>>
return coleco_cartridges; return coleco_cartridges;
} }
Analyser::Static::TargetList Analyser::Static::Coleco::GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms) { Analyser::Static::TargetList Analyser::Static::Coleco::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
TargetList targets; TargetList targets;
auto target = std::make_unique<Target>(Machine::ColecoVision); auto target = std::make_unique<Target>(Machine::ColecoVision);
target->confidence = 1.0f - 1.0f / 32768.0f; target->confidence = 1.0f - 1.0f / 32768.0f;

View File

@ -42,7 +42,7 @@ static std::vector<std::shared_ptr<Storage::Cartridge::Cartridge>>
return vic20_cartridges; return vic20_cartridges;
} }
Analyser::Static::TargetList Analyser::Static::Commodore::GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms) { Analyser::Static::TargetList Analyser::Static::Commodore::GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType) {
TargetList destination; TargetList destination;
auto target = std::make_unique<Target>(); auto target = std::make_unique<Target>();
@ -94,6 +94,7 @@ Analyser::Static::TargetList Analyser::Static::Commodore::GetTargets(const Media
switch(files.front().starting_address) { switch(files.front().starting_address) {
default: default:
LOG("Unrecognised loading address for Commodore program: " << PADHEX(4) << files.front().starting_address); LOG("Unrecognised loading address for Commodore program: " << PADHEX(4) << files.front().starting_address);
[[fallthrough]];
case 0x1001: case 0x1001:
memory_model = Target::MemoryModel::Unexpanded; memory_model = Target::MemoryModel::Unexpanded;
break; break;

View File

@ -31,7 +31,7 @@ Analyser::Static::Target *AppleTarget(const Storage::Encodings::AppleGCR::Sector
return target; return target;
} }
Analyser::Static::Target *OricTarget(const Storage::Encodings::AppleGCR::Sector *sector_zero) { Analyser::Static::Target *OricTarget(const Storage::Encodings::AppleGCR::Sector *) {
using Target = Analyser::Static::Oric::Target; using Target = Analyser::Static::Oric::Target;
auto *const target = new Target; auto *const target = new Target;
target->rom = Target::ROM::Pravetz; target->rom = Target::ROM::Pravetz;
@ -42,7 +42,7 @@ Analyser::Static::Target *OricTarget(const Storage::Encodings::AppleGCR::Sector
} }
Analyser::Static::TargetList Analyser::Static::DiskII::GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms) { Analyser::Static::TargetList Analyser::Static::DiskII::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
// This analyser can comprehend disks only. // This analyser can comprehend disks only.
if(media.disks.empty()) return {}; if(media.disks.empty()) return {};

View File

@ -260,7 +260,7 @@ static Analyser::Static::TargetList CartridgeTargetsFrom(
return targets; return targets;
} }
Analyser::Static::TargetList Analyser::Static::MSX::GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms) { Analyser::Static::TargetList Analyser::Static::MSX::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
TargetList destination; TargetList destination;
// Append targets for any cartridges that look correct. // Append targets for any cartridges that look correct.

View File

@ -9,7 +9,7 @@
#include "StaticAnalyser.hpp" #include "StaticAnalyser.hpp"
#include "Target.hpp" #include "Target.hpp"
Analyser::Static::TargetList Analyser::Static::Macintosh::GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms) { Analyser::Static::TargetList Analyser::Static::Macintosh::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
// This analyser can comprehend disks and mass-storage devices only. // This analyser can comprehend disks and mass-storage devices only.
if(media.disks.empty() && media.mass_storage_devices.empty()) return {}; if(media.disks.empty() && media.mass_storage_devices.empty()) return {};

View File

@ -145,7 +145,7 @@ bool is_bd500(Storage::Encodings::MFM::Parser &parser) {
} }
Analyser::Static::TargetList Analyser::Static::Oric::GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms) { Analyser::Static::TargetList Analyser::Static::Oric::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
auto target = std::make_unique<Target>(); auto target = std::make_unique<Target>();
target->confidence = 0.5; target->confidence = 0.5;

View File

@ -13,7 +13,7 @@
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
Analyser::Static::TargetList Analyser::Static::Sega::GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms) { Analyser::Static::TargetList Analyser::Static::Sega::GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType) {
if(media.cartridges.empty()) if(media.cartridges.empty())
return {}; return {};

View File

@ -28,7 +28,7 @@ static std::vector<Storage::Data::ZX8081::File> GetFiles(const std::shared_ptr<S
return files; return files;
} }
Analyser::Static::TargetList Analyser::Static::ZX8081::GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms) { Analyser::Static::TargetList Analyser::Static::ZX8081::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType potential_platforms) {
TargetList destination; TargetList destination;
if(!media.tapes.empty()) { if(!media.tapes.empty()) {
std::vector<Storage::Data::ZX8081::File> files = GetFiles(media.tapes.front()); std::vector<Storage::Data::ZX8081::File> files = GetFiles(media.tapes.front());

View File

@ -176,7 +176,6 @@ class Cycles: public WrappedInt<Cycles> {
public: public:
forceinline constexpr Cycles(IntType l) noexcept : WrappedInt<Cycles>(l) {} forceinline constexpr Cycles(IntType l) noexcept : WrappedInt<Cycles>(l) {}
forceinline constexpr Cycles() noexcept : WrappedInt<Cycles>() {} forceinline constexpr Cycles() noexcept : WrappedInt<Cycles>() {}
forceinline constexpr Cycles(const Cycles &cycles) noexcept : WrappedInt<Cycles>(cycles.length_) {}
private: private:
friend WrappedInt; friend WrappedInt;
@ -198,7 +197,6 @@ class HalfCycles: public WrappedInt<HalfCycles> {
forceinline constexpr HalfCycles() noexcept : WrappedInt<HalfCycles>() {} forceinline constexpr HalfCycles() noexcept : WrappedInt<HalfCycles>() {}
forceinline constexpr HalfCycles(const Cycles &cycles) noexcept : WrappedInt<HalfCycles>(cycles.as_integral() * 2) {} forceinline constexpr HalfCycles(const Cycles &cycles) noexcept : WrappedInt<HalfCycles>(cycles.as_integral() * 2) {}
forceinline constexpr HalfCycles(const HalfCycles &half_cycles) noexcept : WrappedInt<HalfCycles>(half_cycles.length_) {}
/// @returns The number of whole cycles completely covered by this span of half cycles. /// @returns The number of whole cycles completely covered by this span of half cycles.
forceinline constexpr Cycles cycles() const { forceinline constexpr Cycles cycles() const {

View File

@ -0,0 +1,151 @@
//
// VSyncPredictor.hpp
// Clock Signal
//
// Created by Thomas Harte on 14/06/2020.
// Copyright © 2020 Thomas Harte. All rights reserved.
//
#ifndef VSyncPredictor_hpp
#define VSyncPredictor_hpp
#include "TimeTypes.hpp"
#include <cassert>
#include <cmath>
#include <cstdio>
namespace Time {
/*!
For platforms that provide no avenue into vsync tracking other than block-until-sync,
this class tracks: (i) how long frame draw takes; (ii) the apparent frame period; and
(iii) optionally, timer jitter; in order to suggest when you should next start drawing.
*/
class VSyncPredictor {
public:
/*!
Announces to the predictor that the work of producing an output frame has begun.
*/
void begin_redraw() {
redraw_begin_time_ = nanos_now();
}
/*!
Announces to the predictor that the work of producing an output frame has ended;
the predictor will use the amount of time between each begin/end pair to modify
its expectations as to how long it takes to draw a frame.
*/
void end_redraw() {
redraw_period_.post(nanos_now() - redraw_begin_time_);
}
/*!
Informs the predictor that a block-on-vsync has just ended, i.e. that the moment this
machine calls retrace is now. The predictor uses these notifications to estimate output
frame rate.
*/
void announce_vsync() {
const auto now = nanos_now();
if(last_vsync_) {
last_vsync_ += frame_duration_;
vsync_jitter_.post(last_vsync_ - now);
last_vsync_ = (last_vsync_ + now) >> 1;
} else {
last_vsync_ = now;
}
}
/*!
Sets the frame rate for the target display.
*/
void set_frame_rate(float rate) {
frame_duration_ = Nanos(1'000'000'000.0f / rate);
}
/*!
Adds a record of how much jitter was experienced in scheduling; these values will be
factored into the @c suggested_draw_time if supplied.
A positive number means the timer occurred late. A negative number means it occurred early.
*/
void add_timer_jitter(Time::Nanos jitter) {
timer_jitter_.post(jitter);
}
/*!
Announces to the vsync predictor that output is now paused. This ends frame period
calculations until the next announce_vsync() restarts frame-length counting.
*/
void pause() {
last_vsync_ = 0;
}
/*!
@return The time at which redrawing should begin, given the predicted frame period, how
long it appears to take to draw a frame and how much jitter there is in scheduling
(if those figures are being supplied).
*/
Nanos suggested_draw_time() {
const auto mean = redraw_period_.mean() - timer_jitter_.mean() - vsync_jitter_.mean();
const auto variance = redraw_period_.variance() + timer_jitter_.variance() + vsync_jitter_.variance();
// Permit three standard deviations from the mean, to cover 99.9% of cases.
const auto period = mean - Nanos(3.0f * sqrt(float(variance)));
assert(abs(period) < 10'000'000'000);
return last_vsync_ + period;
}
private:
class VarianceCollector {
public:
VarianceCollector(Time::Nanos default_value) {
sum_ = default_value * 128;
for(int c = 0; c < 128; ++c) {
history_[c] = default_value;
}
}
void post(Time::Nanos value) {
assert(abs(value) < 10'000'000'000); // 10 seconds is a very liberal maximum.
sum_ -= history_[write_pointer_];
sum_ += value;
history_[write_pointer_] = value;
write_pointer_ = (write_pointer_ + 1) & 127;
}
Time::Nanos mean() {
return sum_ / 128;
}
Time::Nanos variance() {
// I haven't yet come up with a better solution that calculating this
// in whole every time, given the way that the mean mutates.
Time::Nanos variance = 0;
for(int c = 0; c < 128; ++c) {
const auto difference = ((history_[c] * 128) - sum_) / 128;
variance += (difference * difference);
}
return variance / 128;
}
private:
Time::Nanos sum_;
Time::Nanos history_[128];
size_t write_pointer_ = 0;
};
Nanos redraw_begin_time_ = 0;
Nanos last_vsync_ = 0;
Nanos frame_duration_ = 1'000'000'000 / 60;
VarianceCollector vsync_jitter_{0};
VarianceCollector redraw_period_{1'000'000'000 / 60}; // A less convincing first guess.
VarianceCollector timer_jitter_{0}; // Seed at 0 in case this feature isn't used by the owner.
};
}
#endif /* VSyncPredictor_hpp */

View File

@ -498,7 +498,7 @@ void WD1770::posit_event(int new_event_type) {
if(get_crc_generator().get_value()) { if(get_crc_generator().get_value()) {
LOG("CRC error; terminating"); LOG("CRC error; terminating");
update_status([this] (Status &status) { update_status([] (Status &status) {
status.crc_error = true; status.crc_error = true;
}); });
goto wait_for_command; goto wait_for_command;
@ -816,8 +816,8 @@ void WD1770::update_status(std::function<void(Status &)> updater) {
if(status_.busy != old_status.busy) update_clocking_observer(); if(status_.busy != old_status.busy) update_clocking_observer();
} }
void WD1770::set_head_load_request(bool head_load) {} void WD1770::set_head_load_request(bool) {}
void WD1770::set_motor_on(bool motor_on) {} void WD1770::set_motor_on(bool) {}
void WD1770::set_head_loaded(bool head_loaded) { void WD1770::set_head_loaded(bool head_loaded) {
head_is_loaded_ = head_loaded; head_is_loaded_ = head_loaded;

View File

@ -31,6 +31,7 @@ class WD1770: public Storage::Disk::MFMController {
@param p The type of controller to emulate. @param p The type of controller to emulate.
*/ */
WD1770(Personality p); WD1770(Personality p);
virtual ~WD1770() {}
/// Sets the value of the double-density input; when @c is_double_density is @c true, reads and writes double-density format data. /// Sets the value of the double-density input; when @c is_double_density is @c true, reads and writes double-density format data.
using Storage::Disk::MFMController::set_is_double_density; using Storage::Disk::MFMController::set_is_double_density;

View File

@ -18,9 +18,14 @@ NCR5380::NCR5380(SCSI::Bus &bus, int clock_rate) :
clock_rate_(clock_rate) { clock_rate_(clock_rate) {
device_id_ = bus_.add_device(); device_id_ = bus_.add_device();
bus_.add_observer(this); bus_.add_observer(this);
// TODO: use clock rate and expected phase. This implementation currently
// provides only CPU-driven polling behaviour.
(void)clock_rate_;
(void)expected_phase_;
} }
void NCR5380::write(int address, uint8_t value, bool dma_acknowledge) { void NCR5380::write(int address, uint8_t value, bool) {
switch(address & 7) { switch(address & 7) {
case 0: case 0:
// LOG("[SCSI 0] Set current SCSI bus state to " << PADHEX(2) << int(value)); // LOG("[SCSI 0] Set current SCSI bus state to " << PADHEX(2) << int(value));
@ -128,7 +133,7 @@ void NCR5380::write(int address, uint8_t value, bool dma_acknowledge) {
} }
} }
uint8_t NCR5380::read(int address, bool dma_acknowledge) { uint8_t NCR5380::read(int address, bool) {
switch(address & 7) { switch(address & 7) {
case 0: case 0:
// LOG("[SCSI 0] Get current SCSI bus state: " << PADHEX(2) << (bus_.get_state() & 0xff)); // LOG("[SCSI 0] Get current SCSI bus state: " << PADHEX(2) << (bus_.get_state() & 0xff));
@ -258,6 +263,7 @@ void NCR5380::scsi_bus_did_change(SCSI::Bus *, SCSI::BusState new_state, double
case ExecutionState::WaitingForBusy: case ExecutionState::WaitingForBusy:
if(!(new_state & SCSI::Line::Busy) || time_since_change < SCSI::DeskewDelay) return; if(!(new_state & SCSI::Line::Busy) || time_since_change < SCSI::DeskewDelay) return;
state_ = ExecutionState::WatchingBusy; state_ = ExecutionState::WatchingBusy;
[[fallthrough]];
case ExecutionState::WatchingBusy: case ExecutionState::WatchingBusy:
if(!(new_state & SCSI::Line::Busy)) { if(!(new_state & SCSI::Line::Busy)) {

View File

@ -37,22 +37,22 @@ enum Line {
class PortHandler { class PortHandler {
public: public:
/// Requests the current input value of @c port from the port handler. /// Requests the current input value of @c port from the port handler.
uint8_t get_port_input(Port port) { return 0xff; } uint8_t get_port_input([[maybe_unused]] Port port) { return 0xff; }
/// Sets the current output value of @c port and provides @c direction_mask, indicating which pins are marked as output. /// Sets the current output value of @c port and provides @c direction_mask, indicating which pins are marked as output.
void set_port_output(Port port, uint8_t value, uint8_t direction_mask) {} void set_port_output([[maybe_unused]] Port port, [[maybe_unused]] uint8_t value, [[maybe_unused]] uint8_t direction_mask) {}
/// Sets the current logical output level for line @c line on port @c port. /// Sets the current logical output level for line @c line on port @c port.
void set_control_line_output(Port port, Line line, bool value) {} void set_control_line_output([[maybe_unused]] Port port, [[maybe_unused]] Line line, [[maybe_unused]] bool value) {}
/// Sets the current logical value of the interrupt line. /// Sets the current logical value of the interrupt line.
void set_interrupt_status(bool status) {} void set_interrupt_status([[maybe_unused]] bool status) {}
/// Provides a measure of time elapsed between other calls. /// Provides a measure of time elapsed between other calls.
void run_for(HalfCycles duration) {} void run_for([[maybe_unused]] HalfCycles duration) {}
/// Receives passed-on flush() calls from the 6522. /// Receives passed-on flush() calls from the 6522.
void flush() {} void flush() {}
}; };
/*! /*!

View File

@ -14,6 +14,6 @@ void IRQDelegatePortHandler::set_interrupt_delegate(Delegate *delegate) {
delegate_ = delegate; delegate_ = delegate;
} }
void IRQDelegatePortHandler::set_interrupt_status(bool new_status) { void IRQDelegatePortHandler::set_interrupt_status(bool) {
if(delegate_) delegate_->mos6522_did_change_interrupt_status(this); if(delegate_) delegate_->mos6522_did_change_interrupt_status(this);
} }

View File

@ -173,9 +173,11 @@ template <class T> class MOS6532 {
bool interrupt_line_ = false; bool interrupt_line_ = false;
// expected to be overridden // expected to be overridden
uint8_t get_port_input(int port) { return 0xff; } void set_port_output([[maybe_unused]] int port, [[maybe_unused]] uint8_t value, [[maybe_unused]] uint8_t output_mask) {}
void set_port_output(int port, uint8_t value, uint8_t output_mask) {} uint8_t get_port_input([[maybe_unused]] int port) {
void set_irq_line(bool new_value) {} return 0xff;
}
void set_irq_line(bool) {}
inline void evaluate_interrupts() { inline void evaluate_interrupts() {
interrupt_line_ = interrupt_line_ =

View File

@ -43,7 +43,7 @@ class AudioGenerator: public ::Outputs::Speaker::SampleSource {
}; };
struct BusHandler { struct BusHandler {
void perform_read(uint16_t address, uint8_t *pixel_data, uint8_t *colour_data) { void perform_read([[maybe_unused]] uint16_t address, [[maybe_unused]] uint8_t *pixel_data, [[maybe_unused]] uint8_t *colour_data) {
*pixel_data = 0xff; *pixel_data = 0xff;
*colour_data = 0xff; *colour_data = 0xff;
} }

View File

@ -148,7 +148,7 @@ uint8_t ACIA::parity(uint8_t value) {
return value ^ (parity_ == Parity::Even); return value ^ (parity_ == Parity::Even);
} }
bool ACIA::serial_line_did_produce_bit(Serial::Line *line, int bit) { bool ACIA::serial_line_did_produce_bit(Serial::Line *, int bit) {
// Shift this bit into the 11-bit input register; this is big enough to hold // Shift this bit into the 11-bit input register; this is big enough to hold
// the largest transmission symbol. // the largest transmission symbol.
++bits_received_; ++bits_received_;

View File

@ -9,13 +9,15 @@
#ifndef i8255_hpp #ifndef i8255_hpp
#define i8255_hpp #define i8255_hpp
#include <cstdint>
namespace Intel { namespace Intel {
namespace i8255 { namespace i8255 {
class PortHandler { class PortHandler {
public: public:
void set_value(int port, uint8_t value) {} void set_value([[maybe_unused]] int port, [[maybe_unused]] uint8_t value) {}
uint8_t get_value(int port) { return 0xff; } uint8_t get_value([[maybe_unused]] int port) { return 0xff; }
}; };
// TODO: Modes 1 and 2. // TODO: Modes 1 and 2.

View File

@ -80,6 +80,10 @@ i8272::i8272(BusHandler &bus_handler, Cycles clock_rate) :
Storage::Disk::MFMController(clock_rate), Storage::Disk::MFMController(clock_rate),
bus_handler_(bus_handler) { bus_handler_(bus_handler) {
posit_event(int(Event8272::CommandByte)); posit_event(int(Event8272::CommandByte));
// TODO: implement DMA, etc. I have a vague intention to implement the IBM PC
// one day, that should help to force that stuff.
(void)bus_handler_;
} }
ClockingHint::Preference i8272::preferred_clocking() const { ClockingHint::Preference i8272::preferred_clocking() const {
@ -880,13 +884,13 @@ bool i8272::seek_is_satisfied(int drive) {
(drives_[drive].target_head_position == -1 && get_drive().get_is_track_zero()); (drives_[drive].target_head_position == -1 && get_drive().get_is_track_zero());
} }
void i8272::set_dma_acknowledge(bool dack) { void i8272::set_dma_acknowledge(bool) {
} }
void i8272::set_terminal_count(bool tc) { void i8272::set_terminal_count(bool) {
} }
void i8272::set_data_input(uint8_t value) { void i8272::set_data_input(uint8_t) {
} }
uint8_t i8272::get_data_output() { uint8_t i8272::get_data_output() {

View File

@ -20,8 +20,9 @@ namespace i8272 {
class BusHandler { class BusHandler {
public: public:
virtual void set_dma_data_request(bool drq) {} virtual ~BusHandler() {}
virtual void set_interrupt(bool irq) {} virtual void set_dma_data_request([[maybe_unused]] bool drq) {}
virtual void set_interrupt([[maybe_unused]] bool irq) {}
}; };
class i8272 : public Storage::Disk::MFMController { class i8272 : public Storage::Disk::MFMController {
@ -45,7 +46,7 @@ class i8272 : public Storage::Disk::MFMController {
virtual void select_drive(int number) = 0; virtual void select_drive(int number) = 0;
private: private:
// The bus handler, for interrupt and DMA-driven usage. // The bus handler, for interrupt and DMA-driven usage. [TODO]
BusHandler &bus_handler_; BusHandler &bus_handler_;
std::unique_ptr<BusHandler> allocated_bus_handler_; std::unique_ptr<BusHandler> allocated_bus_handler_;

View File

@ -40,7 +40,7 @@ enum class TVStandard {
class Base { class Base {
public: public:
static const uint32_t palette_pack(uint8_t r, uint8_t g, uint8_t b) { static uint32_t palette_pack(uint8_t r, uint8_t g, uint8_t b) {
uint32_t result = 0; uint32_t result = 0;
uint8_t *const result_ptr = reinterpret_cast<uint8_t *>(&result); uint8_t *const result_ptr = reinterpret_cast<uint8_t *>(&result);
result_ptr[0] = r; result_ptr[0] = r;
@ -421,7 +421,8 @@ class Base {
*/ */
#define slot(n) \ #define slot(n) \
if(use_end && end == n) return;\ if(use_end && end == n) return; \
[[fallthrough]]; \
case n case n
#define external_slot(n) \ #define external_slot(n) \
@ -449,7 +450,7 @@ class Base {
/*********************************************** /***********************************************
TMS9918 Fetching Code TMS9918 Fetching Code
************************************************/ ************************************************/
template<bool use_end> void fetch_tms_refresh(int start, int end) { template<bool use_end> void fetch_tms_refresh(int start, int end) {
@ -693,7 +694,7 @@ class Base {
/*********************************************** /***********************************************
Master System Fetching Code Master System Fetching Code
************************************************/ ************************************************/
template<bool use_end> void fetch_sms(int start, int end) { template<bool use_end> void fetch_sms(int start, int end) {

View File

@ -30,7 +30,7 @@ class PortHandler {
@param port_b @c true if the input being queried is Port B. @c false if it is Port A. @param port_b @c true if the input being queried is Port B. @c false if it is Port A.
*/ */
virtual uint8_t get_port_input(bool port_b) { virtual uint8_t get_port_input([[maybe_unused]] bool port_b) {
return 0xff; return 0xff;
} }
@ -40,7 +40,7 @@ class PortHandler {
@param port_b @c true if the output being posted is Port B. @c false if it is Port A. @param port_b @c true if the output being posted is Port B. @c false if it is Port A.
@param value the value now being output. @param value the value now being output.
*/ */
virtual void set_port_output(bool port_b, uint8_t value) {} virtual void set_port_output([[maybe_unused]] bool port_b, [[maybe_unused]] uint8_t value) {}
}; };
/*! /*!

View File

@ -23,7 +23,7 @@ void Toggle::set_sample_volume_range(std::int16_t range) {
volume_ = range; volume_ = range;
} }
void Toggle::skip_samples(const std::size_t number_of_samples) {} void Toggle::skip_samples(std::size_t) {}
void Toggle::set_output(bool enabled) { void Toggle::set_output(bool enabled) {
if(is_enabled_ == enabled) return; if(is_enabled_ == enabled) return;

View File

@ -219,7 +219,7 @@ void DiskII::process_event(const Storage::Disk::Drive::Event &event) {
} }
} }
void DiskII::set_component_prefers_clocking(ClockingHint::Source *component, ClockingHint::Preference preference) { void DiskII::set_component_prefers_clocking(ClockingHint::Source *, ClockingHint::Preference) {
drive_is_sleeping_[0] = drives_[0].preferred_clocking() == ClockingHint::Preference::None; drive_is_sleeping_[0] = drives_[0].preferred_clocking() == ClockingHint::Preference::None;
drive_is_sleeping_[1] = drives_[1].preferred_clocking() == ClockingHint::Preference::None; drive_is_sleeping_[1] = drives_[1].preferred_clocking() == ClockingHint::Preference::None;
decide_clocking_preference(); decide_clocking_preference();

View File

@ -307,8 +307,8 @@ void IWM::run_for(const Cycles cycles) {
} else { } else {
shift_register_ = sense(); shift_register_ = sense();
} }
[[fallthrough]];
/* Deliberate fallthrough. */
default: default:
if(drive_is_rotating_[active_drive_]) drives_[active_drive_]->run_for(cycles); if(drive_is_rotating_[active_drive_]) drives_[active_drive_]->run_for(cycles);
break; break;

View File

@ -24,7 +24,7 @@ namespace Apple {
Defines the drive interface used by the IWM, derived from the external pinout as Defines the drive interface used by the IWM, derived from the external pinout as
per e.g. https://old.pinouts.ru/HD/MacExtDrive_pinout.shtml per e.g. https://old.pinouts.ru/HD/MacExtDrive_pinout.shtml
These are subclassed of Storage::Disk::Drive, so accept any disk the emulator supports, These are subclasses of Storage::Disk::Drive, so accept any disk the emulator supports,
and provide the usual read/write interface for on-disk data. and provide the usual read/write interface for on-disk data.
*/ */
struct IWMDrive: public Storage::Disk::Drive { struct IWMDrive: public Storage::Disk::Drive {
@ -82,8 +82,9 @@ class IWM:
uint8_t data_register_ = 0; uint8_t data_register_ = 0;
uint8_t mode_ = 0; uint8_t mode_ = 0;
bool read_write_ready_ = true; // These related to functionality not-yet implemented.
bool write_overran_ = false; // bool read_write_ready_ = true;
// bool write_overran_ = false;
int state_ = 0; int state_ = 0;

View File

@ -61,7 +61,6 @@ class SCC: public ::Outputs::Speaker::SampleSource {
} waves_[4]; } waves_[4];
std::uint8_t channel_enable_ = 0; std::uint8_t channel_enable_ = 0;
std::uint8_t test_register_ = 0;
void evaluate_output_volume(); void evaluate_output_volume();

View File

@ -23,7 +23,7 @@ AsyncTaskQueue::AsyncTaskQueue()
std::function<void(void)> next_function; std::function<void(void)> next_function;
// Take lock, check for a new task // Take lock, check for a new task
std::unique_lock<std::mutex> lock(queue_mutex_); std::unique_lock lock(queue_mutex_);
if(!pending_tasks_.empty()) { if(!pending_tasks_.empty()) {
next_function = pending_tasks_.front(); next_function = pending_tasks_.front();
pending_tasks_.pop_front(); pending_tasks_.pop_front();
@ -60,7 +60,7 @@ void AsyncTaskQueue::enqueue(std::function<void(void)> function) {
#ifdef __APPLE__ #ifdef __APPLE__
dispatch_async(serial_dispatch_queue_, ^{function();}); dispatch_async(serial_dispatch_queue_, ^{function();});
#else #else
std::lock_guard<std::mutex> lock(queue_mutex_); std::lock_guard lock(queue_mutex_);
pending_tasks_.push_back(function); pending_tasks_.push_back(function);
processing_condition_.notify_all(); processing_condition_.notify_all();
#endif #endif
@ -72,9 +72,9 @@ void AsyncTaskQueue::flush() {
#else #else
auto flush_mutex = std::make_shared<std::mutex>(); auto flush_mutex = std::make_shared<std::mutex>();
auto flush_condition = std::make_shared<std::condition_variable>(); auto flush_condition = std::make_shared<std::condition_variable>();
std::unique_lock<std::mutex> lock(*flush_mutex); std::unique_lock lock(*flush_mutex);
enqueue([=] () { enqueue([=] () {
std::unique_lock<std::mutex> inner_lock(*flush_mutex); std::unique_lock inner_lock(*flush_mutex);
flush_condition->notify_all(); flush_condition->notify_all();
}); });
flush_condition->wait(lock); flush_condition->wait(lock);

View File

@ -216,11 +216,8 @@ class ConcreteJoystick: public Joystick {
} }
protected: protected:
virtual void did_set_input(const Input &input, float value) { virtual void did_set_input([[maybe_unused]] const Input &input, [[maybe_unused]] float value) {}
} virtual void did_set_input([[maybe_unused]] const Input &input, [[maybe_unused]] bool value) {}
virtual void did_set_input(const Input &input, bool value) {
}
private: private:
const std::vector<Input> inputs_; const std::vector<Input> inputs_;

View File

@ -19,7 +19,7 @@ Keyboard::Keyboard(const std::set<Key> &essential_modifiers) : essential_modifie
Keyboard::Keyboard(const std::set<Key> &observed_keys, const std::set<Key> &essential_modifiers) : Keyboard::Keyboard(const std::set<Key> &observed_keys, const std::set<Key> &essential_modifiers) :
observed_keys_(observed_keys), essential_modifiers_(essential_modifiers), is_exclusive_(false) {} observed_keys_(observed_keys), essential_modifiers_(essential_modifiers), is_exclusive_(false) {}
bool Keyboard::set_key_pressed(Key key, char value, bool is_pressed) { bool Keyboard::set_key_pressed(Key key, char, bool is_pressed) {
const size_t key_offset = size_t(key); const size_t key_offset = size_t(key);
if(key_offset >= key_states_.size()) { if(key_offset >= key_states_.size()) {
key_states_.resize(key_offset+1, false); key_states_.resize(key_offset+1, false);

View File

@ -20,7 +20,7 @@ class Mouse {
/*! /*!
Indicates a movement of the mouse. Indicates a movement of the mouse.
*/ */
virtual void move(int x, int y) {} virtual void move([[maybe_unused]] int x, [[maybe_unused]] int y) {}
/*! /*!
@returns the number of buttons on this mouse. @returns the number of buttons on this mouse.
@ -34,7 +34,7 @@ class Mouse {
The intention is that @c index be semantic, not positional: The intention is that @c index be semantic, not positional:
0 for the primary button, 1 for the secondary, 2 for the tertiary, etc. 0 for the primary button, 1 for the secondary, 2 for the tertiary, etc.
*/ */
virtual void set_button_pressed(int index, bool is_pressed) {} virtual void set_button_pressed([[maybe_unused]] int index, [[maybe_unused]] bool is_pressed) {}
/*! /*!
Releases all depressed buttons. Releases all depressed buttons.

View File

@ -691,11 +691,11 @@ class FDC: public Intel::i8272::i8272 {
get_drive().set_motor_on(on); get_drive().set_motor_on(on);
} }
void select_drive(int c) { void select_drive(int) {
// TODO: support more than one drive. // TODO: support more than one drive. (and in set_disk)
} }
void set_disk(std::shared_ptr<Storage::Disk::Disk> disk, int drive) { void set_disk(std::shared_ptr<Storage::Disk::Disk> disk, int) {
get_drive().set_disk(disk); get_drive().set_disk(disk);
} }
@ -1075,7 +1075,7 @@ template <bool has_fdc> class ConcreteMachine:
return !media.tapes.empty() || (!media.disks.empty() && has_fdc); return !media.tapes.empty() || (!media.disks.empty() && has_fdc);
} }
void set_component_prefers_clocking(ClockingHint::Source *component, ClockingHint::Preference clocking) final { void set_component_prefers_clocking(ClockingHint::Source *, ClockingHint::Preference) final {
fdc_is_sleeping_ = fdc_.preferred_clocking() == ClockingHint::Preference::None; fdc_is_sleeping_ = fdc_.preferred_clocking() == ClockingHint::Preference::None;
tape_player_is_sleeping_ = tape_player_.preferred_clocking() == ClockingHint::Preference::None; tape_player_is_sleeping_ = tape_player_.preferred_clocking() == ClockingHint::Preference::None;
} }
@ -1112,7 +1112,7 @@ template <bool has_fdc> class ConcreteMachine:
} }
// MARK: - Activity Source // MARK: - Activity Source
void set_activity_observer(Activity::Observer *observer) final { void set_activity_observer([[maybe_unused]] Activity::Observer *observer) final {
if constexpr (has_fdc) fdc_.set_activity_observer(observer); if constexpr (has_fdc) fdc_.set_activity_observer(observer);
} }

View File

@ -32,7 +32,7 @@ class Machine {
class Options: public Reflection::StructImpl<Options>, public Configurable::DisplayOption<Options> { class Options: public Reflection::StructImpl<Options>, public Configurable::DisplayOption<Options> {
friend Configurable::DisplayOption<Options>; friend Configurable::DisplayOption<Options>;
public: public:
Options(Configurable::OptionsType type) : Configurable::DisplayOption<Options>(Configurable::Display::RGB) { Options(Configurable::OptionsType) : Configurable::DisplayOption<Options>(Configurable::Display::RGB) {
if(needs_declare()) { if(needs_declare()) {
declare_display_option(); declare_display_option();
limit_enum(&output, Configurable::Display::RGB, Configurable::Display::CompositeColour, -1); limit_enum(&output, Configurable::Display::RGB, Configurable::Display::CompositeColour, -1);

View File

@ -804,7 +804,7 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
m6502_.run_for(cycles); m6502_.run_for(cycles);
} }
void reset_all_keys() final { void reset_all_keys(Inputs::Keyboard *) final {
open_apple_is_pressed_ = closed_apple_is_pressed_ = key_is_down_ = false; open_apple_is_pressed_ = closed_apple_is_pressed_ = key_is_down_ = false;
} }

View File

@ -30,7 +30,7 @@ class Machine {
class Options: public Reflection::StructImpl<Options>, public Configurable::DisplayOption<Options> { class Options: public Reflection::StructImpl<Options>, public Configurable::DisplayOption<Options> {
friend Configurable::DisplayOption<Options>; friend Configurable::DisplayOption<Options>;
public: public:
Options(Configurable::OptionsType type) : Configurable::DisplayOption<Options>(Configurable::Display::CompositeColour) { Options(Configurable::OptionsType) : Configurable::DisplayOption<Options>(Configurable::Display::CompositeColour) {
if(needs_declare()) { if(needs_declare()) {
declare_display_option(); declare_display_option();
limit_enum(&output, Configurable::Display::CompositeMonochrome, Configurable::Display::CompositeColour, -1); limit_enum(&output, Configurable::Display::CompositeMonochrome, Configurable::Display::CompositeColour, -1);

View File

@ -54,7 +54,7 @@ class Card {
no constraints, that want to be informed of every machine cycle, will receive no constraints, that want to be informed of every machine cycle, will receive
a call to perform_bus_operation every cycle and should use that for time keeping. a call to perform_bus_operation every cycle and should use that for time keeping.
*/ */
virtual void run_for(Cycles half_cycles, int stretches) {} virtual void run_for([[maybe_unused]] Cycles half_cycles, [[maybe_unused]] int stretches) {}
/// Requests a flush of any pending audio or video output. /// Requests a flush of any pending audio or video output.
virtual void flush() {} virtual void flush() {}
@ -89,7 +89,7 @@ class Card {
} }
/*! Cards may supply a target for activity observation if desired. */ /*! Cards may supply a target for activity observation if desired. */
virtual void set_activity_observer(Activity::Observer *observer) {} virtual void set_activity_observer([[maybe_unused]] Activity::Observer *observer) {}
struct Delegate { struct Delegate {
virtual void card_did_change_select_constraints(Card *card) = 0; virtual void card_did_change_select_constraints(Card *card) = 0;

View File

@ -50,7 +50,7 @@ void DiskIICard::perform_bus_operation(Select select, bool is_read, uint16_t add
} }
} }
void DiskIICard::run_for(Cycles cycles, int stretches) { void DiskIICard::run_for(Cycles cycles, int) {
if(diskii_clocking_preference_ == ClockingHint::Preference::None) return; if(diskii_clocking_preference_ == ClockingHint::Preference::None) return;
diskii_.run_for(Cycles(cycles.as_integral() * 2)); diskii_.run_for(Cycles(cycles.as_integral() * 2));
} }
@ -63,7 +63,7 @@ void DiskIICard::set_activity_observer(Activity::Observer *observer) {
diskii_.set_activity_observer(observer); diskii_.set_activity_observer(observer);
} }
void DiskIICard::set_component_prefers_clocking(ClockingHint::Source *component, ClockingHint::Preference preference) { void DiskIICard::set_component_prefers_clocking(ClockingHint::Source *, ClockingHint::Preference preference) {
diskii_clocking_preference_ = preference; diskii_clocking_preference_ = preference;
set_select_constraints((preference != ClockingHint::Preference::RealTime) ? (IO | Device) : None); set_select_constraints((preference != ClockingHint::Preference::RealTime) ? (IO | Device) : None);
} }

View File

@ -252,7 +252,7 @@ void VideoBase::output_low_resolution(uint8_t *target, const uint8_t *const sour
} }
} }
void VideoBase::output_fat_low_resolution(uint8_t *target, const uint8_t *const source, size_t length, int column, int row) const { void VideoBase::output_fat_low_resolution(uint8_t *target, const uint8_t *const source, size_t length, int, int row) const {
const int row_shift = row&4; const int row_shift = row&4;
for(size_t c = 0; c < length; ++c) { for(size_t c = 0; c < length; ++c) {
// Fat low-resolution mode appears not to do anything to try to make odd and // Fat low-resolution mode appears not to do anything to try to make odd and

View File

@ -29,7 +29,7 @@ class BusHandler {
from auxiliary memory to @c auxiliary_target. If the machine has no axiliary memory, from auxiliary memory to @c auxiliary_target. If the machine has no axiliary memory,
it needn't write anything to auxiliary_target. it needn't write anything to auxiliary_target.
*/ */
void perform_read(uint16_t address, size_t count, uint8_t *base_target, uint8_t *auxiliary_target) { void perform_read([[maybe_unused]] uint16_t address, [[maybe_unused]] size_t count, [[maybe_unused]] uint8_t *base_target, [[maybe_unused]] uint8_t *auxiliary_target) {
} }
}; };

View File

@ -135,7 +135,7 @@ class Keyboard {
/*! /*!
The keyboard expects ~10 µs-frequency ticks, i.e. a clock rate of just around 100 kHz. The keyboard expects ~10 µs-frequency ticks, i.e. a clock rate of just around 100 kHz.
*/ */
void run_for(HalfCycles cycle) { void run_for(HalfCycles) { // TODO: honour the HalfCycles argument.
switch(mode_) { switch(mode_) {
default: default:
case Mode::Waiting: return; case Mode::Waiting: return;
@ -210,7 +210,7 @@ class Keyboard {
void enqueue_key_state(uint16_t key, bool is_pressed) { void enqueue_key_state(uint16_t key, bool is_pressed) {
// Front insert; messages will be pop_back'd. // Front insert; messages will be pop_back'd.
std::lock_guard<decltype(key_queue_mutex_)> lock(key_queue_mutex_); std::lock_guard lock(key_queue_mutex_);
// Keys on the keypad are preceded by a $79 keycode; in the internal naming scheme // Keys on the keypad are preceded by a $79 keycode; in the internal naming scheme
// they are indicated by having bit 8 set. So add the $79 prefix if required. // they are indicated by having bit 8 set. So add the $79 prefix if required.
@ -228,7 +228,7 @@ class Keyboard {
switch(command) { switch(command) {
case 0x10: // Inquiry. case 0x10: // Inquiry.
case 0x14: { // Instant. case 0x14: { // Instant.
std::lock_guard<decltype(key_queue_mutex_)> lock(key_queue_mutex_); std::lock_guard lock(key_queue_mutex_);
if(!key_queue_.empty()) { if(!key_queue_.empty()) {
const auto new_message = key_queue_.back(); const auto new_message = key_queue_.back();
key_queue_.pop_back(); key_queue_.pop_back();

View File

@ -183,7 +183,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
using Microcycle = CPU::MC68000::Microcycle; using Microcycle = CPU::MC68000::Microcycle;
forceinline HalfCycles perform_bus_operation(const Microcycle &cycle, int is_supervisor) { forceinline HalfCycles perform_bus_operation(const Microcycle &cycle, int) {
// Advance time. // Advance time.
advance_time(cycle.length); advance_time(cycle.length);
@ -490,7 +490,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
// MARK: Interrupt updates. // MARK: Interrupt updates.
void did_change_interrupt_status(Zilog::SCC::z8530 *sender, bool new_status) final { void did_change_interrupt_status(Zilog::SCC::z8530 *, bool) final {
update_interrupt_input(); update_interrupt_input();
} }
@ -541,7 +541,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
private: private:
bool quickboot_ = false; bool quickboot_ = false;
void set_component_prefers_clocking(ClockingHint::Source *component, ClockingHint::Preference clocking) final { void set_component_prefers_clocking(ClockingHint::Source *, ClockingHint::Preference) final {
scsi_bus_is_clocked_ = scsi_bus_.preferred_clocking() != ClockingHint::Preference::None; scsi_bus_is_clocked_ = scsi_bus_.preferred_clocking() != ClockingHint::Preference::None;
} }
@ -654,7 +654,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
using Port = MOS::MOS6522::Port; using Port = MOS::MOS6522::Port;
using Line = MOS::MOS6522::Line; using Line = MOS::MOS6522::Line;
void set_port_output(Port port, uint8_t value, uint8_t direction_mask) { void set_port_output(Port port, uint8_t value, uint8_t) {
/* /*
Peripheral lines: keyboard data, interrupt configuration. Peripheral lines: keyboard data, interrupt configuration.
(See p176 [/215]) (See p176 [/215])
@ -745,7 +745,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
audio_.flush(); audio_.flush();
} }
void set_interrupt_status(bool status) { void set_interrupt_status(bool) {
machine_.update_interrupt_input(); machine_.update_interrupt_input();
} }

View File

@ -212,7 +212,7 @@ class ConcreteMachine:
using namespace Atari2600; using namespace Atari2600;
Machine *Machine::Atari2600(const Analyser::Static::Target *target, const ROMMachine::ROMFetcher &rom_fetcher) { Machine *Machine::Atari2600(const Analyser::Static::Target *target, const ROMMachine::ROMFetcher &) {
const Target *const atari_target = dynamic_cast<const Target *>(target); const Target *const atari_target = dynamic_cast<const Target *>(target);
return new Atari2600::ConcreteMachine(*atari_target); return new Atari2600::ConcreteMachine(*atari_target);
} }

View File

@ -19,7 +19,7 @@ class BusExtender: public CPU::MOS6502::BusHandler {
public: public:
BusExtender(uint8_t *rom_base, std::size_t rom_size) : rom_base_(rom_base), rom_size_(rom_size) {} BusExtender(uint8_t *rom_base, std::size_t rom_size) : rom_base_(rom_base), rom_size_(rom_size) {}
void advance_cycles(int cycles) {} void advance_cycles(int) {}
protected: protected:
uint8_t *rom_base_; uint8_t *rom_base_;

View File

@ -117,7 +117,6 @@ class Pitfall2: public BusExtender {
uint16_t featcher_address_[8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint16_t featcher_address_[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t top_[8], bottom_[8], mask_[8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint8_t top_[8], bottom_[8], mask_[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t music_mode_[3];
uint8_t random_number_generator_ = 0; uint8_t random_number_generator_ = 0;
uint8_t *rom_ptr_; uint8_t *rom_ptr_;
uint8_t audio_channel_[3]; uint8_t audio_channel_[3];

View File

@ -586,7 +586,7 @@ template<class T> void TIA::perform_motion_step(T &object) {
} }
} }
template<class T> void TIA::perform_border_motion(T &object, int start, int end) { template<class T> void TIA::perform_border_motion(T &object, int, int end) {
while(object.is_moving && object.motion_time < end) while(object.is_moving && object.motion_time < end)
perform_motion_step<T>(object); perform_motion_step<T>(object);
} }

View File

@ -239,15 +239,15 @@ class TIA {
int size = 1; int size = 1;
const bool enqueues = false; const bool enqueues = false;
inline void skip_pixels(const int count, int from_horizontal_counter) { inline void skip_pixels(const int count, int) {
pixel_position = std::max(0, pixel_position - count); pixel_position = std::max(0, pixel_position - count);
} }
inline void reset_pixels(int copy) { inline void reset_pixels(int) {
pixel_position = size; pixel_position = size;
} }
inline void output_pixels(uint8_t *const target, const int count, const uint8_t collision_identity, int from_horizontal_counter) { inline void output_pixels(uint8_t *const target, const int count, const uint8_t collision_identity, [[maybe_unused]] int from_horizontal_counter) {
int output_cursor = 0; int output_cursor = 0;
while(pixel_position && output_cursor < count) while(pixel_position && output_cursor < count)
{ {
@ -257,8 +257,8 @@ class TIA {
} }
} }
void dequeue_pixels(uint8_t *const target, const uint8_t collision_identity, const int time_now) {} void dequeue_pixels([[maybe_unused]] uint8_t *const target, [[maybe_unused]] uint8_t collision_identity, [[maybe_unused]] int time_now) {}
void enqueue_pixels(const int start, const int end, int from_horizontal_counter) {} void enqueue_pixels([[maybe_unused]] int start, [[maybe_unused]] int end, [[maybe_unused]] int from_horizontal_counter) {}
}; };
// missile state // missile state

View File

@ -237,6 +237,7 @@ class ConcreteMachine:
memory = rom_.data(); memory = rom_.data();
break; break;
} }
[[fallthrough]];
case BusDevice::RAM: case BusDevice::RAM:
memory = ram_.data(); memory = ram_.data();
break; break;
@ -529,7 +530,7 @@ class ConcreteMachine:
bool keyboard_needs_clock_ = false; bool keyboard_needs_clock_ = false;
bool mfp_is_realtime_ = false; bool mfp_is_realtime_ = false;
ClockingHint::Preference dma_clocking_preference_ = ClockingHint::Preference::None; ClockingHint::Preference dma_clocking_preference_ = ClockingHint::Preference::None;
void set_component_prefers_clocking(ClockingHint::Source *component, ClockingHint::Preference clocking) final { void set_component_prefers_clocking(ClockingHint::Source *, ClockingHint::Preference) final {
// This is being called by one of the components; avoid any time flushing here as that's // This is being called by one of the components; avoid any time flushing here as that's
// already dealt with (and, just to be absolutely sure, to avoid recursive mania). // already dealt with (and, just to be absolutely sure, to avoid recursive mania).
may_defer_acias_ = may_defer_acias_ =
@ -580,7 +581,7 @@ class ConcreteMachine:
} }
// MARK - MFP input. // MARK - MFP input.
void mfp68901_did_change_interrupt_status(Motorola::MFP68901::MFP68901 *mfp) final { void mfp68901_did_change_interrupt_status(Motorola::MFP68901::MFP68901 *) final {
update_interrupt_input(); update_interrupt_input();
} }

View File

@ -84,7 +84,7 @@ void IntelligentKeyboard::run_for(HalfCycles duration) {
// Forward key changes; implicit assumption here: mutexs are cheap while there's // Forward key changes; implicit assumption here: mutexs are cheap while there's
// negligible contention. // negligible contention.
{ {
std::lock_guard<decltype(key_queue_mutex_)> guard(key_queue_mutex_); std::lock_guard guard(key_queue_mutex_);
for(uint8_t key: key_queue_) { for(uint8_t key: key_queue_) {
output_bytes({key}); output_bytes({key});
} }
@ -286,7 +286,7 @@ void IntelligentKeyboard::set_mouse_position(uint16_t x, uint16_t y) {
mouse_position_[1] = std::min(int(y), mouse_range_[1]); mouse_position_[1] = std::min(int(y), mouse_range_[1]);
} }
void IntelligentKeyboard::set_mouse_keycode_reporting(uint8_t delta_x, uint8_t delta_y) { void IntelligentKeyboard::set_mouse_keycode_reporting(uint8_t, uint8_t) {
LOG("Unimplemented: set mouse keycode reporting"); LOG("Unimplemented: set mouse keycode reporting");
} }
@ -308,7 +308,7 @@ void IntelligentKeyboard::set_mouse_y_upward() {
mouse_y_multiplier_ = -1; mouse_y_multiplier_ = -1;
} }
void IntelligentKeyboard::set_mouse_button_actions(uint8_t actions) { void IntelligentKeyboard::set_mouse_button_actions(uint8_t) {
LOG("Unimplemented: set mouse button actions"); LOG("Unimplemented: set mouse button actions");
} }
@ -348,7 +348,7 @@ void IntelligentKeyboard::post_relative_mouse_event(int x, int y) {
// MARK: - Keyboard Input // MARK: - Keyboard Input
void IntelligentKeyboard::set_key_state(Key key, bool is_pressed) { void IntelligentKeyboard::set_key_state(Key key, bool is_pressed) {
std::lock_guard<decltype(key_queue_mutex_)> guard(key_queue_mutex_); std::lock_guard guard(key_queue_mutex_);
if(is_pressed) { if(is_pressed) {
key_queue_.push_back(uint8_t(key)); key_queue_.push_back(uint8_t(key));
} else { } else {
@ -461,6 +461,10 @@ void IntelligentKeyboard::set_joystick_interrogation_mode() {
} }
void IntelligentKeyboard::set_joystick_keycode_mode(VelocityThreshold horizontal, VelocityThreshold vertical) { void IntelligentKeyboard::set_joystick_keycode_mode(VelocityThreshold horizontal, VelocityThreshold vertical) {
// TODO: honour velocity thresholds.
(void)horizontal;
(void)vertical;
joystick_mode_ = JoystickMode::KeyCode; joystick_mode_ = JoystickMode::KeyCode;
clear_joystick_events(); clear_joystick_events();
} }
@ -494,7 +498,7 @@ void IntelligentKeyboard::interrogate_joysticks() {
} }
} }
void IntelligentKeyboard::set_joystick_monitoring_mode(uint8_t rate) { void IntelligentKeyboard::set_joystick_monitoring_mode(uint8_t) {
LOG("Unimplemented: joystick monitoring mode"); LOG("Unimplemented: joystick monitoring mode");
} }

View File

@ -130,7 +130,7 @@ Video::Video() :
crt_.set_visible_area(crt_.get_rect_for_area(33, 260, 440, 1700, 4.0f / 3.0f)); crt_.set_visible_area(crt_.get_rect_for_area(33, 260, 440, 1700, 4.0f / 3.0f));
} }
void Video::set_ram(uint16_t *ram, size_t size) { void Video::set_ram(uint16_t *ram, size_t) {
ram_ = ram; ram_ = ram;
} }

View File

@ -224,6 +224,7 @@ class ConcreteMachine:
switch(cycle.operation) { switch(cycle.operation) {
case CPU::Z80::PartialMachineCycle::ReadOpcode: case CPU::Z80::PartialMachineCycle::ReadOpcode:
if(!address) pc_zero_accesses_++; if(!address) pc_zero_accesses_++;
[[fallthrough]];
case CPU::Z80::PartialMachineCycle::Read: case CPU::Z80::PartialMachineCycle::Read:
if(address < 0x2000) { if(address < 0x2000) {
if(super_game_module_.replace_bios) { if(super_game_module_.replace_bios) {

View File

@ -39,7 +39,7 @@ namespace C1540 {
/*! /*!
Provides an emulation of the C1540. Provides an emulation of the C1540.
*/ */
class Machine: public MachineBase { class Machine final: public MachineBase {
public: public:
Machine(Personality personality, const ROMMachine::ROMFetcher &rom_fetcher); Machine(Personality personality, const ROMMachine::ROMFetcher &rom_fetcher);

View File

@ -122,7 +122,7 @@ void MachineBase::set_activity_observer(Activity::Observer *observer) {
// MARK: - 6522 delegate // MARK: - 6522 delegate
void MachineBase::mos6522_did_change_interrupt_status(void *mos6522) { void MachineBase::mos6522_did_change_interrupt_status(void *) {
// both VIAs are connected to the IRQ line // both VIAs are connected to the IRQ line
m6502_.set_irq_line(serial_port_VIA_.get_interrupt_line() || drive_VIA_.get_interrupt_line()); m6502_.set_irq_line(serial_port_VIA_.get_interrupt_line() || drive_VIA_.get_interrupt_line());
} }
@ -153,11 +153,11 @@ void MachineBase::process_index_hole() {}
// MARK: - Drive VIA delegate // MARK: - Drive VIA delegate
void MachineBase::drive_via_did_step_head(void *driveVIA, int direction) { void MachineBase::drive_via_did_step_head(void *, int direction) {
get_drive().step(Storage::Disk::HeadPosition(direction, 2)); get_drive().step(Storage::Disk::HeadPosition(direction, 2));
} }
void MachineBase::drive_via_did_set_data_density(void *driveVIA, int density) { void MachineBase::drive_via_did_set_data_density(void *, int density) {
set_expected_bit_length(Storage::Encodings::CommodoreGCR::length_of_a_bit_in_time_zone(unsigned(density))); set_expected_bit_length(Storage::Encodings::CommodoreGCR::length_of_a_bit_in_time_zone(unsigned(density)));
} }
@ -170,7 +170,7 @@ uint8_t SerialPortVIA::get_port_input(MOS::MOS6522::Port port) {
return 0xff; return 0xff;
} }
void SerialPortVIA::set_port_output(MOS::MOS6522::Port port, uint8_t value, uint8_t mask) { void SerialPortVIA::set_port_output(MOS::MOS6522::Port port, uint8_t value, uint8_t) {
if(port) { if(port) {
std::shared_ptr<::Commodore::Serial::Port> serialPort = serial_port_.lock(); std::shared_ptr<::Commodore::Serial::Port> serialPort = serial_port_.lock();
if(serialPort) { if(serialPort) {
@ -243,7 +243,7 @@ void DriveVIA::set_control_line_output(MOS::MOS6522::Port port, MOS::MOS6522::Li
} }
} }
void DriveVIA::set_port_output(MOS::MOS6522::Port port, uint8_t value, uint8_t direction_mask) { void DriveVIA::set_port_output(MOS::MOS6522::Port port, uint8_t value, uint8_t) {
if(port) { if(port) {
if(previous_port_b_output_ != value) { if(previous_port_b_output_ != value) {
// record drive motor state // record drive motor state

View File

@ -75,6 +75,7 @@ namespace Serial {
class Port { class Port {
public: public:
Port() : line_levels_{High, High, High, High, High} {} Port() : line_levels_{High, High, High, High, High} {}
virtual ~Port() {}
/*! /*!
Sets the current level of an output line on this serial port. Sets the current level of an output line on this serial port.

View File

@ -99,7 +99,7 @@ class UserPortVIA: public MOS::MOS6522::IRQDelegatePortHandler {
} }
/// Receives announcements from the 6522 of user-port output, which might affect what's currently being presented onto the serial bus. /// Receives announcements from the 6522 of user-port output, which might affect what's currently being presented onto the serial bus.
void set_port_output(MOS::MOS6522::Port port, uint8_t value, uint8_t mask) { void set_port_output(MOS::MOS6522::Port port, uint8_t value, uint8_t) {
// Line 7 of port A is inverted and output as serial ATN. // Line 7 of port A is inverted and output as serial ATN.
if(!port) { if(!port) {
std::shared_ptr<::Commodore::Serial::Port> serialPort = serial_port_.lock(); std::shared_ptr<::Commodore::Serial::Port> serialPort = serial_port_.lock();
@ -654,7 +654,7 @@ class ConcreteMachine:
return mos6560_.get_speaker(); return mos6560_.get_speaker();
} }
void mos6522_did_change_interrupt_status(void *mos6522) final { void mos6522_did_change_interrupt_status(void *) final {
m6502_.set_nmi_line(user_port_via_.get_interrupt_line()); m6502_.set_nmi_line(user_port_via_.get_interrupt_line());
m6502_.set_irq_line(keyboard_via_.get_interrupt_line()); m6502_.set_irq_line(keyboard_via_.get_interrupt_line());
} }
@ -691,7 +691,7 @@ class ConcreteMachine:
set_use_fast_tape(); set_use_fast_tape();
} }
void set_component_prefers_clocking(ClockingHint::Source *component, ClockingHint::Preference clocking) final { void set_component_prefers_clocking(ClockingHint::Source *, ClockingHint::Preference clocking) final {
tape_is_sleeping_ = clocking == ClockingHint::Preference::None; tape_is_sleeping_ = clocking == ClockingHint::Preference::None;
set_use_fast_tape(); set_use_fast_tape();
} }

View File

@ -215,7 +215,8 @@ class ConcreteMachine:
activity_observer_->set_led_status(caps_led, caps_led_state_); activity_observer_->set_led_status(caps_led, caps_led_state_);
} }
// deliberate fallthrough; fe07 contains the display mode. [[fallthrough]]; // fe07 contains the display mode.
case 0xfe02: case 0xfe03: case 0xfe02: case 0xfe03:
case 0xfe08: case 0xfe09: case 0xfe0a: case 0xfe0b: case 0xfe08: case 0xfe09: case 0xfe0a: case 0xfe0b:
@ -421,7 +422,7 @@ class ConcreteMachine:
m6502_.run_for(cycles); m6502_.run_for(cycles);
} }
void tape_did_change_interrupt_status(Tape *tape) final { void tape_did_change_interrupt_status(Tape *) final {
interrupt_status_ = (interrupt_status_ & ~(Interrupt::TransmitDataEmpty | Interrupt::ReceiveDataFull | Interrupt::HighToneDetect)) | tape_.get_interrupt_status(); interrupt_status_ = (interrupt_status_ & ~(Interrupt::TransmitDataEmpty | Interrupt::ReceiveDataFull | Interrupt::HighToneDetect)) | tape_.get_interrupt_status();
evaluate_interrupts(); evaluate_interrupts();
} }

View File

@ -14,7 +14,7 @@
namespace Electron { namespace Electron {
class Plus3 : public WD::WD1770 { class Plus3 final : public WD::WD1770 {
public: public:
Plus3(); Plus3();
@ -26,7 +26,7 @@ class Plus3 : public WD::WD1770 {
void set_control_register(uint8_t control, uint8_t changes); void set_control_register(uint8_t control, uint8_t changes);
uint8_t last_control_ = 0; uint8_t last_control_ = 0;
void set_motor_on(bool on); void set_motor_on(bool on) override;
std::string drive_name(size_t drive); std::string drive_name(size_t drive);
}; };

View File

@ -52,6 +52,9 @@ void Tape::set_is_in_input_mode(bool is_in_input_mode) {
} }
void Tape::set_counter(uint8_t value) { void Tape::set_counter(uint8_t value) {
// TODO: use value.
(void)value;
output_.cycles_into_pulse = 0; output_.cycles_into_pulse = 0;
output_.bits_remaining_until_empty = 0; output_.bits_remaining_until_empty = 0;
} }

View File

@ -93,7 +93,6 @@ class VideoOutput {
inline void setup_base_address(); inline void setup_base_address();
int output_position_ = 0; int output_position_ = 0;
int unused_cycles_ = 0;
uint8_t palette_[16]; uint8_t palette_[16];
uint8_t screen_mode_ = 6; uint8_t screen_mode_ = 6;

View File

@ -14,14 +14,14 @@ MachineTypes::MappedKeyboardMachine::MappedKeyboardMachine(const std::set<Inputs
keyboard_.set_delegate(this); keyboard_.set_delegate(this);
} }
bool MappedKeyboardMachine::keyboard_did_change_key(Inputs::Keyboard *keyboard, Inputs::Keyboard::Key key, bool is_pressed) { bool MappedKeyboardMachine::keyboard_did_change_key(Inputs::Keyboard *, Inputs::Keyboard::Key key, bool is_pressed) {
const uint16_t mapped_key = get_keyboard_mapper()->mapped_key_for_key(key); const uint16_t mapped_key = get_keyboard_mapper()->mapped_key_for_key(key);
if(mapped_key == KeyNotMapped) return false; if(mapped_key == KeyNotMapped) return false;
set_key_state(mapped_key, is_pressed); set_key_state(mapped_key, is_pressed);
return true; return true;
} }
void MappedKeyboardMachine::reset_all_keys(Inputs::Keyboard *keyboard) { void MappedKeyboardMachine::reset_all_keys(Inputs::Keyboard *) {
// TODO: unify naming. // TODO: unify naming.
clear_all_keys(); clear_all_keys();
} }

View File

@ -26,7 +26,7 @@ struct KeyActions {
Indicates that the key @c key has been either pressed or released, according to Indicates that the key @c key has been either pressed or released, according to
the state of @c isPressed. the state of @c isPressed.
*/ */
virtual void set_key_state(uint16_t key, bool is_pressed) {} virtual void set_key_state([[maybe_unused]] uint16_t key, [[maybe_unused]] bool is_pressed) {}
/*! /*!
Instructs that all keys should now be treated as released. Instructs that all keys should now be treated as released.
@ -49,7 +49,7 @@ class KeyboardMachine: public KeyActions {
/*! /*!
@returns @c true if this machine can type the character @c c as part of a @c type_string; @c false otherwise. @returns @c true if this machine can type the character @c c as part of a @c type_string; @c false otherwise.
*/ */
virtual bool can_type(char c) const { return false; } virtual bool can_type([[maybe_unused]] char c) const { return false; }
/*! /*!
Provides a destination for keyboard input. Provides a destination for keyboard input.

View File

@ -17,14 +17,14 @@ DiskROM::DiskROM(const std::vector<uint8_t> &rom) :
set_is_double_density(true); set_is_double_density(true);
} }
void DiskROM::write(uint16_t address, uint8_t value, bool pc_is_outside_bios) { void DiskROM::write(uint16_t address, uint8_t value, bool) {
switch(address) { switch(address) {
case 0x7ff8: case 0x7ff9: case 0x7ffa: case 0x7ffb: case 0x7ff8: case 0x7ff9: case 0x7ffa: case 0x7ffb:
WD::WD1770::write(address, value); WD::WD1770::write(address, value);
break; break;
case 0x7ffc: { case 0x7ffc: {
const int selected_head = value & 1; const int selected_head = value & 1;
for_all_drives([selected_head] (Storage::Disk::Drive &drive, size_t index) { for_all_drives([selected_head] (Storage::Disk::Drive &drive, size_t) {
drive.set_head(selected_head); drive.set_head(selected_head);
}); });
} break; } break;
@ -32,7 +32,7 @@ void DiskROM::write(uint16_t address, uint8_t value, bool pc_is_outside_bios) {
set_drive(1 << (value & 1)); set_drive(1 << (value & 1));
const bool drive_motor = value & 0x80; const bool drive_motor = value & 0x80;
for_all_drives([drive_motor] (Storage::Disk::Drive &drive, size_t index) { for_all_drives([drive_motor] (Storage::Disk::Drive &drive, size_t) {
drive.set_motor_on(drive_motor); drive.set_motor_on(drive_motor);
}); });
} break; } break;

View File

@ -492,6 +492,8 @@ class ConcreteMachine:
performed_unmapped_access_ = true; performed_unmapped_access_ = true;
} }
pc_address_ = address; // This is retained so as to be able to name the source of an access to cartridge handlers. pc_address_ = address; // This is retained so as to be able to name the source of an access to cartridge handlers.
[[fallthrough]];
case CPU::Z80::PartialMachineCycle::Read: case CPU::Z80::PartialMachineCycle::Read:
if(read_pointers_[address >> 13]) { if(read_pointers_[address >> 13]) {
*cycle.value = read_pointers_[address >> 13][address & 8191]; *cycle.value = read_pointers_[address >> 13][address & 8191];
@ -662,7 +664,7 @@ class ConcreteMachine:
} }
// MARK: - Sleeper // MARK: - Sleeper
void set_component_prefers_clocking(ClockingHint::Source *component, ClockingHint::Preference clocking) final { void set_component_prefers_clocking(ClockingHint::Source *, ClockingHint::Preference) final {
tape_player_is_sleeping_ = tape_player_.preferred_clocking() == ClockingHint::Preference::None; tape_player_is_sleeping_ = tape_player_.preferred_clocking() == ClockingHint::Preference::None;
set_use_fast_tape(); set_use_fast_tape();
} }

View File

@ -47,13 +47,13 @@ class ROMSlotHandler {
virtual ~ROMSlotHandler() {} virtual ~ROMSlotHandler() {}
/*! Advances time by @c half_cycles. */ /*! Advances time by @c half_cycles. */
virtual void run_for(HalfCycles half_cycles) {} virtual void run_for([[maybe_unused]] HalfCycles half_cycles) {}
/*! Announces an attempt to write @c value to @c address. */ /*! Announces an attempt to write @c value to @c address. */
virtual void write(uint16_t address, uint8_t value, bool pc_is_outside_bios) = 0; virtual void write(uint16_t address, uint8_t value, bool pc_is_outside_bios) = 0;
/*! Seeks the result of a read at @c address; this is used only if the area is unmapped. */ /*! Seeks the result of a read at @c address; this is used only if the area is unmapped. */
virtual uint8_t read(uint16_t address) { return 0xff; } virtual uint8_t read([[maybe_unused]] uint16_t address) { return 0xff; }
enum class WrappingStrategy { enum class WrappingStrategy {
/// Repeat causes all accesses to be modulo the size of the ROM. /// Repeat causes all accesses to be modulo the size of the ROM.

View File

@ -155,7 +155,7 @@ class VIAPortHandler: public MOS::MOS6522::IRQDelegatePortHandler {
Reponds to changes in the 6522's port output. On an Oric port B sets the tape motor control Reponds to changes in the 6522's port output. On an Oric port B sets the tape motor control
and the keyboard's active row. Port A is connected to the AY's data bus. and the keyboard's active row. Port A is connected to the AY's data bus.
*/ */
void set_port_output(MOS::MOS6522::Port port, uint8_t value, uint8_t direction_mask) { void set_port_output(MOS::MOS6522::Port port, uint8_t value, uint8_t) {
if(port) { if(port) {
keyboard_.set_active_row(value); keyboard_.set_active_row(value);
tape_player_.set_motor_control(value & 0x40); tape_player_.set_motor_control(value & 0x40);
@ -267,13 +267,13 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface> class Co
switch(disk_interface) { switch(disk_interface) {
default: break; default: break;
case DiskInterface::BD500: case DiskInterface::BD500:
rom_names.emplace_back(machine_name, "the ORIC Byte Drive 500 ROM", "bd500.rom", 8*1024, 0x61952e34); rom_names.emplace_back(machine_name, "the Oric Byte Drive 500 ROM", "bd500.rom", 8*1024, 0x61952e34);
break; break;
case DiskInterface::Jasmin: case DiskInterface::Jasmin:
rom_names.emplace_back(machine_name, "the ORIC Jasmin ROM", "jasmin.rom", 2*1024, 0x37220e89); rom_names.emplace_back(machine_name, "the Oric Jasmin ROM", "jasmin.rom", 2*1024, 0x37220e89);
break; break;
case DiskInterface::Microdisc: case DiskInterface::Microdisc:
rom_names.emplace_back(machine_name, "the ORIC Microdisc ROM", "microdisc.rom", 8*1024, 0xa9664a9c); rom_names.emplace_back(machine_name, "the Oric Microdisc ROM", "microdisc.rom", 8*1024, 0xa9664a9c);
break; break;
case DiskInterface::Pravetz: case DiskInterface::Pravetz:
rom_names.emplace_back(machine_name, "the 8DOS boot ROM", "8dos.rom", 512, 0x49a74c06); rom_names.emplace_back(machine_name, "the 8DOS boot ROM", "8dos.rom", 512, 0x49a74c06);
@ -568,7 +568,7 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface> class Co
} }
// to satisfy MOS::MOS6522IRQDelegate::Delegate // to satisfy MOS::MOS6522IRQDelegate::Delegate
void mos6522_did_change_interrupt_status(void *mos6522) final { void mos6522_did_change_interrupt_status(void *) final {
set_interrupt_line(); set_interrupt_line();
} }
@ -608,7 +608,7 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface> class Co
} }
// WD::WD1770::Delegate // WD::WD1770::Delegate
void wd1770_did_change_output(WD::WD1770 *wd1770) final { void wd1770_did_change_output(WD::WD1770 *) final {
set_interrupt_line(); set_interrupt_line();
} }
@ -648,7 +648,7 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface> class Co
} }
} }
void set_component_prefers_clocking(ClockingHint::Source *component, ClockingHint::Preference preference) final { void set_component_prefers_clocking(ClockingHint::Source *, ClockingHint::Preference) final {
diskii_clocking_preference_ = diskii_.preferred_clocking(); diskii_clocking_preference_ = diskii_.preferred_clocking();
} }

View File

@ -91,7 +91,7 @@ class ScanProducer {
/*! /*!
Sets the display type. Sets the display type.
*/ */
virtual void set_display_type(Outputs::Display::DisplayType display_type) {} virtual void set_display_type(Outputs::Display::DisplayType) {}
/*! /*!
Gets the display type. Gets the display type.

View File

@ -82,6 +82,7 @@ std::vector<std::string> AllMachines(Type type, bool long_names);
/*! /*!
Returns a map from long machine name to the list of options that machine exposes, for all machines. Returns a map from long machine name to the list of options that machine exposes, for all machines.
In all cases, user-friendly selections will have been filled in by default.
*/ */
std::map<std::string, std::unique_ptr<Reflection::Struct>> AllOptionsByMachineName(); std::map<std::string, std::unique_ptr<Reflection::Struct>> AllOptionsByMachineName();

View File

@ -38,7 +38,7 @@ class CharacterMapper {
/// that may not be necessary — it'll often depends on whether the machine needs time to /// that may not be necessary — it'll often depends on whether the machine needs time to
/// observe a modifier like shift before it sees the actual keypress. /// observe a modifier like shift before it sees the actual keypress.
/// @returns @c true if the typer should pause after forwarding @c key; @c false otherwise. /// @returns @c true if the typer should pause after forwarding @c key; @c false otherwise.
virtual bool needs_pause_after_key(uint16_t key) const { return true; } virtual bool needs_pause_after_key([[maybe_unused]] uint16_t key) const { return true; }
protected: protected:
typedef uint16_t KeySequence[16]; typedef uint16_t KeySequence[16];
@ -127,7 +127,7 @@ class TypeRecipient: public Typer::Delegate {
Provided in order to conform to that part of the Typer::Delegate interface that goes above and Provided in order to conform to that part of the Typer::Delegate interface that goes above and
beyond KeyboardMachine::Machine; responds to the end of typing by clearing all keys. beyond KeyboardMachine::Machine; responds to the end of typing by clearing all keys.
*/ */
void typer_reset(Typer *typer) { void typer_reset(Typer *) override {
clear_all_keys(); clear_all_keys();
// It's unsafe to deallocate typer right now, since it is the caller, but also it has a small // It's unsafe to deallocate typer right now, since it is the caller, but also it has a small

View File

@ -31,6 +31,7 @@ class Video {
/// Advances time by @c half-cycles. /// Advances time by @c half-cycles.
void run_for(const HalfCycles); void run_for(const HalfCycles);
/// Forces output to catch up to the current output position. /// Forces output to catch up to the current output position.
void flush(); void flush();

View File

@ -269,6 +269,7 @@ template<bool is_zx81> class ConcreteMachine:
tape_player_.set_motor_control((address >= automatic_tape_motor_start_address_) && (address < automatic_tape_motor_end_address_)); tape_player_.set_motor_control((address >= automatic_tape_motor_start_address_) && (address < automatic_tape_motor_end_address_));
} }
is_opcode_read = true; is_opcode_read = true;
[[fallthrough]];
case CPU::Z80::PartialMachineCycle::Read: case CPU::Z80::PartialMachineCycle::Read:
if(address < ram_base_) { if(address < ram_base_) {

View File

@ -1317,6 +1317,7 @@
4B98A05D1FFAD3F600ADF63B /* CSROMFetcher.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CSROMFetcher.mm; sourceTree = "<group>"; }; 4B98A05D1FFAD3F600ADF63B /* CSROMFetcher.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CSROMFetcher.mm; sourceTree = "<group>"; };
4B98A0601FFADCDE00ADF63B /* MSXStaticAnalyserTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MSXStaticAnalyserTests.mm; sourceTree = "<group>"; }; 4B98A0601FFADCDE00ADF63B /* MSXStaticAnalyserTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MSXStaticAnalyserTests.mm; sourceTree = "<group>"; };
4B98A1CD1FFADEC400ADF63B /* MSX ROMs */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "MSX ROMs"; sourceTree = "<group>"; }; 4B98A1CD1FFADEC400ADF63B /* MSX ROMs */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "MSX ROMs"; sourceTree = "<group>"; };
4B996B2D2496DAC2001660EF /* VSyncPredictor.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VSyncPredictor.hpp; sourceTree = "<group>"; };
4B9BE3FE203A0C0600FFAE60 /* MultiSpeaker.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MultiSpeaker.cpp; sourceTree = "<group>"; }; 4B9BE3FE203A0C0600FFAE60 /* MultiSpeaker.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MultiSpeaker.cpp; sourceTree = "<group>"; };
4B9BE3FF203A0C0600FFAE60 /* MultiSpeaker.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MultiSpeaker.hpp; sourceTree = "<group>"; }; 4B9BE3FF203A0C0600FFAE60 /* MultiSpeaker.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MultiSpeaker.hpp; sourceTree = "<group>"; };
4B9D0C4A22C7D70900DE1AD3 /* 68000BCDTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = 68000BCDTests.mm; sourceTree = "<group>"; }; 4B9D0C4A22C7D70900DE1AD3 /* 68000BCDTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = 68000BCDTests.mm; sourceTree = "<group>"; };
@ -3855,8 +3856,9 @@
4B8A7E85212F988200F2BBC6 /* DeferredQueue.hpp */, 4B8A7E85212F988200F2BBC6 /* DeferredQueue.hpp */,
4BB06B211F316A3F00600C7A /* ForceInline.hpp */, 4BB06B211F316A3F00600C7A /* ForceInline.hpp */,
4B80214322EE7C3E00068002 /* JustInTime.hpp */, 4B80214322EE7C3E00068002 /* JustInTime.hpp */,
4B449C942063389900A095C8 /* TimeTypes.hpp */,
4B644ED023F0FB55006C0CC5 /* ScanSynchroniser.hpp */, 4B644ED023F0FB55006C0CC5 /* ScanSynchroniser.hpp */,
4B449C942063389900A095C8 /* TimeTypes.hpp */,
4B996B2D2496DAC2001660EF /* VSyncPredictor.hpp */,
); );
name = ClockReceiver; name = ClockReceiver;
path = ../../ClockReceiver; path = ../../ClockReceiver;
@ -5137,6 +5139,7 @@
GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_PARAMETER = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.10; MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = YES; MTL_ENABLE_DEBUG_INFO = YES;
@ -5187,6 +5190,7 @@
GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_PARAMETER = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.10; MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;

View File

@ -72,7 +72,7 @@ struct ActivityObserver: public Activity::Observer {
[machine.delegate machine:machine led:[NSString stringWithUTF8String:name.c_str()] didChangeToLit:lit]; [machine.delegate machine:machine led:[NSString stringWithUTF8String:name.c_str()] didChangeToLit:lit];
} }
void announce_drive_event(const std::string &name, DriveEvent event) final { void announce_drive_event(const std::string &name, DriveEvent) final {
[machine.delegate machine:machine ledShouldBlink:[NSString stringWithUTF8String:name.c_str()]]; [machine.delegate machine:machine ledShouldBlink:[NSString stringWithUTF8String:name.c_str()]];
} }
@ -151,7 +151,6 @@ struct ActivityObserver: public Activity::Observer {
MachineTypes::JoystickMachine *_joystickMachine; MachineTypes::JoystickMachine *_joystickMachine;
CSJoystickManager *_joystickManager; CSJoystickManager *_joystickManager;
std::bitset<65536> _depressedKeys;
NSMutableArray<NSString *> *_leds; NSMutableArray<NSString *> *_leds;
CSHighPrecisionTimer *_timer; CSHighPrecisionTimer *_timer;

View File

@ -13,7 +13,7 @@
@implementation NSData (StdVector) @implementation NSData (StdVector)
- (NSNumber *)crc32 { - (NSNumber *)crc32 {
return @(crc32(crc32(0, Z_NULL, 0), self.bytes, (uInt)self.length)); return @(crc32(crc32(0, Z_NULL, 0), self.bytes, (uInt)self.length));
} }
@end @end

View File

@ -29,6 +29,8 @@
Analyser::Static::TargetList _targets; Analyser::Static::TargetList _targets;
} }
// MARK: - File-based Initialiser
- (instancetype)initWithFileAtURL:(NSURL *)url { - (instancetype)initWithFileAtURL:(NSURL *)url {
self = [super init]; self = [super init];
if(self) { if(self) {
@ -42,6 +44,55 @@
return self; return self;
} }
// MARK: - Machine-based Initialisers
- (instancetype)initWithAmstradCPCModel:(CSMachineCPCModel)model {
self = [super init];
if(self) {
using Target = Analyser::Static::AmstradCPC::Target;
auto target = std::make_unique<Target>();
switch(model) {
case CSMachineCPCModel464: target->model = Target::Model::CPC464; break;
case CSMachineCPCModel664: target->model = Target::Model::CPC664; break;
case CSMachineCPCModel6128: target->model = Target::Model::CPC6128; break;
}
_targets.push_back(std::move(target));
}
return self;
}
- (instancetype)initWithAppleIIModel:(CSMachineAppleIIModel)model diskController:(CSMachineAppleIIDiskController)diskController {
self = [super init];
if(self) {
using Target = Analyser::Static::AppleII::Target;
auto target = std::make_unique<Target>();
switch(model) {
default: target->model = Target::Model::II; break;
case CSMachineAppleIIModelAppleIIPlus: target->model = Target::Model::IIplus; break;
case CSMachineAppleIIModelAppleIIe: target->model = Target::Model::IIe; break;
case CSMachineAppleIIModelAppleEnhancedIIe: target->model = Target::Model::EnhancedIIe; break;
}
switch(diskController) {
default:
case CSMachineAppleIIDiskControllerNone: target->disk_controller = Target::DiskController::None; break;
case CSMachineAppleIIDiskControllerSixteenSector: target->disk_controller = Target::DiskController::SixteenSector; break;
case CSMachineAppleIIDiskControllerThirteenSector: target->disk_controller = Target::DiskController::ThirteenSector; break;
}
_targets.push_back(std::move(target));
}
return self;
}
- (instancetype)initWithAtariSTModel:(CSMachineAtariSTModel)model {
self = [super init];
if(self) {
using Target = Analyser::Static::AtariST::Target;
auto target = std::make_unique<Target>();
_targets.push_back(std::move(target));
}
return self;
}
- (instancetype)initWithElectronDFS:(BOOL)dfs adfs:(BOOL)adfs { - (instancetype)initWithElectronDFS:(BOOL)dfs adfs:(BOOL)adfs {
self = [super init]; self = [super init];
if(self) { if(self) {
@ -54,16 +105,21 @@
return self; return self;
} }
- (instancetype)initWithAmstradCPCModel:(CSMachineCPCModel)model { - (instancetype)initWithMacintoshModel:(CSMachineMacintoshModel)model {
self = [super init]; self = [super init];
if(self) { if(self) {
using Target = Analyser::Static::AmstradCPC::Target; using Target = Analyser::Static::Macintosh::Target;
auto target = std::make_unique<Target>(); auto target = std::make_unique<Target>();
using Model = Target::Model;
switch(model) { switch(model) {
case CSMachineCPCModel464: target->model = Analyser::Static::AmstradCPC::Target::Model::CPC464; break; default:
case CSMachineCPCModel664: target->model = Analyser::Static::AmstradCPC::Target::Model::CPC664; break; case CSMachineMacintoshModel128k: target->model = Model::Mac128k; break;
case CSMachineCPCModel6128: target->model = Analyser::Static::AmstradCPC::Target::Model::CPC6128; break; case CSMachineMacintoshModel512k: target->model = Model::Mac512k; break;
case CSMachineMacintoshModel512ke: target->model = Model::Mac512ke; break;
case CSMachineMacintoshModelPlus: target->model = Model::MacPlus; break;
} }
_targets.push_back(std::move(target)); _targets.push_back(std::move(target));
} }
return self; return self;
@ -76,9 +132,9 @@
auto target = std::make_unique<Target>(); auto target = std::make_unique<Target>();
target->has_disk_drive = !!hasDiskDrive; target->has_disk_drive = !!hasDiskDrive;
switch(region) { switch(region) {
case CSMachineMSXRegionAmerican: target->region = Analyser::Static::MSX::Target::Region::USA; break; case CSMachineMSXRegionAmerican: target->region = Target::Region::USA; break;
case CSMachineMSXRegionEuropean: target->region = Analyser::Static::MSX::Target::Region::Europe; break; case CSMachineMSXRegionEuropean: target->region = Target::Region::Europe; break;
case CSMachineMSXRegionJapanese: target->region = Analyser::Static::MSX::Target::Region::Japan; break; case CSMachineMSXRegionJapanese: target->region = Target::Region::Japan; break;
} }
_targets.push_back(std::move(target)); _targets.push_back(std::move(target));
} }
@ -166,57 +222,7 @@ static Analyser::Static::ZX8081::Target::MemoryModel ZX8081MemoryModelFromSize(K
return self; return self;
} }
- (instancetype)initWithAppleIIModel:(CSMachineAppleIIModel)model diskController:(CSMachineAppleIIDiskController)diskController { // MARK: - NIB mapping
self = [super init];
if(self) {
using Target = Analyser::Static::AppleII::Target;
auto target = std::make_unique<Target>();
switch(model) {
default: target->model = Target::Model::II; break;
case CSMachineAppleIIModelAppleIIPlus: target->model = Target::Model::IIplus; break;
case CSMachineAppleIIModelAppleIIe: target->model = Target::Model::IIe; break;
case CSMachineAppleIIModelAppleEnhancedIIe: target->model = Target::Model::EnhancedIIe; break;
}
switch(diskController) {
default:
case CSMachineAppleIIDiskControllerNone: target->disk_controller = Target::DiskController::None; break;
case CSMachineAppleIIDiskControllerSixteenSector: target->disk_controller = Target::DiskController::SixteenSector; break;
case CSMachineAppleIIDiskControllerThirteenSector: target->disk_controller = Target::DiskController::ThirteenSector; break;
}
_targets.push_back(std::move(target));
}
return self;
}
- (instancetype)initWithMacintoshModel:(CSMachineMacintoshModel)model {
self = [super init];
if(self) {
using Target = Analyser::Static::Macintosh::Target;
auto target = std::make_unique<Target>();
using Model = Target::Model;
switch(model) {
default:
case CSMachineMacintoshModel128k: target->model = Model::Mac128k; break;
case CSMachineMacintoshModel512k: target->model = Model::Mac512k; break;
case CSMachineMacintoshModel512ke: target->model = Model::Mac512ke; break;
case CSMachineMacintoshModelPlus: target->model = Model::MacPlus; break;
}
_targets.push_back(std::move(target));
}
return self;
}
- (instancetype)initWithAtariSTModel:(CSMachineAtariSTModel)model {
self = [super init];
if(self) {
using Target = Analyser::Static::AtariST::Target;
auto target = std::make_unique<Target>();
_targets.push_back(std::move(target));
}
return self;
}
- (NSString *)optionsPanelNibName { - (NSString *)optionsPanelNibName {
switch(_targets.front()->machine) { switch(_targets.front()->machine) {

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15702" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct"> <document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="16097" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies> <dependencies>
<deployment identifier="macosx"/> <deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15702"/> <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="16097"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies> </dependencies>
<objects> <objects>
@ -189,7 +189,7 @@ Gw
</tabViewItem> </tabViewItem>
<tabViewItem label="Electron" identifier="electron" id="muc-z9-Vqc"> <tabViewItem label="Electron" identifier="electron" id="muc-z9-Vqc">
<view key="view" id="SRc-2D-95G"> <view key="view" id="SRc-2D-95G">
<rect key="frame" x="10" y="33" width="604" height="94"/> <rect key="frame" x="10" y="33" width="674" height="94"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="JqM-IK-FMP"> <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="JqM-IK-FMP">
@ -220,7 +220,7 @@ Gw
</tabViewItem> </tabViewItem>
<tabViewItem label="Macintosh" identifier="mac" id="lmR-z3-xSm"> <tabViewItem label="Macintosh" identifier="mac" id="lmR-z3-xSm">
<view key="view" id="7Yf-vi-Q0W"> <view key="view" id="7Yf-vi-Q0W">
<rect key="frame" x="10" y="33" width="604" height="94"/> <rect key="frame" x="10" y="33" width="674" height="94"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ZOY-4E-Cfl"> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ZOY-4E-Cfl">
@ -257,7 +257,7 @@ Gw
</tabViewItem> </tabViewItem>
<tabViewItem label="MSX" identifier="msx" id="6SR-DY-zdI"> <tabViewItem label="MSX" identifier="msx" id="6SR-DY-zdI">
<view key="view" id="mWD-An-tR7"> <view key="view" id="mWD-An-tR7">
<rect key="frame" x="10" y="33" width="604" height="94"/> <rect key="frame" x="10" y="33" width="674" height="94"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="8xT-Pr-8SE"> <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="8xT-Pr-8SE">
@ -449,7 +449,7 @@ Gw
</tabViewItem> </tabViewItem>
<tabViewItem label="ZX80" identifier="zx80" id="tMH-kF-GUz"> <tabViewItem label="ZX80" identifier="zx80" id="tMH-kF-GUz">
<view key="view" id="8hL-Vn-Hg0"> <view key="view" id="8hL-Vn-Hg0">
<rect key="frame" x="10" y="33" width="604" height="94"/> <rect key="frame" x="10" y="33" width="674" height="94"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="I1a-Eu-5UB"> <popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="I1a-Eu-5UB">

View File

@ -67,7 +67,7 @@
CVDisplayLinkStart(_displayLink); CVDisplayLinkStart(_displayLink);
} }
static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *now, const CVTimeStamp *outputTime, CVOptionFlags flagsIn, CVOptionFlags *flagsOut, void *displayLinkContext) { static CVReturn DisplayLinkCallback(__unused CVDisplayLinkRef displayLink, const CVTimeStamp *now, const CVTimeStamp *outputTime, __unused CVOptionFlags flagsIn, __unused CVOptionFlags *flagsOut, void *displayLinkContext) {
CSOpenGLView *const view = (__bridge CSOpenGLView *)displayLinkContext; CSOpenGLView *const view = (__bridge CSOpenGLView *)displayLinkContext;
// Schedule an opportunity to check that the display link is still linked to the correct display. // Schedule an opportunity to check that the display link is still linked to the correct display.
@ -298,7 +298,7 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt
if(!self.shouldCaptureMouse) { if(!self.shouldCaptureMouse) {
[_mouseHideTimer invalidate]; [_mouseHideTimer invalidate];
_mouseHideTimer = [NSTimer scheduledTimerWithTimeInterval:3.0 repeats:NO block:^(NSTimer * _Nonnull timer) { _mouseHideTimer = [NSTimer scheduledTimerWithTimeInterval:3.0 repeats:NO block:^(__unused NSTimer * _Nonnull timer) {
[NSCursor setHiddenUntilMouseMoves:YES]; [NSCursor setHiddenUntilMouseMoves:YES];
[self.delegate openGLViewWillHideOSMouseCursor:self]; [self.delegate openGLViewWillHideOSMouseCursor:self];
}]; }];

View File

@ -23,7 +23,7 @@
} }
- (void)setUp { - (void)setUp {
_machine = std::make_unique<RAM68000>(); _machine = std::make_unique<RAM68000>();
} }
- (void)tearDown { - (void)tearDown {
@ -1137,7 +1137,7 @@
- (void)testMULU_Imm { - (void)testMULU_Imm {
self.machine->set_program({ self.machine->set_program({
0xc4fc, 0xffff // MULU.W #$ffff, D2 0xc4fc, 0xffff // MULU.W #$ffff, D2
}); });
auto state = self.machine->get_processor_state(); auto state = self.machine->get_processor_state();
state.data[2] = 0xffff; state.data[2] = 0xffff;

View File

@ -19,7 +19,7 @@
} }
- (void)setUp { - (void)setUp {
_machine = std::make_unique<RAM68000>(); _machine = std::make_unique<RAM68000>();
} }
- (void)tearDown { - (void)tearDown {

View File

@ -19,7 +19,7 @@
} }
- (void)setUp { - (void)setUp {
_machine = std::make_unique<RAM68000>(); _machine = std::make_unique<RAM68000>();
} }
- (void)tearDown { - (void)tearDown {

View File

@ -20,7 +20,7 @@
} }
- (void)setUp { - (void)setUp {
_machine = std::make_unique<RAM68000>(); _machine = std::make_unique<RAM68000>();
} }
- (void)tearDown { - (void)tearDown {

View File

@ -19,7 +19,7 @@
} }
- (void)setUp { - (void)setUp {
_machine = std::make_unique<RAM68000>(); _machine = std::make_unique<RAM68000>();
} }
- (void)tearDown { - (void)tearDown {

View File

@ -20,7 +20,7 @@
} }
- (void)setUp { - (void)setUp {
_machine = std::make_unique<RAM68000>(); _machine = std::make_unique<RAM68000>();
} }
- (void)tearDown { - (void)tearDown {

View File

@ -110,7 +110,7 @@ class CPU::MC68000::ProcessorStorageTests {
} }
- (void)setUp { - (void)setUp {
_machine = std::make_unique<RAM68000>(); _machine = std::make_unique<RAM68000>();
} }
- (void)tearDown { - (void)tearDown {

View File

@ -105,15 +105,15 @@ class EmuTOS: public ComparativeBusHandler {
- (void)testImage:(NSString *)image trace:(NSString *)trace length:(int)length { - (void)testImage:(NSString *)image trace:(NSString *)trace length:(int)length {
const std::vector<ROMMachine::ROM> rom_names = {{"AtariST", "", image.UTF8String, 0, 0 }}; const std::vector<ROMMachine::ROM> rom_names = {{"AtariST", "", image.UTF8String, 0, 0 }};
const auto roms = CSROMFetcher()(rom_names); const auto roms = CSROMFetcher()(rom_names);
NSString *const traceLocation = [[NSBundle bundleForClass:[self class]] pathForResource:trace ofType:@"trace.txt.gz"]; NSString *const traceLocation = [[NSBundle bundleForClass:[self class]] pathForResource:trace ofType:@"trace.txt.gz"];
_machine = std::make_unique<EmuTOS>(*roms[0], traceLocation.UTF8String); _machine = std::make_unique<EmuTOS>(*roms[0], traceLocation.UTF8String);
_machine->run_for(HalfCycles(length)); _machine->run_for(HalfCycles(length));
} }
- (void)testEmuTOSStartup { - (void)testEmuTOSStartup {
[self testImage:@"etos192uk.img" trace:@"etos192uk" length:313490]; [self testImage:@"etos192uk.img" trace:@"etos192uk" length:313490];
// TODO: assert that machine is now STOPped. // TODO: assert that machine is now STOPped.
} }
- (void)testTOSStartup { - (void)testTOSStartup {

73
OSBindings/Qt/.gitignore vendored Normal file
View File

@ -0,0 +1,73 @@
# This file is used to ignore files which are generated
# ----------------------------------------------------------------------------
*~
*.autosave
*.a
*.core
*.moc
*.o
*.obj
*.orig
*.rej
*.so
*.so.*
*_pch.h.cpp
*_resource.rc
*.qm
.#*
*.*#
core
!core/
tags
.DS_Store
.directory
*.debug
Makefile*
*.prl
*.app
moc_*.cpp
ui_*.h
qrc_*.cpp
Thumbs.db
*.res
*.rc
/.qmake.cache
/.qmake.stash
# qtcreator generated files
*.pro.user*
# xemacs temporary files
*.flc
# Vim temporary files
.*.swp
# Visual Studio generated files
*.ib_pdb_index
*.idb
*.ilk
*.pdb
*.sln
*.suo
*.vcproj
*vcproj.*.*.user
*.ncb
*.sdf
*.opensdf
*.vcxproj
*vcxproj.*
# MinGW generated files
*.Debug
*.Release
# Python byte code
*.pyc
# Binaries
# --------
*.dll
*.exe

View File

@ -0,0 +1,261 @@
QT += core gui multimedia widgets
CONFIG += c++17
# Permit multiple source files in different directories to have the same file name.
CONFIG += object_parallel_to_source
# Link against ZLib.
INCLUDEPATH += $$[QT_INSTALL_PREFIX]/src/3rdparty/zlib
LIBS += -lz
# Add flags (i) to identify that this is a Qt build; and
# (ii) to disable asserts in release builds.
DEFINES += TARGET_QT
QMAKE_CXXFLAGS_RELEASE += -DNDEBUG
# Generate warnings for any use of APIs deprecated prior to Qt 6.0.0.
# Development was performed against Qt 5.14.
DEFINES += QT_DEPRECATED_WARNINGS
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000
SOURCES += \
../../Analyser/Dynamic/*.cpp \
../../Analyser/Dynamic/MultiMachine/*.cpp \
../../Analyser/Dynamic/MultiMachine/Implementation/*.cpp \
\
../../Analyser/Static/*.cpp \
../../Analyser/Static/Acorn/*.cpp \
../../Analyser/Static/AmstradCPC/*.cpp \
../../Analyser/Static/AppleII/*.cpp \
../../Analyser/Static/Atari2600/*.cpp \
../../Analyser/Static/AtariST/*.cpp \
../../Analyser/Static/Coleco/*.cpp \
../../Analyser/Static/Commodore/*.cpp \
../../Analyser/Static/Disassembler/*.cpp \
../../Analyser/Static/DiskII/*.cpp \
../../Analyser/Static/Macintosh/*.cpp \
../../Analyser/Static/MSX/*.cpp \
../../Analyser/Static/Oric/*.cpp \
../../Analyser/Static/Sega/*.cpp \
../../Analyser/Static/ZX8081/*.cpp \
\
../../Components/1770/*.cpp \
../../Components/5380/*.cpp \
../../Components/6522/Implementation/*.cpp \
../../Components/6560/*.cpp \
../../Components/6850/*.cpp \
../../Components/68901/*.cpp \
../../Components/8272/*.cpp \
../../Components/8530/*.cpp \
../../Components/9918/*.cpp \
../../Components/AudioToggle/*.cpp \
../../Components/AY38910/*.cpp \
../../Components/DiskII/*.cpp \
../../Components/KonamiSCC/*.cpp \
../../Components/OPx/*.cpp \
../../Components/SN76489/*.cpp \
../../Components/Serial/*.cpp \
\
../../Concurrency/*.cpp \
\
../../Inputs/*.cpp \
\
../../Machines/*.cpp \
../../Machines/AmstradCPC/*.cpp \
../../Machines/Apple/AppleII/*.cpp \
../../Machines/Apple/Macintosh/*.cpp \
../../Machines/Atari/2600/*.cpp \
../../Machines/Atari/ST/*.cpp \
../../Machines/ColecoVision/*.cpp \
../../Machines/Commodore/*.cpp \
../../Machines/Commodore/1540/Implementation/*.cpp \
../../Machines/Commodore/Vic-20/*.cpp \
../../Machines/Electron/*.cpp \
../../Machines/MasterSystem/*.cpp \
../../Machines/MSX/*.cpp \
../../Machines/Oric/*.cpp \
../../Machines/Utility/*.cpp \
../../Machines/ZX8081/*.cpp \
\
../../Outputs/*.cpp \
../../Outputs/CRT/*.cpp \
../../Outputs/OpenGL/*.cpp \
../../Outputs/OpenGL/Primitives/*.cpp \
\
../../Processors/6502/Implementation/*.cpp \
../../Processors/6502/State/*.cpp \
../../Processors/68000/Implementation/*.cpp \
../../Processors/68000/State/*.cpp \
../../Processors/Z80/Implementation/*.cpp \
../../Processors/Z80/State/*.cpp \
\
../../Reflection/*.cpp \
\
../../SignalProcessing/*.cpp \
\
../../Storage/*.cpp \
../../Storage/Cartridge/*.cpp \
../../Storage/Cartridge/Encodings/*.cpp \
../../Storage/Cartridge/Formats/*.cpp \
../../Storage/Data/*.cpp \
../../Storage/Disk/*.cpp \
../../Storage/Disk/Controller/*.cpp \
../../Storage/Disk/DiskImage/Formats/*.cpp \
../../Storage/Disk/DiskImage/Formats/Utility/*.cpp \
../../Storage/Disk/Encodings/*.cpp \
../../Storage/Disk/Encodings/AppleGCR/*.cpp \
../../Storage/Disk/Encodings/MFM/*.cpp \
../../Storage/Disk/Parsers/*.cpp \
../../Storage/Disk/Track/*.cpp \
../../Storage/MassStorage/*.cpp \
../../Storage/MassStorage/Encodings/*.cpp \
../../Storage/MassStorage/Formats/*.cpp \
../../Storage/MassStorage/SCSI/*.cpp \
../../Storage/Tape/*.cpp \
../../Storage/Tape/Formats/*.cpp \
../../Storage/Tape/Parsers/*.cpp \
\
main.cpp \
mainwindow.cpp \
scantargetwidget.cpp \
timer.cpp
HEADERS += \
../../Activity/*.hpp \
\
../../Analyser/*.hpp \
../../Analyser/Dynamic/*.hpp \
../../Analyser/Dynamic/MultiMachine/*.hpp \
../../Analyser/Dynamic/MultiMachine/Implementation/*.hpp \
\
../../Analyser/Static/*.hpp \
../../Analyser/Static/Acorn/*.hpp \
../../Analyser/Static/AmstradCPC/*.hpp \
../../Analyser/Static/AppleII/*.hpp \
../../Analyser/Static/Atari2600/*.hpp \
../../Analyser/Static/AtariST/*.hpp \
../../Analyser/Static/Coleco/*.hpp \
../../Analyser/Static/Commodore/*.hpp \
../../Analyser/Static/Disassembler/*.hpp \
../../Analyser/Static/DiskII/*.hpp \
../../Analyser/Static/Macintosh/*.hpp \
../../Analyser/Static/MSX/*.hpp \
../../Analyser/Static/Oric/*.hpp \
../../Analyser/Static/Sega/*.hpp \
../../Analyser/Static/ZX8081/*.hpp \
\
../../ClockReceiver/*.hpp \
\
../../Components/1770/*.hpp \
../../Components/5380/*.hpp \
../../Components/6522/*.hpp \
../../Components/6522/Implementation/*.hpp \
../../Components/6532/*.hpp \
../../Components/6560/*.hpp \
../../Components/6845/*.hpp \
../../Components/6850/*.hpp \
../../Components/8255/*.hpp \
../../Components/8272/*.hpp \
../../Components/8530/*.hpp \
../../Components/9918/*.hpp \
../../Components/9918/Implementation/*.hpp \
../../Components/68901/*.hpp \
../../Components/AudioToggle/*.hpp \
../../Components/AY38910/*.hpp \
../../Components/DiskII/*.hpp \
../../Components/KonamiSCC/*.hpp \
../../Components/OPx/*.hpp \
../../Components/OPx/Implementation/*.hpp \
../../Components/Serial/*.hpp \
../../Components/SN76489/*.hpp \
\
../../Concurrency/*.hpp \
\
../../Configurable/*.hpp \
\
../../Inputs/*.hpp \
../../Inputs/QuadratureMouse/*.hpp \
\
../../Machines/*.hpp \
../../Machines/AmstradCPC/*.hpp \
../../Machines/Apple/AppleII/*.hpp \
../../Machines/Apple/Macintosh/*.hpp \
../../Machines/Atari/2600/*.hpp \
../../Machines/Atari/ST/*.hpp \
../../Machines/ColecoVision/*.hpp \
../../Machines/Commodore/*.hpp \
../../Machines/Commodore/1540/Implementation/*.hpp \
../../Machines/Commodore/Vic-20/*.hpp \
../../Machines/Electron/*.hpp \
../../Machines/MasterSystem/*.hpp \
../../Machines/MSX/*.hpp \
../../Machines/Oric/*.hpp \
../../Machines/Utility/*.hpp \
../../Machines/ZX8081/*.hpp \
\
../../Numeric/*.hpp \
\
../../Outputs/*.hpp \
../../Outputs/CRT/*.hpp \
../../Outputs/CRT/Internals/*.hpp \
../../Outputs/OpenGL/*.hpp \
../../Outputs/OpenGL/Primitives/*.hpp \
../../Outputs/Speaker/*.hpp \
../../Outputs/Speaker/Implementation/*.hpp \
\
../../Processors/6502/*.hpp \
../../Processors/6502/Implementation/*.hpp \
../../Processors/6502/State/*.hpp \
../../Processors/68000/*.hpp \
../../Processors/68000/Implementation/*.hpp \
../../Processors/68000/State/*.hpp \
../../Processors/Z80/*.hpp \
../../Processors/Z80/Implementation/*.hpp \
../../Processors/Z80/State/*.hpp \
\
../../Reflection/*.hpp \
\
../../SignalProcessing/*.hpp \
\
../../Storage/*.hpp \
../../Storage/Cartridge/*.hpp \
../../Storage/Cartridge/Encodings/*.hpp \
../../Storage/Cartridge/Formats/*.hpp \
../../Storage/Data/*.hpp \
../../Storage/Disk/*.hpp \
../../Storage/Disk/Controller/*.hpp \
../../Storage/Disk/DiskImage/*.hpp \
../../Storage/Disk/DiskImage/Formats/*.hpp \
../../Storage/Disk/DiskImage/Formats/Utility/*.hpp \
../../Storage/Disk/DPLL/*.hpp \
../../Storage/Disk/Encodings/*.hpp \
../../Storage/Disk/Encodings/AppleGCR/*.hpp \
../../Storage/Disk/Encodings/MFM/*.hpp \
../../Storage/Disk/Parsers/*.hpp \
../../Storage/Disk/Track/*.hpp \
../../Storage/MassStorage/*.hpp \
../../Storage/MassStorage/Encodings/*.hpp \
../../Storage/MassStorage/Formats/*.hpp \
../../Storage/MassStorage/SCSI/*.hpp \
../../Storage/Tape/*.hpp \
../../Storage/Tape/Formats/*.hpp \
../../Storage/Tape/Parsers/*.hpp \
\
audiobuffer.h \
functionthread.h \
mainwindow.h \
scantargetwidget.h \
settings.h \
timer.h
FORMS += \
mainwindow.ui
TRANSLATIONS += \
ClockSignal_en_GB.ts
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

View File

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="ClockSignal_en_GB"></TS>

View File

@ -0,0 +1,95 @@
#ifndef AUDIOSOURCE_H
#define AUDIOSOURCE_H
#include <cstdint>
#include <mutex>
#include <vector>
#include <QIODevice>
/*!
* \brief Provides an intermediate receipticle for audio data.
*
* Provides a QIODevice that will attempt to buffer the minimum amount
* of data before handing it off to a polling QAudioOutput.
*
* Adding an extra buffer increases worst-case latency but resolves a
* startup race condition in which it is difficult to tell how much data a
* QAudioOutput that is populated by pushing data currently has buffered;
* it also works around what empirically seemed to be a minimum 16384-byte
* latency on push audio generation.
*/
struct AudioBuffer: public QIODevice {
AudioBuffer() {
open(QIODevice::ReadOnly | QIODevice::Unbuffered);
}
void setDepth(size_t depth) {
std::lock_guard lock(mutex);
buffer.resize(depth);
}
// AudioBuffer-specific behaviour: always provide the latest data,
// even if that means skipping some.
qint64 readData(char *data, const qint64 maxlen) override {
if(!maxlen) {
return 0;
}
std::lock_guard lock(mutex);
if(readPointer == writePointer || buffer.empty()) return 0;
const size_t dataAvailable = std::min(writePointer - readPointer, size_t(maxlen));
size_t bytesToCopy = dataAvailable;
while(bytesToCopy) {
const size_t nextLength = std::min(buffer.size() - (readPointer % buffer.size()), bytesToCopy);
memcpy(data, &buffer[readPointer % buffer.size()], nextLength);
bytesToCopy -= nextLength;
data += nextLength;
readPointer += nextLength;
}
return qint64(dataAvailable);
}
qint64 bytesAvailable() const override {
std::lock_guard lock(mutex);
return qint64(writePointer - readPointer);
}
// Required to make QIODevice concrete; not used.
qint64 writeData(const char *, qint64) override {
return 0;
}
// Posts a new set of source data. This buffer permits only the amount of data
// specified by @c setDepth to be enqueued into the future. Additional writes
// after the buffer is full will overwrite the newest data.
void write(const std::vector<int16_t> &source) {
std::lock_guard lock(mutex);
if(buffer.empty()) return;
const size_t sourceSize = source.size() * sizeof(int16_t);
size_t bytesToCopy = sourceSize;
auto data = reinterpret_cast<const uint8_t *>(source.data());
while(bytesToCopy) {
size_t nextLength = std::min(buffer.size() - (writePointer % buffer.size()), bytesToCopy);
memcpy(&buffer[writePointer % buffer.size()], data, nextLength);
bytesToCopy -= nextLength;
data += nextLength;
writePointer += nextLength;
}
readPointer = std::max(readPointer, writePointer - buffer.size());
}
private:
mutable std::mutex mutex;
std::vector<uint8_t> buffer;
mutable size_t readPointer = 0;
size_t writePointer = 0;
};
#endif // AUDIOSOURCE_H

View File

@ -0,0 +1,91 @@
#ifndef FUNCTIONTHREAD_H
#define FUNCTIONTHREAD_H
#include <atomic>
#include <QApplication>
#include <QDebug>
#include <QEvent>
#include <QThread>
/*!
* \brief The LambdaThread class
*
* Provides a QThread to which lambdas can be posted.
*
* Disclaimer: this might be a crutch that reveals a misunderstanding of the Qt
* threading infrastructure. We'll see.
*/
class FunctionThread: public QThread {
public:
~FunctionThread() {
stop();
}
void run() override {
// Gymnastics here: events posted directly to the QThread will occur on the thread
// that created the QThread. To have events occur within a QThread, they have to be
// posted to an object created on that thread. FunctionPerformer fills that role.
if(!performer) performer = std::make_unique<FunctionPerformer>();
performerFlag.clear();
exec();
}
void stop() {
if(isRunning()) {
performAsync([this] {
this->quit();
});
}
wait();
}
void start() {
if(isRunning()) {
return;
}
// TODO: I've assumed a race condition here with the creation of performer; if QThread
// blocks on completion of `run` when starting then this is redundant.
performerFlag.test_and_set();
QThread::start();
while(performerFlag.test_and_set());
}
/*!
* \brief Schedules a function to be performed on this thread. Control
* must return to the main event loop for the function to be performed;
* use QCoreApplication::sendPostedEvents() to ensure the function is
* performed before then, if required.
*
* \param function The function to perform.
*/
void performAsync(const std::function<void(void)> &function) {
QApplication::instance()->postEvent(performer.get(), new FunctionEvent(function));
QCoreApplication::sendPostedEvents();
}
private:
struct FunctionEvent: public QEvent {
FunctionEvent(const std::function<void(void)> &function) : QEvent(QEvent::Type::User), function(function) {}
std::function<void(void)> function;
};
struct FunctionPerformer: public QObject {
FunctionPerformer(): QObject() {}
bool event(QEvent *event) override {
if(event->type() == QEvent::Type::User) {
const auto functionEvent = dynamic_cast<FunctionEvent *>(event);
if(functionEvent) {
functionEvent->function();
return true;
}
}
return QObject::event(event);
}
};
std::unique_ptr<FunctionPerformer> performer;
std::atomic_flag performerFlag;
};
#endif // FUNCTIONTHREAD_H

26
OSBindings/Qt/main.cpp Normal file
View File

@ -0,0 +1,26 @@
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
// "Calling QSurfaceFormat::setDefaultFormat() before constructing the
// QApplication instance is mandatory on some platforms ... when an
// OpenGL core profile context is requested."
QSurfaceFormat format;
format.setVersion(3, 2);
format.setProfile(QSurfaceFormat::CoreProfile);
format.setDepthBufferSize(0);
format.setStencilBufferSize(0);
QSurfaceFormat::setDefaultFormat(format);
// TODO: something with QCommandLineParser to accept a file to launch.
QApplication a(argc, argv);
MainWindow *w = new MainWindow();
w->setAttribute(Qt::WA_DeleteOnClose);
w->show();
return a.exec();
}

Some files were not shown because too many files have changed in this diff Show More