From fc81bfa59b5536664ab840ae4a30892ca0b8c37c Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 19 Feb 2018 18:36:31 -0500 Subject: [PATCH 1/4] Eliminates tape player call when tape is not playing. --- Machines/MSX/MSX.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Machines/MSX/MSX.cpp b/Machines/MSX/MSX.cpp index 81c6861d4..050c0ed3f 100644 --- a/Machines/MSX/MSX.cpp +++ b/Machines/MSX/MSX.cpp @@ -116,7 +116,8 @@ class ConcreteMachine: public ConfigurationTarget::Machine, public KeyboardMachine::Machine, public Configurable::Device, - public MemoryMap { + public MemoryMap, + public Sleeper::SleepObserver { public: ConcreteMachine(): z80_(*this), @@ -135,6 +136,7 @@ class ConcreteMachine: ay_.set_port_handler(&ay_port_handler_); speaker_.set_input_rate(3579545.0f / 2.0f); + tape_player_.set_sleep_observer(this); } void setup_output(float aspect_ratio) override { @@ -460,8 +462,8 @@ class ConcreteMachine: default: break; } - // Update the tape. (TODO: allow for sleeping) - tape_player_.run_for(cycle.length.as_int()); + if(!tape_player_is_sleeping_) + tape_player_.run_for(cycle.length.as_int()); // Per the best information I currently have, the MSX inserts an extra cycle into each opcode read, // but otherwise runs without pause. @@ -568,6 +570,11 @@ class ConcreteMachine: return selection_set; } + // MARK: - Sleeper + void set_component_is_sleeping(void *component, bool is_sleeping) override { + tape_player_is_sleeping_ = tape_player_.is_sleeping(); + } + private: void update_audio() { speaker_.run_for(audio_queue_, time_since_ay_update_.divide_cycles(Cycles(2))); @@ -628,6 +635,7 @@ class ConcreteMachine: Outputs::Speaker::LowpassSpeaker> speaker_; Storage::Tape::BinaryTapePlayer tape_player_; + bool tape_player_is_sleeping_ = false; bool allow_fast_tape_ = false; bool use_fast_tape_ = false; void set_use_fast_tape() { From f237dcf904908e9e3ac4e0e14074c7c60c196ede Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 19 Feb 2018 18:44:12 -0500 Subject: [PATCH 2/4] Avoids deadlock when one bestEffortUpdate action implies another. --- .../Mac/Clock Signal/Documents/MachineDocument.swift | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift b/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift index 34ea26be3..95076a01d 100644 --- a/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift +++ b/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift @@ -158,13 +158,15 @@ class MachineDocument: func runForNumberOfCycles(_ numberOfCycles: Int32) { bestEffortLock.lock() if let bestEffortUpdater = bestEffortUpdater { + bestEffortLock.unlock() let cyclesToRunFor = min(numberOfCycles, Int32(bestEffortUpdater.clockRate / 10)) if actionLock.try() { self.machine.runForNumber(ofCycles: cyclesToRunFor) actionLock.unlock() } + } else { + bestEffortLock.unlock() } - bestEffortLock.unlock() } // MARK: CSAudioQueueDelegate @@ -178,13 +180,15 @@ class MachineDocument: final func openGLView(_ view: CSOpenGLView, drawViewOnlyIfDirty onlyIfDirty: Bool) { bestEffortLock.lock() if let bestEffortUpdater = bestEffortUpdater { + bestEffortLock.unlock() bestEffortUpdater.update() if drawLock.try() { self.machine.drawView(forPixelSize: view.backingSize, onlyIfDirty: onlyIfDirty) drawLock.unlock() } + } else { + bestEffortLock.unlock() } - bestEffortLock.unlock() } final func openGLView(_ view: CSOpenGLView, didReceiveFileAt URL: URL) { From b215cf83d5504090f15e55c46be99a96304b9ede Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 19 Feb 2018 19:54:18 -0500 Subject: [PATCH 3/4] Eliminates implicit update queue flush, as unnecessary. --- OSBindings/Mac/Clock Signal/Updater/CSBestEffortUpdater.mm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OSBindings/Mac/Clock Signal/Updater/CSBestEffortUpdater.mm b/OSBindings/Mac/Clock Signal/Updater/CSBestEffortUpdater.mm index 80c82bd1f..40684a021 100644 --- a/OSBindings/Mac/Clock Signal/Updater/CSBestEffortUpdater.mm +++ b/OSBindings/Mac/Clock Signal/Updater/CSBestEffortUpdater.mm @@ -39,9 +39,9 @@ struct UpdaterDelegate: public Concurrency::BestEffortUpdater::Delegate { return self; } -- (void)dealloc { - _updater.flush(); -} +//- (void)dealloc { +// _updater.flush(); +//} - (void)update { _updater.update(); From 270723ae7271e671a5087ca998afbd269276d3b6 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 19 Feb 2018 19:54:42 -0500 Subject: [PATCH 4/4] Forces the MSX's perform_machine_cycle into the Z80. --- Machines/MSX/MSX.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Machines/MSX/MSX.cpp b/Machines/MSX/MSX.cpp index 050c0ed3f..a1e600b06 100644 --- a/Machines/MSX/MSX.cpp +++ b/Machines/MSX/MSX.cpp @@ -38,6 +38,7 @@ #include "../../Outputs/Speaker/Implementation/SampleSource.hpp" #include "../../Configurable/StandardOptions.hpp" +#include "../../ClockReceiver/ForceInline.hpp" namespace MSX { @@ -280,7 +281,7 @@ class ConcreteMachine: } // MARK: Z80::BusHandler - HalfCycles perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) { + forceinline HalfCycles perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) { if(time_until_interrupt_ > 0) { time_until_interrupt_ -= cycle.length; if(time_until_interrupt_ <= HalfCycles(0)) { @@ -573,6 +574,7 @@ class ConcreteMachine: // MARK: - Sleeper void set_component_is_sleeping(void *component, bool is_sleeping) override { tape_player_is_sleeping_ = tape_player_.is_sleeping(); + set_use_fast_tape(); } private: @@ -639,7 +641,7 @@ class ConcreteMachine: bool allow_fast_tape_ = false; bool use_fast_tape_ = false; void set_use_fast_tape() { - use_fast_tape_ = allow_fast_tape_ && tape_player_.has_tape(); + use_fast_tape_ = !tape_player_is_sleeping_ && allow_fast_tape_ && tape_player_.has_tape(); } i8255PortHandler i8255_port_handler_;