1
0
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:
Thomas Harte 2018-01-30 22:23:06 -05:00
parent ca48497e87
commit c12aaea747
7 changed files with 135 additions and 11 deletions

View File

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

View File

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

View File

@ -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() {

View File

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

View File

@ -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) {

View File

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

View File

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