1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-29 12:50:28 +00:00

Introduces a joystick analogue to the shared keyboard interface, and implements it for the Vic-20.

This commit is contained in:
Thomas Harte 2017-10-14 22:36:31 -04:00
parent 3a05ce36de
commit ee179aa7bd
7 changed files with 132 additions and 81 deletions

9
Inputs/Joystick.cpp Normal file
View File

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

35
Inputs/Joystick.hpp Normal file
View File

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

View File

@ -30,6 +30,14 @@
namespace Commodore { namespace Commodore {
namespace Vic20 { 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 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 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<Vic6560> {
uint8_t *colour_memory; // Colour memory must be contiguous. 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: class ConcreteMachine:
public CPU::MOS6502::BusHandler, public CPU::MOS6502::BusHandler,
public MOS::MOS6522::IRQDelegatePortHandler::Delegate, public MOS::MOS6522::IRQDelegatePortHandler::Delegate,
@ -253,6 +293,9 @@ class ConcreteMachine:
// set the NTSC clock rate // set the NTSC clock rate
set_region(NTSC); set_region(NTSC);
// install a joystick
joysticks_.push_back(new Joystick(*user_port_via_port_handler_, *keyboard_via_port_handler_));
} }
~ConcreteMachine() { ~ConcreteMachine() {
@ -340,9 +383,8 @@ class ConcreteMachine:
keyboard_via_port_handler_->clear_all_keys(); keyboard_via_port_handler_->clear_all_keys();
} }
void set_joystick_state(JoystickInput input, bool isPressed) override final { std::vector<Inputs::Joystick *> &get_joysticks() override {
user_port_via_port_handler_->set_joystick_state(input, isPressed); return joysticks_;
keyboard_via_port_handler_->set_joystick_state(input, isPressed);
} }
void set_memory_size(MemorySize size) override final { void set_memory_size(MemorySize size) override final {
@ -580,6 +622,7 @@ class ConcreteMachine:
Region region_; Region region_;
Commodore::Vic20::KeyboardMapper keyboard_mapper_; Commodore::Vic20::KeyboardMapper keyboard_mapper_;
std::vector<Inputs::Joystick *> joysticks_;
std::unique_ptr<Vic6560> mos6560_; std::unique_ptr<Vic6560> mos6560_;
std::shared_ptr<UserPortVIA> user_port_via_port_handler_; std::shared_ptr<UserPortVIA> user_port_via_port_handler_;

View File

@ -11,6 +11,8 @@
#include "../../ConfigurationTarget.hpp" #include "../../ConfigurationTarget.hpp"
#include "../../CRTMachine.hpp" #include "../../CRTMachine.hpp"
#include "../../KeyboardMachine.hpp"
#include "../../JoystickMachine.hpp"
#include "../../Typer.hpp" #include "../../Typer.hpp"
#include <cstdint> #include <cstdint>
@ -59,18 +61,11 @@ enum Key: uint16_t {
#undef key #undef key
}; };
enum JoystickInput {
Up = 0x04,
Down = 0x08,
Left = 0x10,
Right = 0x80,
Fire = 0x20
};
class Machine: class Machine:
public CRTMachine::Machine, public CRTMachine::Machine,
public ConfigurationTarget::Machine, public ConfigurationTarget::Machine,
public KeyboardMachine::Machine { public KeyboardMachine::Machine,
public JoystickMachine::Machine {
public: public:
virtual ~Machine(); virtual ~Machine();
@ -81,9 +76,6 @@ class Machine:
virtual void set_rom(ROMSlot slot, size_t length, const uint8_t *data) = 0; virtual void set_rom(ROMSlot slot, size_t length, const uint8_t *data) = 0;
// TODO: take a std::vector<uint8_t> to collapse length and data. // TODO: take a std::vector<uint8_t> 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. /// Sets the memory size of this Vic-20.
virtual void set_memory_size(MemorySize size) = 0; virtual void set_memory_size(MemorySize size) = 0;

View File

@ -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 <vector>
namespace JoystickMachine {
class Machine {
public:
virtual std::vector<Inputs::Joystick *> &get_joysticks() = 0;
};
}
#endif /* JoystickMachine_hpp */

View File

@ -100,6 +100,7 @@
4B69FB441C4D941400B5F0AA /* TapeUEF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B69FB421C4D941400B5F0AA /* TapeUEF.cpp */; }; 4B69FB441C4D941400B5F0AA /* TapeUEF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B69FB421C4D941400B5F0AA /* TapeUEF.cpp */; };
4B69FB461C4D950F00B5F0AA /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B69FB451C4D950F00B5F0AA /* libz.tbd */; }; 4B69FB461C4D950F00B5F0AA /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B69FB451C4D950F00B5F0AA /* libz.tbd */; };
4B6A4C991F58F09E00E3F787 /* 6502Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B6A4C951F58F09E00E3F787 /* 6502Base.cpp */; }; 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 */; }; 4B7136861F78724F008B8ED9 /* Encoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7136841F78724F008B8ED9 /* Encoder.cpp */; };
4B7136891F78725F008B8ED9 /* Shifter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7136871F78725F008B8ED9 /* Shifter.cpp */; }; 4B7136891F78725F008B8ED9 /* Shifter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7136871F78725F008B8ED9 /* Shifter.cpp */; };
4B71368E1F788112008B8ED9 /* Parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B71368C1F788112008B8ED9 /* Parser.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 = "<group>"; }; 4B6A4C911F58F09E00E3F787 /* 6502AllRAM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = 6502AllRAM.cpp; sourceTree = "<group>"; };
4B6A4C921F58F09E00E3F787 /* 6502AllRAM.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = 6502AllRAM.hpp; sourceTree = "<group>"; }; 4B6A4C921F58F09E00E3F787 /* 6502AllRAM.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = 6502AllRAM.hpp; sourceTree = "<group>"; };
4B6A4C951F58F09E00E3F787 /* 6502Base.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = 6502Base.cpp; sourceTree = "<group>"; }; 4B6A4C951F58F09E00E3F787 /* 6502Base.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = 6502Base.cpp; sourceTree = "<group>"; };
4B7041271F92C26900735E45 /* JoystickMachine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = JoystickMachine.hpp; sourceTree = "<group>"; };
4B7041291F92C2A700735E45 /* Joystick.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Joystick.cpp; sourceTree = "<group>"; };
4B70412A1F92C2A700735E45 /* Joystick.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Joystick.hpp; sourceTree = "<group>"; };
4B7136841F78724F008B8ED9 /* Encoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Encoder.cpp; sourceTree = "<group>"; }; 4B7136841F78724F008B8ED9 /* Encoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Encoder.cpp; sourceTree = "<group>"; };
4B7136851F78724F008B8ED9 /* Encoder.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Encoder.hpp; sourceTree = "<group>"; }; 4B7136851F78724F008B8ED9 /* Encoder.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Encoder.hpp; sourceTree = "<group>"; };
4B7136871F78725F008B8ED9 /* Shifter.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Shifter.cpp; sourceTree = "<group>"; }; 4B7136871F78725F008B8ED9 /* Shifter.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Shifter.cpp; sourceTree = "<group>"; };
@ -1748,6 +1752,8 @@
children = ( children = (
4B86E2591F8C628F006FAA45 /* Keyboard.cpp */, 4B86E2591F8C628F006FAA45 /* Keyboard.cpp */,
4B86E25A1F8C628F006FAA45 /* Keyboard.hpp */, 4B86E25A1F8C628F006FAA45 /* Keyboard.hpp */,
4B7041291F92C2A700735E45 /* Joystick.cpp */,
4B70412A1F92C2A700735E45 /* Joystick.hpp */,
); );
name = Inputs; name = Inputs;
path = ../../Inputs; path = ../../Inputs;
@ -2203,6 +2209,7 @@
4B1E85731D170228001EF87D /* Typer.cpp */, 4B1E85731D170228001EF87D /* Typer.cpp */,
4BA9C3CF1D8164A9002DDB61 /* ConfigurationTarget.hpp */, 4BA9C3CF1D8164A9002DDB61 /* ConfigurationTarget.hpp */,
4B046DC31CFE651500E9E45E /* CRTMachine.hpp */, 4B046DC31CFE651500E9E45E /* CRTMachine.hpp */,
4B7041271F92C26900735E45 /* JoystickMachine.hpp */,
4B8E4ECD1DCE483D003716C3 /* KeyboardMachine.hpp */, 4B8E4ECD1DCE483D003716C3 /* KeyboardMachine.hpp */,
4B2A33291DB8544D002876E3 /* MemoryFuzzer.hpp */, 4B2A33291DB8544D002876E3 /* MemoryFuzzer.hpp */,
4B1E85741D170228001EF87D /* Typer.hpp */, 4B1E85741D170228001EF87D /* Typer.hpp */,
@ -2995,6 +3002,7 @@
4BC5E4921D7ED365008CF980 /* StaticAnalyser.cpp in Sources */, 4BC5E4921D7ED365008CF980 /* StaticAnalyser.cpp in Sources */,
4BC830D11D6E7C690000A26F /* Tape.cpp in Sources */, 4BC830D11D6E7C690000A26F /* Tape.cpp in Sources */,
4B54C0C51F8D91D90050900F /* KeyboardMapper.cpp in Sources */, 4B54C0C51F8D91D90050900F /* KeyboardMapper.cpp in Sources */,
4B70412B1F92C2A700735E45 /* Joystick.cpp in Sources */,
4B69FB441C4D941400B5F0AA /* TapeUEF.cpp in Sources */, 4B69FB441C4D941400B5F0AA /* TapeUEF.cpp in Sources */,
4B86E25B1F8C628F006FAA45 /* Keyboard.cpp in Sources */, 4B86E25B1F8C628F006FAA45 /* Keyboard.cpp in Sources */,
4B4518851F75E91A00926311 /* DiskController.cpp in Sources */, 4B4518851F75E91A00926311 /* DiskController.cpp in Sources */,

View File

@ -69,44 +69,6 @@ using namespace Commodore::Vic20;
#pragma mark - Keyboard map #pragma mark - Keyboard map
/*- (void)setKey:(uint16_t)key isPressed:(BOOL)isPressed { /*- (void)setKey:(uint16_t)key isPressed:(BOOL)isPressed {
static NSDictionary<NSNumber *, NSNumber *> *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) { switch(key) {
case VK_UpArrow: _vic20->set_joystick_state(JoystickInput::Up, isPressed); break; case VK_UpArrow: _vic20->set_joystick_state(JoystickInput::Up, isPressed); break;
case VK_DownArrow: _vic20->set_joystick_state(JoystickInput::Down, isPressed); break; case VK_DownArrow: _vic20->set_joystick_state(JoystickInput::Down, isPressed); break;
@ -114,28 +76,6 @@ using namespace Commodore::Vic20;
case VK_RightArrow: _vic20->set_joystick_state(JoystickInput::Right, 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; 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;
}
}
}
}*/ }*/
#pragma mark - Public configuration options #pragma mark - Public configuration options