1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-02-19 23:29:05 +00:00

Switched the Objective-C code to using dynamic_cast alone to decide whether to post keyboard or joystick events.

This commit is contained in:
Thomas Harte 2017-10-15 21:25:56 -04:00
parent 18798c9886
commit 542ec4312f
13 changed files with 99 additions and 161 deletions

View File

@ -3,7 +3,6 @@
// //
#import "CSMachine.h" #import "CSMachine.h"
#import "CSKeyboardMachine.h"
#import "CSFastLoading.h" #import "CSFastLoading.h"
#import "CSAtari2600.h" #import "CSAtari2600.h"
@ -17,3 +16,5 @@
#import "CSOpenGLView.h" #import "CSOpenGLView.h"
#import "CSAudioQueue.h" #import "CSAudioQueue.h"
#import "CSBestEffortUpdater.h" #import "CSBestEffortUpdater.h"
#include "KeyCodes.h"

View File

@ -187,48 +187,22 @@ class MachineDocument:
} }
// MARK: Input management // MARK: Input management
fileprivate func withKeyboardMachine(_ action: (CSKeyboardMachine) -> ()) {
if let keyboardMachine = self.machine as? CSKeyboardMachine {
action(keyboardMachine)
}
}
fileprivate func withJoystickMachine(_ action: (CSJoystickMachine) -> ()) {
if let joystickMachine = self.machine as? CSJoystickMachine {
action(joystickMachine)
}
}
fileprivate func sendJoystickEvent(_ machine: CSJoystickMachine, keyCode: UInt16, isPressed: Bool) {
switch keyCode {
case 123: machine.setDirection(.left, onPad: 0, isPressed: isPressed)
case 126: machine.setDirection(.up, onPad: 0, isPressed: isPressed)
case 124: machine.setDirection(.right, onPad: 0, isPressed: isPressed)
case 125: machine.setDirection(.down, onPad: 0, isPressed: isPressed)
default: machine.setButtonAt(0, onPad: 0, isPressed: isPressed)
}
}
func windowDidResignKey(_ notification: Notification) { func windowDidResignKey(_ notification: Notification) {
self.withKeyboardMachine { $0.clearAllKeys() } self.machine.clearAllKeys()
} }
func keyDown(_ event: NSEvent) { func keyDown(_ event: NSEvent) {
self.withKeyboardMachine { $0.setKey(event.keyCode, isPressed: true) } self.machine.setKey(event.keyCode, isPressed: true)
self.withJoystickMachine { sendJoystickEvent($0, keyCode: event.keyCode, isPressed: true) }
} }
func keyUp(_ event: NSEvent) { func keyUp(_ event: NSEvent) {
self.withKeyboardMachine { $0.setKey(event.keyCode, isPressed: false) } self.machine.setKey(event.keyCode, isPressed: false)
self.withJoystickMachine { sendJoystickEvent($0, keyCode: event.keyCode, isPressed: false) }
} }
func flagsChanged(_ newModifiers: NSEvent) { func flagsChanged(_ newModifiers: NSEvent) {
self.withKeyboardMachine { self.machine.setKey(VK_Shift, isPressed: newModifiers.modifierFlags.contains(.shift))
$0.setKey(VK_Shift, isPressed: newModifiers.modifierFlags.contains(.shift)) self.machine.setKey(VK_Control, isPressed: newModifiers.modifierFlags.contains(.control))
$0.setKey(VK_Control, isPressed: newModifiers.modifierFlags.contains(.control)) self.machine.setKey(VK_Command, isPressed: newModifiers.modifierFlags.contains(.command))
$0.setKey(VK_Command, isPressed: newModifiers.modifierFlags.contains(.command)) self.machine.setKey(VK_Option, isPressed: newModifiers.modifierFlags.contains(.option))
$0.setKey(VK_Option, isPressed: newModifiers.modifierFlags.contains(.option))
}
} }
} }

View File

@ -1,22 +0,0 @@
//
// CSJoystickMachine.h
// Clock Signal
//
// Created by Thomas Harte on 03/10/2016.
// Copyright © 2016 Thomas Harte. All rights reserved.
//
typedef NS_ENUM(NSInteger, CSJoystickDirection)
{
CSJoystickDirectionUp,
CSJoystickDirectionDown,
CSJoystickDirectionLeft,
CSJoystickDirectionRight
};
@protocol CSJoystickMachine <NSObject>
- (void)setButtonAtIndex:(NSUInteger)button onPad:(NSUInteger)pad isPressed:(BOOL)isPressed;
- (void)setDirection:(CSJoystickDirection)direction onPad:(NSUInteger)pad isPressed:(BOOL)isPressed;
@end

View File

@ -1,16 +0,0 @@
//
// CSKeyboardMachine.h
// Clock Signal
//
// Created by Thomas Harte on 05/06/2016.
// Copyright © 2016 Thomas Harte. All rights reserved.
//
#import "KeyCodes.h"
@protocol CSKeyboardMachine <NSObject>
- (void)setKey:(uint16_t)key isPressed:(BOOL)isPressed;
- (void)clearAllKeys;
@end

View File

@ -35,6 +35,9 @@
- (void)setView:(CSOpenGLView *)view aspectRatio:(float)aspectRatio; - (void)setView:(CSOpenGLView *)view aspectRatio:(float)aspectRatio;
- (void)drawViewForPixelSize:(CGSize)pixelSize onlyIfDirty:(BOOL)onlyIfDirty; - (void)drawViewForPixelSize:(CGSize)pixelSize onlyIfDirty:(BOOL)onlyIfDirty;
- (void)setKey:(uint16_t)key isPressed:(BOOL)isPressed;
- (void)clearAllKeys;
@property (nonatomic, strong) CSAudioQueue *audioQueue; @property (nonatomic, strong) CSAudioQueue *audioQueue;
@property (nonatomic, readonly) CSOpenGLView *view; @property (nonatomic, readonly) CSOpenGLView *view;
@property (nonatomic, weak) id<CSMachineDelegate> delegate; @property (nonatomic, weak) id<CSMachineDelegate> delegate;
@ -46,9 +49,4 @@
- (void)paste:(NSString *)string; - (void)paste:(NSString *)string;
// This is an informal implementation of the CSKeyboardMachine protocol; specific machines
// can decide whether they opt in as keyboard machines.
- (void)setKey:(uint16_t)key isPressed:(BOOL)isPressed;
- (void)clearAllKeys;
@end @end

View File

@ -10,10 +10,11 @@
#import "CSMachine+Subclassing.h" #import "CSMachine+Subclassing.h"
#import "CSMachine+Target.h" #import "CSMachine+Target.h"
#import "CSKeyboardMachine.h" #include "KeyCodes.h"
#include "Typer.hpp" #include "Typer.hpp"
#include "ConfigurationTarget.hpp" #include "ConfigurationTarget.hpp"
#include "JoystickMachine.hpp"
#include "KeyboardMachine.hpp"
@interface CSMachine() @interface CSMachine()
- (void)speaker:(Outputs::Speaker *)speaker didCompleteSamples:(const int16_t *)samples length:(int)length; - (void)speaker:(Outputs::Speaker *)speaker didCompleteSamples:(const int16_t *)samples length:(int)length;
@ -187,75 +188,103 @@ struct MachineDelegate: CRTMachine::Machine::Delegate, public LockProtectedDeleg
- (void)setKey:(uint16_t)key isPressed:(BOOL)isPressed { - (void)setKey:(uint16_t)key isPressed:(BOOL)isPressed {
auto keyboard_machine = dynamic_cast<KeyboardMachine::Machine *>(_machine); auto keyboard_machine = dynamic_cast<KeyboardMachine::Machine *>(_machine);
if(!keyboard_machine) return; if(keyboard_machine) {
@synchronized(self) {
Inputs::Keyboard &keyboard = keyboard_machine->get_keyboard();
@synchronized(self) { // Connect the Carbon-era Mac keyboard scancodes to Clock Signal's 'universal' enumeration in order
Inputs::Keyboard &keyboard = keyboard_machine->get_keyboard(); // to pass into the platform-neutral realm.
// Connect the Carbon-era Mac keyboard scancodes to Clock Signal's 'universal' enumeration in order
// to pass into the platform-neutral realm.
#define BIND(source, dest) case source: keyboard.set_key_pressed(Inputs::Keyboard::Key::dest, isPressed); break #define BIND(source, dest) case source: keyboard.set_key_pressed(Inputs::Keyboard::Key::dest, isPressed); break
switch(key) { switch(key) {
BIND(VK_ANSI_0, k0); BIND(VK_ANSI_1, k1); BIND(VK_ANSI_2, k2); BIND(VK_ANSI_3, k3); BIND(VK_ANSI_4, k4); BIND(VK_ANSI_0, k0); BIND(VK_ANSI_1, k1); BIND(VK_ANSI_2, k2); BIND(VK_ANSI_3, k3); BIND(VK_ANSI_4, k4);
BIND(VK_ANSI_5, k5); BIND(VK_ANSI_6, k6); BIND(VK_ANSI_7, k7); BIND(VK_ANSI_8, k8); BIND(VK_ANSI_9, k9); BIND(VK_ANSI_5, k5); BIND(VK_ANSI_6, k6); BIND(VK_ANSI_7, k7); BIND(VK_ANSI_8, k8); BIND(VK_ANSI_9, k9);
BIND(VK_ANSI_Q, Q); BIND(VK_ANSI_W, W); BIND(VK_ANSI_E, E); BIND(VK_ANSI_R, R); BIND(VK_ANSI_T, T); BIND(VK_ANSI_Q, Q); BIND(VK_ANSI_W, W); BIND(VK_ANSI_E, E); BIND(VK_ANSI_R, R); BIND(VK_ANSI_T, T);
BIND(VK_ANSI_Y, Y); BIND(VK_ANSI_U, U); BIND(VK_ANSI_I, I); BIND(VK_ANSI_O, O); BIND(VK_ANSI_P, P); BIND(VK_ANSI_Y, Y); BIND(VK_ANSI_U, U); BIND(VK_ANSI_I, I); BIND(VK_ANSI_O, O); BIND(VK_ANSI_P, P);
BIND(VK_ANSI_A, A); BIND(VK_ANSI_S, S); BIND(VK_ANSI_D, D); BIND(VK_ANSI_F, F); BIND(VK_ANSI_G, G); BIND(VK_ANSI_A, A); BIND(VK_ANSI_S, S); BIND(VK_ANSI_D, D); BIND(VK_ANSI_F, F); BIND(VK_ANSI_G, G);
BIND(VK_ANSI_H, H); BIND(VK_ANSI_J, J); BIND(VK_ANSI_K, K); BIND(VK_ANSI_L, L); BIND(VK_ANSI_H, H); BIND(VK_ANSI_J, J); BIND(VK_ANSI_K, K); BIND(VK_ANSI_L, L);
BIND(VK_ANSI_Z, Z); BIND(VK_ANSI_X, X); BIND(VK_ANSI_C, C); BIND(VK_ANSI_V, V); BIND(VK_ANSI_Z, Z); BIND(VK_ANSI_X, X); BIND(VK_ANSI_C, C); BIND(VK_ANSI_V, V);
BIND(VK_ANSI_B, B); BIND(VK_ANSI_N, N); BIND(VK_ANSI_M, M); BIND(VK_ANSI_B, B); BIND(VK_ANSI_N, N); BIND(VK_ANSI_M, M);
BIND(VK_F1, F1); BIND(VK_F2, F2); BIND(VK_F3, F3); BIND(VK_F4, F4); BIND(VK_F1, F1); BIND(VK_F2, F2); BIND(VK_F3, F3); BIND(VK_F4, F4);
BIND(VK_F5, F5); BIND(VK_F6, F6); BIND(VK_F7, F7); BIND(VK_F8, F8); BIND(VK_F5, F5); BIND(VK_F6, F6); BIND(VK_F7, F7); BIND(VK_F8, F8);
BIND(VK_F9, F9); BIND(VK_F10, F10); BIND(VK_F11, F11); BIND(VK_F12, F12); BIND(VK_F9, F9); BIND(VK_F10, F10); BIND(VK_F11, F11); BIND(VK_F12, F12);
BIND(VK_ANSI_Keypad0, KeyPad0); BIND(VK_ANSI_Keypad1, KeyPad1); BIND(VK_ANSI_Keypad2, KeyPad2); BIND(VK_ANSI_Keypad0, KeyPad0); BIND(VK_ANSI_Keypad1, KeyPad1); BIND(VK_ANSI_Keypad2, KeyPad2);
BIND(VK_ANSI_Keypad3, KeyPad3); BIND(VK_ANSI_Keypad4, KeyPad4); BIND(VK_ANSI_Keypad5, KeyPad5); BIND(VK_ANSI_Keypad3, KeyPad3); BIND(VK_ANSI_Keypad4, KeyPad4); BIND(VK_ANSI_Keypad5, KeyPad5);
BIND(VK_ANSI_Keypad6, KeyPad6); BIND(VK_ANSI_Keypad7, KeyPad7); BIND(VK_ANSI_Keypad8, KeyPad8); BIND(VK_ANSI_Keypad6, KeyPad6); BIND(VK_ANSI_Keypad7, KeyPad7); BIND(VK_ANSI_Keypad8, KeyPad8);
BIND(VK_ANSI_Keypad9, KeyPad9); BIND(VK_ANSI_Keypad9, KeyPad9);
BIND(VK_ANSI_Equal, Equals); BIND(VK_ANSI_Minus, Hyphen); BIND(VK_ANSI_Equal, Equals); BIND(VK_ANSI_Minus, Hyphen);
BIND(VK_ANSI_RightBracket, CloseSquareBracket); BIND(VK_ANSI_LeftBracket, OpenSquareBracket); BIND(VK_ANSI_RightBracket, CloseSquareBracket); BIND(VK_ANSI_LeftBracket, OpenSquareBracket);
BIND(VK_ANSI_Quote, Quote); BIND(VK_ANSI_Grave, BackTick); BIND(VK_ANSI_Quote, Quote); BIND(VK_ANSI_Grave, BackTick);
BIND(VK_ANSI_Semicolon, Semicolon); BIND(VK_ANSI_Semicolon, Semicolon);
BIND(VK_ANSI_Backslash, BackSlash); BIND(VK_ANSI_Slash, ForwardSlash); BIND(VK_ANSI_Backslash, BackSlash); BIND(VK_ANSI_Slash, ForwardSlash);
BIND(VK_ANSI_Comma, Comma); BIND(VK_ANSI_Period, FullStop); BIND(VK_ANSI_Comma, Comma); BIND(VK_ANSI_Period, FullStop);
BIND(VK_ANSI_KeypadDecimal, KeyPadDecimalPoint); BIND(VK_ANSI_KeypadEquals, KeyPadEquals); BIND(VK_ANSI_KeypadDecimal, KeyPadDecimalPoint); BIND(VK_ANSI_KeypadEquals, KeyPadEquals);
BIND(VK_ANSI_KeypadMultiply, KeyPadAsterisk); BIND(VK_ANSI_KeypadDivide, KeyPadSlash); BIND(VK_ANSI_KeypadMultiply, KeyPadAsterisk); BIND(VK_ANSI_KeypadDivide, KeyPadSlash);
BIND(VK_ANSI_KeypadPlus, KeyPadPlus); BIND(VK_ANSI_KeypadMinus, KeyPadMinus); BIND(VK_ANSI_KeypadPlus, KeyPadPlus); BIND(VK_ANSI_KeypadMinus, KeyPadMinus);
BIND(VK_ANSI_KeypadClear, KeyPadDelete); BIND(VK_ANSI_KeypadEnter, KeyPadEnter); BIND(VK_ANSI_KeypadClear, KeyPadDelete); BIND(VK_ANSI_KeypadEnter, KeyPadEnter);
BIND(VK_Return, Enter); BIND(VK_Tab, Tab); BIND(VK_Return, Enter); BIND(VK_Tab, Tab);
BIND(VK_Space, Space); BIND(VK_Delete, BackSpace); BIND(VK_Space, Space); BIND(VK_Delete, BackSpace);
BIND(VK_Control, LeftControl); BIND(VK_Option, LeftOption); BIND(VK_Control, LeftControl); BIND(VK_Option, LeftOption);
BIND(VK_Command, LeftMeta); BIND(VK_Shift, LeftShift); BIND(VK_Command, LeftMeta); BIND(VK_Shift, LeftShift);
BIND(VK_RightControl, RightControl); BIND(VK_RightOption, RightOption); BIND(VK_RightControl, RightControl); BIND(VK_RightOption, RightOption);
BIND(VK_Escape, Escape); BIND(VK_CapsLock, CapsLock); BIND(VK_Escape, Escape); BIND(VK_CapsLock, CapsLock);
BIND(VK_Home, Home); BIND(VK_End, End); BIND(VK_Home, Home); BIND(VK_End, End);
BIND(VK_PageUp, PageUp); BIND(VK_PageDown, PageDown); BIND(VK_PageUp, PageUp); BIND(VK_PageDown, PageDown);
BIND(VK_RightShift, RightShift); BIND(VK_RightShift, RightShift);
BIND(VK_Help, Help); BIND(VK_Help, Help);
BIND(VK_ForwardDelete, Delete); BIND(VK_ForwardDelete, Delete);
BIND(VK_LeftArrow, Left); BIND(VK_RightArrow, Right); BIND(VK_LeftArrow, Left); BIND(VK_RightArrow, Right);
BIND(VK_DownArrow, Down); BIND(VK_UpArrow, Up); BIND(VK_DownArrow, Down); BIND(VK_UpArrow, Up);
} }
#undef BIND #undef BIND
}
return;
}
auto joystick_machine = dynamic_cast<JoystickMachine::Machine *>(_machine);
if(joystick_machine) {
@synchronized(self) {
std::vector<std::unique_ptr<Inputs::Joystick>> &joysticks = joystick_machine->get_joysticks();
if(!joysticks.empty()) {
switch(key) {
case VK_LeftArrow: joysticks[0]->set_digital_input(Inputs::Joystick::DigitalInput::Left, isPressed); break;
case VK_RightArrow: joysticks[0]->set_digital_input(Inputs::Joystick::DigitalInput::Right, isPressed); break;
case VK_UpArrow: joysticks[0]->set_digital_input(Inputs::Joystick::DigitalInput::Up, isPressed); break;
case VK_DownArrow: joysticks[0]->set_digital_input(Inputs::Joystick::DigitalInput::Down, isPressed); break;
default:
joysticks[0]->set_digital_input(Inputs::Joystick::DigitalInput::Fire, isPressed); break;
break;
}
}
}
} }
} }
- (void)clearAllKeys { - (void)clearAllKeys {
auto keyboard_machine = dynamic_cast<KeyboardMachine::Machine *>(_machine); auto keyboard_machine = dynamic_cast<KeyboardMachine::Machine *>(_machine);
if(!keyboard_machine) return; if(keyboard_machine) {
@synchronized(self) {
keyboard_machine->get_keyboard().reset_all_keys();
}
}
@synchronized(self) { auto joystick_machine = dynamic_cast<JoystickMachine::Machine *>(_machine);
keyboard_machine->get_keyboard().reset_all_keys(); if(joystick_machine) {
@synchronized(self) {
for(auto &joystick : joystick_machine->get_joysticks()) {
joystick->reset_all_inputs();
}
}
} }
} }

View File

@ -7,9 +7,8 @@
// //
#import "CSMachine.h" #import "CSMachine.h"
#import "CSKeyboardMachine.h"
@interface CSAmstradCPC : CSMachine <CSKeyboardMachine> @interface CSAmstradCPC : CSMachine
- (instancetype)init; - (instancetype)init;

View File

@ -8,9 +8,8 @@
#include "CSMachine.h" #include "CSMachine.h"
#include "Atari2600Inputs.h" #include "Atari2600Inputs.h"
#import "CSJoystickMachine.h"
@interface CSAtari2600 : CSMachine <CSJoystickMachine> @interface CSAtari2600 : CSMachine
- (instancetype)init; - (instancetype)init;

View File

@ -24,26 +24,6 @@
return self; return self;
} }
- (void)setDirection:(CSJoystickDirection)direction onPad:(NSUInteger)pad isPressed:(BOOL)isPressed {
// Atari2600DigitalInput input;
// switch(direction)
// {
// case CSJoystickDirectionUp: input = pad ? Atari2600DigitalInputJoy2Up : Atari2600DigitalInputJoy1Up; break;
// case CSJoystickDirectionDown: input = pad ? Atari2600DigitalInputJoy2Down : Atari2600DigitalInputJoy1Down; break;
// case CSJoystickDirectionLeft: input = pad ? Atari2600DigitalInputJoy2Left : Atari2600DigitalInputJoy1Left; break;
// case CSJoystickDirectionRight: input = pad ? Atari2600DigitalInputJoy2Right : Atari2600DigitalInputJoy1Right; break;
// }
// @synchronized(self) {
// _atari2600->set_digital_input(input, isPressed ? true : false);
// }
}
- (void)setButtonAtIndex:(NSUInteger)button onPad:(NSUInteger)pad isPressed:(BOOL)isPressed {
// @synchronized(self) {
// _atari2600->set_digital_input(pad ? Atari2600DigitalInputJoy2Fire : Atari2600DigitalInputJoy1Fire, isPressed ? true : false);
// }
}
- (void)setResetLineEnabled:(BOOL)enabled { - (void)setResetLineEnabled:(BOOL)enabled {
@synchronized(self) { @synchronized(self) {
_atari2600->set_reset_switch(enabled ? true : false); _atari2600->set_reset_switch(enabled ? true : false);

View File

@ -7,10 +7,9 @@
// //
#import "CSMachine.h" #import "CSMachine.h"
#import "CSKeyboardMachine.h"
#import "CSFastLoading.h" #import "CSFastLoading.h"
@interface CSElectron : CSMachine <CSKeyboardMachine, CSFastLoading> @interface CSElectron : CSMachine <CSFastLoading>
- (instancetype)init; - (instancetype)init;

View File

@ -7,10 +7,9 @@
// //
#import "CSMachine.h" #import "CSMachine.h"
#import "CSKeyboardMachine.h"
#import "CSFastLoading.h" #import "CSFastLoading.h"
@interface CSOric : CSMachine <CSKeyboardMachine, CSFastLoading> @interface CSOric : CSMachine <CSFastLoading>
- (instancetype)init; - (instancetype)init;

View File

@ -7,7 +7,6 @@
// //
#import "CSMachine.h" #import "CSMachine.h"
#import "CSKeyboardMachine.h"
#import "CSFastLoading.h" #import "CSFastLoading.h"
typedef NS_ENUM(NSInteger, CSVic20Country) typedef NS_ENUM(NSInteger, CSVic20Country)
@ -26,7 +25,7 @@ typedef NS_ENUM(NSInteger, CSVic20MemorySize)
CSVic20MemorySize32Kb, CSVic20MemorySize32Kb,
}; };
@interface CSVic20 : CSMachine <CSKeyboardMachine, CSFastLoading> @interface CSVic20 : CSMachine <CSFastLoading>
- (instancetype)init; - (instancetype)init;

View File

@ -7,10 +7,9 @@
// //
#import "CSMachine.h" #import "CSMachine.h"
#import "CSKeyboardMachine.h"
#import "CSFastLoading.h" #import "CSFastLoading.h"
@interface CSZX8081 : CSMachine <CSKeyboardMachine, CSFastLoading> @interface CSZX8081 : CSMachine <CSFastLoading>
@property (nonatomic, assign) BOOL useFastLoadingHack; @property (nonatomic, assign) BOOL useFastLoadingHack;