mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-27 16:31:31 +00:00
Merge pull request #714 from TomHarte/STJoystick
Adds Joystick key code mode, ensures events aren't posted in interrogation mode.
This commit is contained in:
commit
627d3c28ea
@ -100,13 +100,46 @@ void IntelligentKeyboard::run_for(HalfCycles duration) {
|
||||
// machine advertises as joystick 1 is mapped to the Atari ST's joystick 2, so as to
|
||||
// maintain both the normal emulation expections that the first joystick is the primary
|
||||
// one and the Atari ST's convention that the main joystick is in port 2.
|
||||
for(size_t c = 0; c < 2; ++c) {
|
||||
const auto joystick = static_cast<Joystick *>(joysticks_[c ^ 1].get());
|
||||
if(joystick->has_event()) {
|
||||
output_bytes({
|
||||
uint8_t(0xfe | c),
|
||||
joystick->get_state()
|
||||
});
|
||||
if(joystick_mode_ == JoystickMode::Event || joystick_mode_ == JoystickMode::KeyCode) {
|
||||
for(size_t c = 0; c < 2; ++c) {
|
||||
const auto joystick = static_cast<Joystick *>(joysticks_[c ^ 1].get());
|
||||
if(joystick->has_event()) {
|
||||
|
||||
if(joystick_mode_ == JoystickMode::Event) {
|
||||
// Event mode: forward a joystick event message.
|
||||
output_bytes({
|
||||
uint8_t(0xfe | c),
|
||||
joystick->get_state()
|
||||
});
|
||||
} else {
|
||||
// Key code mode: decompose the joystick event into
|
||||
// instantaneous key events.
|
||||
const auto event_mask = joystick->event_mask();
|
||||
const auto new_state = joystick->get_state();
|
||||
const auto new_presses = (event_mask ^ new_state) & new_state;
|
||||
|
||||
// Send cursor keys for the movement.
|
||||
const Key keys[] = {Key::Up, Key::Down, Key::Left, Key::Right};
|
||||
for(int key = 0; key < 4; ++key) {
|
||||
if(new_presses & (1 << key)) {
|
||||
output_bytes({
|
||||
uint8_t(keys[key]),
|
||||
uint8_t(0x80 | uint8_t(keys[key]))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Check also for fire, but the key to send depends
|
||||
// on the joystick.
|
||||
if(new_presses & 0x80) {
|
||||
const Key fire_buttons[] = {Key::Joystick1Button, Key::Joystick2Button};
|
||||
output_bytes({
|
||||
uint8_t(fire_buttons[c]),
|
||||
uint8_t(0x80 | uint8_t(fire_buttons[c]))
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -425,21 +458,45 @@ void IntelligentKeyboard::disable_joysticks() {
|
||||
|
||||
void IntelligentKeyboard::set_joystick_event_mode() {
|
||||
joystick_mode_ = JoystickMode::Event;
|
||||
clear_joystick_events();
|
||||
}
|
||||
|
||||
void IntelligentKeyboard::set_joystick_interrogation_mode() {
|
||||
joystick_mode_ = JoystickMode::Interrogation;
|
||||
}
|
||||
|
||||
void IntelligentKeyboard::interrogate_joysticks() {
|
||||
void IntelligentKeyboard::set_joystick_keycode_mode(VelocityThreshold horizontal, VelocityThreshold vertical) {
|
||||
joystick_mode_ = JoystickMode::KeyCode;
|
||||
clear_joystick_events();
|
||||
}
|
||||
|
||||
void IntelligentKeyboard::clear_joystick_events() {
|
||||
const auto joystick1 = static_cast<Joystick *>(joysticks_[0].get());
|
||||
const auto joystick2 = static_cast<Joystick *>(joysticks_[1].get());
|
||||
joystick1->get_state();
|
||||
joystick2->get_state();
|
||||
}
|
||||
|
||||
output_bytes({
|
||||
0xfd,
|
||||
joystick2->get_state(),
|
||||
joystick1->get_state()
|
||||
});
|
||||
void IntelligentKeyboard::interrogate_joysticks() {
|
||||
if(joystick_mode_ != JoystickMode::Interrogation) {
|
||||
// Joystick::get_state() implicitly clears Joystick::has_event,
|
||||
// so don't permit interrogation if the user isn't in interrogation
|
||||
// mode because it might cause dropped events.
|
||||
output_bytes({
|
||||
0xfd,
|
||||
0x00,
|
||||
0x00
|
||||
});
|
||||
} else {
|
||||
const auto joystick1 = static_cast<Joystick *>(joysticks_[0].get());
|
||||
const auto joystick2 = static_cast<Joystick *>(joysticks_[1].get());
|
||||
|
||||
output_bytes({
|
||||
0xfd,
|
||||
joystick2->get_state(),
|
||||
joystick1->get_state()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void IntelligentKeyboard::set_joystick_monitoring_mode(uint8_t rate) {
|
||||
@ -449,7 +506,3 @@ void IntelligentKeyboard::set_joystick_monitoring_mode(uint8_t rate) {
|
||||
void IntelligentKeyboard::set_joystick_fire_button_monitoring_mode() {
|
||||
LOG("Unimplemented: joystick fire button monitoring mode");
|
||||
}
|
||||
|
||||
void IntelligentKeyboard::set_joystick_keycode_mode(VelocityThreshold horizontal, VelocityThreshold vertical) {
|
||||
LOG("Unimplemented: joystick keycode mode");
|
||||
}
|
||||
|
@ -40,7 +40,9 @@ enum class Key: uint16_t {
|
||||
Insert = 0x52, Delete,
|
||||
ISO = 0x60, Undo, Help, KeypadOpenBracket, KeypadCloseBracket, KeypadDivide, KeypadMultiply,
|
||||
Keypad7, Keypad8, Keypad9, Keypad4, Keypad5, Keypad6, Keypad1, Keypad2, Keypad3, Keypad0, KeypadDecimalPoint,
|
||||
KeypadEnter
|
||||
KeypadEnter,
|
||||
Joystick1Button = 0x74, // These keycodes are used only in joystick keycode mode.
|
||||
Joystick2Button = 0x75,
|
||||
};
|
||||
static_assert(uint16_t(Key::RightShift) == 0x36, "RightShift should have key code 0x36; check intermediate entries");
|
||||
static_assert(uint16_t(Key::F10) == 0x44, "F10 should have key code 0x44; check intermediate entries");
|
||||
@ -143,8 +145,10 @@ class IntelligentKeyboard:
|
||||
void set_joystick_keycode_mode(VelocityThreshold horizontal, VelocityThreshold vertical);
|
||||
void interrogate_joysticks();
|
||||
|
||||
void clear_joystick_events();
|
||||
|
||||
enum class JoystickMode {
|
||||
Disabled, Event, Interrogation
|
||||
Disabled, Event, Interrogation, KeyCode
|
||||
} joystick_mode_ = JoystickMode::Event;
|
||||
|
||||
class Joystick: public Inputs::ConcreteJoystick {
|
||||
@ -181,6 +185,10 @@ class IntelligentKeyboard:
|
||||
return returned_state_ != state_;
|
||||
}
|
||||
|
||||
uint8_t event_mask() {
|
||||
return returned_state_ ^ state_;
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t state_ = 0x00;
|
||||
uint8_t returned_state_ = 0x00;
|
||||
|
Loading…
Reference in New Issue
Block a user