From 8755824c64b480ead176ebef2e91115839ce5229 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 22 Jul 2017 17:25:53 -0400 Subject: [PATCH 01/52] Added some documentation. --- Components/1770/1770.hpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/Components/1770/1770.hpp b/Components/1770/1770.hpp index 285552be7..507393946 100644 --- a/Components/1770/1770.hpp +++ b/Components/1770/1770.hpp @@ -14,20 +14,35 @@ namespace WD { +/*! + Provides an emulation of various Western Digital drive controllers, including the + WD1770, WD1772, FDC1773 and FDC1793. +*/ class WD1770: public Storage::Disk::Controller { public: enum Personality { - P1770, // implies automatic motor-on management with Type 2 commands offering a spin-up disable + P1770, // implies automatic motor-on management, with Type 2 commands offering a spin-up disable P1772, // as per the 1770, with different stepping rates P1773, // implements the side number-testing logic of the 1793; omits spin-up/loading logic P1793 // implies Type 2 commands use side number testing logic; spin-up/loading is by HLD and HLT }; + + /*! + Constructs an instance of the drive controller that behaves according to personality @c p. + @param p The type of controller to emulate. + */ WD1770(Personality p); + /// Sets the value of the double-density input; when @c is_double_density is @c true, reads and writes double-density format data. void set_is_double_density(bool is_double_density); + + /// Writes @c value to the register at @c address. Only the low two bits of the address are decoded. void set_register(int address, uint8_t value); + + /// Fetches the value of the register @c address. Only the low two bits of the address are decoded. uint8_t get_register(int address); + /// Runs the controller for @c number_of_cycles cycles. void run_for_cycles(unsigned int number_of_cycles); enum Flag: uint8_t { @@ -47,8 +62,12 @@ class WD1770: public Storage::Disk::Controller { Busy = 0x01 }; + /// @returns The current value of the IRQ line output. inline bool get_interrupt_request_line() { return status_.interrupt_request; } + + /// @returns The current value of the DRQ line output. inline bool get_data_request_line() { return status_.data_request; } + class Delegate { public: virtual void wd1770_did_change_output(WD1770 *wd1770) = 0; From 825b38850e52ace5f13ed01d71d43e52277dc800 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 22 Jul 2017 17:30:58 -0400 Subject: [PATCH 02/52] Removes non-idiomatic line break. --- Concurrency/AsyncTaskQueue.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Concurrency/AsyncTaskQueue.hpp b/Concurrency/AsyncTaskQueue.hpp index f695cd2a1..34c54bb61 100644 --- a/Concurrency/AsyncTaskQueue.hpp +++ b/Concurrency/AsyncTaskQueue.hpp @@ -26,7 +26,6 @@ namespace Concurrency { causing it to block until all previously-enqueued functions are complete. */ class AsyncTaskQueue { - public: AsyncTaskQueue(); ~AsyncTaskQueue(); From d46da6ac9d1290782eabbc7819d807ca28661e4d Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 22 Jul 2017 17:31:12 -0400 Subject: [PATCH 03/52] Added documentation. --- Machines/CRTMachine.hpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Machines/CRTMachine.hpp b/Machines/CRTMachine.hpp index 9cc2f869f..0a192a3c7 100644 --- a/Machines/CRTMachine.hpp +++ b/Machines/CRTMachine.hpp @@ -23,12 +23,25 @@ class Machine { public: Machine() : clock_is_unlimited_(false) {} + /*! + Causes the machine to set up its CRT and, if it has one, speaker. The caller guarantees + that an OpenGL context is bound. + */ virtual void setup_output(float aspect_ratio) = 0; + + /*! + Gives the machine a chance to release all owned resources. The caller guarantees that the + OpenGL context is bound. + */ virtual void close_output() = 0; + /// @returns The CRT this machine is drawing to. Should not be @c nullptr. virtual std::shared_ptr get_crt() = 0; + + /// @returns The speaker that receives this machine's output, or @c nullptr if this machine is mute. virtual std::shared_ptr get_speaker() = 0; + /// Runs the machine for @c number_of_cycle cycles. virtual void run_for_cycles(int number_of_cycles) = 0; // TODO: sever the clock-rate stuff. From 1bbb4cb478b94bbd16d2b25fc07113281a8ab4ea Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 22 Jul 2017 17:39:51 -0400 Subject: [PATCH 04/52] Increased documentation. --- Machines/KeyboardMachine.hpp | 8 ++++++++ Machines/MemoryFuzzer.hpp | 3 +++ NumberTheory/CRC.hpp | 12 ++++++++++++ StaticAnalyser/Acorn/Disk.hpp | 1 + 4 files changed, 24 insertions(+) diff --git a/Machines/KeyboardMachine.hpp b/Machines/KeyboardMachine.hpp index a5aa972b7..6399d6f58 100644 --- a/Machines/KeyboardMachine.hpp +++ b/Machines/KeyboardMachine.hpp @@ -13,7 +13,15 @@ namespace KeyboardMachine { class Machine { public: + /*! + 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 isPressed) = 0; + + /*! + Instructs that all keys should now be treated as released. + */ virtual void clear_all_keys() = 0; }; diff --git a/Machines/MemoryFuzzer.hpp b/Machines/MemoryFuzzer.hpp index 3de6bdcbd..614692d54 100644 --- a/Machines/MemoryFuzzer.hpp +++ b/Machines/MemoryFuzzer.hpp @@ -15,7 +15,10 @@ namespace Memory { +/// Stores @c size random bytes from @c buffer onwards. void Fuzz(uint8_t *buffer, size_t size); + +// Replaces all existing vector contents with random bytes. void Fuzz(std::vector &buffer); } diff --git a/NumberTheory/CRC.hpp b/NumberTheory/CRC.hpp index b9f4aed3e..801495b81 100644 --- a/NumberTheory/CRC.hpp +++ b/NumberTheory/CRC.hpp @@ -13,8 +13,13 @@ namespace NumberTheory { +/*! Provides a class capable of accumulating a CRC16 from source data. */ class CRC16 { public: + /*! + Instantiates a CRC16 that will compute the CRC16 specified by the supplied + @c polynomial and @c reset_value. + */ CRC16(uint16_t polynomial, uint16_t reset_value) : reset_value_(reset_value), value_(reset_value) { for(int c = 0; c < 256; c++) { @@ -27,11 +32,18 @@ class CRC16 { } } + /// Resets the CRC to the reset value. inline void reset() { value_ = reset_value_; } + + /// Updates the CRC to include @c byte. inline void add(uint8_t byte) { value_ = (uint16_t)((value_ << 8) ^ xor_table[(value_ >> 8) ^ byte]); } + + /// @returns The current value of the CRC. inline uint16_t get_value() const { return value_; } + + /// Sets the current value of the CRC. inline void set_value(uint16_t value) { value_ = value; } private: diff --git a/StaticAnalyser/Acorn/Disk.hpp b/StaticAnalyser/Acorn/Disk.hpp index 5b7bc3ed7..43e6810c0 100644 --- a/StaticAnalyser/Acorn/Disk.hpp +++ b/StaticAnalyser/Acorn/Disk.hpp @@ -15,6 +15,7 @@ namespace StaticAnalyser { namespace Acorn { +/// Describes a DFS- or ADFS-format catalogue(/directory) — the list of files available and the catalogue's boot option. struct Catalogue { std::string name; std::list files; From 31b4f8fa31b04bfe869aac0828edf5fa8a2b9730 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 22 Jul 2017 17:40:06 -0400 Subject: [PATCH 05/52] Added an expository TODO. --- NumberTheory/Factors.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/NumberTheory/Factors.hpp b/NumberTheory/Factors.hpp index 98832d247..9fe660bc2 100644 --- a/NumberTheory/Factors.hpp +++ b/NumberTheory/Factors.hpp @@ -16,6 +16,7 @@ namespace NumberTheory { @returns The greatest common divisor of @c a and @c b as computed by Euclid's algorithm. */ template T greatest_common_divisor(T a, T b) { + // TODO: replace with the C++17 GCD function, once available. if(a < b) { std::swap(a, b); } From 1ba3f262a2fad6ccafbb206fa95369fe8a43bba7 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 22 Jul 2017 21:46:50 -0400 Subject: [PATCH 06/52] Sketched out a template for clock-receiving components to allow them to be implemented in terms of either half or whole cycles. --- Components/ClockReceiver.hpp | 55 +++++++++++++++++++ .../Clock Signal.xcodeproj/project.pbxproj | 2 + 2 files changed, 57 insertions(+) create mode 100644 Components/ClockReceiver.hpp diff --git a/Components/ClockReceiver.hpp b/Components/ClockReceiver.hpp new file mode 100644 index 000000000..2e2a0501d --- /dev/null +++ b/Components/ClockReceiver.hpp @@ -0,0 +1,55 @@ +// +// ClockReceiver.hpp +// Clock Signal +// +// Created by Thomas Harte on 22/07/2017. +// Copyright © 2017 Thomas Harte. All rights reserved. +// + +#ifndef ClockReceiver_hpp +#define ClockReceiver_hpp + +/*! Describes an integer number of whole cycles — pairs of clock signal transitions. */ +class Cycles { + public: + Cycles(int l) : length_(l) {} + operator int() const { return length_; } + + private: + int length_; +}; + +/*! Describes an integer number of half cycles — single clock signal transitions. */ +class HalfCycles { + public: + HalfCycles(int l) : length_(l) {} + HalfCycles(const Cycles &cycles) : length_(int(cycles) << 1) {} + operator int() const { return length_; } + + private: + int length_; +}; + +/*! + ClockReceiver is a template for components that receove a clock, measured either + in cycles or in half cycles. They are expected to implement either of the run_for + methods; buying into the template means that the other run_for will automatically + map appropriately to the implemented one, so callers may use either. +*/ +template class ClockReceiver { + public: + void run_for(const Cycles &cycles) { + static_cast(this)->run_for(HalfCycles(cycles)); + } + + void run_for(const HalfCycles &half_cycles) { + int cycles = int(half_cycles) + half_cycle_carry; + half_cycle_carry = cycles & 1; + run_for(Cycles(cycles >> 1)); + } + + private: + int half_cycle_carry; +}; + +#endif /* ClockReceiver_hpp */ diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 2925ec984..3970d170e 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -563,6 +563,7 @@ 4B4DC8271D2C2470003C5BF8 /* C1540.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = C1540.hpp; sourceTree = ""; }; 4B4DC8291D2C27A4003C5BF8 /* SerialBus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SerialBus.cpp; sourceTree = ""; }; 4B4DC82A1D2C27A4003C5BF8 /* SerialBus.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SerialBus.hpp; sourceTree = ""; }; + 4B4EA7E01F24349400C216B4 /* ClockReceiver.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ClockReceiver.hpp; sourceTree = ""; }; 4B5073051DDD3B9400C48FBD /* ArrayBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayBuilder.cpp; sourceTree = ""; }; 4B5073061DDD3B9400C48FBD /* ArrayBuilder.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ArrayBuilder.hpp; sourceTree = ""; }; 4B5073091DDFCFDF00C48FBD /* ArrayBuilderTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ArrayBuilderTests.mm; sourceTree = ""; }; @@ -1988,6 +1989,7 @@ 4BC9DF4A1D04691600F44158 /* Components */ = { isa = PBXGroup; children = ( + 4B4EA7E01F24349400C216B4 /* ClockReceiver.hpp */, 4BD468F81D8DF4290084958B /* 1770 */, 4BC9DF4B1D04691600F44158 /* 6522 */, 4B1E85791D174DEC001EF87D /* 6532 */, From 83628b285b1ddb2601a00b538b6a6c76d16c70c0 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 22 Jul 2017 21:52:21 -0400 Subject: [PATCH 07/52] Experimentally turned the 6502 into a clock receiver. No problem encountered. --- Machines/Atari2600/Cartridges/Cartridge.hpp | 2 +- Machines/Commodore/1540/C1540.cpp | 2 +- Machines/Commodore/Vic-20/Vic20.hpp | 2 +- Machines/Electron/Electron.hpp | 2 +- Machines/Oric/Oric.cpp | 2 +- Processors/6502/6502.hpp | 9 +++++---- 6 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Machines/Atari2600/Cartridges/Cartridge.hpp b/Machines/Atari2600/Cartridges/Cartridge.hpp index fa445fcd1..3eb467171 100644 --- a/Machines/Atari2600/Cartridges/Cartridge.hpp +++ b/Machines/Atari2600/Cartridges/Cartridge.hpp @@ -22,7 +22,7 @@ template class Cartridge: Cartridge(const std::vector &rom) : rom_(rom) {} - void run_for_cycles(int number_of_cycles) { CPU::MOS6502::Processor>::run_for_cycles(number_of_cycles); } + void run_for_cycles(int number_of_cycles) { CPU::MOS6502::Processor>::run_for(Cycles(number_of_cycles)); } void set_reset_line(bool state) { CPU::MOS6502::Processor>::set_reset_line(state); } void advance_cycles(unsigned int cycles) {} diff --git a/Machines/Commodore/1540/C1540.cpp b/Machines/Commodore/1540/C1540.cpp index ca92c51c2..ae3266038 100644 --- a/Machines/Commodore/1540/C1540.cpp +++ b/Machines/Commodore/1540/C1540.cpp @@ -80,7 +80,7 @@ void Machine::set_disk(std::shared_ptr disk) { } void Machine::run_for_cycles(int number_of_cycles) { - CPU::MOS6502::Processor::run_for_cycles(number_of_cycles); + CPU::MOS6502::Processor::run_for(Cycles(number_of_cycles)); set_motor_on(drive_VIA_.get_motor_enabled()); if(drive_VIA_.get_motor_enabled()) // TODO: motor speed up/down Storage::Disk::Controller::run_for_cycles(number_of_cycles); diff --git a/Machines/Commodore/Vic-20/Vic20.hpp b/Machines/Commodore/Vic-20/Vic20.hpp index e70c845cd..6981022b7 100644 --- a/Machines/Commodore/Vic-20/Vic20.hpp +++ b/Machines/Commodore/Vic-20/Vic20.hpp @@ -174,7 +174,7 @@ class Machine: virtual void close_output(); virtual std::shared_ptr get_crt() { return mos6560_->get_crt(); } virtual std::shared_ptr get_speaker() { return mos6560_->get_speaker(); } - virtual void run_for_cycles(int number_of_cycles) { CPU::MOS6502::Processor::run_for_cycles(number_of_cycles); } + virtual void run_for_cycles(int number_of_cycles) { CPU::MOS6502::Processor::run_for(Cycles(number_of_cycles)); } // to satisfy MOS::MOS6522::Delegate virtual void mos6522_did_change_interrupt_status(void *mos6522); diff --git a/Machines/Electron/Electron.hpp b/Machines/Electron/Electron.hpp index f24462a51..d730bc803 100644 --- a/Machines/Electron/Electron.hpp +++ b/Machines/Electron/Electron.hpp @@ -94,7 +94,7 @@ class Machine: virtual void close_output(); virtual std::shared_ptr get_crt(); virtual std::shared_ptr get_speaker(); - virtual void run_for_cycles(int number_of_cycles) { CPU::MOS6502::Processor::run_for_cycles(number_of_cycles); } + virtual void run_for_cycles(int number_of_cycles) { CPU::MOS6502::Processor::run_for(Cycles(number_of_cycles)); } // to satisfy Tape::Delegate virtual void tape_did_change_interrupt_status(Tape *tape); diff --git a/Machines/Oric/Oric.cpp b/Machines/Oric/Oric.cpp index 3310cc319..54a6100f7 100644 --- a/Machines/Oric/Oric.cpp +++ b/Machines/Oric/Oric.cpp @@ -199,7 +199,7 @@ std::shared_ptr Machine::get_speaker() { } void Machine::run_for_cycles(int number_of_cycles) { - CPU::MOS6502::Processor::run_for_cycles(number_of_cycles); + CPU::MOS6502::Processor::run_for(Cycles(number_of_cycles)); } #pragma mark - The 6522 diff --git a/Processors/6502/6502.hpp b/Processors/6502/6502.hpp index 75763455c..8eb871286 100644 --- a/Processors/6502/6502.hpp +++ b/Processors/6502/6502.hpp @@ -13,6 +13,7 @@ #include #include "../RegisterSizes.hpp" +#include "../../Components/ClockReceiver.hpp" namespace CPU { namespace MOS6502 { @@ -127,7 +128,7 @@ class ProcessorBase { that will cause call outs when the program counter reaches those addresses. @c return_from_subroutine can be used to exit from a jammed state. */ -template class Processor: public ProcessorBase { +template class Processor: public ProcessorBase, public ClockReceiver> { private: const MicroOp *scheduled_program_counter_; @@ -290,9 +291,9 @@ template class Processor: public ProcessorBase { The 6502 will call that method for all bus accesses. The 6502 is guaranteed to perform one bus operation call per cycle. If it is a read operation then @c value will be seeded with the value 0xff. - @param number_of_cycles The number of cycles to run the 6502 for. + @param cycles The number of cycles to run the 6502 for. */ - void run_for_cycles(int number_of_cycles) { + void run_for(const Cycles &cycles) { static const MicroOp doBranch[] = { CycleReadFromPC, CycleAddSignedOperandToPC, @@ -339,7 +340,7 @@ template class Processor: public ProcessorBase { if(number_of_cycles <= 0) break; checkSchedule(); - number_of_cycles += cycles_left_to_run_; + int number_of_cycles = int(cycles) + cycles_left_to_run_; while(number_of_cycles > 0) { From 2ff157cf7a8251bd483ef68d8ead59658009e03e Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 22 Jul 2017 22:17:29 -0400 Subject: [PATCH 08/52] Switched CRTMachine over to use `Cycles` as an explicit statement of units, and followed through on the effects of that. --- Machines/Atari2600/Atari2600.hpp | 2 +- Machines/Atari2600/Bus.hpp | 3 ++- Machines/Atari2600/Cartridges/Cartridge.hpp | 2 +- Machines/CRTMachine.hpp | 5 ++-- Machines/Commodore/Vic-20/Vic20.hpp | 2 +- Machines/Electron/Electron.hpp | 2 +- Machines/Oric/Oric.cpp | 4 ++-- Machines/Oric/Oric.hpp | 2 +- Machines/ZX8081/ZX8081.cpp | 4 ++-- Machines/ZX8081/ZX8081.hpp | 2 +- .../Mac/Clock Signal/Machine/CSMachine.mm | 2 +- .../Machine/Wrappers/CSElectron.mm | 6 ++--- .../Clock Signal/Machine/Wrappers/CSOric.mm | 24 +++++++------------ Processors/6502/6502AllRAM.cpp | 4 ++-- Processors/6502/6502AllRAM.hpp | 2 +- 15 files changed, 29 insertions(+), 37 deletions(-) diff --git a/Machines/Atari2600/Atari2600.hpp b/Machines/Atari2600/Atari2600.hpp index a682001bb..3ba31e972 100644 --- a/Machines/Atari2600/Atari2600.hpp +++ b/Machines/Atari2600/Atari2600.hpp @@ -44,7 +44,7 @@ class Machine: virtual void close_output(); virtual std::shared_ptr get_crt() { return bus_->tia_->get_crt(); } virtual std::shared_ptr get_speaker() { return bus_->speaker_; } - virtual void run_for_cycles(int number_of_cycles) { bus_->run_for_cycles(number_of_cycles); } + virtual void run_for(const Cycles &cycles) { bus_->run_for(cycles); } // to satisfy Outputs::CRT::Delegate virtual void crt_did_end_batch_of_frames(Outputs::CRT::CRT *crt, unsigned int number_of_frames, unsigned int number_of_unexpected_vertical_syncs); diff --git a/Machines/Atari2600/Bus.hpp b/Machines/Atari2600/Bus.hpp index 8d5d731a9..81e0fe5b1 100644 --- a/Machines/Atari2600/Bus.hpp +++ b/Machines/Atari2600/Bus.hpp @@ -13,6 +13,7 @@ #include "PIA.hpp" #include "Speaker.hpp" #include "TIA.hpp" +#include "../../Components/ClockReceiver.hpp" namespace Atari2600 { @@ -24,7 +25,7 @@ class Bus { cycles_since_video_update_(0), cycles_since_6532_update_(0) {} - virtual void run_for_cycles(int number_of_cycles) = 0; + virtual void run_for(const Cycles &cycles) = 0; virtual void set_reset_line(bool state) = 0; // the RIOT, TIA and speaker diff --git a/Machines/Atari2600/Cartridges/Cartridge.hpp b/Machines/Atari2600/Cartridges/Cartridge.hpp index 3eb467171..38dc63ecb 100644 --- a/Machines/Atari2600/Cartridges/Cartridge.hpp +++ b/Machines/Atari2600/Cartridges/Cartridge.hpp @@ -22,7 +22,7 @@ template class Cartridge: Cartridge(const std::vector &rom) : rom_(rom) {} - void run_for_cycles(int number_of_cycles) { CPU::MOS6502::Processor>::run_for(Cycles(number_of_cycles)); } + void run_for(const Cycles &cycles) { CPU::MOS6502::Processor>::run_for(cycles); } void set_reset_line(bool state) { CPU::MOS6502::Processor>::set_reset_line(state); } void advance_cycles(unsigned int cycles) {} diff --git a/Machines/CRTMachine.hpp b/Machines/CRTMachine.hpp index 0a192a3c7..84a57684d 100644 --- a/Machines/CRTMachine.hpp +++ b/Machines/CRTMachine.hpp @@ -11,6 +11,7 @@ #include "../Outputs/CRT/CRT.hpp" #include "../Outputs/Speaker.hpp" +#include "../Components/ClockReceiver.hpp" namespace CRTMachine { @@ -41,8 +42,8 @@ class Machine { /// @returns The speaker that receives this machine's output, or @c nullptr if this machine is mute. virtual std::shared_ptr get_speaker() = 0; - /// Runs the machine for @c number_of_cycle cycles. - virtual void run_for_cycles(int number_of_cycles) = 0; + /// Runs the machine for @c cycles. + virtual void run_for(const Cycles &cycles) = 0; // TODO: sever the clock-rate stuff. double get_clock_rate() { diff --git a/Machines/Commodore/Vic-20/Vic20.hpp b/Machines/Commodore/Vic-20/Vic20.hpp index 6981022b7..2bda32a8e 100644 --- a/Machines/Commodore/Vic-20/Vic20.hpp +++ b/Machines/Commodore/Vic-20/Vic20.hpp @@ -174,7 +174,7 @@ class Machine: virtual void close_output(); virtual std::shared_ptr get_crt() { return mos6560_->get_crt(); } virtual std::shared_ptr get_speaker() { return mos6560_->get_speaker(); } - virtual void run_for_cycles(int number_of_cycles) { CPU::MOS6502::Processor::run_for(Cycles(number_of_cycles)); } + virtual void run_for(const Cycles &cycles) { CPU::MOS6502::Processor::run_for(cycles); } // to satisfy MOS::MOS6522::Delegate virtual void mos6522_did_change_interrupt_status(void *mos6522); diff --git a/Machines/Electron/Electron.hpp b/Machines/Electron/Electron.hpp index d730bc803..b6824535b 100644 --- a/Machines/Electron/Electron.hpp +++ b/Machines/Electron/Electron.hpp @@ -94,7 +94,7 @@ class Machine: virtual void close_output(); virtual std::shared_ptr get_crt(); virtual std::shared_ptr get_speaker(); - virtual void run_for_cycles(int number_of_cycles) { CPU::MOS6502::Processor::run_for(Cycles(number_of_cycles)); } + virtual void run_for(const Cycles &cycles) { CPU::MOS6502::Processor::run_for(cycles); } // to satisfy Tape::Delegate virtual void tape_did_change_interrupt_status(Tape *tape); diff --git a/Machines/Oric/Oric.cpp b/Machines/Oric/Oric.cpp index 54a6100f7..d82639d54 100644 --- a/Machines/Oric/Oric.cpp +++ b/Machines/Oric/Oric.cpp @@ -198,8 +198,8 @@ std::shared_ptr Machine::get_speaker() { return via_.ay8910; } -void Machine::run_for_cycles(int number_of_cycles) { - CPU::MOS6502::Processor::run_for(Cycles(number_of_cycles)); +void Machine::run_for(const Cycles &cycles) { + CPU::MOS6502::Processor::run_for(cycles); } #pragma mark - The 6522 diff --git a/Machines/Oric/Oric.hpp b/Machines/Oric/Oric.hpp index 43766d710..be1df2c78 100644 --- a/Machines/Oric/Oric.hpp +++ b/Machines/Oric/Oric.hpp @@ -85,7 +85,7 @@ class Machine: virtual void close_output(); virtual std::shared_ptr get_crt(); virtual std::shared_ptr get_speaker(); - virtual void run_for_cycles(int number_of_cycles); + virtual void run_for(const Cycles &cyclesß); // to satisfy MOS::MOS6522IRQDelegate::Delegate void mos6522_did_change_interrupt_status(void *mos6522); diff --git a/Machines/ZX8081/ZX8081.cpp b/Machines/ZX8081/ZX8081.cpp index 23fe0db44..8d0d2b42a 100644 --- a/Machines/ZX8081/ZX8081.cpp +++ b/Machines/ZX8081/ZX8081.cpp @@ -205,8 +205,8 @@ std::shared_ptr Machine::get_speaker() { return nullptr; } -void Machine::run_for_cycles(int number_of_cycles) { - CPU::Z80::Processor::run_for_cycles(number_of_cycles); +void Machine::run_for(const Cycles &cycles) { + CPU::Z80::Processor::run_for_cycles(int(cycles)); } void Machine::configure_as_target(const StaticAnalyser::Target &target) { diff --git a/Machines/ZX8081/ZX8081.hpp b/Machines/ZX8081/ZX8081.hpp index c2f36a6ff..e6b460c4e 100644 --- a/Machines/ZX8081/ZX8081.hpp +++ b/Machines/ZX8081/ZX8081.hpp @@ -56,7 +56,7 @@ class Machine: std::shared_ptr get_crt(); std::shared_ptr get_speaker(); - void run_for_cycles(int number_of_cycles); + void run_for(const Cycles &cycles); void configure_as_target(const StaticAnalyser::Target &target); diff --git a/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm b/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm index 16861bdaa..6ed1e1d79 100644 --- a/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm +++ b/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm @@ -104,7 +104,7 @@ struct MachineDelegate: CRTMachine::Machine::Delegate { - (void)runForNumberOfCycles:(int)numberOfCycles { @synchronized(self) { - self.machine->run_for_cycles(numberOfCycles); + self.machine->run_for(Cycles(numberOfCycles)); } } diff --git a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSElectron.mm b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSElectron.mm index 493b4836c..0dfd05a63 100644 --- a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSElectron.mm +++ b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSElectron.mm @@ -25,8 +25,7 @@ - (instancetype)init { self = [super init]; - if(self) - { + if(self) { [self setOSROM:[self rom:@"os"]]; [self setBASICROM:[self rom:@"basic"]]; [self setDFSROM:[self rom:@"DFS-1770-2.20"]]; @@ -38,8 +37,7 @@ return self; } -- (NSData *)rom:(NSString *)name -{ +- (NSData *)rom:(NSString *)name { return [[NSBundle mainBundle] dataForResource:name withExtension:@"rom" subdirectory:@"ROMImages/Electron"]; } diff --git a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSOric.mm b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSOric.mm index 4680b4464..de5bcb3ef 100644 --- a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSOric.mm +++ b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSOric.mm @@ -15,16 +15,13 @@ #import "NSData+StdVector.h" #import "NSBundle+DataResource.h" -@implementation CSOric -{ +@implementation CSOric { Oric::Machine _oric; } -- (instancetype)init -{ +- (instancetype)init { self = [super init]; - if(self) - { + if(self) { NSData *basic10 = [self rom:@"basic10"]; NSData *basic11 = [self rom:@"basic11"]; NSData *colour = [self rom:@"colour"]; @@ -38,23 +35,19 @@ return self; } -- (NSData *)rom:(NSString *)name -{ +- (NSData *)rom:(NSString *)name { return [[NSBundle mainBundle] dataForResource:name withExtension:@"rom" subdirectory:@"ROMImages/Oric"]; } -- (CRTMachine::Machine * const)machine -{ +- (CRTMachine::Machine * const)machine { return &_oric; } #pragma mark - CSKeyboardMachine -- (void)setKey:(uint16_t)key isPressed:(BOOL)isPressed -{ +- (void)setKey:(uint16_t)key isPressed:(BOOL)isPressed { @synchronized(self) { - switch(key) - { + switch(key) { case VK_ANSI_0: _oric.set_key_state(Oric::Key::Key0, isPressed); break; case VK_ANSI_1: _oric.set_key_state(Oric::Key::Key1, isPressed); break; case VK_ANSI_2: _oric.set_key_state(Oric::Key::Key2, isPressed); break; @@ -137,8 +130,7 @@ } } -- (void)clearAllKeys -{ +- (void)clearAllKeys { _oric.clear_all_keys(); } diff --git a/Processors/6502/6502AllRAM.cpp b/Processors/6502/6502AllRAM.cpp index e9d864fe8..e706f599f 100644 --- a/Processors/6502/6502AllRAM.cpp +++ b/Processors/6502/6502AllRAM.cpp @@ -36,8 +36,8 @@ class ConcreteAllRAMProcessor: public AllRAMProcessor, public Processor::run_for_cycles(number_of_cycles); + void run_for(const Cycles &cycles) { + Processor::run_for(cycles); } bool is_jammed() { diff --git a/Processors/6502/6502AllRAM.hpp b/Processors/6502/6502AllRAM.hpp index a2009a323..8f9190668 100644 --- a/Processors/6502/6502AllRAM.hpp +++ b/Processors/6502/6502AllRAM.hpp @@ -22,7 +22,7 @@ class AllRAMProcessor: static AllRAMProcessor *Processor(); virtual ~AllRAMProcessor() {} - virtual void run_for_cycles(int number_of_cycles) = 0; + virtual void run_for(const Cycles &cycles) = 0; virtual bool is_jammed() = 0; virtual void set_irq_line(bool value) = 0; virtual void set_nmi_line(bool value) = 0; From b0c2325adcf0a0586b8c9460589aa97d64a72d56 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 22 Jul 2017 22:21:26 -0400 Subject: [PATCH 09/52] Corrected run call, and accepted that jam handling is gone forever. --- .../Bridges/TestMachine6502.mm | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.mm b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.mm index fab9428c0..81e9d1afb 100644 --- a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.mm +++ b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.mm @@ -11,22 +11,6 @@ #include "6502AllRAM.hpp" #import "TestMachine+ForSubclassEyesOnly.h" -const uint8_t CSTestMachine6502JamOpcode = CPU::MOS6502::JamOpcode; - -#pragma mark - C++ jam handler - -//class MachineJamHandler: public CPU::MOS6502::AllRAMProcessor::JamHandler { -// public: -// MachineJamHandler(CSTestMachine6502 *targetMachine) : _targetMachine(targetMachine) {} -// -// void processor_did_jam(CPU::MOS6502::AllRAMProcessor::Processor *processor, uint16_t address) override { -// [_targetMachine.jamHandler testMachine:_targetMachine didJamAtAddress:address]; -// } -// -// private: -// CSTestMachine6502 *_targetMachine; -//}; - #pragma mark - Register enum map static CPU::MOS6502::Register registerForRegister(CSTestMachine6502Register reg) { @@ -45,7 +29,6 @@ static CPU::MOS6502::Register registerForRegister(CSTestMachine6502Register reg) @implementation CSTestMachine6502 { CPU::MOS6502::AllRAMProcessor *_processor; -// MachineJamHandler *_cppJamHandler; } #pragma mark - Lifecycle @@ -117,7 +100,7 @@ static CPU::MOS6502::Register registerForRegister(CSTestMachine6502Register reg) } - (void)runForNumberOfCycles:(int)cycles { - _processor->run_for_cycles(cycles); + _processor->run_for(Cycles(cycles)); } @end From c2a7dffa7d21f0f5d6369ab69f4e0ca91c57f1a5 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 22 Jul 2017 23:02:28 -0400 Subject: [PATCH 10/52] Converted the ZX80/81 video component into a ClockReceiver. As it happens, it's most convenient to take the half-cycle bus here. --- Machines/ZX8081/Video.cpp | 4 ++-- Machines/ZX8081/Video.hpp | 7 ++++--- Machines/ZX8081/ZX8081.cpp | 10 +++++----- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Machines/ZX8081/Video.cpp b/Machines/ZX8081/Video.cpp index 5531e7dee..766c6a1f6 100644 --- a/Machines/ZX8081/Video.cpp +++ b/Machines/ZX8081/Video.cpp @@ -29,9 +29,9 @@ Video::Video() : crt_->set_visible_area(Outputs::CRT::Rect(0.1f, 0.1f, 0.8f, 0.8f)); } -void Video::run_for_cycles(int number_of_cycles) { +void Video::run_for(const HalfCycles &half_cycles) { // Just keep a running total of the amount of time that remains owed to the CRT. - cycles_since_update_ += (unsigned int)number_of_cycles << 1; + cycles_since_update_ += (unsigned int)int(half_cycles); } void Video::flush() { diff --git a/Machines/ZX8081/Video.hpp b/Machines/ZX8081/Video.hpp index 9c63021ba..9ae254b8d 100644 --- a/Machines/ZX8081/Video.hpp +++ b/Machines/ZX8081/Video.hpp @@ -10,6 +10,7 @@ #define Machines_ZX8081_Video_hpp #include "../../Outputs/CRT/CRT.hpp" +#include "../../Components/ClockReceiver.hpp" namespace ZX8081 { @@ -23,15 +24,15 @@ namespace ZX8081 { a 1-bit graphic and output over the next 4 cycles, picking between the white level and the black level. */ -class Video { +class Video: public ClockReceiver