mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-25 16:31:42 +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) :
|
||||
machines_(std::move(machines)),
|
||||
configuration_target_(machines_) {}
|
||||
configuration_target_(machines_),
|
||||
crt_machine_(machines_) {}
|
||||
|
||||
ConfigurationTarget::Machine *MultiMachine::configuration_target() {
|
||||
return &configuration_target_;
|
||||
}
|
||||
|
||||
CRTMachine::Machine *MultiMachine::crt_machine() {
|
||||
return nullptr;
|
||||
return &crt_machine_;
|
||||
}
|
||||
|
||||
JoystickMachine::Machine *MultiMachine::joystick_machine() {
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "../../../Machines/DynamicMachine.hpp"
|
||||
|
||||
#include "Implementation/MultiConfigurationTarget.hpp"
|
||||
#include "Implementation/MultiCRTMachine.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
@ -46,6 +47,7 @@ class MultiMachine: public ::Machine::DynamicMachine {
|
||||
std::vector<std::unique_ptr<DynamicMachine>> machines_;
|
||||
|
||||
MultiConfigurationTarget configuration_target_;
|
||||
MultiCRTMachine crt_machine_;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -45,10 +45,10 @@ class Machine: public ROMMachine::Machine {
|
||||
virtual void run_for(const Cycles cycles) = 0;
|
||||
|
||||
// TODO: sever the clock-rate stuff.
|
||||
double get_clock_rate() {
|
||||
virtual double get_clock_rate() {
|
||||
return clock_rate_;
|
||||
}
|
||||
bool get_clock_is_unlimited() {
|
||||
virtual bool get_clock_is_unlimited() {
|
||||
return clock_is_unlimited_;
|
||||
}
|
||||
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_is_unlimited(Machine *machine) = 0;
|
||||
};
|
||||
void set_delegate(Delegate *delegate) { delegate_ = delegate; }
|
||||
virtual void set_delegate(Delegate *delegate) { delegate_ = delegate; }
|
||||
|
||||
protected:
|
||||
void set_clock_rate(double clock_rate) {
|
||||
|
@ -570,6 +570,8 @@
|
||||
4BBB14311CD2CECE00BDB55C /* IntermediateShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBB142F1CD2CECE00BDB55C /* IntermediateShader.cpp */; };
|
||||
4BBB70A4202011C2002FE009 /* 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 */; };
|
||||
4BBF49AF1ED2880200AB3669 /* FUSETests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BBF49AE1ED2880200AB3669 /* FUSETests.swift */; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@ -2659,6 +2663,8 @@
|
||||
children = (
|
||||
4BBB70A2202011C2002FE009 /* MultiConfigurationTarget.hpp */,
|
||||
4BBB70A3202011C2002FE009 /* MultiConfigurationTarget.cpp */,
|
||||
4BBB70A6202014E2002FE009 /* MultiCRTMachine.cpp */,
|
||||
4BBB70A7202014E2002FE009 /* MultiCRTMachine.hpp */,
|
||||
);
|
||||
path = Implementation;
|
||||
sourceTree = "<group>";
|
||||
@ -3368,6 +3374,7 @@
|
||||
4B055AEA1FAE9B990060FFFF /* 6502Storage.cpp in Sources */,
|
||||
4B055AA71FAE85EF0060FFFF /* SegmentParser.cpp in Sources */,
|
||||
4B055AC11FAE98DC0060FFFF /* MachineForTarget.cpp in Sources */,
|
||||
4BBB70A9202014E2002FE009 /* MultiCRTMachine.cpp in Sources */,
|
||||
4B055AD81FAE9B180060FFFF /* Video.cpp in Sources */,
|
||||
4B89452F201967B4007DE474 /* StaticAnalyser.cpp in Sources */,
|
||||
4B894531201967B4007DE474 /* StaticAnalyser.cpp in Sources */,
|
||||
@ -3533,6 +3540,7 @@
|
||||
4BD5F1951D13528900631CD1 /* CSBestEffortUpdater.mm in Sources */,
|
||||
4B894532201967B4007DE474 /* 6502.cpp in Sources */,
|
||||
4B4518811F75E91A00926311 /* PCMPatchedTrack.cpp in Sources */,
|
||||
4BBB70A8202014E2002FE009 /* MultiCRTMachine.cpp in Sources */,
|
||||
4B8805F71DCFF6C9003085B1 /* Commodore.cpp in Sources */,
|
||||
4BBF99181C8FBA6F0075DAFB /* TextureTarget.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.
|
||||
*/
|
||||
void run_for(const Cycles cycles) {
|
||||
if(!delegate_) return;
|
||||
|
||||
std::size_t cycles_remaining = static_cast<size_t>(cycles.as_int());
|
||||
if(!cycles_remaining) return;
|
||||
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
|
||||
if(output_buffer_pointer_ == output_buffer_.size()) {
|
||||
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;
|
||||
@ -126,9 +126,7 @@ template <typename T> class LowpassSpeaker: public Speaker {
|
||||
// Announce to delegate if full.
|
||||
if(output_buffer_pointer_ == output_buffer_.size()) {
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user