From e7aeed2f033054b21b70342ddb888172522a7189 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 19 Jun 2016 13:10:52 -0400 Subject: [PATCH 1/3] Established a general pattern for machines that can type things. Started working on the Vic typing itself. --- Machines/Typer.cpp | 47 +++++++++++++++++ Machines/Typer.hpp | 50 +++++++++++++++++++ Machines/Vic-20/Vic20.cpp | 29 ++++++++++- Machines/Vic-20/Vic20.hpp | 14 +++++- .../Clock Signal.xcodeproj/project.pbxproj | 6 +++ 5 files changed, 144 insertions(+), 2 deletions(-) create mode 100644 Machines/Typer.cpp create mode 100644 Machines/Typer.hpp diff --git a/Machines/Typer.cpp b/Machines/Typer.cpp new file mode 100644 index 000000000..d030708c9 --- /dev/null +++ b/Machines/Typer.cpp @@ -0,0 +1,47 @@ +// +// Typer.cpp +// Clock Signal +// +// Created by Thomas Harte on 19/06/2016. +// Copyright © 2016 Thomas Harte. All rights reserved. +// + +#include "Typer.hpp" +#include + +using namespace Utility; + +Typer::Typer(const char *string, int delay, int frequency, Delegate *delegate) : + _counter(-delay), _frequency(frequency), _string(strdup(string)), _string_pointer(0), _delegate(delegate) {} + +void Typer::update(int duration) +{ + if(_string) + { + if(_counter < 0 && _counter + duration >= 0) + { + _delegate->typer_set_next_character(this, _string[_string_pointer]); + _string_pointer++; + } + + _counter += duration; + while(_counter > _frequency) + { + _counter -= _frequency; + _delegate->typer_set_next_character(this, _string[_string_pointer]); + _string_pointer++; + + if(!_string[_string_pointer]) + { + free(_string); + _string = nullptr; + return; + } + } + } +} + +Typer::~Typer() +{ + free(_string); +} diff --git a/Machines/Typer.hpp b/Machines/Typer.hpp new file mode 100644 index 000000000..3596b9a12 --- /dev/null +++ b/Machines/Typer.hpp @@ -0,0 +1,50 @@ +// +// Typer.hpp +// Clock Signal +// +// Created by Thomas Harte on 19/06/2016. +// Copyright © 2016 Thomas Harte. All rights reserved. +// + +#ifndef Typer_hpp +#define Typer_hpp + +#include + +namespace Utility { + +class Typer { + public: + class Delegate { + public: + virtual void typer_set_next_character(Typer *typer, char character) = 0; + }; + + Typer(const char *string, int delay, int frequency, Delegate *delegate); + ~Typer(); + void update(int duration); + + private: + char *_string; + int _frequency; + int _counter; + Delegate *_delegate; + size_t _string_pointer; +}; + +class TypeRecipient: public Typer::Delegate { + public: + void set_typer_for_string(const char *string) + { + _typer = std::unique_ptr(new Typer(string, get_typer_delay(), get_typer_frequency(), this)); + } + + protected: + virtual int get_typer_delay() = 0; + virtual int get_typer_frequency() = 0; + std::unique_ptr _typer; +}; + +} + +#endif /* Typer_hpp */ diff --git a/Machines/Vic-20/Vic20.cpp b/Machines/Vic-20/Vic20.cpp index 71888551f..d92bdbcb9 100644 --- a/Machines/Vic-20/Vic20.cpp +++ b/Machines/Vic-20/Vic20.cpp @@ -81,6 +81,7 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin _userPortVIA.run_for_half_cycles(2); _keyboardVIA.run_for_half_cycles(2); + if(_typer) _typer->update(1); return 1; } @@ -125,7 +126,8 @@ void Machine::add_prg(size_t length, const uint8_t *data) _rom_length = (uint16_t)(length - 2); if(_rom_address >= 0x1000 && _rom_address+_rom_length < 0x2000) { - memcpy(&_screenMemory[_rom_address - 0x1000], &data[2], length - 2); + set_typer_for_string("run\n"); +// memcpy(&_screenMemory[_rom_address - 0x1000], &data[2], length - 2); } else { @@ -134,3 +136,28 @@ void Machine::add_prg(size_t length, const uint8_t *data) } } } + +#pragma mark - Typer + +int Machine::get_typer_delay() +{ + return 263*60*65 / 2; // wait half a second +} + +int Machine::get_typer_frequency() +{ + return 2*263*65; // accept a new character every two fields +} + +void Machine::typer_set_next_character(::Utility::Typer *typer, char character) +{ + clear_all_keys(); + switch(character) + { + case 'r': set_key_state(Key::KeyR, true); break; + case 'u': set_key_state(Key::KeyU, true); break; + case 'n': set_key_state(Key::KeyN, true); break; + case '\n': set_key_state(Key::KeyReturn, true); break; + } + printf("."); +} diff --git a/Machines/Vic-20/Vic20.hpp b/Machines/Vic-20/Vic20.hpp index 4fb639a55..768eb2fd6 100644 --- a/Machines/Vic-20/Vic20.hpp +++ b/Machines/Vic-20/Vic20.hpp @@ -12,7 +12,9 @@ #include "../../Processors/6502/CPU6502.hpp" #include "../../Components/6560/6560.hpp" #include "../../Components/6522/6522.hpp" + #include "../CRTMachine.hpp" +#include "../Typer.hpp" namespace Vic20 { @@ -88,7 +90,12 @@ class KeyboardVIA: public MOS::MOS6522, public MOS::MOS6522IRQDeleg uint8_t _activation_mask; }; -class Machine: public CPU6502::Processor, public CRTMachine::Machine, public MOS::MOS6522IRQDelegate::Delegate { +class Machine: + public CPU6502::Processor, + public CRTMachine::Machine, + public MOS::MOS6522IRQDelegate::Delegate, + public Utility::TypeRecipient { + public: Machine(); ~Machine(); @@ -114,6 +121,11 @@ class Machine: public CPU6502::Processor, public CRTMachine::Machine, p // to satisfy MOS::MOS6522::Delegate virtual void mos6522_did_change_interrupt_status(void *mos6522); + // for Utility::TypeRecipient + virtual int get_typer_delay(); + virtual int get_typer_frequency(); + virtual void typer_set_next_character(Utility::Typer *typer, char character); + private: uint8_t _characterROM[0x1000]; uint8_t _basicROM[0x2000]; diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 1571aec89..d7c054aac 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ 4B14145E1B5887AA00E04248 /* CPU6502AllRAM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1414591B58879D00E04248 /* CPU6502AllRAM.cpp */; }; 4B1414601B58885000E04248 /* WolfgangLorenzTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B14145F1B58885000E04248 /* WolfgangLorenzTests.swift */; }; 4B1414621B58888700E04248 /* KlausDormannTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B1414611B58888700E04248 /* KlausDormannTests.swift */; }; + 4B1E85751D170228001EF87D /* Typer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1E85731D170228001EF87D /* Typer.cpp */; }; 4B2409551C45AB05004DA684 /* Speaker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2409531C45AB05004DA684 /* Speaker.cpp */; }; 4B2A539F1D117D36003C6002 /* CSAudioQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B2A53911D117D36003C6002 /* CSAudioQueue.m */; }; 4B2A53A01D117D36003C6002 /* CSMachine.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B2A53961D117D36003C6002 /* CSMachine.mm */; }; @@ -352,6 +353,8 @@ 4B14145A1B58879D00E04248 /* CPU6502AllRAM.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CPU6502AllRAM.hpp; sourceTree = ""; }; 4B14145F1B58885000E04248 /* WolfgangLorenzTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WolfgangLorenzTests.swift; sourceTree = ""; }; 4B1414611B58888700E04248 /* KlausDormannTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KlausDormannTests.swift; sourceTree = ""; }; + 4B1E85731D170228001EF87D /* Typer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Typer.cpp; sourceTree = ""; }; + 4B1E85741D170228001EF87D /* Typer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Typer.hpp; sourceTree = ""; }; 4B2409531C45AB05004DA684 /* Speaker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Speaker.cpp; path = ../../Outputs/Speaker.cpp; sourceTree = ""; }; 4B2409541C45AB05004DA684 /* Speaker.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Speaker.hpp; path = ../../Outputs/Speaker.hpp; sourceTree = ""; }; 4B24095A1C45DF85004DA684 /* Stepper.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Stepper.hpp; sourceTree = ""; }; @@ -1251,6 +1254,8 @@ 4B2E2D961C3A06EC00138695 /* Atari2600 */, 4B2E2D9E1C3A070900138695 /* Electron */, 4B886FF61D03B632004291C3 /* Vic-20 */, + 4B1E85731D170228001EF87D /* Typer.cpp */, + 4B1E85741D170228001EF87D /* Typer.hpp */, ); name = Machines; path = ../../Machines; @@ -1764,6 +1769,7 @@ 4B69FB441C4D941400B5F0AA /* TapeUEF.cpp in Sources */, 4BBF99141C8FBA6F0075DAFB /* CRTInputBufferBuilder.cpp in Sources */, 4B2409551C45AB05004DA684 /* Speaker.cpp in Sources */, + 4B1E85751D170228001EF87D /* Typer.cpp in Sources */, 4B2E2D9D1C3A070400138695 /* Electron.cpp in Sources */, 4B69FB3D1C4D908A00B5F0AA /* Tape.cpp in Sources */, 4B55CE5D1C3B7D6F0093A61B /* CSOpenGLView.m in Sources */, From 3fc472d5cb68bf221142932f9e3e94da39bffc63 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 19 Jun 2016 13:46:53 -0400 Subject: [PATCH 2/3] Expanded typing to include phase for machines that need to go through multiple keypresses to reach a certain state, expanded Vic to be able to type most things (still bodged on lowercase though), and to schedule a 'run' if it's supposed to be loading into RAM, spotting that opportunity actually to do so. --- Machines/Typer.cpp | 35 ++++++--- Machines/Typer.hpp | 5 +- Machines/Vic-20/Vic20.cpp | 158 ++++++++++++++++++++++++++++++++++---- Machines/Vic-20/Vic20.hpp | 4 +- 4 files changed, 172 insertions(+), 30 deletions(-) diff --git a/Machines/Typer.cpp b/Machines/Typer.cpp index d030708c9..a580d9747 100644 --- a/Machines/Typer.cpp +++ b/Machines/Typer.cpp @@ -12,7 +12,7 @@ using namespace Utility; Typer::Typer(const char *string, int delay, int frequency, Delegate *delegate) : - _counter(-delay), _frequency(frequency), _string(strdup(string)), _string_pointer(0), _delegate(delegate) {} + _counter(-delay), _frequency(frequency), _string(strdup(string)), _string_pointer(0), _delegate(delegate), _phase(0) {} void Typer::update(int duration) { @@ -20,27 +20,38 @@ void Typer::update(int duration) { if(_counter < 0 && _counter + duration >= 0) { - _delegate->typer_set_next_character(this, _string[_string_pointer]); - _string_pointer++; + type_next_character(); } _counter += duration; while(_counter > _frequency) { _counter -= _frequency; - _delegate->typer_set_next_character(this, _string[_string_pointer]); - _string_pointer++; - - if(!_string[_string_pointer]) - { - free(_string); - _string = nullptr; - return; - } + type_next_character(); } } } +void Typer::type_next_character() +{ + if(_delegate->typer_set_next_character(this, _string[_string_pointer], _phase)) + { + _phase = 0; + if(!_string[_string_pointer]) + { + free(_string); + _string = nullptr; + return; + } + + _string_pointer++; + } + else + { + _phase++; + } +} + Typer::~Typer() { free(_string); diff --git a/Machines/Typer.hpp b/Machines/Typer.hpp index 3596b9a12..aa553471a 100644 --- a/Machines/Typer.hpp +++ b/Machines/Typer.hpp @@ -17,7 +17,7 @@ class Typer { public: class Delegate { public: - virtual void typer_set_next_character(Typer *typer, char character) = 0; + virtual bool typer_set_next_character(Typer *typer, char character, int phase) = 0; }; Typer(const char *string, int delay, int frequency, Delegate *delegate); @@ -28,8 +28,11 @@ class Typer { char *_string; int _frequency; int _counter; + int _phase; Delegate *_delegate; size_t _string_pointer; + + void type_next_character(); }; class TypeRecipient: public Typer::Delegate { diff --git a/Machines/Vic-20/Vic20.cpp b/Machines/Vic-20/Vic20.cpp index d92bdbcb9..7f696c073 100644 --- a/Machines/Vic-20/Vic20.cpp +++ b/Machines/Vic-20/Vic20.cpp @@ -126,14 +126,11 @@ void Machine::add_prg(size_t length, const uint8_t *data) _rom_length = (uint16_t)(length - 2); if(_rom_address >= 0x1000 && _rom_address+_rom_length < 0x2000) { - set_typer_for_string("run\n"); -// memcpy(&_screenMemory[_rom_address - 0x1000], &data[2], length - 2); - } - else - { - _rom = new uint8_t[length - 2]; - memcpy(_rom, &data[2], length - 2); + set_typer_for_string("RUN\n"); } + + _rom = new uint8_t[length - 2]; + memcpy(_rom, &data[2], length - 2); } } @@ -141,7 +138,7 @@ void Machine::add_prg(size_t length, const uint8_t *data) int Machine::get_typer_delay() { - return 263*60*65 / 2; // wait half a second + return 1*263*60*65; // wait two seconds } int Machine::get_typer_frequency() @@ -149,15 +146,144 @@ int Machine::get_typer_frequency() return 2*263*65; // accept a new character every two fields } -void Machine::typer_set_next_character(::Utility::Typer *typer, char character) +bool Machine::typer_set_next_character(::Utility::Typer *typer, char character, int phase) { - clear_all_keys(); - switch(character) + // If there's a 'ROM' installed that can never be accessed, assume that this typing was scheduled because + // it should be in RAM. So copy it there. + if(_rom && _rom_address >= 0x1000 && _rom_address+_rom_length < 0x2000) { - case 'r': set_key_state(Key::KeyR, true); break; - case 'u': set_key_state(Key::KeyU, true); break; - case 'n': set_key_state(Key::KeyN, true); break; - case '\n': set_key_state(Key::KeyReturn, true); break; + memcpy(&_screenMemory[_rom_address - 0x1000], _rom, _rom_length); + delete[] _rom; + _rom = nullptr; } - printf("."); + + if(!phase) clear_all_keys(); + + // The following table is arranged in ASCII order + Key key_sequences[][3] = { + {NotMapped}, {NotMapped}, {NotMapped}, {NotMapped}, {NotMapped}, {NotMapped}, {NotMapped}, {NotMapped}, + {KeyDelete, TerminateSequence}, + {NotMapped}, + {KeyReturn, TerminateSequence}, + {NotMapped}, {NotMapped}, {NotMapped}, {NotMapped}, {NotMapped}, + {NotMapped}, {NotMapped}, {NotMapped}, {NotMapped}, + {NotMapped}, {NotMapped}, {NotMapped}, {NotMapped}, + {NotMapped}, {NotMapped}, {NotMapped}, {NotMapped}, + {NotMapped}, {NotMapped}, {NotMapped}, {NotMapped}, + + {KeySpace, TerminateSequence}, // space + + {KeyLShift, Key1, TerminateSequence}, // ! + {KeyLShift, Key2, TerminateSequence}, // " + {KeyLShift, Key3, TerminateSequence}, // # + {KeyLShift, Key4, TerminateSequence}, // $ + {KeyLShift, Key5, TerminateSequence}, // % + {KeyLShift, Key6, TerminateSequence}, // & + {KeyLShift, Key7, TerminateSequence}, // ' + {KeyLShift, Key8, TerminateSequence}, // ( + {KeyLShift, Key9, TerminateSequence}, // ) + + {KeyAsterisk, TerminateSequence}, // * + {KeyPlus, TerminateSequence}, // + + {KeyComma, TerminateSequence}, // , + {KeyDash, TerminateSequence}, // - + {KeyFullStop, TerminateSequence}, // . + {KeySlash, TerminateSequence}, // / + + {Key0, TerminateSequence}, // 0 + {Key1, TerminateSequence}, // 1 + {Key2, TerminateSequence}, // 2 + {Key3, TerminateSequence}, // 3 + {Key4, TerminateSequence}, // 4 + {Key5, TerminateSequence}, // 5 + {Key6, TerminateSequence}, // 6 + {Key7, TerminateSequence}, // 7 + {Key8, TerminateSequence}, // 8 + {Key9, TerminateSequence}, // 9 + + {KeyColon, TerminateSequence}, // : + {KeySemicolon, TerminateSequence}, // ; + {KeyLShift, KeyComma, TerminateSequence}, // < + {KeyEquals, TerminateSequence}, // = + {KeyLShift, KeyFullStop, TerminateSequence}, // > + {KeyLShift, KeySlash, TerminateSequence}, // ? + {KeyAt, TerminateSequence}, // @ + + {KeyA, TerminateSequence}, // A + {KeyB, TerminateSequence}, // B + {KeyC, TerminateSequence}, // C + {KeyD, TerminateSequence}, // D + {KeyE, TerminateSequence}, // E + {KeyF, TerminateSequence}, // F + {KeyG, TerminateSequence}, // G + {KeyH, TerminateSequence}, // H + {KeyI, TerminateSequence}, // I + {KeyJ, TerminateSequence}, // J + {KeyK, TerminateSequence}, // K + {KeyL, TerminateSequence}, // L + {KeyM, TerminateSequence}, // M + {KeyN, TerminateSequence}, // N + {KeyO, TerminateSequence}, // O + {KeyP, TerminateSequence}, // P + {KeyQ, TerminateSequence}, // Q + {KeyR, TerminateSequence}, // R + {KeyS, TerminateSequence}, // S + {KeyT, TerminateSequence}, // T + {KeyU, TerminateSequence}, // U + {KeyV, TerminateSequence}, // V + {KeyW, TerminateSequence}, // W + {KeyX, TerminateSequence}, // X + {KeyY, TerminateSequence}, // Y + {KeyZ, TerminateSequence}, // Z + + {KeyLShift, KeyColon, TerminateSequence}, // [ + {NotMapped}, // '\' + {KeyLShift, KeyFullStop, TerminateSequence}, // ] + {NotMapped}, // ^ + {NotMapped}, // _ + {NotMapped}, // ` + + {KeyLShift, KeyA, TerminateSequence}, // A + {KeyLShift, KeyB, TerminateSequence}, // B + {KeyLShift, KeyC, TerminateSequence}, // C + {KeyLShift, KeyD, TerminateSequence}, // D + {KeyLShift, KeyE, TerminateSequence}, // E + {KeyLShift, KeyF, TerminateSequence}, // F + {KeyLShift, KeyG, TerminateSequence}, // G + {KeyLShift, KeyH, TerminateSequence}, // H + {KeyLShift, KeyI, TerminateSequence}, // I + {KeyLShift, KeyJ, TerminateSequence}, // J + {KeyLShift, KeyK, TerminateSequence}, // K + {KeyLShift, KeyL, TerminateSequence}, // L + {KeyLShift, KeyM, TerminateSequence}, // M + {KeyLShift, KeyN, TerminateSequence}, // N + {KeyLShift, KeyO, TerminateSequence}, // O + {KeyLShift, KeyP, TerminateSequence}, // P + {KeyLShift, KeyQ, TerminateSequence}, // Q + {KeyLShift, KeyR, TerminateSequence}, // R + {KeyLShift, KeyS, TerminateSequence}, // S + {KeyLShift, KeyT, TerminateSequence}, // T + {KeyLShift, KeyU, TerminateSequence}, // U + {KeyLShift, KeyV, TerminateSequence}, // V + {KeyLShift, KeyW, TerminateSequence}, // W + {KeyLShift, KeyX, TerminateSequence}, // X + {KeyLShift, KeyY, TerminateSequence}, // Y + {KeyLShift, KeyZ, TerminateSequence}, // Z + + }; + Key *key_sequence = nullptr; + + character &= 0x7f; + if(character < sizeof(key_sequences) / sizeof(*key_sequences)) + { + key_sequence = key_sequences[character]; + } + + if(key_sequence && key_sequence[phase] != NotMapped) + { + set_key_state(key_sequence[phase], true); + return key_sequence[phase+1] == TerminateSequence; + } + + return true; } diff --git a/Machines/Vic-20/Vic20.hpp b/Machines/Vic-20/Vic20.hpp index 768eb2fd6..7b888de7d 100644 --- a/Machines/Vic-20/Vic20.hpp +++ b/Machines/Vic-20/Vic20.hpp @@ -44,6 +44,8 @@ enum Key: uint16_t { KeyI = key(1, 0x10), KeyP = key(1, 0x20), KeyAsterisk = key(1, 0x40), KeyReturn = key(1, 0x80), Key1 = key(0, 0x01), Key3 = key(0, 0x02), Key5 = key(0, 0x04), Key7 = key(0, 0x08), Key9 = key(0, 0x10), KeyPlus = key(0, 0x20), KeyGBP = key(0, 0x40), KeyDelete = key(0, 0x80), + + TerminateSequence = 0, NotMapped = 0xffff }; class UserPortVIA: public MOS::MOS6522, public MOS::MOS6522IRQDelegate { @@ -124,7 +126,7 @@ class Machine: // for Utility::TypeRecipient virtual int get_typer_delay(); virtual int get_typer_frequency(); - virtual void typer_set_next_character(Utility::Typer *typer, char character); + virtual bool typer_set_next_character(Utility::Typer *typer, char character, int phase); private: uint8_t _characterROM[0x1000]; From ef3ed1f4369c0b8a25d4f0fbdc15d4224395a80d Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 19 Jun 2016 16:35:04 -0400 Subject: [PATCH 3/3] Implemented full paste ability for any machine that is a typer. --- Machines/Vic-20/Vic20.cpp | 153 +++++++----------- .../Documents/MachineDocument.swift | 8 + .../Mac/Clock Signal/Machine/CSMachine.h | 2 + .../Mac/Clock Signal/Machine/CSMachine.mm | 7 + Processors/6502/CPU6502.hpp | 10 ++ 5 files changed, 84 insertions(+), 96 deletions(-) diff --git a/Machines/Vic-20/Vic20.cpp b/Machines/Vic-20/Vic20.cpp index 7f696c073..17973f035 100644 --- a/Machines/Vic-20/Vic20.cpp +++ b/Machines/Vic-20/Vic20.cpp @@ -138,7 +138,7 @@ void Machine::add_prg(size_t length, const uint8_t *data) int Machine::get_typer_delay() { - return 1*263*60*65; // wait two seconds + return get_reset_line() ? 1*263*60*65 : 0; // wait two seconds if resetting } int Machine::get_typer_frequency() @@ -173,102 +173,58 @@ bool Machine::typer_set_next_character(::Utility::Typer *typer, char character, {KeySpace, TerminateSequence}, // space - {KeyLShift, Key1, TerminateSequence}, // ! - {KeyLShift, Key2, TerminateSequence}, // " - {KeyLShift, Key3, TerminateSequence}, // # - {KeyLShift, Key4, TerminateSequence}, // $ - {KeyLShift, Key5, TerminateSequence}, // % - {KeyLShift, Key6, TerminateSequence}, // & - {KeyLShift, Key7, TerminateSequence}, // ' - {KeyLShift, Key8, TerminateSequence}, // ( - {KeyLShift, Key9, TerminateSequence}, // ) + {KeyLShift, Key1, TerminateSequence}, {KeyLShift, Key2, TerminateSequence}, // !, " + {KeyLShift, Key3, TerminateSequence}, {KeyLShift, Key4, TerminateSequence}, // #, $ + {KeyLShift, Key5, TerminateSequence}, {KeyLShift, Key6, TerminateSequence}, // %, & + {KeyLShift, Key7, TerminateSequence}, {KeyLShift, Key8, TerminateSequence}, // ', ( + {KeyLShift, Key9, TerminateSequence}, {KeyAsterisk, TerminateSequence}, // ), * + {KeyPlus, TerminateSequence}, {KeyComma, TerminateSequence}, // +, , + {KeyDash, TerminateSequence}, {KeyFullStop, TerminateSequence}, // -, . + {KeySlash, TerminateSequence}, // / - {KeyAsterisk, TerminateSequence}, // * - {KeyPlus, TerminateSequence}, // + - {KeyComma, TerminateSequence}, // , - {KeyDash, TerminateSequence}, // - - {KeyFullStop, TerminateSequence}, // . - {KeySlash, TerminateSequence}, // / + {Key0, TerminateSequence}, {Key1, TerminateSequence}, // 0, 1 + {Key2, TerminateSequence}, {Key3, TerminateSequence}, // 2, 3 + {Key4, TerminateSequence}, {Key5, TerminateSequence}, // 4, 5 + {Key6, TerminateSequence}, {Key7, TerminateSequence}, // 6, 7 + {Key8, TerminateSequence}, {Key9, TerminateSequence}, // 8, 9 - {Key0, TerminateSequence}, // 0 - {Key1, TerminateSequence}, // 1 - {Key2, TerminateSequence}, // 2 - {Key3, TerminateSequence}, // 3 - {Key4, TerminateSequence}, // 4 - {Key5, TerminateSequence}, // 5 - {Key6, TerminateSequence}, // 6 - {Key7, TerminateSequence}, // 7 - {Key8, TerminateSequence}, // 8 - {Key9, TerminateSequence}, // 9 - - {KeyColon, TerminateSequence}, // : - {KeySemicolon, TerminateSequence}, // ; - {KeyLShift, KeyComma, TerminateSequence}, // < - {KeyEquals, TerminateSequence}, // = - {KeyLShift, KeyFullStop, TerminateSequence}, // > - {KeyLShift, KeySlash, TerminateSequence}, // ? + {KeyColon, TerminateSequence}, {KeySemicolon, TerminateSequence}, // :, ; + {KeyLShift, KeyComma, TerminateSequence}, {KeyEquals, TerminateSequence}, // <, = + {KeyLShift, KeyFullStop, TerminateSequence}, {KeyLShift, KeySlash, TerminateSequence}, // >, ? {KeyAt, TerminateSequence}, // @ - {KeyA, TerminateSequence}, // A - {KeyB, TerminateSequence}, // B - {KeyC, TerminateSequence}, // C - {KeyD, TerminateSequence}, // D - {KeyE, TerminateSequence}, // E - {KeyF, TerminateSequence}, // F - {KeyG, TerminateSequence}, // G - {KeyH, TerminateSequence}, // H - {KeyI, TerminateSequence}, // I - {KeyJ, TerminateSequence}, // J - {KeyK, TerminateSequence}, // K - {KeyL, TerminateSequence}, // L - {KeyM, TerminateSequence}, // M - {KeyN, TerminateSequence}, // N - {KeyO, TerminateSequence}, // O - {KeyP, TerminateSequence}, // P - {KeyQ, TerminateSequence}, // Q - {KeyR, TerminateSequence}, // R - {KeyS, TerminateSequence}, // S - {KeyT, TerminateSequence}, // T - {KeyU, TerminateSequence}, // U - {KeyV, TerminateSequence}, // V - {KeyW, TerminateSequence}, // W - {KeyX, TerminateSequence}, // X - {KeyY, TerminateSequence}, // Y - {KeyZ, TerminateSequence}, // Z + {KeyA, TerminateSequence}, {KeyB, TerminateSequence}, {KeyC, TerminateSequence}, {KeyD, TerminateSequence}, // A, B, C, D + {KeyE, TerminateSequence}, {KeyF, TerminateSequence}, {KeyG, TerminateSequence}, {KeyH, TerminateSequence}, // E, F, G, H + {KeyI, TerminateSequence}, {KeyJ, TerminateSequence}, {KeyK, TerminateSequence}, {KeyL, TerminateSequence}, // I, J, K L + {KeyM, TerminateSequence}, {KeyN, TerminateSequence}, {KeyO, TerminateSequence}, {KeyP, TerminateSequence}, // M, N, O, P + {KeyQ, TerminateSequence}, {KeyR, TerminateSequence}, {KeyS, TerminateSequence}, {KeyT, TerminateSequence}, // Q, R, S, T + {KeyU, TerminateSequence}, {KeyV, TerminateSequence}, {KeyW, TerminateSequence}, {KeyX, TerminateSequence}, // U, V, W X + {KeyY, TerminateSequence}, {KeyZ, TerminateSequence}, // Y, Z - {KeyLShift, KeyColon, TerminateSequence}, // [ - {NotMapped}, // '\' - {KeyLShift, KeyFullStop, TerminateSequence}, // ] - {NotMapped}, // ^ - {NotMapped}, // _ - {NotMapped}, // ` + {KeyLShift, KeyColon, TerminateSequence}, {NotMapped}, // [, '\' + {KeyLShift, KeyFullStop, TerminateSequence}, {NotMapped}, // ], ^ + {NotMapped}, {NotMapped}, // _, ` - {KeyLShift, KeyA, TerminateSequence}, // A - {KeyLShift, KeyB, TerminateSequence}, // B - {KeyLShift, KeyC, TerminateSequence}, // C - {KeyLShift, KeyD, TerminateSequence}, // D - {KeyLShift, KeyE, TerminateSequence}, // E - {KeyLShift, KeyF, TerminateSequence}, // F - {KeyLShift, KeyG, TerminateSequence}, // G - {KeyLShift, KeyH, TerminateSequence}, // H - {KeyLShift, KeyI, TerminateSequence}, // I - {KeyLShift, KeyJ, TerminateSequence}, // J - {KeyLShift, KeyK, TerminateSequence}, // K - {KeyLShift, KeyL, TerminateSequence}, // L - {KeyLShift, KeyM, TerminateSequence}, // M - {KeyLShift, KeyN, TerminateSequence}, // N - {KeyLShift, KeyO, TerminateSequence}, // O - {KeyLShift, KeyP, TerminateSequence}, // P - {KeyLShift, KeyQ, TerminateSequence}, // Q - {KeyLShift, KeyR, TerminateSequence}, // R - {KeyLShift, KeyS, TerminateSequence}, // S - {KeyLShift, KeyT, TerminateSequence}, // T - {KeyLShift, KeyU, TerminateSequence}, // U - {KeyLShift, KeyV, TerminateSequence}, // V - {KeyLShift, KeyW, TerminateSequence}, // W - {KeyLShift, KeyX, TerminateSequence}, // X - {KeyLShift, KeyY, TerminateSequence}, // Y - {KeyLShift, KeyZ, TerminateSequence}, // Z + {KeyA, TerminateSequence}, {KeyB, TerminateSequence}, {KeyC, TerminateSequence}, {KeyD, TerminateSequence}, // A, B, C, D + {KeyE, TerminateSequence}, {KeyF, TerminateSequence}, {KeyG, TerminateSequence}, {KeyH, TerminateSequence}, // E, F, G, H + {KeyI, TerminateSequence}, {KeyJ, TerminateSequence}, {KeyK, TerminateSequence}, {KeyL, TerminateSequence}, // I, J, K L + {KeyM, TerminateSequence}, {KeyN, TerminateSequence}, {KeyO, TerminateSequence}, {KeyP, TerminateSequence}, // M, N, O, P + {KeyQ, TerminateSequence}, {KeyR, TerminateSequence}, {KeyS, TerminateSequence}, {KeyT, TerminateSequence}, // Q, R, S, T + {KeyU, TerminateSequence}, {KeyV, TerminateSequence}, {KeyW, TerminateSequence}, {KeyX, TerminateSequence}, // U, V, W X + {KeyY, TerminateSequence}, {KeyZ, TerminateSequence}, // Y, Z +// {KeyLShift, KeyA, TerminateSequence}, {KeyLShift, KeyB, TerminateSequence}, // a, b +// {KeyLShift, KeyC, TerminateSequence}, {KeyLShift, KeyD, TerminateSequence}, // c, d +// {KeyLShift, KeyE, TerminateSequence}, {KeyLShift, KeyF, TerminateSequence}, // e, f +// {KeyLShift, KeyG, TerminateSequence}, {KeyLShift, KeyH, TerminateSequence}, // g, h +// {KeyLShift, KeyI, TerminateSequence}, {KeyLShift, KeyJ, TerminateSequence}, // i, j +// {KeyLShift, KeyK, TerminateSequence}, {KeyLShift, KeyL, TerminateSequence}, // k, l +// {KeyLShift, KeyM, TerminateSequence}, {KeyLShift, KeyN, TerminateSequence}, // m, n +// {KeyLShift, KeyO, TerminateSequence}, {KeyLShift, KeyP, TerminateSequence}, // o, p +// {KeyLShift, KeyQ, TerminateSequence}, {KeyLShift, KeyR, TerminateSequence}, // q, r +// {KeyLShift, KeyS, TerminateSequence}, {KeyLShift, KeyT, TerminateSequence}, // s, t +// {KeyLShift, KeyU, TerminateSequence}, {KeyLShift, KeyV, TerminateSequence}, // u, v +// {KeyLShift, KeyW, TerminateSequence}, {KeyLShift, KeyX, TerminateSequence}, // w, x +// {KeyLShift, KeyY, TerminateSequence}, {KeyLShift, KeyZ, TerminateSequence}, // y, z }; Key *key_sequence = nullptr; @@ -277,12 +233,17 @@ bool Machine::typer_set_next_character(::Utility::Typer *typer, char character, if(character < sizeof(key_sequences) / sizeof(*key_sequences)) { key_sequence = key_sequences[character]; - } - if(key_sequence && key_sequence[phase] != NotMapped) - { - set_key_state(key_sequence[phase], true); - return key_sequence[phase+1] == TerminateSequence; + if(key_sequence[0] != NotMapped) + { + if(phase > 0) + { + set_key_state(key_sequence[phase-1], true); + return key_sequence[phase] == TerminateSequence; + } + else + return false; + } } return true; diff --git a/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift b/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift index 82cf9cc4c..fa81b1509 100644 --- a/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift +++ b/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift @@ -80,6 +80,14 @@ class MachineDocument: super.close() } + // MARK: the pasteboard + func paste(sender: AnyObject!) { + let pasteboard = NSPasteboard.generalPasteboard() + if let string = pasteboard.stringForType(NSPasteboardTypeString) { + self.machine().paste(string) + } + } + // MARK: CSBestEffortUpdaterDelegate final func bestEffortUpdater(bestEffortUpdater: CSBestEffortUpdater!, runForCycles cycles: UInt, didSkipPreviousUpdate: Bool) { runForNumberOfCycles(Int32(cycles)) diff --git a/OSBindings/Mac/Clock Signal/Machine/CSMachine.h b/OSBindings/Mac/Clock Signal/Machine/CSMachine.h index 7d35033a1..1a503e8c5 100644 --- a/OSBindings/Mac/Clock Signal/Machine/CSMachine.h +++ b/OSBindings/Mac/Clock Signal/Machine/CSMachine.h @@ -30,4 +30,6 @@ @property (nonatomic, weak) id delegate; @property (nonatomic, readonly) double clockRate; +- (void)paste:(NSString *)string; + @end diff --git a/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm b/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm index 15c17ce83..f5d577749 100644 --- a/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm +++ b/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm @@ -8,6 +8,7 @@ #import "CSMachine.h" #import "CSMachine+Subclassing.h" +#include "Typer.hpp" @interface CSMachine() - (void)speaker:(Outputs::Speaker *)speaker didCompleteSamples:(const int16_t *)samples length:(int)length; @@ -92,4 +93,10 @@ struct SpeakerDelegate: public Outputs::Speaker::Delegate { return self.machine->get_clock_rate(); } +- (void)paste:(NSString *)paste { + Utility::TypeRecipient *typeRecipient = dynamic_cast(self.machine); + if(typeRecipient) + typeRecipient->set_typer_for_string([paste UTF8String]); +} + @end diff --git a/Processors/6502/CPU6502.hpp b/Processors/6502/CPU6502.hpp index e335df436..5bd2c5653 100644 --- a/Processors/6502/CPU6502.hpp +++ b/Processors/6502/CPU6502.hpp @@ -1150,6 +1150,16 @@ template class Processor { _reset_line_is_enabled = active; } + /*! + Gets the current level of the RST line. + + @returns @c true if the line is logically active; @c false otherwise. + */ + inline bool get_reset_line() + { + return _reset_line_is_enabled; + } + /*! Sets the current level of the IRQ line.