mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
Attempts to get as far as running the MultiMachine.
In doing so, fixes the long-standing bug that machines that output audio but don't have a listener produce a divide by zero.
This commit is contained in:
parent
ca48497e87
commit
c12aaea747
@ -0,0 +1,70 @@
|
|||||||
|
//
|
||||||
|
// MultiCRTMachine.cpp
|
||||||
|
// Clock Signal
|
||||||
|
//
|
||||||
|
// Created by Thomas Harte on 29/01/2018.
|
||||||
|
// Copyright © 2018 Thomas Harte. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "MultiCRTMachine.hpp"
|
||||||
|
|
||||||
|
using namespace Analyser::Dynamic;
|
||||||
|
|
||||||
|
MultiCRTMachine::MultiCRTMachine(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines) :
|
||||||
|
machines_(machines) {}
|
||||||
|
|
||||||
|
void MultiCRTMachine::setup_output(float aspect_ratio) {
|
||||||
|
for(const auto &machine: machines_) {
|
||||||
|
CRTMachine::Machine *crt_machine = machine->crt_machine();
|
||||||
|
if(crt_machine) crt_machine->setup_output(aspect_ratio);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiCRTMachine::close_output() {
|
||||||
|
for(const auto &machine: machines_) {
|
||||||
|
CRTMachine::Machine *crt_machine = machine->crt_machine();
|
||||||
|
if(crt_machine) crt_machine->close_output();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Outputs::CRT::CRT *MultiCRTMachine::get_crt() {
|
||||||
|
CRTMachine::Machine *crt_machine = machines_.front()->crt_machine();
|
||||||
|
return crt_machine ? crt_machine->get_crt() : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Outputs::Speaker::Speaker *MultiCRTMachine::get_speaker() {
|
||||||
|
CRTMachine::Machine *crt_machine = machines_.front()->crt_machine();
|
||||||
|
return crt_machine ? crt_machine->get_speaker() : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiCRTMachine::run_for(const Cycles cycles) {
|
||||||
|
for(const auto &machine: machines_) {
|
||||||
|
CRTMachine::Machine *crt_machine = machine->crt_machine();
|
||||||
|
if(crt_machine) crt_machine->run_for(cycles);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: announce an opportunity potentially to reorder the list of machines.
|
||||||
|
}
|
||||||
|
|
||||||
|
double MultiCRTMachine::get_clock_rate() {
|
||||||
|
// TODO: something smarter than this? Not all clock rates will necessarily be the same.
|
||||||
|
CRTMachine::Machine *crt_machine = machines_.front()->crt_machine();
|
||||||
|
return crt_machine ? crt_machine->get_clock_rate() : 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MultiCRTMachine::get_clock_is_unlimited() {
|
||||||
|
CRTMachine::Machine *crt_machine = machines_.front()->crt_machine();
|
||||||
|
return crt_machine ? crt_machine->get_clock_is_unlimited() : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiCRTMachine::set_delegate(::CRTMachine::Machine::Delegate *delegate) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiCRTMachine::machine_did_change_clock_rate(Machine *machine) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiCRTMachine::machine_did_change_clock_is_unlimited(Machine *machine) {
|
||||||
|
// TODO
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
//
|
||||||
|
// MultiCRTMachine.hpp
|
||||||
|
// Clock Signal
|
||||||
|
//
|
||||||
|
// Created by Thomas Harte on 29/01/2018.
|
||||||
|
// Copyright © 2018 Thomas Harte. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef MultiCRTMachine_hpp
|
||||||
|
#define MultiCRTMachine_hpp
|
||||||
|
|
||||||
|
#include "../../../../Machines/CRTMachine.hpp"
|
||||||
|
#include "../../../../Machines/DynamicMachine.hpp"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Analyser {
|
||||||
|
namespace Dynamic {
|
||||||
|
|
||||||
|
struct MultiCRTMachine: public ::CRTMachine::Machine, public ::CRTMachine::Machine::Delegate {
|
||||||
|
public:
|
||||||
|
MultiCRTMachine(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines);
|
||||||
|
|
||||||
|
void setup_output(float aspect_ratio) override;
|
||||||
|
void close_output() override;
|
||||||
|
Outputs::CRT::CRT *get_crt() override;
|
||||||
|
Outputs::Speaker::Speaker *get_speaker() override;
|
||||||
|
void run_for(const Cycles cycles) override;
|
||||||
|
double get_clock_rate() override;
|
||||||
|
bool get_clock_is_unlimited() override;
|
||||||
|
void set_delegate(::CRTMachine::Machine::Delegate *delegate) override;
|
||||||
|
|
||||||
|
void machine_did_change_clock_rate(Machine *machine) override;
|
||||||
|
void machine_did_change_clock_is_unlimited(Machine *machine) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* MultiCRTMachine_hpp */
|
@ -12,14 +12,15 @@ using namespace Analyser::Dynamic;
|
|||||||
|
|
||||||
MultiMachine::MultiMachine(std::vector<std::unique_ptr<DynamicMachine>> &&machines) :
|
MultiMachine::MultiMachine(std::vector<std::unique_ptr<DynamicMachine>> &&machines) :
|
||||||
machines_(std::move(machines)),
|
machines_(std::move(machines)),
|
||||||
configuration_target_(machines_) {}
|
configuration_target_(machines_),
|
||||||
|
crt_machine_(machines_) {}
|
||||||
|
|
||||||
ConfigurationTarget::Machine *MultiMachine::configuration_target() {
|
ConfigurationTarget::Machine *MultiMachine::configuration_target() {
|
||||||
return &configuration_target_;
|
return &configuration_target_;
|
||||||
}
|
}
|
||||||
|
|
||||||
CRTMachine::Machine *MultiMachine::crt_machine() {
|
CRTMachine::Machine *MultiMachine::crt_machine() {
|
||||||
return nullptr;
|
return &crt_machine_;
|
||||||
}
|
}
|
||||||
|
|
||||||
JoystickMachine::Machine *MultiMachine::joystick_machine() {
|
JoystickMachine::Machine *MultiMachine::joystick_machine() {
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "../../../Machines/DynamicMachine.hpp"
|
#include "../../../Machines/DynamicMachine.hpp"
|
||||||
|
|
||||||
#include "Implementation/MultiConfigurationTarget.hpp"
|
#include "Implementation/MultiConfigurationTarget.hpp"
|
||||||
|
#include "Implementation/MultiCRTMachine.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -46,6 +47,7 @@ class MultiMachine: public ::Machine::DynamicMachine {
|
|||||||
std::vector<std::unique_ptr<DynamicMachine>> machines_;
|
std::vector<std::unique_ptr<DynamicMachine>> machines_;
|
||||||
|
|
||||||
MultiConfigurationTarget configuration_target_;
|
MultiConfigurationTarget configuration_target_;
|
||||||
|
MultiCRTMachine crt_machine_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -45,10 +45,10 @@ class Machine: public ROMMachine::Machine {
|
|||||||
virtual void run_for(const Cycles cycles) = 0;
|
virtual void run_for(const Cycles cycles) = 0;
|
||||||
|
|
||||||
// TODO: sever the clock-rate stuff.
|
// TODO: sever the clock-rate stuff.
|
||||||
double get_clock_rate() {
|
virtual double get_clock_rate() {
|
||||||
return clock_rate_;
|
return clock_rate_;
|
||||||
}
|
}
|
||||||
bool get_clock_is_unlimited() {
|
virtual bool get_clock_is_unlimited() {
|
||||||
return clock_is_unlimited_;
|
return clock_is_unlimited_;
|
||||||
}
|
}
|
||||||
class Delegate {
|
class Delegate {
|
||||||
@ -56,7 +56,7 @@ class Machine: public ROMMachine::Machine {
|
|||||||
virtual void machine_did_change_clock_rate(Machine *machine) = 0;
|
virtual void machine_did_change_clock_rate(Machine *machine) = 0;
|
||||||
virtual void machine_did_change_clock_is_unlimited(Machine *machine) = 0;
|
virtual void machine_did_change_clock_is_unlimited(Machine *machine) = 0;
|
||||||
};
|
};
|
||||||
void set_delegate(Delegate *delegate) { delegate_ = delegate; }
|
virtual void set_delegate(Delegate *delegate) { delegate_ = delegate; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void set_clock_rate(double clock_rate) {
|
void set_clock_rate(double clock_rate) {
|
||||||
|
@ -570,6 +570,8 @@
|
|||||||
4BBB14311CD2CECE00BDB55C /* IntermediateShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBB142F1CD2CECE00BDB55C /* IntermediateShader.cpp */; };
|
4BBB14311CD2CECE00BDB55C /* IntermediateShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBB142F1CD2CECE00BDB55C /* IntermediateShader.cpp */; };
|
||||||
4BBB70A4202011C2002FE009 /* MultiConfigurationTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBB70A3202011C2002FE009 /* MultiConfigurationTarget.cpp */; };
|
4BBB70A4202011C2002FE009 /* MultiConfigurationTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBB70A3202011C2002FE009 /* MultiConfigurationTarget.cpp */; };
|
||||||
4BBB70A5202011C2002FE009 /* MultiConfigurationTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBB70A3202011C2002FE009 /* MultiConfigurationTarget.cpp */; };
|
4BBB70A5202011C2002FE009 /* MultiConfigurationTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBB70A3202011C2002FE009 /* MultiConfigurationTarget.cpp */; };
|
||||||
|
4BBB70A8202014E2002FE009 /* MultiCRTMachine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBB70A6202014E2002FE009 /* MultiCRTMachine.cpp */; };
|
||||||
|
4BBB70A9202014E2002FE009 /* MultiCRTMachine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBB70A6202014E2002FE009 /* MultiCRTMachine.cpp */; };
|
||||||
4BBC951E1F368D83008F4C34 /* i8272.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBC951C1F368D83008F4C34 /* i8272.cpp */; };
|
4BBC951E1F368D83008F4C34 /* i8272.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBC951C1F368D83008F4C34 /* i8272.cpp */; };
|
||||||
4BBF49AF1ED2880200AB3669 /* FUSETests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BBF49AE1ED2880200AB3669 /* FUSETests.swift */; };
|
4BBF49AF1ED2880200AB3669 /* FUSETests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BBF49AE1ED2880200AB3669 /* FUSETests.swift */; };
|
||||||
4BBF99141C8FBA6F0075DAFB /* TextureBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBF99081C8FBA6F0075DAFB /* TextureBuilder.cpp */; };
|
4BBF99141C8FBA6F0075DAFB /* TextureBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBF99081C8FBA6F0075DAFB /* TextureBuilder.cpp */; };
|
||||||
@ -1253,6 +1255,8 @@
|
|||||||
4BBB709C2020109C002FE009 /* DynamicMachine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DynamicMachine.hpp; sourceTree = "<group>"; };
|
4BBB709C2020109C002FE009 /* DynamicMachine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DynamicMachine.hpp; sourceTree = "<group>"; };
|
||||||
4BBB70A2202011C2002FE009 /* MultiConfigurationTarget.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MultiConfigurationTarget.hpp; sourceTree = "<group>"; };
|
4BBB70A2202011C2002FE009 /* MultiConfigurationTarget.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MultiConfigurationTarget.hpp; sourceTree = "<group>"; };
|
||||||
4BBB70A3202011C2002FE009 /* MultiConfigurationTarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MultiConfigurationTarget.cpp; sourceTree = "<group>"; };
|
4BBB70A3202011C2002FE009 /* MultiConfigurationTarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MultiConfigurationTarget.cpp; sourceTree = "<group>"; };
|
||||||
|
4BBB70A6202014E2002FE009 /* MultiCRTMachine.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MultiCRTMachine.cpp; sourceTree = "<group>"; };
|
||||||
|
4BBB70A7202014E2002FE009 /* MultiCRTMachine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MultiCRTMachine.hpp; sourceTree = "<group>"; };
|
||||||
4BBC34241D2208B100FFC9DF /* CSFastLoading.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSFastLoading.h; sourceTree = "<group>"; };
|
4BBC34241D2208B100FFC9DF /* CSFastLoading.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSFastLoading.h; sourceTree = "<group>"; };
|
||||||
4BBC951C1F368D83008F4C34 /* i8272.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = i8272.cpp; path = 8272/i8272.cpp; sourceTree = "<group>"; };
|
4BBC951C1F368D83008F4C34 /* i8272.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = i8272.cpp; path = 8272/i8272.cpp; sourceTree = "<group>"; };
|
||||||
4BBC951D1F368D83008F4C34 /* i8272.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = i8272.hpp; path = 8272/i8272.hpp; sourceTree = "<group>"; };
|
4BBC951D1F368D83008F4C34 /* i8272.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = i8272.hpp; path = 8272/i8272.hpp; sourceTree = "<group>"; };
|
||||||
@ -2659,6 +2663,8 @@
|
|||||||
children = (
|
children = (
|
||||||
4BBB70A2202011C2002FE009 /* MultiConfigurationTarget.hpp */,
|
4BBB70A2202011C2002FE009 /* MultiConfigurationTarget.hpp */,
|
||||||
4BBB70A3202011C2002FE009 /* MultiConfigurationTarget.cpp */,
|
4BBB70A3202011C2002FE009 /* MultiConfigurationTarget.cpp */,
|
||||||
|
4BBB70A6202014E2002FE009 /* MultiCRTMachine.cpp */,
|
||||||
|
4BBB70A7202014E2002FE009 /* MultiCRTMachine.hpp */,
|
||||||
);
|
);
|
||||||
path = Implementation;
|
path = Implementation;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -3368,6 +3374,7 @@
|
|||||||
4B055AEA1FAE9B990060FFFF /* 6502Storage.cpp in Sources */,
|
4B055AEA1FAE9B990060FFFF /* 6502Storage.cpp in Sources */,
|
||||||
4B055AA71FAE85EF0060FFFF /* SegmentParser.cpp in Sources */,
|
4B055AA71FAE85EF0060FFFF /* SegmentParser.cpp in Sources */,
|
||||||
4B055AC11FAE98DC0060FFFF /* MachineForTarget.cpp in Sources */,
|
4B055AC11FAE98DC0060FFFF /* MachineForTarget.cpp in Sources */,
|
||||||
|
4BBB70A9202014E2002FE009 /* MultiCRTMachine.cpp in Sources */,
|
||||||
4B055AD81FAE9B180060FFFF /* Video.cpp in Sources */,
|
4B055AD81FAE9B180060FFFF /* Video.cpp in Sources */,
|
||||||
4B89452F201967B4007DE474 /* StaticAnalyser.cpp in Sources */,
|
4B89452F201967B4007DE474 /* StaticAnalyser.cpp in Sources */,
|
||||||
4B894531201967B4007DE474 /* StaticAnalyser.cpp in Sources */,
|
4B894531201967B4007DE474 /* StaticAnalyser.cpp in Sources */,
|
||||||
@ -3533,6 +3540,7 @@
|
|||||||
4BD5F1951D13528900631CD1 /* CSBestEffortUpdater.mm in Sources */,
|
4BD5F1951D13528900631CD1 /* CSBestEffortUpdater.mm in Sources */,
|
||||||
4B894532201967B4007DE474 /* 6502.cpp in Sources */,
|
4B894532201967B4007DE474 /* 6502.cpp in Sources */,
|
||||||
4B4518811F75E91A00926311 /* PCMPatchedTrack.cpp in Sources */,
|
4B4518811F75E91A00926311 /* PCMPatchedTrack.cpp in Sources */,
|
||||||
|
4BBB70A8202014E2002FE009 /* MultiCRTMachine.cpp in Sources */,
|
||||||
4B8805F71DCFF6C9003085B1 /* Commodore.cpp in Sources */,
|
4B8805F71DCFF6C9003085B1 /* Commodore.cpp in Sources */,
|
||||||
4BBF99181C8FBA6F0075DAFB /* TextureTarget.cpp in Sources */,
|
4BBF99181C8FBA6F0075DAFB /* TextureTarget.cpp in Sources */,
|
||||||
4BC76E691C98E31700E6EF73 /* FIRFilter.cpp in Sources */,
|
4BC76E691C98E31700E6EF73 /* FIRFilter.cpp in Sources */,
|
||||||
|
@ -82,6 +82,8 @@ template <typename T> class LowpassSpeaker: public Speaker {
|
|||||||
at construction, filtering it and passing it on to the speaker's delegate if there is one.
|
at construction, filtering it and passing it on to the speaker's delegate if there is one.
|
||||||
*/
|
*/
|
||||||
void run_for(const Cycles cycles) {
|
void run_for(const Cycles cycles) {
|
||||||
|
if(!delegate_) return;
|
||||||
|
|
||||||
std::size_t cycles_remaining = static_cast<size_t>(cycles.as_int());
|
std::size_t cycles_remaining = static_cast<size_t>(cycles.as_int());
|
||||||
if(!cycles_remaining) return;
|
if(!cycles_remaining) return;
|
||||||
if(filter_parameters_.parameters_are_dirty) update_filter_coefficients();
|
if(filter_parameters_.parameters_are_dirty) update_filter_coefficients();
|
||||||
@ -99,9 +101,7 @@ template <typename T> class LowpassSpeaker: public Speaker {
|
|||||||
// announce to delegate if full
|
// announce to delegate if full
|
||||||
if(output_buffer_pointer_ == output_buffer_.size()) {
|
if(output_buffer_pointer_ == output_buffer_.size()) {
|
||||||
output_buffer_pointer_ = 0;
|
output_buffer_pointer_ = 0;
|
||||||
if(delegate_) {
|
delegate_->speaker_did_complete_samples(this, output_buffer_);
|
||||||
delegate_->speaker_did_complete_samples(this, output_buffer_);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cycles_remaining -= cycles_to_read;
|
cycles_remaining -= cycles_to_read;
|
||||||
@ -126,9 +126,7 @@ template <typename T> class LowpassSpeaker: public Speaker {
|
|||||||
// Announce to delegate if full.
|
// Announce to delegate if full.
|
||||||
if(output_buffer_pointer_ == output_buffer_.size()) {
|
if(output_buffer_pointer_ == output_buffer_.size()) {
|
||||||
output_buffer_pointer_ = 0;
|
output_buffer_pointer_ = 0;
|
||||||
if(delegate_) {
|
delegate_->speaker_did_complete_samples(this, output_buffer_);
|
||||||
delegate_->speaker_did_complete_samples(this, output_buffer_);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the next loop around is going to reuse some of the samples just collected, use a memmove to
|
// If the next loop around is going to reuse some of the samples just collected, use a memmove to
|
||||||
|
Loading…
Reference in New Issue
Block a user