diff --git a/Analyser/Dynamic/MultiMachine/Implementation/MultiJoystickMachine.cpp b/Analyser/Dynamic/MultiMachine/Implementation/MultiJoystickMachine.cpp index d6d17fcd3..6a0aa4ecf 100644 --- a/Analyser/Dynamic/MultiMachine/Implementation/MultiJoystickMachine.cpp +++ b/Analyser/Dynamic/MultiMachine/Implementation/MultiJoystickMachine.cpp @@ -25,11 +25,11 @@ class MultiJoystick: public Inputs::Joystick { } } - std::vector get_inputs() override { - std::vector inputs; + std::vector get_inputs() override { + std::vector inputs; for(const auto &joystick: joysticks_) { - std::vector joystick_inputs = joystick->get_inputs(); + std::vector joystick_inputs = joystick->get_inputs(); for(const auto &input: joystick_inputs) { if(std::find(inputs.begin(), inputs.end(), input) != inputs.end()) { inputs.push_back(input); @@ -40,9 +40,9 @@ class MultiJoystick: public Inputs::Joystick { return inputs; } - void set_digital_input(const DigitalInput &digital_input, bool is_active) override { + void set_input(const Input &digital_input, bool is_active) override { for(const auto &joystick: joysticks_) { - joystick->set_digital_input(digital_input, is_active); + joystick->set_input(digital_input, is_active); } } void reset_all_inputs() override { diff --git a/Inputs/Joystick.hpp b/Inputs/Joystick.hpp index e5d0b4820..ee15eee2f 100644 --- a/Inputs/Joystick.hpp +++ b/Inputs/Joystick.hpp @@ -21,29 +21,57 @@ class Joystick { public: virtual ~Joystick() {} - struct DigitalInput { + struct Input { + /// Defines the broad type of the input. enum Type { - Up, Down, Left, Right, Fire, + // Half-axis inputs. + Up, Down, Left, Right, + // Full-axis inputs. + Horizontal, Vertical, + // Fire buttons. + Fire, + // Other labelled keys. Key - } type; - union { + }; + const Type type; + + enum Precision { + Analogue, Digital + }; + const Precision precision; + + /*! + Holds extra information pertaining to the input. + + @c Type::Key inputs declare the symbol printed on them. + + All other types of input have an associated index, indicating whether they + are the zeroth, first, second, third, etc of those things. E.g. a joystick + may have two fire buttons, which will be buttons 0 and 1. + */ + union Info { struct { int index; } control; struct { wchar_t symbol; } key; - } info; + }; + Info info; + // TODO: Find a way to make the above safely const; may mean not using a union. - DigitalInput(Type type, int index = 0) : type(type) { + Input(Type type, int index = 0, Precision precision = Precision::Digital) : + type(type), + precision(precision) { info.control.index = index; } - DigitalInput(wchar_t symbol) : type(Key) { + Input(wchar_t symbol) : type(Key), precision(Precision::Digital) { info.key.symbol = symbol; } - bool operator == (const DigitalInput &rhs) { + bool operator == (const Input &rhs) { if(rhs.type != type) return false; + if(rhs.precision != precision) return false; if(rhs.type == Key) { return rhs.info.key.symbol == info.key.symbol; } else { @@ -52,13 +80,16 @@ class Joystick { } }; - virtual std::vector get_inputs() = 0; + virtual std::vector get_inputs() = 0; + + // Host interface. Note that the two set_inputs have logic to map + // between analogue and digital inputs; if you override + virtual void set_input(const Input &input, bool is_active) = 0; + virtual void set_input(const Input &input, float value) {} - // Host interface. - virtual void set_digital_input(const DigitalInput &digital_input, bool is_active) = 0; virtual void reset_all_inputs() { for(const auto &input: get_inputs()) { - set_digital_input(input, false); + set_input(input, false); } } }; diff --git a/Machines/Atari2600/Atari2600.cpp b/Machines/Atari2600/Atari2600.cpp index 55a7b5fa1..4f84e58ac 100644 --- a/Machines/Atari2600/Atari2600.cpp +++ b/Machines/Atari2600/Atari2600.cpp @@ -42,25 +42,25 @@ class Joystick: public Inputs::Joystick { Joystick(Bus *bus, std::size_t shift, std::size_t fire_tia_input) : bus_(bus), shift_(shift), fire_tia_input_(fire_tia_input) {} - std::vector get_inputs() override { + std::vector get_inputs() override { return { - DigitalInput(DigitalInput::Up), - DigitalInput(DigitalInput::Down), - DigitalInput(DigitalInput::Left), - DigitalInput(DigitalInput::Right), - DigitalInput(DigitalInput::Fire) + Input(Input::Up), + Input(Input::Down), + Input(Input::Left), + Input(Input::Right), + Input(Input::Fire) }; } - void set_digital_input(const DigitalInput &digital_input, bool is_active) override { + void set_input(const Input &digital_input, bool is_active) override { switch(digital_input.type) { - case DigitalInput::Up: bus_->mos6532_.update_port_input(0, 0x10 >> shift_, is_active); break; - case DigitalInput::Down: bus_->mos6532_.update_port_input(0, 0x20 >> shift_, is_active); break; - case DigitalInput::Left: bus_->mos6532_.update_port_input(0, 0x40 >> shift_, is_active); break; - case DigitalInput::Right: bus_->mos6532_.update_port_input(0, 0x80 >> shift_, is_active); break; + case Input::Up: bus_->mos6532_.update_port_input(0, 0x10 >> shift_, is_active); break; + case Input::Down: bus_->mos6532_.update_port_input(0, 0x20 >> shift_, is_active); break; + case Input::Left: bus_->mos6532_.update_port_input(0, 0x40 >> shift_, is_active); break; + case Input::Right: bus_->mos6532_.update_port_input(0, 0x80 >> shift_, is_active); break; // TODO: latching - case DigitalInput::Fire: + case Input::Fire: if(is_active) bus_->tia_input_value_[fire_tia_input_] &= ~0x80; else diff --git a/Machines/ColecoVision/ColecoVision.cpp b/Machines/ColecoVision/ColecoVision.cpp index aec0a447b..101e7a617 100644 --- a/Machines/ColecoVision/ColecoVision.cpp +++ b/Machines/ColecoVision/ColecoVision.cpp @@ -34,28 +34,28 @@ namespace Vision { class Joystick: public Inputs::Joystick { public: - std::vector get_inputs() override { + std::vector get_inputs() override { return { - DigitalInput(DigitalInput::Up), - DigitalInput(DigitalInput::Down), - DigitalInput(DigitalInput::Left), - DigitalInput(DigitalInput::Right), + Input(Input::Up), + Input(Input::Down), + Input(Input::Left), + Input(Input::Right), - DigitalInput(DigitalInput::Fire, 0), - DigitalInput(DigitalInput::Fire, 1), + Input(Input::Fire, 0), + Input(Input::Fire, 1), - DigitalInput('0'), DigitalInput('1'), DigitalInput('2'), - DigitalInput('3'), DigitalInput('4'), DigitalInput('5'), - DigitalInput('6'), DigitalInput('7'), DigitalInput('8'), - DigitalInput('9'), DigitalInput('*'), DigitalInput('#'), + Input('0'), Input('1'), Input('2'), + Input('3'), Input('4'), Input('5'), + Input('6'), Input('7'), Input('8'), + Input('9'), Input('*'), Input('#'), }; } - void set_digital_input(const DigitalInput &digital_input, bool is_active) override { + void set_input(const Input &digital_input, bool is_active) override { switch(digital_input.type) { default: return; - case DigitalInput::Key: + case Input::Key: if(!is_active) keypad_ |= 0xf; else { uint8_t mask = 0xf; @@ -78,11 +78,11 @@ class Joystick: public Inputs::Joystick { } break; - case DigitalInput::Up: if(is_active) direction_ &= ~0x01; else direction_ |= 0x01; break; - case DigitalInput::Right: if(is_active) direction_ &= ~0x02; else direction_ |= 0x02; break; - case DigitalInput::Down: if(is_active) direction_ &= ~0x04; else direction_ |= 0x04; break; - case DigitalInput::Left: if(is_active) direction_ &= ~0x08; else direction_ |= 0x08; break; - case DigitalInput::Fire: + case Input::Up: if(is_active) direction_ &= ~0x01; else direction_ |= 0x01; break; + case Input::Right: if(is_active) direction_ &= ~0x02; else direction_ |= 0x02; break; + case Input::Down: if(is_active) direction_ &= ~0x04; else direction_ |= 0x04; break; + case Input::Left: if(is_active) direction_ &= ~0x08; else direction_ |= 0x08; break; + case Input::Fire: switch(digital_input.info.control.index) { default: break; case 0: if(is_active) direction_ &= ~0x40; else direction_ |= 0x40; break; diff --git a/Machines/Commodore/Vic-20/Vic20.cpp b/Machines/Commodore/Vic-20/Vic20.cpp index cb7248524..0fe5cc65c 100644 --- a/Machines/Commodore/Vic-20/Vic20.cpp +++ b/Machines/Commodore/Vic-20/Vic20.cpp @@ -263,25 +263,25 @@ class Joystick: public Inputs::Joystick { user_port_via_port_handler_(user_port_via_port_handler), keyboard_via_port_handler_(keyboard_via_port_handler) {} - std::vector get_inputs() override { + std::vector get_inputs() override { return { - DigitalInput(DigitalInput::Up), - DigitalInput(DigitalInput::Down), - DigitalInput(DigitalInput::Left), - DigitalInput(DigitalInput::Right), - DigitalInput(DigitalInput::Fire) + Input(Input::Up), + Input(Input::Down), + Input(Input::Left), + Input(Input::Right), + Input(Input::Fire) }; } - void set_digital_input(const DigitalInput &digital_input, bool is_active) override { + void set_input(const Input &digital_input, bool is_active) override { JoystickInput mapped_input; switch(digital_input.type) { 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; + case Input::Up: mapped_input = Up; break; + case Input::Down: mapped_input = Down; break; + case Input::Left: mapped_input = Left; break; + case Input::Right: mapped_input = Right; break; + case Input::Fire: mapped_input = Fire; break; } user_port_via_port_handler_.set_joystick_state(mapped_input, is_active); diff --git a/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm b/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm index 310f6df99..a91c3e246 100644 --- a/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm +++ b/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm @@ -252,19 +252,21 @@ struct SpeakerDelegate: public Outputs::Speaker::Speaker::Delegate, public LockP @synchronized(self) { std::vector> &joysticks = joystick_machine->get_joysticks(); if(!joysticks.empty()) { + // Convert to a C++ bool so that the following calls are resolved correctly even if overloaded. + bool is_pressed = !!isPressed; 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; - case VK_Space: joysticks[0]->set_digital_input(Inputs::Joystick::DigitalInput::Fire, isPressed); break; - case VK_ANSI_A: joysticks[0]->set_digital_input(Inputs::Joystick::DigitalInput(Inputs::Joystick::DigitalInput::Fire, 0), isPressed); break; - case VK_ANSI_S: joysticks[0]->set_digital_input(Inputs::Joystick::DigitalInput(Inputs::Joystick::DigitalInput::Fire, 1), isPressed); break; + case VK_LeftArrow: joysticks[0]->set_input(Inputs::Joystick::Input::Left, is_pressed); break; + case VK_RightArrow: joysticks[0]->set_input(Inputs::Joystick::Input::Right, is_pressed); break; + case VK_UpArrow: joysticks[0]->set_input(Inputs::Joystick::Input::Up, is_pressed); break; + case VK_DownArrow: joysticks[0]->set_input(Inputs::Joystick::Input::Down, is_pressed); break; + case VK_Space: joysticks[0]->set_input(Inputs::Joystick::Input::Fire, is_pressed); break; + case VK_ANSI_A: joysticks[0]->set_input(Inputs::Joystick::Input(Inputs::Joystick::Input::Fire, 0), is_pressed); break; + case VK_ANSI_S: joysticks[0]->set_input(Inputs::Joystick::Input(Inputs::Joystick::Input::Fire, 1), is_pressed); break; default: if(characters) { - joysticks[0]->set_digital_input(Inputs::Joystick::DigitalInput([characters characterAtIndex:0]), isPressed); + joysticks[0]->set_input(Inputs::Joystick::Input([characters characterAtIndex:0]), is_pressed); } else { - joysticks[0]->set_digital_input(Inputs::Joystick::DigitalInput::Fire, isPressed); + joysticks[0]->set_input(Inputs::Joystick::Input::Fire, is_pressed); } break; } diff --git a/OSBindings/SDL/main.cpp b/OSBindings/SDL/main.cpp index d80f4c4a1..cbd5ffa03 100644 --- a/OSBindings/SDL/main.cpp +++ b/OSBindings/SDL/main.cpp @@ -464,16 +464,16 @@ int main(int argc, char *argv[]) { std::vector> &joysticks = joystick_machine->get_joysticks(); if(!joysticks.empty()) { switch(event.key.keysym.scancode) { - case SDL_SCANCODE_LEFT: joysticks[0]->set_digital_input(Inputs::Joystick::DigitalInput::Left, is_pressed); break; - case SDL_SCANCODE_RIGHT: joysticks[0]->set_digital_input(Inputs::Joystick::DigitalInput::Right, is_pressed); break; - case SDL_SCANCODE_UP: joysticks[0]->set_digital_input(Inputs::Joystick::DigitalInput::Up, is_pressed); break; - case SDL_SCANCODE_DOWN: joysticks[0]->set_digital_input(Inputs::Joystick::DigitalInput::Down, is_pressed); break; - case SDL_SCANCODE_SPACE: joysticks[0]->set_digital_input(Inputs::Joystick::DigitalInput::Fire, is_pressed); break; - case SDL_SCANCODE_A: joysticks[0]->set_digital_input(Inputs::Joystick::DigitalInput(Inputs::Joystick::DigitalInput::Fire, 0), is_pressed); break; - case SDL_SCANCODE_S: joysticks[0]->set_digital_input(Inputs::Joystick::DigitalInput(Inputs::Joystick::DigitalInput::Fire, 1), is_pressed); break; + case SDL_SCANCODE_LEFT: joysticks[0]->set_input(Inputs::Joystick::Input::Left, is_pressed); break; + case SDL_SCANCODE_RIGHT: joysticks[0]->set_input(Inputs::Joystick::Input::Right, is_pressed); break; + case SDL_SCANCODE_UP: joysticks[0]->set_input(Inputs::Joystick::Input::Up, is_pressed); break; + case SDL_SCANCODE_DOWN: joysticks[0]->set_input(Inputs::Joystick::Input::Down, is_pressed); break; + case SDL_SCANCODE_SPACE: joysticks[0]->set_input(Inputs::Joystick::Input::Fire, is_pressed); break; + case SDL_SCANCODE_A: joysticks[0]->set_input(Inputs::Joystick::Input(Inputs::Joystick::Input::Fire, 0), is_pressed); break; + case SDL_SCANCODE_S: joysticks[0]->set_input(Inputs::Joystick::Input(Inputs::Joystick::Input::Fire, 1), is_pressed); break; default: { const char *key_name = SDL_GetKeyName(event.key.keysym.sym); - joysticks[0]->set_digital_input(Inputs::Joystick::DigitalInput(key_name[0]), is_pressed); + joysticks[0]->set_input(Inputs::Joystick::Input(key_name[0]), is_pressed); } break; } }