From ee179aa7bd0f98dfe804d01c20bbadb8a620fb11 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 14 Oct 2017 22:36:31 -0400 Subject: [PATCH] Introduces a joystick analogue to the shared keyboard interface, and implements it for the Vic-20. --- Inputs/Joystick.cpp | 9 +++ Inputs/Joystick.hpp | 35 +++++++++ Machines/Commodore/Vic-20/Vic20.cpp | 49 ++++++++++++- Machines/Commodore/Vic-20/Vic20.hpp | 16 ++--- Machines/JoystickMachine.hpp | 24 +++++++ .../Clock Signal.xcodeproj/project.pbxproj | 8 +++ .../Clock Signal/Machine/Wrappers/CSVic20.mm | 72 ++----------------- 7 files changed, 132 insertions(+), 81 deletions(-) create mode 100644 Inputs/Joystick.cpp create mode 100644 Inputs/Joystick.hpp create mode 100644 Machines/JoystickMachine.hpp diff --git a/Inputs/Joystick.cpp b/Inputs/Joystick.cpp new file mode 100644 index 000000000..df0104423 --- /dev/null +++ b/Inputs/Joystick.cpp @@ -0,0 +1,9 @@ +// +// Joystick.cpp +// Clock Signal +// +// Created by Thomas Harte on 14/10/2017. +// Copyright © 2017 Thomas Harte. All rights reserved. +// + +#include "Joystick.hpp" diff --git a/Inputs/Joystick.hpp b/Inputs/Joystick.hpp new file mode 100644 index 000000000..4b2223075 --- /dev/null +++ b/Inputs/Joystick.hpp @@ -0,0 +1,35 @@ +// +// Joystick.hpp +// Clock Signal +// +// Created by Thomas Harte on 14/10/2017. +// Copyright © 2017 Thomas Harte. All rights reserved. +// + +#ifndef Joystick_hpp +#define Joystick_hpp + +#include + +namespace Inputs { + +/*! + Provides an intermediate idealised model of a simple joystick, allowing a host + machine to toggle states, while an interested party either observes or polls. +*/ +class Joystick { + public: + virtual ~Joystick() {} + + enum class DigitalInput { + Up, Down, Left, Right, Fire + }; + + // Host interface. + virtual void set_digital_input(DigitalInput digital_input, bool is_active) = 0; + virtual void reset_all_inputs() = 0; +}; + +} + +#endif /* Joystick_hpp */ diff --git a/Machines/Commodore/Vic-20/Vic20.cpp b/Machines/Commodore/Vic-20/Vic20.cpp index 3ac582610..a4d76525a 100644 --- a/Machines/Commodore/Vic-20/Vic20.cpp +++ b/Machines/Commodore/Vic-20/Vic20.cpp @@ -30,6 +30,14 @@ namespace Commodore { namespace Vic20 { +enum JoystickInput { + Up = 0x04, + Down = 0x08, + Left = 0x10, + Right = 0x80, + Fire = 0x20 +}; + /*! Models the user-port VIA, which is the Vic's connection point for controlling its tape recorder — sensing the presence or absence of a tape and controlling the tape motor — and reading the current @@ -214,6 +222,38 @@ class Vic6560: public MOS::MOS6560 { uint8_t *colour_memory; // Colour memory must be contiguous. }; +/*! + Interfaces a joystick to the two VIAs. +*/ +class Joystick: public Inputs::Joystick { + public: + Joystick(UserPortVIA &user_port_via_port_handler, KeyboardVIA &keyboard_via_port_handler) : + user_port_via_port_handler_(user_port_via_port_handler), + keyboard_via_port_handler_(keyboard_via_port_handler) {} + + void set_digital_input(DigitalInput digital_input, bool is_active) override { + JoystickInput mapped_input; + switch (digital_input) { + default: return; + case DigitalInput::Up: mapped_input = Up; break; + case DigitalInput::Down: mapped_input = Down; break; + case DigitalInput::Left: mapped_input = Left; break; + case DigitalInput::Right: mapped_input = Right; break; + case DigitalInput::Fire: mapped_input = Fire; break; + } + + user_port_via_port_handler_.set_joystick_state(mapped_input, is_active); + keyboard_via_port_handler_.set_joystick_state(mapped_input, is_active); + } + + void reset_all_inputs() override { + } + + private: + UserPortVIA &user_port_via_port_handler_; + KeyboardVIA &keyboard_via_port_handler_; +}; + class ConcreteMachine: public CPU::MOS6502::BusHandler, public MOS::MOS6522::IRQDelegatePortHandler::Delegate, @@ -253,6 +293,9 @@ class ConcreteMachine: // set the NTSC clock rate set_region(NTSC); + + // install a joystick + joysticks_.push_back(new Joystick(*user_port_via_port_handler_, *keyboard_via_port_handler_)); } ~ConcreteMachine() { @@ -340,9 +383,8 @@ class ConcreteMachine: keyboard_via_port_handler_->clear_all_keys(); } - void set_joystick_state(JoystickInput input, bool isPressed) override final { - user_port_via_port_handler_->set_joystick_state(input, isPressed); - keyboard_via_port_handler_->set_joystick_state(input, isPressed); + std::vector &get_joysticks() override { + return joysticks_; } void set_memory_size(MemorySize size) override final { @@ -580,6 +622,7 @@ class ConcreteMachine: Region region_; Commodore::Vic20::KeyboardMapper keyboard_mapper_; + std::vector joysticks_; std::unique_ptr mos6560_; std::shared_ptr user_port_via_port_handler_; diff --git a/Machines/Commodore/Vic-20/Vic20.hpp b/Machines/Commodore/Vic-20/Vic20.hpp index 53e94b28f..829c207f6 100644 --- a/Machines/Commodore/Vic-20/Vic20.hpp +++ b/Machines/Commodore/Vic-20/Vic20.hpp @@ -11,6 +11,8 @@ #include "../../ConfigurationTarget.hpp" #include "../../CRTMachine.hpp" +#include "../../KeyboardMachine.hpp" +#include "../../JoystickMachine.hpp" #include "../../Typer.hpp" #include @@ -59,18 +61,11 @@ enum Key: uint16_t { #undef key }; -enum JoystickInput { - Up = 0x04, - Down = 0x08, - Left = 0x10, - Right = 0x80, - Fire = 0x20 -}; - class Machine: public CRTMachine::Machine, public ConfigurationTarget::Machine, - public KeyboardMachine::Machine { + public KeyboardMachine::Machine, + public JoystickMachine::Machine { public: virtual ~Machine(); @@ -81,9 +76,6 @@ class Machine: virtual void set_rom(ROMSlot slot, size_t length, const uint8_t *data) = 0; // TODO: take a std::vector to collapse length and data. - /// Sets the state of joystick input @c input. - virtual void set_joystick_state(JoystickInput input, bool isPressed) = 0; - /// Sets the memory size of this Vic-20. virtual void set_memory_size(MemorySize size) = 0; diff --git a/Machines/JoystickMachine.hpp b/Machines/JoystickMachine.hpp new file mode 100644 index 000000000..bc7c4a783 --- /dev/null +++ b/Machines/JoystickMachine.hpp @@ -0,0 +1,24 @@ +// +// JoystickMachine.hpp +// Clock Signal +// +// Created by Thomas Harte on 14/10/2017. +// Copyright © 2017 Thomas Harte. All rights reserved. +// + +#ifndef JoystickMachine_hpp +#define JoystickMachine_hpp + +#include "../Inputs/Joystick.hpp" +#include + +namespace JoystickMachine { + +class Machine { + public: + virtual std::vector &get_joysticks() = 0; +}; + +} + +#endif /* JoystickMachine_hpp */ diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index b5f6f2549..db6b35038 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -100,6 +100,7 @@ 4B69FB441C4D941400B5F0AA /* TapeUEF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B69FB421C4D941400B5F0AA /* TapeUEF.cpp */; }; 4B69FB461C4D950F00B5F0AA /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B69FB451C4D950F00B5F0AA /* libz.tbd */; }; 4B6A4C991F58F09E00E3F787 /* 6502Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B6A4C951F58F09E00E3F787 /* 6502Base.cpp */; }; + 4B70412B1F92C2A700735E45 /* Joystick.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7041291F92C2A700735E45 /* Joystick.cpp */; }; 4B7136861F78724F008B8ED9 /* Encoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7136841F78724F008B8ED9 /* Encoder.cpp */; }; 4B7136891F78725F008B8ED9 /* Shifter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7136871F78725F008B8ED9 /* Shifter.cpp */; }; 4B71368E1F788112008B8ED9 /* Parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B71368C1F788112008B8ED9 /* Parser.cpp */; }; @@ -672,6 +673,9 @@ 4B6A4C911F58F09E00E3F787 /* 6502AllRAM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = 6502AllRAM.cpp; sourceTree = ""; }; 4B6A4C921F58F09E00E3F787 /* 6502AllRAM.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = 6502AllRAM.hpp; sourceTree = ""; }; 4B6A4C951F58F09E00E3F787 /* 6502Base.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = 6502Base.cpp; sourceTree = ""; }; + 4B7041271F92C26900735E45 /* JoystickMachine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = JoystickMachine.hpp; sourceTree = ""; }; + 4B7041291F92C2A700735E45 /* Joystick.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Joystick.cpp; sourceTree = ""; }; + 4B70412A1F92C2A700735E45 /* Joystick.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Joystick.hpp; sourceTree = ""; }; 4B7136841F78724F008B8ED9 /* Encoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Encoder.cpp; sourceTree = ""; }; 4B7136851F78724F008B8ED9 /* Encoder.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Encoder.hpp; sourceTree = ""; }; 4B7136871F78725F008B8ED9 /* Shifter.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Shifter.cpp; sourceTree = ""; }; @@ -1748,6 +1752,8 @@ children = ( 4B86E2591F8C628F006FAA45 /* Keyboard.cpp */, 4B86E25A1F8C628F006FAA45 /* Keyboard.hpp */, + 4B7041291F92C2A700735E45 /* Joystick.cpp */, + 4B70412A1F92C2A700735E45 /* Joystick.hpp */, ); name = Inputs; path = ../../Inputs; @@ -2203,6 +2209,7 @@ 4B1E85731D170228001EF87D /* Typer.cpp */, 4BA9C3CF1D8164A9002DDB61 /* ConfigurationTarget.hpp */, 4B046DC31CFE651500E9E45E /* CRTMachine.hpp */, + 4B7041271F92C26900735E45 /* JoystickMachine.hpp */, 4B8E4ECD1DCE483D003716C3 /* KeyboardMachine.hpp */, 4B2A33291DB8544D002876E3 /* MemoryFuzzer.hpp */, 4B1E85741D170228001EF87D /* Typer.hpp */, @@ -2995,6 +3002,7 @@ 4BC5E4921D7ED365008CF980 /* StaticAnalyser.cpp in Sources */, 4BC830D11D6E7C690000A26F /* Tape.cpp in Sources */, 4B54C0C51F8D91D90050900F /* KeyboardMapper.cpp in Sources */, + 4B70412B1F92C2A700735E45 /* Joystick.cpp in Sources */, 4B69FB441C4D941400B5F0AA /* TapeUEF.cpp in Sources */, 4B86E25B1F8C628F006FAA45 /* Keyboard.cpp in Sources */, 4B4518851F75E91A00926311 /* DiskController.cpp in Sources */, diff --git a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm index 6a23f93e9..fbfbbe20c 100644 --- a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm +++ b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm @@ -69,73 +69,13 @@ using namespace Commodore::Vic20; #pragma mark - Keyboard map /*- (void)setKey:(uint16_t)key isPressed:(BOOL)isPressed { - static NSDictionary *vicKeysByKeys = @{ - @(VK_Space): @(Key::KeySpace), - @(VK_Return): @(Key::KeyReturn), - @(VK_Delete): @(Key::KeyDelete), - @(VK_ANSI_Comma): @(Key::KeyComma), - @(VK_ANSI_Period): @(Key::KeyFullStop), - @(VK_ANSI_Minus): @(Key::KeyDash), - @(VK_ANSI_Equal): @(Key::KeyEquals), - @(VK_ANSI_Semicolon): @(Key::KeyColon), - @(VK_ANSI_Quote): @(Key::KeySemicolon), - @(VK_ANSI_Slash): @(Key::KeySlash), - @(VK_Option): @(Key::KeyCBM), - @(VK_Control): @(Key::KeyControl), - - @(VK_F1): @(Key::KeyF1), @(VK_F3): @(Key::KeyF3), - @(VK_F5): @(Key::KeyF5), @(VK_F7): @(Key::KeyF7), - - @(VK_ANSI_Grave): @(Key::KeyLeft), - @(VK_Tab): @(Key::KeyRunStop), - @(VK_ANSI_LeftBracket): @(Key::KeyAt), - @(VK_ANSI_RightBracket): @(Key::KeyAsterisk), - @(VK_ANSI_Backslash): @(Key::KeyUp), - - @(VK_RightArrow): @(Key::KeyRight), - @(VK_DownArrow): @(Key::KeyDown), - }; - - // Not yet mapped: - // KeyHome - // KeyPlus - // KeyGBP - - if(key == VK_Tab && isPressed) { - _joystickMode ^= YES; - } - - @synchronized(self) { - if(_joystickMode) { - switch(key) { - case VK_UpArrow: _vic20->set_joystick_state(JoystickInput::Up, isPressed); break; - case VK_DownArrow: _vic20->set_joystick_state(JoystickInput::Down, isPressed); break; - case VK_LeftArrow: _vic20->set_joystick_state(JoystickInput::Left, isPressed); break; - case VK_RightArrow: _vic20->set_joystick_state(JoystickInput::Right, isPressed); break; - case VK_ANSI_A: _vic20->set_joystick_state(JoystickInput::Fire, isPressed); break; - } - } else { - switch(key) { - default: { - NSNumber *targetKey = vicKeysByKeys[@(key)]; - if(targetKey) - { - _vic20->set_key_state((Key)targetKey.integerValue, isPressed); - } - else - { - NSLog(@"Unmapped: %02x", key); - } - } break; - - case VK_Shift: - // Yuck - _vic20->set_key_state(Key::KeyLShift, isPressed); - _vic20->set_key_state(Key::KeyRShift, isPressed); - break; - } + switch(key) { + case VK_UpArrow: _vic20->set_joystick_state(JoystickInput::Up, isPressed); break; + case VK_DownArrow: _vic20->set_joystick_state(JoystickInput::Down, isPressed); break; + case VK_LeftArrow: _vic20->set_joystick_state(JoystickInput::Left, isPressed); break; + case VK_RightArrow: _vic20->set_joystick_state(JoystickInput::Right, isPressed); break; + case VK_ANSI_A: _vic20->set_joystick_state(JoystickInput::Fire, isPressed); break; } - } }*/ #pragma mark - Public configuration options