mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-23 20:29:42 +00:00
Introduces 'non-exclusive' emulator-space keyboards.
i.e. sets of keys that don't amount to an entire keyboard in the modern sense. Experimentally used by the Master System for its reset key.
This commit is contained in:
parent
278585fd94
commit
a8645f80bf
@ -35,9 +35,13 @@ void MultiKeyboardMachine::type_string(const std::string &string) {
|
||||
}
|
||||
}
|
||||
|
||||
void MultiKeyboardMachine::keyboard_did_change_key(Inputs::Keyboard *keyboard, Inputs::Keyboard::Key key, bool is_pressed) {
|
||||
for(const auto &machine: machines_) {
|
||||
uint16_t mapped_key = machine->get_keyboard_mapper()->mapped_key_for_key(key);
|
||||
if(mapped_key != KeyNotMapped) machine->set_key_state(mapped_key, is_pressed);
|
||||
}
|
||||
Inputs::Keyboard &MultiKeyboardMachine::get_keyboard() {
|
||||
return keyboard_;
|
||||
}
|
||||
|
||||
//void MultiKeyboardMachine::keyboard_did_change_key(Inputs::Keyboard *keyboard, Inputs::Keyboard::Key key, bool is_pressed) {
|
||||
// for(const auto &machine: machines_) {
|
||||
// uint16_t mapped_key = machine->get_keyboard_mapper()->mapped_key_for_key(key);
|
||||
// if(mapped_key != KeyNotMapped) machine->set_key_state(mapped_key, is_pressed);
|
||||
// }
|
||||
//}
|
||||
|
@ -32,10 +32,11 @@ class MultiKeyboardMachine: public KeyboardMachine::Machine {
|
||||
void clear_all_keys() override;
|
||||
void set_key_state(uint16_t key, bool is_pressed) override;
|
||||
void type_string(const std::string &) override;
|
||||
void keyboard_did_change_key(Inputs::Keyboard *keyboard, Inputs::Keyboard::Key key, bool is_pressed) override;
|
||||
Inputs::Keyboard &get_keyboard() override;
|
||||
|
||||
private:
|
||||
std::vector<::KeyboardMachine::Machine *> machines_;
|
||||
Inputs::Keyboard keyboard_;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -702,6 +702,23 @@ HalfCycles TMS9918::get_time_until_interrupt() {
|
||||
return half_cycles_before_internal_cycles(std::min(local_cycles_until_line_interrupt, time_until_frame_interrupt));
|
||||
}
|
||||
|
||||
HalfCycles TMS9918::get_time_until_line(int line) {
|
||||
if(line < 0) line += mode_timing_.total_lines;
|
||||
|
||||
int cycles_to_next_interrupt_threshold = mode_timing_.line_interrupt_position - write_pointer_.column;
|
||||
int line_of_next_interrupt_threshold = write_pointer_.row;
|
||||
if(cycles_to_next_interrupt_threshold <= 0) {
|
||||
cycles_to_next_interrupt_threshold += 342;
|
||||
++line_of_next_interrupt_threshold;
|
||||
}
|
||||
|
||||
if(line_of_next_interrupt_threshold > line) {
|
||||
line += mode_timing_.total_lines;
|
||||
}
|
||||
|
||||
return half_cycles_before_internal_cycles(cycles_to_next_interrupt_threshold + (line - line_of_next_interrupt_threshold)*342);
|
||||
}
|
||||
|
||||
bool TMS9918::get_interrupt_line() {
|
||||
return ((status_ & StatusInterrupt) && generate_interrupts_) || (enable_line_interrupts_ && line_interrupt_pending_);
|
||||
}
|
||||
|
@ -74,6 +74,16 @@ class TMS9918: public Base {
|
||||
*/
|
||||
HalfCycles get_time_until_interrupt();
|
||||
|
||||
/*!
|
||||
Returns the amount of time until the nominated line interrupt position is
|
||||
reached on line @c line. If no line interrupt position is defined for
|
||||
this VDP, returns the time until the 'beginning' of that line, whatever
|
||||
that may mean.
|
||||
|
||||
@line is relative to the first pixel line of the display and may be negative.
|
||||
*/
|
||||
HalfCycles get_time_until_line(int line);
|
||||
|
||||
/*!
|
||||
@returns @c true if the interrupt line is currently active; @c false otherwise.
|
||||
*/
|
||||
|
@ -10,7 +10,13 @@
|
||||
|
||||
using namespace Inputs;
|
||||
|
||||
Keyboard::Keyboard() {}
|
||||
Keyboard::Keyboard() {
|
||||
for(int k = 0; k < int(Key::Help); ++k) {
|
||||
observed_keys_.insert(Key(k));
|
||||
}
|
||||
}
|
||||
|
||||
Keyboard::Keyboard(const std::set<Key> &observed_keys) : observed_keys_(observed_keys), is_exclusive_(false) {}
|
||||
|
||||
void Keyboard::set_key_pressed(Key key, char value, bool is_pressed) {
|
||||
std::size_t key_offset = static_cast<std::size_t>(key);
|
||||
@ -36,3 +42,11 @@ bool Keyboard::get_key_state(Key key) {
|
||||
if(key_offset >= key_states_.size()) return false;
|
||||
return key_states_[key_offset];
|
||||
}
|
||||
|
||||
const std::set<Keyboard::Key> &Keyboard::observed_keys() {
|
||||
return observed_keys_;
|
||||
}
|
||||
|
||||
bool Keyboard::is_exclusive() {
|
||||
return is_exclusive_;
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
#define Keyboard_hpp
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
namespace Inputs {
|
||||
|
||||
@ -20,8 +21,6 @@ namespace Inputs {
|
||||
*/
|
||||
class Keyboard {
|
||||
public:
|
||||
Keyboard();
|
||||
|
||||
enum class Key {
|
||||
Escape, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PrintScreen, ScrollLock, Pause,
|
||||
BackTick, k1, k2, k3, k4, k5, k6, k7, k8, k9, k0, Hyphen, Equals, BackSpace,
|
||||
@ -39,10 +38,26 @@ class Keyboard {
|
||||
Help
|
||||
};
|
||||
|
||||
/// Constructs a Keyboard that declares itself to observe all keys.
|
||||
Keyboard();
|
||||
|
||||
/// Constructs a Keyboard that declares itself to observe only members of @c observed_keys.
|
||||
Keyboard(const std::set<Key> &observed_keys);
|
||||
|
||||
// Host interface.
|
||||
virtual void set_key_pressed(Key key, char value, bool is_pressed);
|
||||
virtual void reset_all_keys();
|
||||
|
||||
/// @returns a set of all Keys that this keyboard responds to.
|
||||
virtual const std::set<Key> &observed_keys();
|
||||
|
||||
/*
|
||||
@returns @c true if this keyboard, on its original machine, looked
|
||||
like a complete keyboard — i.e. if a user would expect this keyboard
|
||||
to be the only thing a real keyboard maps to.
|
||||
*/
|
||||
virtual bool is_exclusive();
|
||||
|
||||
// Delegate interface.
|
||||
struct Delegate {
|
||||
virtual void keyboard_did_change_key(Keyboard *keyboard, Key key, bool is_pressed) = 0;
|
||||
@ -52,8 +67,10 @@ class Keyboard {
|
||||
bool get_key_state(Key key);
|
||||
|
||||
private:
|
||||
std::set<Key> observed_keys_;
|
||||
std::vector<bool> key_states_;
|
||||
Delegate *delegate_ = nullptr;
|
||||
bool is_exclusive_ = true;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -757,7 +757,7 @@ class i8255PortHandler : public Intel::i8255::PortHandler {
|
||||
template <bool has_fdc> class ConcreteMachine:
|
||||
public CRTMachine::Machine,
|
||||
public MediaTarget::Machine,
|
||||
public KeyboardMachine::Machine,
|
||||
public KeyboardMachine::MappedMachine,
|
||||
public Utility::TypeRecipient,
|
||||
public CPU::Z80::BusHandler,
|
||||
public ClockingHint::Observer,
|
||||
|
@ -75,9 +75,9 @@ uint16_t KeyboardMapper::mapped_key_for_key(Inputs::Keyboard::Key key) {
|
||||
}
|
||||
|
||||
uint16_t *CharacterMapper::sequence_for_character(char character) {
|
||||
#define KEYS(...) {__VA_ARGS__, KeyboardMachine::Machine::KeyEndSequence}
|
||||
#define SHIFT(...) {KeyShift, __VA_ARGS__, KeyboardMachine::Machine::KeyEndSequence}
|
||||
#define X {KeyboardMachine::Machine::KeyNotMapped}
|
||||
#define KEYS(...) {__VA_ARGS__, KeyboardMachine::MappedMachine::KeyEndSequence}
|
||||
#define SHIFT(...) {KeyShift, __VA_ARGS__, KeyboardMachine::MappedMachine::KeyEndSequence}
|
||||
#define X {KeyboardMachine::MappedMachine::KeyNotMapped}
|
||||
static KeySequence key_sequences[] = {
|
||||
/* NUL */ X, /* SOH */ X,
|
||||
/* STX */ X, /* ETX */ X,
|
||||
|
@ -33,7 +33,7 @@ enum Key: uint16_t {
|
||||
#undef Line
|
||||
};
|
||||
|
||||
struct KeyboardMapper: public KeyboardMachine::Machine::KeyboardMapper {
|
||||
struct KeyboardMapper: public KeyboardMachine::MappedMachine::KeyboardMapper {
|
||||
uint16_t mapped_key_for_key(Inputs::Keyboard::Key key);
|
||||
};
|
||||
|
||||
|
@ -40,7 +40,7 @@ namespace {
|
||||
template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
|
||||
public CRTMachine::Machine,
|
||||
public MediaTarget::Machine,
|
||||
public KeyboardMachine::Machine,
|
||||
public KeyboardMachine::MappedMachine,
|
||||
public CPU::MOS6502::BusHandler,
|
||||
public Inputs::Keyboard,
|
||||
public AppleII::Machine,
|
||||
|
@ -68,13 +68,13 @@ uint16_t KeyboardMapper::mapped_key_for_key(Inputs::Keyboard::Key key) {
|
||||
BIND(F7, KeyF7);
|
||||
}
|
||||
#undef BIND
|
||||
return KeyboardMachine::Machine::KeyNotMapped;
|
||||
return KeyboardMachine::MappedMachine::KeyNotMapped;
|
||||
}
|
||||
|
||||
uint16_t *CharacterMapper::sequence_for_character(char character) {
|
||||
#define KEYS(...) {__VA_ARGS__, KeyboardMachine::Machine::KeyEndSequence}
|
||||
#define SHIFT(...) {KeyLShift, __VA_ARGS__, KeyboardMachine::Machine::KeyEndSequence}
|
||||
#define X {KeyboardMachine::Machine::KeyNotMapped}
|
||||
#define KEYS(...) {__VA_ARGS__, KeyboardMachine::MappedMachine::KeyEndSequence}
|
||||
#define SHIFT(...) {KeyLShift, __VA_ARGS__, KeyboardMachine::MappedMachine::KeyEndSequence}
|
||||
#define X {KeyboardMachine::MappedMachine::KeyNotMapped}
|
||||
static KeySequence key_sequences[] = {
|
||||
/* NUL */ X, /* SOH */ X,
|
||||
/* STX */ X, /* ETX */ X,
|
||||
|
@ -38,7 +38,7 @@ enum Key: uint16_t {
|
||||
#undef key
|
||||
};
|
||||
|
||||
struct KeyboardMapper: public KeyboardMachine::Machine::KeyboardMapper {
|
||||
struct KeyboardMapper: public KeyboardMachine::MappedMachine::KeyboardMapper {
|
||||
uint16_t mapped_key_for_key(Inputs::Keyboard::Key key);
|
||||
};
|
||||
|
||||
|
@ -281,7 +281,7 @@ class Joystick: public Inputs::ConcreteJoystick {
|
||||
class ConcreteMachine:
|
||||
public CRTMachine::Machine,
|
||||
public MediaTarget::Machine,
|
||||
public KeyboardMachine::Machine,
|
||||
public KeyboardMachine::MappedMachine,
|
||||
public JoystickMachine::Machine,
|
||||
public Configurable::Device,
|
||||
public CPU::MOS6502::BusHandler,
|
||||
|
@ -42,7 +42,7 @@ class ConcreteMachine:
|
||||
public Machine,
|
||||
public CRTMachine::Machine,
|
||||
public MediaTarget::Machine,
|
||||
public KeyboardMachine::Machine,
|
||||
public KeyboardMachine::MappedMachine,
|
||||
public Configurable::Device,
|
||||
public CPU::MOS6502::BusHandler,
|
||||
public Tape::Delegate,
|
||||
|
@ -56,10 +56,10 @@ uint16_t KeyboardMapper::mapped_key_for_key(Inputs::Keyboard::Key key) {
|
||||
}
|
||||
|
||||
uint16_t *CharacterMapper::sequence_for_character(char character) {
|
||||
#define KEYS(...) {__VA_ARGS__, KeyboardMachine::Machine::KeyEndSequence}
|
||||
#define SHIFT(...) {KeyShift, __VA_ARGS__, KeyboardMachine::Machine::KeyEndSequence}
|
||||
#define CTRL(...) {KeyControl, __VA_ARGS__, KeyboardMachine::Machine::KeyEndSequence}
|
||||
#define X {KeyboardMachine::Machine::KeyNotMapped}
|
||||
#define KEYS(...) {__VA_ARGS__, KeyboardMachine::MappedMachine::KeyEndSequence}
|
||||
#define SHIFT(...) {KeyShift, __VA_ARGS__, KeyboardMachine::MappedMachine::KeyEndSequence}
|
||||
#define CTRL(...) {KeyControl, __VA_ARGS__, KeyboardMachine::MappedMachine::KeyEndSequence}
|
||||
#define X {KeyboardMachine::MappedMachine::KeyNotMapped}
|
||||
static KeySequence key_sequences[] = {
|
||||
/* NUL */ X, /* SOH */ X,
|
||||
/* STX */ X, /* ETX */ X,
|
||||
|
@ -33,7 +33,7 @@ enum Key: uint16_t {
|
||||
KeyBreak = 0xfffd,
|
||||
};
|
||||
|
||||
struct KeyboardMapper: public KeyboardMachine::Machine::KeyboardMapper {
|
||||
struct KeyboardMapper: public KeyboardMachine::MappedMachine::KeyboardMapper {
|
||||
uint16_t mapped_key_for_key(Inputs::Keyboard::Key key);
|
||||
};
|
||||
|
||||
|
@ -10,27 +10,27 @@
|
||||
|
||||
using namespace KeyboardMachine;
|
||||
|
||||
Machine::Machine() {
|
||||
MappedMachine::MappedMachine() {
|
||||
keyboard_.set_delegate(this);
|
||||
}
|
||||
|
||||
void Machine::keyboard_did_change_key(Inputs::Keyboard *keyboard, Inputs::Keyboard::Key key, bool is_pressed) {
|
||||
void MappedMachine::keyboard_did_change_key(Inputs::Keyboard *keyboard, Inputs::Keyboard::Key key, bool is_pressed) {
|
||||
uint16_t mapped_key = get_keyboard_mapper()->mapped_key_for_key(key);
|
||||
if(mapped_key != KeyNotMapped) set_key_state(mapped_key, is_pressed);
|
||||
}
|
||||
|
||||
void Machine::reset_all_keys(Inputs::Keyboard *keyboard) {
|
||||
void MappedMachine::reset_all_keys(Inputs::Keyboard *keyboard) {
|
||||
// TODO: unify naming.
|
||||
clear_all_keys();
|
||||
}
|
||||
|
||||
Inputs::Keyboard &Machine::get_keyboard() {
|
||||
Inputs::Keyboard &MappedMachine::get_keyboard() {
|
||||
return keyboard_;
|
||||
}
|
||||
|
||||
void Machine::type_string(const std::string &) {
|
||||
}
|
||||
|
||||
Machine::KeyboardMapper *Machine::get_keyboard_mapper() {
|
||||
MappedMachine::KeyboardMapper *MappedMachine::get_keyboard_mapper() {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -33,13 +33,10 @@ struct KeyActions {
|
||||
};
|
||||
|
||||
/*!
|
||||
Describes the full functionality of being an emulated machine with a keyboard: not just being
|
||||
able to receive key actions, but being able to vend a generic keyboard and a keyboard mapper.
|
||||
Describes an emulated machine which exposes a keyboard and accepts a typed string.
|
||||
*/
|
||||
class Machine: public Inputs::Keyboard::Delegate, public KeyActions {
|
||||
class Machine: public KeyActions {
|
||||
public:
|
||||
Machine();
|
||||
|
||||
/*!
|
||||
Causes the machine to attempt to type the supplied string.
|
||||
|
||||
@ -50,7 +47,16 @@ class Machine: public Inputs::Keyboard::Delegate, public KeyActions {
|
||||
/*!
|
||||
Provides a destination for keyboard input.
|
||||
*/
|
||||
virtual Inputs::Keyboard &get_keyboard();
|
||||
virtual Inputs::Keyboard &get_keyboard() = 0;
|
||||
};
|
||||
|
||||
/*!
|
||||
Provides a base class for machines that want to provide a keyboard mapper,
|
||||
allowing automatic mapping from keyboard inputs to KeyActions.
|
||||
*/
|
||||
class MappedMachine: public Inputs::Keyboard::Delegate, public Machine {
|
||||
public:
|
||||
MappedMachine();
|
||||
|
||||
/*!
|
||||
A keyboard mapper attempts to provide a physical mapping between host keys and emulated keys.
|
||||
@ -76,6 +82,12 @@ class Machine: public Inputs::Keyboard::Delegate, public KeyActions {
|
||||
*/
|
||||
virtual KeyboardMapper *get_keyboard_mapper();
|
||||
|
||||
/*!
|
||||
Provides a keyboard that obtains this machine's keyboard mapper, maps
|
||||
the key and supplies it via the KeyActions.
|
||||
*/
|
||||
virtual Inputs::Keyboard &get_keyboard() override;
|
||||
|
||||
private:
|
||||
void keyboard_did_change_key(Inputs::Keyboard *keyboard, Inputs::Keyboard::Key key, bool is_pressed) override;
|
||||
void reset_all_keys(Inputs::Keyboard *keyboard) override;
|
||||
|
@ -57,5 +57,5 @@ uint16_t MSX::KeyboardMapper::mapped_key_for_key(Inputs::Keyboard::Key key) {
|
||||
default: break;
|
||||
}
|
||||
#undef BIND
|
||||
return KeyboardMachine::Machine::KeyNotMapped;
|
||||
return KeyboardMachine::MappedMachine::KeyNotMapped;
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ enum Key: uint16_t {
|
||||
#undef Line
|
||||
};
|
||||
|
||||
struct KeyboardMapper: public KeyboardMachine::Machine::KeyboardMapper {
|
||||
struct KeyboardMapper: public KeyboardMachine::MappedMachine::KeyboardMapper {
|
||||
uint16_t mapped_key_for_key(Inputs::Keyboard::Key key);
|
||||
};
|
||||
|
||||
|
@ -139,7 +139,7 @@ class ConcreteMachine:
|
||||
public CPU::Z80::BusHandler,
|
||||
public CRTMachine::Machine,
|
||||
public MediaTarget::Machine,
|
||||
public KeyboardMachine::Machine,
|
||||
public KeyboardMachine::MappedMachine,
|
||||
public Configurable::Device,
|
||||
public JoystickMachine::Machine,
|
||||
public MemoryMap,
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "../CRTMachine.hpp"
|
||||
#include "../JoystickMachine.hpp"
|
||||
#include "../KeyboardMachine.hpp"
|
||||
|
||||
#include "../../ClockReceiver/ForceInline.hpp"
|
||||
|
||||
@ -81,6 +82,8 @@ class ConcreteMachine:
|
||||
public Machine,
|
||||
public CPU::Z80::BusHandler,
|
||||
public CRTMachine::Machine,
|
||||
public KeyboardMachine::Machine,
|
||||
public Inputs::Keyboard::Delegate,
|
||||
public Configurable::Device,
|
||||
public JoystickMachine::Machine {
|
||||
|
||||
@ -94,7 +97,8 @@ class ConcreteMachine:
|
||||
(target.model == Target::Model::SG1000) ? TI::SN76489::Personality::SN76489 : TI::SN76489::Personality::SMS,
|
||||
audio_queue_,
|
||||
sn76489_divider),
|
||||
speaker_(sn76489_) {
|
||||
speaker_(sn76489_),
|
||||
keyboard_({Inputs::Keyboard::Key::Enter, Inputs::Keyboard::Key::Escape}) {
|
||||
// Pick the clock rate based on the region.
|
||||
const double clock_rate = target.region == Target::Region::Europe ? 3546893.0 : 3579540.0;
|
||||
speaker_.set_input_rate(static_cast<float>(clock_rate / sn76489_divider));
|
||||
@ -146,6 +150,8 @@ class ConcreteMachine:
|
||||
|
||||
// Apple a relatively low low-pass filter. More guidance needed here.
|
||||
speaker_.set_high_frequency_cutoff(8000);
|
||||
|
||||
keyboard_.set_delegate(this);
|
||||
}
|
||||
|
||||
~ConcreteMachine() {
|
||||
@ -164,6 +170,8 @@ class ConcreteMachine:
|
||||
(region_ == Target::Region::Europe) ?
|
||||
TI::TMS::TVStandard::PAL : TI::TMS::TVStandard::NTSC);
|
||||
get_crt()->set_video_signal(Outputs::CRT::VideoSignal::Composite);
|
||||
|
||||
time_until_debounce_ = vdp_->get_time_until_line(-1);
|
||||
}
|
||||
|
||||
void close_output() override {
|
||||
@ -213,7 +221,7 @@ class ConcreteMachine:
|
||||
}
|
||||
|
||||
if(write_pointers_[address >> 10]) write_pointers_[address >> 10][address & 1023] = *cycle.value;
|
||||
else LOG("Ignored write to ROM");
|
||||
// else LOG("Ignored write to ROM");
|
||||
break;
|
||||
|
||||
case CPU::Z80::PartialMachineCycle::Input:
|
||||
@ -320,6 +328,15 @@ class ConcreteMachine:
|
||||
}
|
||||
}
|
||||
|
||||
// The pause button is debounced and takes effect only one line before pixels
|
||||
// begin; time_until_debounce_ keeps track of the time until then.
|
||||
time_until_debounce_ -= cycle.length;
|
||||
if(time_until_debounce_ <= HalfCycles(0)) {
|
||||
z80_.set_non_maskable_interrupt_line(pause_is_pressed_);
|
||||
update_video();
|
||||
time_until_debounce_ = vdp_->get_time_until_line(-1);
|
||||
}
|
||||
|
||||
return HalfCycles(0);
|
||||
}
|
||||
|
||||
@ -333,6 +350,23 @@ class ConcreteMachine:
|
||||
return joysticks_;
|
||||
}
|
||||
|
||||
// MARK: - Keyboard (i.e. the pause and reset buttons).
|
||||
Inputs::Keyboard &get_keyboard() override {
|
||||
return keyboard_;
|
||||
}
|
||||
|
||||
void keyboard_did_change_key(Inputs::Keyboard *, Inputs::Keyboard::Key key, bool is_pressed) override {
|
||||
if(key == Inputs::Keyboard::Key::Enter) {
|
||||
pause_is_pressed_ = is_pressed;
|
||||
} else if(key == Inputs::Keyboard::Key::Escape) {
|
||||
reset_is_pressed_ = is_pressed;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void reset_all_keys(Inputs::Keyboard *) override {
|
||||
}
|
||||
|
||||
// MARK: - Configuration options.
|
||||
std::vector<std::unique_ptr<Configurable::Option>> get_options() override {
|
||||
return Sega::MasterSystem::get_options();
|
||||
@ -388,10 +422,13 @@ class ConcreteMachine:
|
||||
Outputs::Speaker::LowpassSpeaker<TI::SN76489> speaker_;
|
||||
|
||||
std::vector<std::unique_ptr<Inputs::Joystick>> joysticks_;
|
||||
Inputs::Keyboard keyboard_;
|
||||
bool reset_is_pressed_ = false, pause_is_pressed_ = false;
|
||||
|
||||
HalfCycles time_since_vdp_update_;
|
||||
HalfCycles time_since_sn76489_update_;
|
||||
HalfCycles time_until_interrupt_;
|
||||
HalfCycles time_until_debounce_;
|
||||
|
||||
uint8_t ram_[8*1024];
|
||||
uint8_t bios_[8*1024];
|
||||
|
@ -48,13 +48,13 @@ uint16_t KeyboardMapper::mapped_key_for_key(Inputs::Keyboard::Key key) {
|
||||
}
|
||||
#undef BIND
|
||||
|
||||
return KeyboardMachine::Machine::KeyNotMapped;
|
||||
return KeyboardMachine::MappedMachine::KeyNotMapped;
|
||||
}
|
||||
|
||||
uint16_t *CharacterMapper::sequence_for_character(char character) {
|
||||
#define KEYS(...) {__VA_ARGS__, KeyboardMachine::Machine::KeyEndSequence}
|
||||
#define SHIFT(...) {KeyLeftShift, __VA_ARGS__, KeyboardMachine::Machine::KeyEndSequence}
|
||||
#define X {KeyboardMachine::Machine::KeyNotMapped}
|
||||
#define KEYS(...) {__VA_ARGS__, KeyboardMachine::MappedMachine::KeyEndSequence}
|
||||
#define SHIFT(...) {KeyLeftShift, __VA_ARGS__, KeyboardMachine::MappedMachine::KeyEndSequence}
|
||||
#define X {KeyboardMachine::MappedMachine::KeyNotMapped}
|
||||
static KeySequence key_sequences[] = {
|
||||
/* NUL */ X, /* SOH */ X,
|
||||
/* STX */ X, /* ETX */ X,
|
||||
|
@ -35,7 +35,7 @@ enum Key: uint16_t {
|
||||
KeyNMI = 0xfffd,
|
||||
};
|
||||
|
||||
struct KeyboardMapper: public KeyboardMachine::Machine::KeyboardMapper {
|
||||
struct KeyboardMapper: public KeyboardMachine::MappedMachine::KeyboardMapper {
|
||||
uint16_t mapped_key_for_key(Inputs::Keyboard::Key key);
|
||||
};
|
||||
|
||||
|
@ -194,7 +194,7 @@ class VIAPortHandler: public MOS::MOS6522::IRQDelegatePortHandler {
|
||||
template <Analyser::Static::Oric::Target::DiskInterface disk_interface> class ConcreteMachine:
|
||||
public CRTMachine::Machine,
|
||||
public MediaTarget::Machine,
|
||||
public KeyboardMachine::Machine,
|
||||
public KeyboardMachine::MappedMachine,
|
||||
public Configurable::Device,
|
||||
public CPU::MOS6502::BusHandler,
|
||||
public MOS::MOS6522::IRQDelegatePortHandler::Delegate,
|
||||
|
@ -43,14 +43,14 @@ void Typer::run_for(const HalfCycles duration) {
|
||||
bool Typer::try_type_next_character() {
|
||||
uint16_t *sequence = character_mapper_->sequence_for_character(string_[string_pointer_]);
|
||||
|
||||
if(!sequence || sequence[0] == KeyboardMachine::Machine::KeyNotMapped) {
|
||||
if(!sequence || sequence[0] == KeyboardMachine::MappedMachine::KeyNotMapped) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!phase_) delegate_->clear_all_keys();
|
||||
else {
|
||||
delegate_->set_key_state(sequence[phase_ - 1], true);
|
||||
return sequence[phase_] != KeyboardMachine::Machine::KeyEndSequence;
|
||||
return sequence[phase_] != KeyboardMachine::MappedMachine::KeyEndSequence;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -75,6 +75,6 @@ bool Typer::type_next_character() {
|
||||
uint16_t *CharacterMapper::table_lookup_sequence_for_character(KeySequence *sequences, std::size_t length, char character) {
|
||||
std::size_t ucharacter = static_cast<std::size_t>((unsigned char)character);
|
||||
if(ucharacter > (length / sizeof(KeySequence))) return nullptr;
|
||||
if(sequences[ucharacter][0] == KeyboardMachine::Machine::KeyNotMapped) return nullptr;
|
||||
if(sequences[ucharacter][0] == KeyboardMachine::MappedMachine::KeyNotMapped) return nullptr;
|
||||
return sequences[ucharacter];
|
||||
}
|
||||
|
@ -30,15 +30,15 @@ uint16_t KeyboardMapper::mapped_key_for_key(Inputs::Keyboard::Key key) {
|
||||
BIND(Space, KeySpace);
|
||||
}
|
||||
#undef BIND
|
||||
return KeyboardMachine::Machine::KeyNotMapped;
|
||||
return KeyboardMachine::MappedMachine::KeyNotMapped;
|
||||
}
|
||||
|
||||
CharacterMapper::CharacterMapper(bool is_zx81) : is_zx81_(is_zx81) {}
|
||||
|
||||
uint16_t *CharacterMapper::sequence_for_character(char character) {
|
||||
#define KEYS(...) {__VA_ARGS__, KeyboardMachine::Machine::KeyEndSequence}
|
||||
#define SHIFT(...) {KeyShift, __VA_ARGS__, KeyboardMachine::Machine::KeyEndSequence}
|
||||
#define X {KeyboardMachine::Machine::KeyNotMapped}
|
||||
#define KEYS(...) {__VA_ARGS__, KeyboardMachine::MappedMachine::KeyEndSequence}
|
||||
#define SHIFT(...) {KeyShift, __VA_ARGS__, KeyboardMachine::MappedMachine::KeyEndSequence}
|
||||
#define X {KeyboardMachine::MappedMachine::KeyNotMapped}
|
||||
static KeySequence zx81_key_sequences[] = {
|
||||
/* NUL */ X, /* SOH */ X,
|
||||
/* STX */ X, /* ETX */ X,
|
||||
|
@ -25,7 +25,7 @@ enum Key: uint16_t {
|
||||
KeySpace = 0x0700 | 0x01, KeyDot = 0x0700 | 0x02, KeyM = 0x0700 | 0x04, KeyN = 0x0700 | 0x08, KeyB = 0x0700 | 0x10,
|
||||
};
|
||||
|
||||
struct KeyboardMapper: public KeyboardMachine::Machine::KeyboardMapper {
|
||||
struct KeyboardMapper: public KeyboardMachine::MappedMachine::KeyboardMapper {
|
||||
uint16_t mapped_key_for_key(Inputs::Keyboard::Key key);
|
||||
};
|
||||
|
||||
|
@ -60,7 +60,7 @@ std::vector<std::unique_ptr<Configurable::Option>> get_options() {
|
||||
template<bool is_zx81> class ConcreteMachine:
|
||||
public CRTMachine::Machine,
|
||||
public MediaTarget::Machine,
|
||||
public KeyboardMachine::Machine,
|
||||
public KeyboardMachine::MappedMachine,
|
||||
public Configurable::Device,
|
||||
public Utility::TypeRecipient,
|
||||
public CPU::Z80::BusHandler,
|
||||
|
@ -301,7 +301,7 @@ class MachineDocument:
|
||||
if let menuItem = item as? NSMenuItem {
|
||||
switch item.action {
|
||||
case #selector(self.useKeyboardAsKeyboard):
|
||||
if machine == nil || !machine.hasKeyboard {
|
||||
if machine == nil || !machine.hasExclusiveKeyboard {
|
||||
menuItem.state = .off
|
||||
return false
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ typedef NS_ENUM(NSInteger, CSMachineKeyboardInputMode) {
|
||||
- (bool)supportsVideoSignal:(CSMachineVideoSignal)videoSignal;
|
||||
|
||||
// Input control.
|
||||
@property (nonatomic, readonly) BOOL hasKeyboard;
|
||||
@property (nonatomic, readonly) BOOL hasExclusiveKeyboard;
|
||||
@property (nonatomic, readonly) BOOL hasJoystick;
|
||||
@property (nonatomic, assign) CSMachineKeyboardInputMode inputMode;
|
||||
@property (nonatomic, nullable) CSJoystickManager *joystickManager;
|
||||
|
@ -91,7 +91,9 @@ struct ActivityObserver: public Activity::Observer {
|
||||
_machine.reset(Machine::MachineForTargets(_analyser.targets, CSROMFetcher(), error));
|
||||
if(!_machine) return nil;
|
||||
|
||||
_inputMode = _machine->keyboard_machine() ? CSMachineKeyboardInputModeKeyboard : CSMachineKeyboardInputModeJoystick;
|
||||
_inputMode =
|
||||
(_machine->keyboard_machine() && _machine->keyboard_machine()->get_keyboard().is_exclusive())
|
||||
? CSMachineKeyboardInputModeKeyboard : CSMachineKeyboardInputModeJoystick;
|
||||
|
||||
_leds = [[NSMutableArray alloc] init];
|
||||
Activity::Source *const activity_source = _machine->activity_source();
|
||||
@ -301,80 +303,85 @@ struct ActivityObserver: public Activity::Observer {
|
||||
|
||||
- (void)setKey:(uint16_t)key characters:(NSString *)characters isPressed:(BOOL)isPressed {
|
||||
auto keyboard_machine = _machine->keyboard_machine();
|
||||
if(self.inputMode == CSMachineKeyboardInputModeKeyboard && keyboard_machine) {
|
||||
// Don't pass anything on if this is not new information.
|
||||
if(_depressedKeys[key] == !!isPressed) return;
|
||||
_depressedKeys[key] = !!isPressed;
|
||||
if(keyboard_machine && (self.inputMode == CSMachineKeyboardInputModeKeyboard || !keyboard_machine->get_keyboard().is_exclusive())) {
|
||||
Inputs::Keyboard::Key mapped_key = Inputs::Keyboard::Key::Help; // Make an innocuous default guess.
|
||||
#define BIND(source, dest) case source: mapped_key = Inputs::Keyboard::Key::dest; break;
|
||||
// Connect the Carbon-era Mac keyboard scancodes to Clock Signal's 'universal' enumeration in order
|
||||
// to pass into the platform-neutral realm.
|
||||
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_5, k5); BIND(VK_ANSI_6, k6); BIND(VK_ANSI_7, k7); BIND(VK_ANSI_8, k8); BIND(VK_ANSI_9, k9);
|
||||
|
||||
// Pick an ASCII code, if any.
|
||||
char pressedKey = '\0';
|
||||
if(characters.length) {
|
||||
unichar firstCharacter = [characters characterAtIndex:0];
|
||||
if(firstCharacter < 128) {
|
||||
pressedKey = (char)firstCharacter;
|
||||
}
|
||||
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_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_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_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_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_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_Keypad9, KeyPad9);
|
||||
|
||||
BIND(VK_ANSI_Equal, Equals); BIND(VK_ANSI_Minus, Hyphen);
|
||||
BIND(VK_ANSI_RightBracket, CloseSquareBracket); BIND(VK_ANSI_LeftBracket, OpenSquareBracket);
|
||||
BIND(VK_ANSI_Quote, Quote); BIND(VK_ANSI_Grave, BackTick);
|
||||
|
||||
BIND(VK_ANSI_Semicolon, Semicolon);
|
||||
BIND(VK_ANSI_Backslash, BackSlash); BIND(VK_ANSI_Slash, ForwardSlash);
|
||||
BIND(VK_ANSI_Comma, Comma); BIND(VK_ANSI_Period, FullStop);
|
||||
|
||||
BIND(VK_ANSI_KeypadDecimal, KeyPadDecimalPoint); BIND(VK_ANSI_KeypadEquals, KeyPadEquals);
|
||||
BIND(VK_ANSI_KeypadMultiply, KeyPadAsterisk); BIND(VK_ANSI_KeypadDivide, KeyPadSlash);
|
||||
BIND(VK_ANSI_KeypadPlus, KeyPadPlus); BIND(VK_ANSI_KeypadMinus, KeyPadMinus);
|
||||
BIND(VK_ANSI_KeypadClear, KeyPadDelete); BIND(VK_ANSI_KeypadEnter, KeyPadEnter);
|
||||
|
||||
BIND(VK_Return, Enter); BIND(VK_Tab, Tab);
|
||||
BIND(VK_Space, Space); BIND(VK_Delete, BackSpace);
|
||||
BIND(VK_Control, LeftControl); BIND(VK_Option, LeftOption);
|
||||
BIND(VK_Command, LeftMeta); BIND(VK_Shift, LeftShift);
|
||||
BIND(VK_RightControl, RightControl); BIND(VK_RightOption, RightOption);
|
||||
BIND(VK_Escape, Escape); BIND(VK_CapsLock, CapsLock);
|
||||
BIND(VK_Home, Home); BIND(VK_End, End);
|
||||
BIND(VK_PageUp, PageUp); BIND(VK_PageDown, PageDown);
|
||||
|
||||
BIND(VK_RightShift, RightShift);
|
||||
BIND(VK_Help, Help);
|
||||
BIND(VK_ForwardDelete, Delete);
|
||||
|
||||
BIND(VK_LeftArrow, Left); BIND(VK_RightArrow, Right);
|
||||
BIND(VK_DownArrow, Down); BIND(VK_UpArrow, Up);
|
||||
}
|
||||
|
||||
@synchronized(self) {
|
||||
Inputs::Keyboard &keyboard = keyboard_machine->get_keyboard();
|
||||
|
||||
// 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, pressedKey, isPressed); break
|
||||
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_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_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_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_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_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_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_Keypad6, KeyPad6); BIND(VK_ANSI_Keypad7, KeyPad7); BIND(VK_ANSI_Keypad8, KeyPad8);
|
||||
BIND(VK_ANSI_Keypad9, KeyPad9);
|
||||
|
||||
BIND(VK_ANSI_Equal, Equals); BIND(VK_ANSI_Minus, Hyphen);
|
||||
BIND(VK_ANSI_RightBracket, CloseSquareBracket); BIND(VK_ANSI_LeftBracket, OpenSquareBracket);
|
||||
BIND(VK_ANSI_Quote, Quote); BIND(VK_ANSI_Grave, BackTick);
|
||||
|
||||
BIND(VK_ANSI_Semicolon, Semicolon);
|
||||
BIND(VK_ANSI_Backslash, BackSlash); BIND(VK_ANSI_Slash, ForwardSlash);
|
||||
BIND(VK_ANSI_Comma, Comma); BIND(VK_ANSI_Period, FullStop);
|
||||
|
||||
BIND(VK_ANSI_KeypadDecimal, KeyPadDecimalPoint); BIND(VK_ANSI_KeypadEquals, KeyPadEquals);
|
||||
BIND(VK_ANSI_KeypadMultiply, KeyPadAsterisk); BIND(VK_ANSI_KeypadDivide, KeyPadSlash);
|
||||
BIND(VK_ANSI_KeypadPlus, KeyPadPlus); BIND(VK_ANSI_KeypadMinus, KeyPadMinus);
|
||||
BIND(VK_ANSI_KeypadClear, KeyPadDelete); BIND(VK_ANSI_KeypadEnter, KeyPadEnter);
|
||||
|
||||
BIND(VK_Return, Enter); BIND(VK_Tab, Tab);
|
||||
BIND(VK_Space, Space); BIND(VK_Delete, BackSpace);
|
||||
BIND(VK_Control, LeftControl); BIND(VK_Option, LeftOption);
|
||||
BIND(VK_Command, LeftMeta); BIND(VK_Shift, LeftShift);
|
||||
BIND(VK_RightControl, RightControl); BIND(VK_RightOption, RightOption);
|
||||
BIND(VK_Escape, Escape); BIND(VK_CapsLock, CapsLock);
|
||||
BIND(VK_Home, Home); BIND(VK_End, End);
|
||||
BIND(VK_PageUp, PageUp); BIND(VK_PageDown, PageDown);
|
||||
|
||||
BIND(VK_RightShift, RightShift);
|
||||
BIND(VK_Help, Help);
|
||||
BIND(VK_ForwardDelete, Delete);
|
||||
|
||||
BIND(VK_LeftArrow, Left); BIND(VK_RightArrow, Right);
|
||||
BIND(VK_DownArrow, Down); BIND(VK_UpArrow, Up);
|
||||
}
|
||||
#undef BIND
|
||||
|
||||
Inputs::Keyboard &keyboard = keyboard_machine->get_keyboard();
|
||||
|
||||
if(keyboard.observed_keys().find(mapped_key) != keyboard.observed_keys().end()) {
|
||||
// Don't pass anything on if this is not new information.
|
||||
if(_depressedKeys[key] == !!isPressed) return;
|
||||
_depressedKeys[key] = !!isPressed;
|
||||
|
||||
// Pick an ASCII code, if any.
|
||||
char pressedKey = '\0';
|
||||
if(characters.length) {
|
||||
unichar firstCharacter = [characters characterAtIndex:0];
|
||||
if(firstCharacter < 128) {
|
||||
pressedKey = (char)firstCharacter;
|
||||
}
|
||||
}
|
||||
|
||||
@synchronized(self) {
|
||||
keyboard.set_key_pressed(mapped_key, pressedKey, isPressed);
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
auto joystick_machine = _machine->joystick_machine();
|
||||
@ -536,8 +543,8 @@ struct ActivityObserver: public Activity::Observer {
|
||||
return !!_machine->joystick_machine();
|
||||
}
|
||||
|
||||
- (BOOL)hasKeyboard {
|
||||
return !!_machine->keyboard_machine();
|
||||
- (BOOL)hasExclusiveKeyboard {
|
||||
return !!_machine->keyboard_machine() && _machine->keyboard_machine()->get_keyboard().is_exclusive();
|
||||
}
|
||||
|
||||
#pragma mark - Activity observation
|
||||
|
@ -116,7 +116,7 @@
|
||||
NSAssert(vdp.get_interrupt_line(), @"Interrupt line wasn't set when promised");
|
||||
}
|
||||
|
||||
- (void)testPrediction {
|
||||
- (void)testInterruptPrediction {
|
||||
TI::TMS::TMS9918 vdp(TI::TMS::Personality::SMSVDP);
|
||||
|
||||
for(int c = 0; c < 256; ++c) {
|
||||
@ -134,7 +134,7 @@
|
||||
vdp.set_register(1, 0x8a);
|
||||
|
||||
// Now run through an entire frame...
|
||||
int half_cycles = 262*224*2;
|
||||
int half_cycles = 262*228*2;
|
||||
int last_time_until_interrupt = vdp.get_time_until_interrupt().as_int();
|
||||
while(half_cycles--) {
|
||||
// Validate that an interrupt happened if one was expected, and clear anything that's present.
|
||||
@ -157,4 +157,20 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testTimeUntilLine {
|
||||
TI::TMS::TMS9918 vdp(TI::TMS::Personality::SMSVDP);
|
||||
|
||||
int time_until_line = vdp.get_time_until_line(-1).as_int();
|
||||
for(int c = 0; c < 262*228*5; ++c) {
|
||||
vdp.run_for(HalfCycles(1));
|
||||
|
||||
const int time_remaining_until_line = vdp.get_time_until_line(-1).as_int();
|
||||
--time_until_line;
|
||||
if(time_until_line) {
|
||||
NSAssert(time_remaining_until_line == time_until_line, @"Discontinuity found in distance-to-line prediction; expected %d but got %d", time_until_line, time_remaining_until_line);
|
||||
}
|
||||
time_until_line = time_remaining_until_line;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -610,7 +610,7 @@ int main(int argc, char *argv[]) {
|
||||
case SDL_KEYDOWN:
|
||||
// Syphon off the key-press if it's control+shift+V (paste).
|
||||
if(event.key.keysym.sym == SDLK_v && (SDL_GetModState()&KMOD_CTRL) && (SDL_GetModState()&KMOD_SHIFT)) {
|
||||
KeyboardMachine::Machine *keyboard_machine = machine->keyboard_machine();
|
||||
const auto keyboard_machine = machine->keyboard_machine();
|
||||
if(keyboard_machine) {
|
||||
keyboard_machine->type_string(SDL_GetClipboardText());
|
||||
break;
|
||||
@ -686,7 +686,7 @@ int main(int argc, char *argv[]) {
|
||||
SDL_ShowCursor((fullscreen_mode&SDL_WINDOW_FULLSCREEN_DESKTOP) ? SDL_DISABLE : SDL_ENABLE);
|
||||
|
||||
// Announce a potential discontinuity in keyboard input.
|
||||
auto keyboard_machine = machine->keyboard_machine();
|
||||
const auto keyboard_machine = machine->keyboard_machine();
|
||||
if(keyboard_machine) {
|
||||
keyboard_machine->get_keyboard().reset_all_keys();
|
||||
}
|
||||
@ -695,17 +695,19 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
const bool is_pressed = event.type == SDL_KEYDOWN;
|
||||
|
||||
KeyboardMachine::Machine *const keyboard_machine = machine->keyboard_machine();
|
||||
const auto keyboard_machine = machine->keyboard_machine();
|
||||
if(keyboard_machine) {
|
||||
Inputs::Keyboard::Key key = Inputs::Keyboard::Key::Space;
|
||||
if(!KeyboardKeyForSDLScancode(event.key.keysym.scancode, key)) break;
|
||||
|
||||
char key_value = '\0';
|
||||
const char *key_name = SDL_GetKeyName(event.key.keysym.sym);
|
||||
if(key_name[0] >= 0) key_value = key_name[0];
|
||||
if(keyboard_machine->get_keyboard().observed_keys().find(key) != keyboard_machine->get_keyboard().observed_keys().end()) {
|
||||
char key_value = '\0';
|
||||
const char *key_name = SDL_GetKeyName(event.key.keysym.sym);
|
||||
if(key_name[0] >= 0) key_value = key_name[0];
|
||||
|
||||
keyboard_machine->get_keyboard().set_key_pressed(key, key_value, is_pressed);
|
||||
break;
|
||||
keyboard_machine->get_keyboard().set_key_pressed(key, key_value, is_pressed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
JoystickMachine::Machine *const joystick_machine = machine->joystick_machine();
|
||||
|
Loading…
Reference in New Issue
Block a user