1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-25 18:30:07 +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 {
public:
/// 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.
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.
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 {
StepNormal,
@ -39,10 +39,10 @@ class Observer {
};
/// 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.
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::mutex mutex;
{
std::lock_guard<decltype(machines_mutex_)> machines_lock(machines_mutex_);
std::lock_guard<std::mutex> lock(mutex);
std::lock_guard machines_lock(machines_mutex_);
std::lock_guard lock(mutex);
outstanding_machines = machines_.size();
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]() {
if(machine) function(machine);
std::lock_guard<std::mutex> lock(mutex);
std::lock_guard lock(mutex);
outstanding_machines--;
condition.notify_all();
});
}
}
std::unique_lock<std::mutex> lock(mutex);
std::unique_lock lock(mutex);
condition.wait(lock, [&outstanding_machines] { return !outstanding_machines; });
}
template <typename MachineType>
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_) {
const auto typed_machine = ::Machine::get<MachineType>(*machine.get());
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) {
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();
if(machine) machine->set_scan_target(scan_target);
}
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();
if(machine) return machine->get_scan_status();
return Outputs::Display::ScanStatus();
@ -74,7 +74,7 @@ void MultiScanProducer::did_change_machine_order() {
perform_serial([](MachineTypes::ScanProducer *machine) {
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();
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;
private:
void run_for(const Cycles cycles) final {}
void run_for(const Cycles) final {}
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) {
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;
}
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) {
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;
}
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) {
{
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();
}
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 *) {
std::lock_guard<decltype(machines_mutex_)> machines_lock(machines_mutex_);
std::lock_guard machines_lock(machines_mutex_);
#ifndef NDEBUG
for(const auto &machine: machines_) {
auto timed_machine = machine->timed_machine();

View File

@ -57,7 +57,7 @@ static std::vector<std::shared_ptr<Storage::Cartridge::Cartridge>>
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>();
target->confidence = 0.5; // TODO: a proper estimation
target->has_dfs = false;

View File

@ -179,7 +179,7 @@ static bool CheckBootSector(const std::shared_ptr<Storage::Disk::Disk> &disk, co
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;
auto target = std::make_unique<Target>();
target->confidence = 0.5;

View File

@ -9,7 +9,7 @@
#include "StaticAnalyser.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>();
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;
}
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.
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;
}
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.
target.paging_model =
(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?
auto target = std::make_unique<Target>();
target->confidence = 0.5;

View File

@ -9,7 +9,7 @@
#include "StaticAnalyser.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.
if(media.disks.empty()) return {};

View File

@ -52,7 +52,7 @@ static std::vector<std::shared_ptr<Storage::Cartridge::Cartridge>>
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;
auto target = std::make_unique<Target>(Machine::ColecoVision);
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;
}
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;
auto target = std::make_unique<Target>();
@ -94,6 +94,7 @@ Analyser::Static::TargetList Analyser::Static::Commodore::GetTargets(const Media
switch(files.front().starting_address) {
default:
LOG("Unrecognised loading address for Commodore program: " << PADHEX(4) << files.front().starting_address);
[[fallthrough]];
case 0x1001:
memory_model = Target::MemoryModel::Unexpanded;
break;

View File

@ -31,7 +31,7 @@ Analyser::Static::Target *AppleTarget(const Storage::Encodings::AppleGCR::Sector
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;
auto *const target = new Target;
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.
if(media.disks.empty()) return {};

View File

@ -260,7 +260,7 @@ static Analyser::Static::TargetList CartridgeTargetsFrom(
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;
// Append targets for any cartridges that look correct.

View File

@ -9,7 +9,7 @@
#include "StaticAnalyser.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.
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>();
target->confidence = 0.5;

View File

@ -13,7 +13,7 @@
#include <algorithm>
#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())
return {};

View File

@ -28,7 +28,7 @@ static std::vector<Storage::Data::ZX8081::File> GetFiles(const std::shared_ptr<S
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;
if(!media.tapes.empty()) {
std::vector<Storage::Data::ZX8081::File> files = GetFiles(media.tapes.front());

View File

@ -176,7 +176,6 @@ class Cycles: public WrappedInt<Cycles> {
public:
forceinline constexpr Cycles(IntType l) noexcept : WrappedInt<Cycles>(l) {}
forceinline constexpr Cycles() noexcept : WrappedInt<Cycles>() {}
forceinline constexpr Cycles(const Cycles &cycles) noexcept : WrappedInt<Cycles>(cycles.length_) {}
private:
friend WrappedInt;
@ -198,7 +197,6 @@ class HalfCycles: public 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 HalfCycles &half_cycles) noexcept : WrappedInt<HalfCycles>(half_cycles.length_) {}
/// @returns The number of whole cycles completely covered by this span of half cycles.
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()) {
LOG("CRC error; terminating");
update_status([this] (Status &status) {
update_status([] (Status &status) {
status.crc_error = true;
});
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();
}
void WD1770::set_head_load_request(bool head_load) {}
void WD1770::set_motor_on(bool motor_on) {}
void WD1770::set_head_load_request(bool) {}
void WD1770::set_motor_on(bool) {}
void WD1770::set_head_loaded(bool 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.
*/
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.
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) {
device_id_ = bus_.add_device();
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) {
case 0:
// 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) {
case 0:
// 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:
if(!(new_state & SCSI::Line::Busy) || time_since_change < SCSI::DeskewDelay) return;
state_ = ExecutionState::WatchingBusy;
[[fallthrough]];
case ExecutionState::WatchingBusy:
if(!(new_state & SCSI::Line::Busy)) {

View File

@ -37,22 +37,22 @@ enum Line {
class PortHandler {
public:
/// 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.
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.
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.
void set_interrupt_status(bool status) {}
void set_interrupt_status([[maybe_unused]] bool status) {}
/// 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.
void flush() {}
void flush() {}
};
/*!

View File

@ -14,6 +14,6 @@ void IRQDelegatePortHandler::set_interrupt_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);
}

View File

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

View File

@ -43,7 +43,7 @@ class AudioGenerator: public ::Outputs::Speaker::SampleSource {
};
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;
*colour_data = 0xff;
}

View File

@ -148,7 +148,7 @@ uint8_t ACIA::parity(uint8_t value) {
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
// the largest transmission symbol.
++bits_received_;

View File

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

View File

@ -80,6 +80,10 @@ i8272::i8272(BusHandler &bus_handler, Cycles clock_rate) :
Storage::Disk::MFMController(clock_rate),
bus_handler_(bus_handler) {
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 {
@ -880,13 +884,13 @@ bool i8272::seek_is_satisfied(int drive) {
(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() {

View File

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

View File

@ -40,7 +40,7 @@ enum class TVStandard {
class Base {
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;
uint8_t *const result_ptr = reinterpret_cast<uint8_t *>(&result);
result_ptr[0] = r;
@ -421,7 +421,8 @@ class Base {
*/
#define slot(n) \
if(use_end && end == n) return;\
if(use_end && end == n) return; \
[[fallthrough]]; \
case 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) {
@ -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) {

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.
*/
virtual uint8_t get_port_input(bool port_b) {
virtual uint8_t get_port_input([[maybe_unused]] bool port_b) {
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 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;
}
void Toggle::skip_samples(const std::size_t number_of_samples) {}
void Toggle::skip_samples(std::size_t) {}
void Toggle::set_output(bool enabled) {
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_[1] = drives_[1].preferred_clocking() == ClockingHint::Preference::None;
decide_clocking_preference();

View File

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

View File

@ -24,7 +24,7 @@ namespace Apple {
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
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.
*/
struct IWMDrive: public Storage::Disk::Drive {
@ -82,8 +82,9 @@ class IWM:
uint8_t data_register_ = 0;
uint8_t mode_ = 0;
bool read_write_ready_ = true;
bool write_overran_ = false;
// These related to functionality not-yet implemented.
// bool read_write_ready_ = true;
// bool write_overran_ = false;
int state_ = 0;

View File

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

View File

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

View File

@ -216,11 +216,8 @@ class ConcreteJoystick: public Joystick {
}
protected:
virtual void did_set_input(const Input &input, float value) {
}
virtual void did_set_input(const Input &input, bool 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) {}
private:
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) :
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);
if(key_offset >= key_states_.size()) {
key_states_.resize(key_offset+1, false);

View File

@ -20,7 +20,7 @@ class 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.
@ -34,7 +34,7 @@ class Mouse {
The intention is that @c index be semantic, not positional:
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.

View File

@ -691,11 +691,11 @@ class FDC: public Intel::i8272::i8272 {
get_drive().set_motor_on(on);
}
void select_drive(int c) {
// TODO: support more than one drive.
void select_drive(int) {
// 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);
}
@ -1075,7 +1075,7 @@ template <bool has_fdc> class ConcreteMachine:
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;
tape_player_is_sleeping_ = tape_player_.preferred_clocking() == ClockingHint::Preference::None;
}
@ -1112,7 +1112,7 @@ template <bool has_fdc> class ConcreteMachine:
}
// 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);
}

View File

@ -32,7 +32,7 @@ class Machine {
class Options: public Reflection::StructImpl<Options>, public Configurable::DisplayOption<Options> {
friend Configurable::DisplayOption<Options>;
public:
Options(Configurable::OptionsType type) : Configurable::DisplayOption<Options>(Configurable::Display::RGB) {
Options(Configurable::OptionsType) : Configurable::DisplayOption<Options>(Configurable::Display::RGB) {
if(needs_declare()) {
declare_display_option();
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);
}
void reset_all_keys() final {
void reset_all_keys(Inputs::Keyboard *) final {
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> {
friend Configurable::DisplayOption<Options>;
public:
Options(Configurable::OptionsType type) : Configurable::DisplayOption<Options>(Configurable::Display::CompositeColour) {
Options(Configurable::OptionsType) : Configurable::DisplayOption<Options>(Configurable::Display::CompositeColour) {
if(needs_declare()) {
declare_display_option();
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
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.
virtual void flush() {}
@ -89,7 +89,7 @@ class Card {
}
/*! 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 {
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;
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);
}
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;
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;
for(size_t c = 0; c < length; ++c) {
// 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,
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.
*/
void run_for(HalfCycles cycle) {
void run_for(HalfCycles) { // TODO: honour the HalfCycles argument.
switch(mode_) {
default:
case Mode::Waiting: return;
@ -210,7 +210,7 @@ class Keyboard {
void enqueue_key_state(uint16_t key, bool is_pressed) {
// 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
// they are indicated by having bit 8 set. So add the $79 prefix if required.
@ -228,7 +228,7 @@ class Keyboard {
switch(command) {
case 0x10: // Inquiry.
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()) {
const auto new_message = key_queue_.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;
forceinline HalfCycles perform_bus_operation(const Microcycle &cycle, int is_supervisor) {
forceinline HalfCycles perform_bus_operation(const Microcycle &cycle, int) {
// Advance time.
advance_time(cycle.length);
@ -490,7 +490,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
// 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();
}
@ -541,7 +541,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
private:
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;
}
@ -654,7 +654,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
using Port = MOS::MOS6522::Port;
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.
(See p176 [/215])
@ -745,7 +745,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
audio_.flush();
}
void set_interrupt_status(bool status) {
void set_interrupt_status(bool) {
machine_.update_interrupt_input();
}

View File

@ -212,7 +212,7 @@ class ConcreteMachine:
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);
return new Atari2600::ConcreteMachine(*atari_target);
}

View File

@ -19,7 +19,7 @@ class BusExtender: public CPU::MOS6502::BusHandler {
public:
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:
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};
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 *rom_ptr_;
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)
perform_motion_step<T>(object);
}

View File

@ -239,15 +239,15 @@ class TIA {
int size = 1;
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);
}
inline void reset_pixels(int copy) {
inline void reset_pixels(int) {
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;
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 enqueue_pixels(const int start, const int end, int from_horizontal_counter) {}
void dequeue_pixels([[maybe_unused]] uint8_t *const target, [[maybe_unused]] uint8_t collision_identity, [[maybe_unused]] int time_now) {}
void enqueue_pixels([[maybe_unused]] int start, [[maybe_unused]] int end, [[maybe_unused]] int from_horizontal_counter) {}
};
// missile state

View File

@ -237,6 +237,7 @@ class ConcreteMachine:
memory = rom_.data();
break;
}
[[fallthrough]];
case BusDevice::RAM:
memory = ram_.data();
break;
@ -529,7 +530,7 @@ class ConcreteMachine:
bool keyboard_needs_clock_ = false;
bool mfp_is_realtime_ = false;
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
// already dealt with (and, just to be absolutely sure, to avoid recursive mania).
may_defer_acias_ =
@ -580,7 +581,7 @@ class ConcreteMachine:
}
// 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();
}

View File

@ -84,7 +84,7 @@ void IntelligentKeyboard::run_for(HalfCycles duration) {
// Forward key changes; implicit assumption here: mutexs are cheap while there's
// 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_) {
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]);
}
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");
}
@ -308,7 +308,7 @@ void IntelligentKeyboard::set_mouse_y_upward() {
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");
}
@ -348,7 +348,7 @@ void IntelligentKeyboard::post_relative_mouse_event(int x, int y) {
// MARK: - Keyboard Input
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) {
key_queue_.push_back(uint8_t(key));
} else {
@ -461,6 +461,10 @@ void IntelligentKeyboard::set_joystick_interrogation_mode() {
}
void IntelligentKeyboard::set_joystick_keycode_mode(VelocityThreshold horizontal, VelocityThreshold vertical) {
// TODO: honour velocity thresholds.
(void)horizontal;
(void)vertical;
joystick_mode_ = JoystickMode::KeyCode;
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");
}

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));
}
void Video::set_ram(uint16_t *ram, size_t size) {
void Video::set_ram(uint16_t *ram, size_t) {
ram_ = ram;
}

View File

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

View File

@ -39,7 +39,7 @@ namespace C1540 {
/*!
Provides an emulation of the C1540.
*/
class Machine: public MachineBase {
class Machine final: public MachineBase {
public:
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
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
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
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));
}
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)));
}
@ -170,7 +170,7 @@ uint8_t SerialPortVIA::get_port_input(MOS::MOS6522::Port port) {
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) {
std::shared_ptr<::Commodore::Serial::Port> serialPort = serial_port_.lock();
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(previous_port_b_output_ != value) {
// record drive motor state

View File

@ -75,6 +75,7 @@ namespace Serial {
class Port {
public:
Port() : line_levels_{High, High, High, High, High} {}
virtual ~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.
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.
if(!port) {
std::shared_ptr<::Commodore::Serial::Port> serialPort = serial_port_.lock();
@ -654,7 +654,7 @@ class ConcreteMachine:
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_irq_line(keyboard_via_.get_interrupt_line());
}
@ -691,7 +691,7 @@ class ConcreteMachine:
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;
set_use_fast_tape();
}

View File

@ -215,7 +215,8 @@ class ConcreteMachine:
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 0xfe08: case 0xfe09: case 0xfe0a: case 0xfe0b:
@ -421,7 +422,7 @@ class ConcreteMachine:
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();
evaluate_interrupts();
}

View File

@ -14,7 +14,7 @@
namespace Electron {
class Plus3 : public WD::WD1770 {
class Plus3 final : public WD::WD1770 {
public:
Plus3();
@ -26,7 +26,7 @@ class Plus3 : public WD::WD1770 {
void set_control_register(uint8_t control, uint8_t changes);
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);
};

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) {
// TODO: use value.
(void)value;
output_.cycles_into_pulse = 0;
output_.bits_remaining_until_empty = 0;
}

View File

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

View File

@ -14,14 +14,14 @@ MachineTypes::MappedKeyboardMachine::MappedKeyboardMachine(const std::set<Inputs
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);
if(mapped_key == KeyNotMapped) return false;
set_key_state(mapped_key, is_pressed);
return true;
}
void MappedKeyboardMachine::reset_all_keys(Inputs::Keyboard *keyboard) {
void MappedKeyboardMachine::reset_all_keys(Inputs::Keyboard *) {
// TODO: unify naming.
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
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.
@ -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.
*/
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.

View File

@ -17,14 +17,14 @@ DiskROM::DiskROM(const std::vector<uint8_t> &rom) :
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) {
case 0x7ff8: case 0x7ff9: case 0x7ffa: case 0x7ffb:
WD::WD1770::write(address, value);
break;
case 0x7ffc: {
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);
});
} break;
@ -32,7 +32,7 @@ void DiskROM::write(uint16_t address, uint8_t value, bool pc_is_outside_bios) {
set_drive(1 << (value & 1));
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);
});
} break;

View File

@ -492,6 +492,8 @@ class ConcreteMachine:
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.
[[fallthrough]];
case CPU::Z80::PartialMachineCycle::Read:
if(read_pointers_[address >> 13]) {
*cycle.value = read_pointers_[address >> 13][address & 8191];
@ -662,7 +664,7 @@ class ConcreteMachine:
}
// 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;
set_use_fast_tape();
}

View File

@ -47,13 +47,13 @@ class ROMSlotHandler {
virtual ~ROMSlotHandler() {}
/*! 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. */
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. */
virtual uint8_t read(uint16_t address) { return 0xff; }
virtual uint8_t read([[maybe_unused]] uint16_t address) { return 0xff; }
enum class WrappingStrategy {
/// 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
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) {
keyboard_.set_active_row(value);
tape_player_.set_motor_control(value & 0x40);
@ -267,13 +267,13 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface> class Co
switch(disk_interface) {
default: break;
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;
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;
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;
case DiskInterface::Pravetz:
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
void mos6522_did_change_interrupt_status(void *mos6522) final {
void mos6522_did_change_interrupt_status(void *) final {
set_interrupt_line();
}
@ -608,7 +608,7 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface> class Co
}
// WD::WD1770::Delegate
void wd1770_did_change_output(WD::WD1770 *wd1770) final {
void wd1770_did_change_output(WD::WD1770 *) final {
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();
}

View File

@ -91,7 +91,7 @@ class ScanProducer {
/*!
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.

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.
In all cases, user-friendly selections will have been filled in by default.
*/
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
/// 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.
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:
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
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();
// 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.
void run_for(const HalfCycles);
/// Forces output to catch up to the current output position.
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_));
}
is_opcode_read = true;
[[fallthrough]];
case CPU::Z80::PartialMachineCycle::Read:
if(address < ram_base_) {

View File

@ -1317,6 +1317,7 @@
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>"; };
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>"; };
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>"; };
@ -3855,8 +3856,9 @@
4B8A7E85212F988200F2BBC6 /* DeferredQueue.hpp */,
4BB06B211F316A3F00600C7A /* ForceInline.hpp */,
4B80214322EE7C3E00068002 /* JustInTime.hpp */,
4B449C942063389900A095C8 /* TimeTypes.hpp */,
4B644ED023F0FB55006C0CC5 /* ScanSynchroniser.hpp */,
4B449C942063389900A095C8 /* TimeTypes.hpp */,
4B996B2D2496DAC2001660EF /* VSyncPredictor.hpp */,
);
name = ClockReceiver;
path = ../../ClockReceiver;
@ -5137,6 +5139,7 @@
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_PARAMETER = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = YES;
@ -5187,6 +5190,7 @@
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_PARAMETER = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.10;
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];
}
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()]];
}
@ -151,7 +151,6 @@ struct ActivityObserver: public Activity::Observer {
MachineTypes::JoystickMachine *_joystickMachine;
CSJoystickManager *_joystickManager;
std::bitset<65536> _depressedKeys;
NSMutableArray<NSString *> *_leds;
CSHighPrecisionTimer *_timer;

View File

@ -13,7 +13,7 @@
@implementation NSData (StdVector)
- (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

View File

@ -29,6 +29,8 @@
Analyser::Static::TargetList _targets;
}
// MARK: - File-based Initialiser
- (instancetype)initWithFileAtURL:(NSURL *)url {
self = [super init];
if(self) {
@ -42,6 +44,55 @@
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 {
self = [super init];
if(self) {
@ -54,16 +105,21 @@
return self;
}
- (instancetype)initWithAmstradCPCModel:(CSMachineCPCModel)model {
- (instancetype)initWithMacintoshModel:(CSMachineMacintoshModel)model {
self = [super init];
if(self) {
using Target = Analyser::Static::AmstradCPC::Target;
using Target = Analyser::Static::Macintosh::Target;
auto target = std::make_unique<Target>();
using Model = Target::Model;
switch(model) {
case CSMachineCPCModel464: target->model = Analyser::Static::AmstradCPC::Target::Model::CPC464; break;
case CSMachineCPCModel664: target->model = Analyser::Static::AmstradCPC::Target::Model::CPC664; break;
case CSMachineCPCModel6128: target->model = Analyser::Static::AmstradCPC::Target::Model::CPC6128; break;
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;
@ -76,9 +132,9 @@
auto target = std::make_unique<Target>();
target->has_disk_drive = !!hasDiskDrive;
switch(region) {
case CSMachineMSXRegionAmerican: target->region = Analyser::Static::MSX::Target::Region::USA; break;
case CSMachineMSXRegionEuropean: target->region = Analyser::Static::MSX::Target::Region::Europe; break;
case CSMachineMSXRegionJapanese: target->region = Analyser::Static::MSX::Target::Region::Japan; break;
case CSMachineMSXRegionAmerican: target->region = Target::Region::USA; break;
case CSMachineMSXRegionEuropean: target->region = Target::Region::Europe; break;
case CSMachineMSXRegionJapanese: target->region = Target::Region::Japan; break;
}
_targets.push_back(std::move(target));
}
@ -166,57 +222,7 @@ static Analyser::Static::ZX8081::Target::MemoryModel ZX8081MemoryModelFromSize(K
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)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;
}
// MARK: - NIB mapping
- (NSString *)optionsPanelNibName {
switch(_targets.front()->machine) {

View File

@ -1,8 +1,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>
<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"/>
</dependencies>
<objects>
@ -189,7 +189,7 @@ Gw
</tabViewItem>
<tabViewItem label="Electron" identifier="electron" id="muc-z9-Vqc">
<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"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="JqM-IK-FMP">
@ -220,7 +220,7 @@ Gw
</tabViewItem>
<tabViewItem label="Macintosh" identifier="mac" id="lmR-z3-xSm">
<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"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ZOY-4E-Cfl">
@ -257,7 +257,7 @@ Gw
</tabViewItem>
<tabViewItem label="MSX" identifier="msx" id="6SR-DY-zdI">
<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"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="8xT-Pr-8SE">
@ -449,7 +449,7 @@ Gw
</tabViewItem>
<tabViewItem label="ZX80" identifier="zx80" id="tMH-kF-GUz">
<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"/>
<subviews>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="I1a-Eu-5UB">

View File

@ -67,7 +67,7 @@
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;
// 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) {
[_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];
[self.delegate openGLViewWillHideOSMouseCursor:self];
}];

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -105,15 +105,15 @@ class EmuTOS: public ComparativeBusHandler {
- (void)testImage:(NSString *)image trace:(NSString *)trace length:(int)length {
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"];
_machine = std::make_unique<EmuTOS>(*roms[0], traceLocation.UTF8String);
_machine->run_for(HalfCycles(length));
_machine = std::make_unique<EmuTOS>(*roms[0], traceLocation.UTF8String);
_machine->run_for(HalfCycles(length));
}
- (void)testEmuTOSStartup {
[self testImage:@"etos192uk.img" trace:@"etos192uk" length:313490];
// TODO: assert that machine is now STOPped.
// TODO: assert that machine is now STOPped.
}
- (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